Do not bind accessors in toplevel thunks to their thunks' names

In #3352 an optimization to transform `ra = .field` into

```
ra = \#rcd -[ra]-> #rcd.field
```

rather than

```
__ra1 = \#rcd -[__ra1] -> #rcd.field

ra = LambdaSet { __ra1 }
```

was introduced. However, this optimization is not correct when `ra =
.field` is defined as a toplevel thunk, for in such situations we
indeed want the thunk `ra` to return the lambda set it resolves to,
rather than repointing at itself.

Besides reverting this change, another option would be to convert
accessors into closures before translation of Can to IR. However, this
complicates the translation algorithm more than it already is, and I'd
like to avoid additional special-cases.

Closes #4606
This commit is contained in:
Ayaz Hafiz 2022-12-01 11:05:33 -06:00
parent 22a84c8b21
commit 078f0147ee
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
4 changed files with 45 additions and 30 deletions

View file

@ -2255,36 +2255,6 @@ fn canonicalize_pending_body<'a>(
(loc_can_expr, def_references)
}
// Turn f = .foo into f = \rcd -[f]-> rcd.foo
(
Pattern::Identifier(defined_symbol)
| Pattern::AbilityMemberSpecialization {
ident: defined_symbol,
..
},
ast::Expr::RecordAccessorFunction(field),
) => {
let (loc_can_expr, can_output) = (
Loc::at(
loc_expr.region,
Accessor(AccessorData {
name: *defined_symbol,
function_var: var_store.fresh(),
record_var: var_store.fresh(),
ext_var: var_store.fresh(),
closure_var: var_store.fresh(),
field_var: var_store.fresh(),
field: (*field).into(),
}),
),
Output::default(),
);
let def_references = DefReferences::Value(can_output.references.clone());
output.union(can_output);
(loc_can_expr, def_references)
}
_ => {
let (loc_can_expr, can_output) =
canonicalize_expr(env, var_store, scope, loc_expr.region, &loc_expr.value);

View file

@ -1092,3 +1092,22 @@ fn update_record_that_is_a_thunk_single_field() {
RocStr
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn toplevel_accessor_fn_thunk() {
assert_evals_to!(
indoc!(
r#"
app "test" provides [main] to "./platform"
ra = .field
main =
ra { field : 15u8 }
"#
),
15u8,
u8
)
}

View file

@ -0,0 +1,12 @@
procedure Test.1 ():
let Test.6 : {} = Struct {};
ret Test.6;
procedure Test.2 (Test.7):
ret Test.7;
procedure Test.0 ():
let Test.9 : U8 = 15i64;
let Test.4 : {} = CallByName Test.1;
let Test.3 : U8 = CallByName Test.2 Test.9;
ret Test.3;

View file

@ -2082,3 +2082,17 @@ fn anonymous_closure_lifted_to_named_issue_2403() {
"#
)
}
#[mono_test]
fn toplevel_accessor_fn_thunk() {
indoc!(
r#"
app "test" provides [main] to "./platform"
ra = .field
main =
ra { field : 15u8 }
"#
)
}