diff --git a/compiler/mono/src/ir.rs b/compiler/mono/src/ir.rs index 97522dd561..b05fc75072 100644 --- a/compiler/mono/src/ir.rs +++ b/compiler/mono/src/ir.rs @@ -3053,7 +3053,7 @@ fn specialize_naked_symbol<'a>( let opt_fn_var = Some(variable); // if this is a function symbol, ensure that it's properly specialized! - reuse_function_symbol( + specialize_symbol( env, procs, layout_cache, @@ -3558,7 +3558,7 @@ pub fn with_hole<'a>( // this symbol is already defined; nothing to do } Field::Function(symbol, variable) => { - stmt = reuse_function_symbol( + stmt = specialize_symbol( env, procs, layout_cache, @@ -4114,7 +4114,7 @@ pub fn with_hole<'a>( Stmt::Let(*symbol, access_expr, *field_layout, arena.alloc(stmt)); if record_needs_specialization { - stmt = reuse_function_symbol( + stmt = specialize_symbol( env, procs, layout_cache, @@ -4804,8 +4804,7 @@ fn construct_closure_data<'a>( // symbols to be inlined when specializing the closure body elsewhere. for &&(symbol, var) in symbols { if procs.partial_exprs.contains(symbol) { - result = - reuse_function_symbol(env, procs, layout_cache, Some(var), symbol, result, symbol); + result = specialize_symbol(env, procs, layout_cache, Some(var), symbol, result, symbol); } } @@ -6318,6 +6317,20 @@ fn store_pattern_help<'a>( match can_pat { Identifier(symbol) => { + if let Some((_, var)) = procs.partial_exprs.get(outer_symbol) { + // It might be the case that symbol we're storing hasn't been reified to a value + // yet, if it's polymorphic. Do that now. + stmt = specialize_symbol( + env, + procs, + layout_cache, + Some(var), + *symbol, + stmt, + outer_symbol, + ); + } + substitute_in_exprs(env.arena, &mut stmt, *symbol, outer_symbol); } Underscore => { @@ -6771,7 +6784,7 @@ fn let_empty_struct<'a>(assigned: Symbol, hole: &'a Stmt<'a>) -> Stmt<'a> { /// If the symbol is a function, make sure it is properly specialized // TODO: rename this now that we handle polymorphic non-function expressions too -fn reuse_function_symbol<'a>( +fn specialize_symbol<'a>( env: &mut Env<'a, '_>, procs: &mut Procs<'a>, layout_cache: &mut LayoutCache<'a>, @@ -6980,7 +6993,7 @@ fn assign_to_symbol<'a>( match can_reuse_symbol(env, procs, &loc_arg.value) { Imported(original) | LocalFunction(original) | UnspecializedExpr(original) => { // for functions we must make sure they are specialized correctly - reuse_function_symbol( + specialize_symbol( env, procs, layout_cache, diff --git a/compiler/test_gen/src/gen_str.rs b/compiler/test_gen/src/gen_str.rs index d5e5f6da83..de5119e68b 100644 --- a/compiler/test_gen/src/gen_str.rs +++ b/compiler/test_gen/src/gen_str.rs @@ -1587,3 +1587,19 @@ fn str_to_dec() { RocDec ); } + +#[test] +#[cfg(any(feature = "gen-llvm"))] +fn issue_2811() { + assert_evals_to!( + indoc!( + r#" + x = Command { tool: "bash" } + Command c = x + c.tool + "# + ), + RocStr::from("bash"), + RocStr + ); +} diff --git a/compiler/test_mono/generated/issue_2811.txt b/compiler/test_mono/generated/issue_2811.txt new file mode 100644 index 0000000000..ee169bc476 --- /dev/null +++ b/compiler/test_mono/generated/issue_2811.txt @@ -0,0 +1,3 @@ +procedure Test.0 (): + let Test.6 : Str = "bash"; + ret Test.6; diff --git a/compiler/test_mono/src/tests.rs b/compiler/test_mono/src/tests.rs index 64149bd120..ff9b7bfcaa 100644 --- a/compiler/test_mono/src/tests.rs +++ b/compiler/test_mono/src/tests.rs @@ -1282,6 +1282,17 @@ fn issue_2583_specialize_errors_behind_unified_branches() { ) } +#[mono_test] +fn issue_2811() { + indoc!( + r#" + x = Command { tool: "bash" } + Command c = x + c.tool + "# + ) +} + // #[ignore] // #[mono_test] // fn static_str_closure() {