Skip to content

fix[next]: lower function definitions to let bindings - #2905

Open
tehrengruber wants to merge 2 commits into
mainfrom
tehrengruber/simplify-inline-fundefs
Open

tehrengruber wants to merge 2 commits into
mainfrom
tehrengruber/simplify-inline-fundefs

Conversation

@tehrengruber

@tehrengruber tehrengruber commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

InlineFundefs replaced every SymRef matching a program-level function definition, regardless of any binder of the same name in between. A lambda parameter named like a field operator was therefore silently replaced by that function, producing an ill-typed program (e.g. an AssertionError in type_synthesizer._canonicalize_nb_fields).

Instead of substituting references, all function definitions are now bound in nested lets wrapping every statement expression, and Program.function_definitions is cleared. Regular scoping rules then apply, i.e. an inner binder shadows the function definition, and unused bindings are removed by dead code elimination, which makes the separate prune_unreferenced_fundefs pass obsolete. The lets are nested in topological order since function definitions may call each other.

Follow-up to #2833 (comment), where tuple-comprehension targets made this easy to hit.

AI disclaimer: This PR has been created with the help of AI tools. The code has been reviewed, but tests were only briefly sighted.

`InlineFundefs` replaced every `SymRef` matching a program-level function
definition, regardless of any binder of the same name in between. A lambda
parameter named like a function definition was therefore silently replaced
by that function, producing an ill-typed program (e.g. an `AssertionError`
in `type_synthesizer._canonicalize_nb_fields`).

Instead of substituting references, bind all function definitions in a
`let` wrapping every statement expression. Regular scoping rules then
apply, i.e. an inner binder shadows the function definition, and unused
bindings are removed by dead code elimination, which makes the separate
`prune_unreferenced_fundefs` pass obsolete.
@tehrengruber

tehrengruber commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor Author

Since the PR does not inline every function right away it might lead to some problems in the dace backend. We might want to force inline functions for dace and maybe even gtfn. The approach in this PR generally better since we start with a smaller IR (after the first inline lambda which removes unused functions) that we can optimize before inlining later. We force inline all lambdas anyway right now.

The traced `flux` function definition is polymorphic in its parameter `d`,
it is called with an `I` and a `J` offset. Type inference can not type a
`let` bound function used at several types, which the function definitions
are lowered to now. Dropping the `fundef` decorator makes tracing inline
`flux` as a lambda instead, which keeps the test unchanged otherwise.
@havogt
havogt self-requested a review September 23, 2026 09:00

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant