-
Notifications
You must be signed in to change notification settings - Fork 219
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Initial work on rewriting closures to regular functions with hi… #1959
Conversation
56b7021
to
3553aaf
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've yet to go through the whole PR so far, but here's an initial review of mostly the type system related parts. Tomorrow I'll revisit this and go through the name resolution and monomorphization changes.
5f5a3de
to
2de4113
Compare
@alehander92 what is the status of this PR? |
@kevaundray we discussed some lang/impl questions that appeared while working on this PR with @jfecher through the last week, and I prepared some fixes for this PR and the initial closure conversion.(also rebased after upstream dropped the old ssa backend) (More advanced capabilities can be merged as a subsequent patch probably?): I'll try to push the current changes soon |
a0e395e
to
55755da
Compare
I've just pushed the rebased version of the original changes, soon I'll push some more fixes |
a3c9ad7
to
2778375
Compare
I refactored, so we can use only the |
fab657a
to
4a0c2ee
Compare
Does this mean we can't return closures at all? I also noticed the current tests mostly test free functions rather than closures with an environment. What cases are expected to be implemented by this PR? |
3f5b6d7
to
2960ee0
Compare
Looks like this PR crashes for the input: fn main() {
let x: u32 = 32;
let f = if x > 2 {
|| x
} else {
|| x + 2342
};
dep::std::println(f());
} Also, when trying: use dep::std::println;
fn main() {
let x: u32 = 32;
let f = if x > 2 {
|| x
} else {
three
};
println(f());
}
fn three() -> u32 {
3
} I get the rather confusing error message:
Some suggestions to improve this:
|
I tested just now and it seems we're able to return lambdas but not closures that capture an environment. I'd like if that functionality were part of this PR as well. At the same time, I don't want to step on your toes and make things more difficult since I'm aware keeping up with merge conflicts gets increasingly difficult the larger the PR. So let me know if this would be too much. I'll try to be more consistent in reviewing these PRs in a more timely manner as well. |
925b351
to
1e82485
Compare
I agree with 2 and 3: i've fixed those in the last commit for 1: i've fixed the unify/display logic, so it should behave correctly in type checking, however part of the logic itself remains before the monomorphization pass: should I move this as well? now, with those fixes, both examples fail with the same kind of ICE, I'll try to look into it. Overally, it would be good to fix the returning of closures, but in my understanding it's deeply related to the implicit genericness of functions with closures and instantiating them, which we planned for the next MR, so i think it would be easier to separate them like that(if we remain with the 2 MR plan) |
1e82485
to
42980c7
Compare
Co-authored-by: jfecher <jfecher11@gmail.com>
Co-authored-by: jfecher <jfecher11@gmail.com>
3af1f13
to
5cc3429
Compare
@jfecher thanks for the help and summary: sounds good. sorry, had to fix one test again: now they all pass locally (at least I also removed the |
hm , we can try that in the new work |
* master: chore: replace usage of `Directive::Quotient` with brillig opcode (#1766) chore: clippy fix (#2136) feat: Initial work on rewriting closures to regular functions with hi… (#1959) chore: Decouple acir blockid from ssa valueid (#2103) chore: Initialize copy array from previous values in `array_set` (#2106) chore: rename `ssa_refactor` module to `ssa` (#2129) chore: Use `--show-output` flag on execution rather than compilation (#2116) fix(globals): Accurately filter literals for resolving globals (#2126) feat: Optimize away constant calls to black box functions (#1981)
* master: (50 commits) chore: update stale comment on `create_circuit` (#2173) chore: Replace `resolve_path` function with a trait that impls normalize (#2157) chore: clippy fix (#2174) feat!: Allow specifying new package name with `--name` flag (#2144) chore!: remove unused flags on LSP command (#2170) chore: Hide the `show_ssa` and `show_brillig` flags (#2171) chore: bump `clap` to 4.3.19 (#2167) chore: Move the long line of `nargo info` to `long_about` (#2151) chore: Refactor `normalize_path` into an API on FileManager (#2156) fix: Implement slices of structs (#2150) chore: Refreshed ACIR artifacts (#2148) chore: Rebuild ACIR test artifacts (#2147) chore: remove short flags for `--show-ssa` and `--deny-warnings` (#2141) chore: replace usage of `Directive::Quotient` with brillig opcode (#1766) chore: clippy fix (#2136) feat: Initial work on rewriting closures to regular functions with hi… (#1959) chore: Decouple acir blockid from ssa valueid (#2103) chore: Initialize copy array from previous values in `array_set` (#2106) chore: rename `ssa_refactor` module to `ssa` (#2129) chore: Use `--show-output` flag on execution rather than compilation (#2116) ...
Did this go into v0.10.0? It doesn't seem to show up in the changelogs 🤔 Separately anything / what should go into the docs? |
There's few more things related to this PR that we'd like to get merged first:
Those are both small changes so it should be done today/tomorrow, after that I'll send a PR to docs describing the changes related to closures & give some examples on how to use them. |
The changes in Noir have been merged, I've submitted a PR for docs: noir-lang/docs#356 |
Description
This commit implements the following mechanism:
On a line where a lambda expression is encountered, we initialize a tuple for the captured lambda environment and we rewrite the lambda to a regular function taking this environment as an additional parameter. All calls to the closure are then modified to insert this hidden parameter.
In other words, the following code:
is rewritten to:
In the presence of nested closures, we propagate the captured variables implicitly through all intermediate closures:
To make these transforms possible, the following changes were made to the logic of the HIR resolver and the monomorphization pass:
In the HIR resolver pass, the code determines the precise list of variables captured by each lambda. Along with the list, we compute the index of each captured var within the parent closure's environment (when the capture is propagated).
Introduction of a new
Closure
type in order to be able to recognize the call-sites that need the automatic environment variable treatment. It's a bit unfortunate that the Closure type is defined within theAST
modules that are used to describe the output of the monomorphization pass, because we aim to eliminate all closures during the pass. A better solution would have been possible if the type check pass after HIR resolution was outputting types specific to the HIR pass (then the closures would exist only within this separate non-simplified type system).The majority of the work is in the Lambda processing step in the monomorphizer which performs the necessary transformations based on the above information.
Remaining things to do:
There are a number of pending TODO items for various minor unresolved loose ends in the code.
There are a lot of possible additional tests to be written.
Update docs
Problem*
Resolves #1254
Documentation
This PR requires documentation updates when merged.
PR Checklist*
cargo fmt
on default settings.:
cargo fmt