mirror of
https://github.com/roc-lang/roc.git
synced 2025-07-24 06:55:15 +00:00
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:
parent
22a84c8b21
commit
078f0147ee
4 changed files with 45 additions and 30 deletions
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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;
|
|
@ -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 }
|
||||
"#
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue