mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-22 08:17:40 +03:00
Merge pull request #2417 from rtfeldman/i/2322
Inline polymorphic calls at usage sites
This commit is contained in:
commit
2d8bdfd863
@ -4179,9 +4179,6 @@ pub fn with_hole<'a>(
|
||||
LocalFunction(_) => {
|
||||
unreachable!("if this was known to be a function, we would not be here")
|
||||
}
|
||||
UnspecializedExpr(_) => {
|
||||
unreachable!("if this was known to be an unspecialized expression, we would not be here")
|
||||
}
|
||||
Imported(thunk_name) => {
|
||||
debug_assert!(procs.is_imported_module_thunk(thunk_name));
|
||||
|
||||
@ -4240,6 +4237,49 @@ pub fn with_hole<'a>(
|
||||
unreachable!("calling a non-closure layout")
|
||||
}
|
||||
},
|
||||
UnspecializedExpr(symbol) => match full_layout {
|
||||
RawFunctionLayout::Function(arg_layouts, lambda_set, ret_layout) => {
|
||||
let closure_data_symbol = env.unique_symbol();
|
||||
|
||||
result = match_on_lambda_set(
|
||||
env,
|
||||
lambda_set,
|
||||
closure_data_symbol,
|
||||
arg_symbols,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
assigned,
|
||||
hole,
|
||||
);
|
||||
|
||||
let (lambda_expr, lambda_expr_var) =
|
||||
procs.partial_exprs.get(symbol).unwrap();
|
||||
|
||||
let snapshot = env.subs.snapshot();
|
||||
let cache_snapshot = layout_cache.snapshot();
|
||||
let _unified = roc_unify::unify::unify(
|
||||
env.subs,
|
||||
fn_var,
|
||||
lambda_expr_var,
|
||||
roc_unify::unify::Mode::Eq,
|
||||
);
|
||||
|
||||
result = with_hole(
|
||||
env,
|
||||
lambda_expr.clone(),
|
||||
fn_var,
|
||||
procs,
|
||||
layout_cache,
|
||||
closure_data_symbol,
|
||||
env.arena.alloc(result),
|
||||
);
|
||||
env.subs.rollback_to(snapshot);
|
||||
layout_cache.rollback_to(cache_snapshot);
|
||||
}
|
||||
RawFunctionLayout::ZeroArgumentThunk(_) => {
|
||||
unreachable!("calling a non-closure layout")
|
||||
}
|
||||
},
|
||||
NotASymbol => {
|
||||
// the expression is not a symbol. That means it's an expression
|
||||
// evaluating to a function value.
|
||||
@ -5184,6 +5224,7 @@ fn is_literal_like(expr: &roc_can::expr::Expr) -> bool {
|
||||
| ZeroArgumentTag { .. }
|
||||
| Tag { .. }
|
||||
| Record { .. }
|
||||
| Call(..)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -3207,3 +3207,20 @@ fn polymophic_expression_captured_inside_closure() {
|
||||
u8
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn issue_2322() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
double = \x -> x * 2
|
||||
doubleBind = \x -> (\_ -> double x)
|
||||
doubleThree = doubleBind 3
|
||||
doubleThree {}
|
||||
"#
|
||||
),
|
||||
6,
|
||||
i64
|
||||
)
|
||||
}
|
||||
|
17
compiler/test_mono/generated/aliased_polymorphic_closure.txt
Normal file
17
compiler/test_mono/generated/aliased_polymorphic_closure.txt
Normal file
@ -0,0 +1,17 @@
|
||||
procedure Test.2 (Test.6, #Attr.12):
|
||||
let Test.1 : Builtin(Int(U8)) = StructAtIndex 0 #Attr.12;
|
||||
let Test.11 : LambdaSet(LambdaSet { set: [( Test.4, [Builtin(Int(U8))])], representation: Struct([Builtin(Int(U8))]) }) = Struct {Test.1};
|
||||
ret Test.11;
|
||||
|
||||
procedure Test.4 (Test.5, #Attr.12):
|
||||
let Test.1 : Builtin(Int(U8)) = StructAtIndex 0 #Attr.12;
|
||||
ret Test.1;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.1 : Builtin(Int(U8)) = 1i64;
|
||||
let Test.8 : Struct([]) = Struct {};
|
||||
let Test.10 : Struct([]) = Struct {};
|
||||
let Test.14 : LambdaSet(LambdaSet { set: [( Test.2, [Builtin(Int(U8))])], representation: Struct([Builtin(Int(U8))]) }) = Struct {Test.1};
|
||||
let Test.9 : LambdaSet(LambdaSet { set: [( Test.4, [Builtin(Int(U8))])], representation: Struct([Builtin(Int(U8))]) }) = CallByName Test.2 Test.10 Test.14;
|
||||
let Test.7 : Builtin(Int(U8)) = CallByName Test.4 Test.8 Test.9;
|
||||
ret Test.7;
|
@ -1,21 +1,21 @@
|
||||
procedure List.7 (#Attr.2):
|
||||
let Test.7 : Builtin(Int(U64)) = lowlevel ListLen #Attr.2;
|
||||
ret Test.7;
|
||||
let Test.8 : Builtin(Int(U64)) = lowlevel ListLen #Attr.2;
|
||||
ret Test.8;
|
||||
|
||||
procedure Test.1 (Test.5):
|
||||
let Test.2 : Builtin(Int(I64)) = 41i64;
|
||||
let Test.11 : LambdaSet(LambdaSet { set: [( Test.3, [Builtin(Int(I64))])], representation: Struct([Builtin(Int(I64))]) }) = Struct {Test.2};
|
||||
let Test.10 : Builtin(List(LambdaSet(LambdaSet { set: [( Test.3, [Builtin(Int(I64))])], representation: Struct([Builtin(Int(I64))]) }))) = Array [Test.11];
|
||||
ret Test.10;
|
||||
let Test.12 : LambdaSet(LambdaSet { set: [( Test.3, [Builtin(Int(I64))])], representation: Struct([Builtin(Int(I64))]) }) = Struct {Test.2};
|
||||
let Test.11 : Builtin(List(LambdaSet(LambdaSet { set: [( Test.3, [Builtin(Int(I64))])], representation: Struct([Builtin(Int(I64))]) }))) = Array [Test.12];
|
||||
ret Test.11;
|
||||
|
||||
procedure Test.3 (Test.9, #Attr.12):
|
||||
procedure Test.3 (Test.10, #Attr.12):
|
||||
let Test.2 : Builtin(Int(I64)) = StructAtIndex 0 #Attr.12;
|
||||
let Test.2 : Builtin(Int(I64)) = 41i64;
|
||||
ret Test.2;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.8 : Struct([]) = Struct {};
|
||||
let Test.4 : Builtin(List(LambdaSet(LambdaSet { set: [( Test.3, [Builtin(Int(I64))])], representation: Struct([Builtin(Int(I64))]) }))) = CallByName Test.1 Test.8;
|
||||
let Test.6 : Builtin(Int(U64)) = CallByName List.7 Test.4;
|
||||
dec Test.4;
|
||||
let Test.9 : Struct([]) = Struct {};
|
||||
let Test.7 : Builtin(List(LambdaSet(LambdaSet { set: [( Test.3, [Builtin(Int(I64))])], representation: Struct([Builtin(Int(I64))]) }))) = CallByName Test.1 Test.9;
|
||||
let Test.6 : Builtin(Int(U64)) = CallByName List.7 Test.7;
|
||||
dec Test.7;
|
||||
ret Test.6;
|
||||
|
@ -3,14 +3,14 @@ procedure Test.1 (Test.5):
|
||||
let Test.3 : LambdaSet(LambdaSet { set: [( Test.3, [Builtin(Int(I64))])], representation: Struct([Builtin(Int(I64))]) }) = Struct {Test.2};
|
||||
ret Test.3;
|
||||
|
||||
procedure Test.3 (Test.9, #Attr.12):
|
||||
procedure Test.3 (Test.10, #Attr.12):
|
||||
let Test.2 : Builtin(Int(I64)) = StructAtIndex 0 #Attr.12;
|
||||
let Test.2 : Builtin(Int(I64)) = 42i64;
|
||||
ret Test.2;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.8 : Struct([]) = Struct {};
|
||||
let Test.4 : LambdaSet(LambdaSet { set: [( Test.3, [Builtin(Int(I64))])], representation: Struct([Builtin(Int(I64))]) }) = CallByName Test.1 Test.8;
|
||||
let Test.7 : Struct([]) = Struct {};
|
||||
let Test.6 : Builtin(Int(I64)) = CallByName Test.3 Test.7 Test.4;
|
||||
let Test.9 : Struct([]) = Struct {};
|
||||
let Test.8 : LambdaSet(LambdaSet { set: [( Test.3, [Builtin(Int(I64))])], representation: Struct([Builtin(Int(I64))]) }) = CallByName Test.1 Test.9;
|
||||
let Test.6 : Builtin(Int(I64)) = CallByName Test.3 Test.7 Test.8;
|
||||
ret Test.6;
|
||||
|
@ -1,42 +1,42 @@
|
||||
procedure Num.24 (#Attr.2, #Attr.3):
|
||||
let Test.17 : Builtin(Int(I64)) = lowlevel NumMul #Attr.2 #Attr.3;
|
||||
ret Test.17;
|
||||
let Test.18 : Builtin(Int(I64)) = lowlevel NumMul #Attr.2 #Attr.3;
|
||||
ret Test.18;
|
||||
|
||||
procedure Test.1 (Test.6):
|
||||
let Test.22 : Builtin(Bool) = StructAtIndex 1 Test.6;
|
||||
let Test.23 : Builtin(Bool) = false;
|
||||
let Test.24 : Builtin(Bool) = lowlevel Eq Test.23 Test.22;
|
||||
if Test.24 then
|
||||
let Test.8 : Builtin(Int(I64)) = StructAtIndex 0 Test.6;
|
||||
ret Test.8;
|
||||
else
|
||||
let Test.10 : Builtin(Int(I64)) = StructAtIndex 0 Test.6;
|
||||
ret Test.10;
|
||||
|
||||
procedure Test.1 (Test.6):
|
||||
let Test.33 : Builtin(Bool) = false;
|
||||
let Test.34 : Builtin(Bool) = lowlevel Eq Test.33 Test.6;
|
||||
if Test.34 then
|
||||
let Test.22 : Builtin(Bool) = false;
|
||||
let Test.23 : Builtin(Bool) = lowlevel Eq Test.22 Test.6;
|
||||
if Test.23 then
|
||||
let Test.8 : Builtin(Int(I64)) = 3i64;
|
||||
ret Test.8;
|
||||
else
|
||||
let Test.10 : Builtin(Int(I64)) = 5i64;
|
||||
ret Test.10;
|
||||
|
||||
procedure Test.1 (Test.6):
|
||||
let Test.30 : Builtin(Bool) = StructAtIndex 1 Test.6;
|
||||
let Test.31 : Builtin(Bool) = false;
|
||||
let Test.32 : Builtin(Bool) = lowlevel Eq Test.31 Test.30;
|
||||
if Test.32 then
|
||||
let Test.8 : Builtin(Int(I64)) = StructAtIndex 0 Test.6;
|
||||
ret Test.8;
|
||||
else
|
||||
let Test.10 : Builtin(Int(I64)) = StructAtIndex 0 Test.6;
|
||||
ret Test.10;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.37 : Builtin(Bool) = true;
|
||||
let Test.5 : Builtin(Int(I64)) = CallByName Test.1 Test.37;
|
||||
let Test.35 : Builtin(Bool) = false;
|
||||
let Test.3 : Builtin(Int(I64)) = CallByName Test.1 Test.35;
|
||||
let Test.28 : Builtin(Int(I64)) = 11i64;
|
||||
let Test.29 : Builtin(Bool) = true;
|
||||
let Test.27 : Struct([Builtin(Int(I64)), Builtin(Bool)]) = Struct {Test.28, Test.29};
|
||||
let Test.4 : Builtin(Int(I64)) = CallByName Test.1 Test.27;
|
||||
let Test.25 : Builtin(Int(I64)) = 7i64;
|
||||
let Test.26 : Builtin(Bool) = false;
|
||||
let Test.19 : Struct([Builtin(Int(I64)), Builtin(Bool)]) = Struct {Test.25, Test.26};
|
||||
let Test.2 : Builtin(Int(I64)) = CallByName Test.1 Test.19;
|
||||
let Test.18 : Builtin(Int(I64)) = CallByName Num.24 Test.2 Test.3;
|
||||
let Test.16 : Builtin(Int(I64)) = CallByName Num.24 Test.18 Test.4;
|
||||
let Test.15 : Builtin(Int(I64)) = CallByName Num.24 Test.16 Test.5;
|
||||
let Test.40 : Builtin(Int(I64)) = 7i64;
|
||||
let Test.41 : Builtin(Bool) = false;
|
||||
let Test.39 : Struct([Builtin(Int(I64)), Builtin(Bool)]) = Struct {Test.40, Test.41};
|
||||
let Test.35 : Builtin(Int(I64)) = CallByName Test.1 Test.39;
|
||||
let Test.38 : Builtin(Bool) = false;
|
||||
let Test.36 : Builtin(Int(I64)) = CallByName Test.1 Test.38;
|
||||
let Test.25 : Builtin(Int(I64)) = CallByName Num.24 Test.35 Test.36;
|
||||
let Test.33 : Builtin(Int(I64)) = 11i64;
|
||||
let Test.34 : Builtin(Bool) = true;
|
||||
let Test.27 : Struct([Builtin(Int(I64)), Builtin(Bool)]) = Struct {Test.33, Test.34};
|
||||
let Test.26 : Builtin(Int(I64)) = CallByName Test.1 Test.27;
|
||||
let Test.16 : Builtin(Int(I64)) = CallByName Num.24 Test.25 Test.26;
|
||||
let Test.24 : Builtin(Bool) = true;
|
||||
let Test.17 : Builtin(Int(I64)) = CallByName Test.1 Test.24;
|
||||
let Test.15 : Builtin(Int(I64)) = CallByName Num.24 Test.16 Test.17;
|
||||
ret Test.15;
|
||||
|
@ -1238,6 +1238,19 @@ fn monomorphized_applied_tag() {
|
||||
)
|
||||
}
|
||||
|
||||
#[mono_test]
|
||||
fn aliased_polymorphic_closure() {
|
||||
indoc!(
|
||||
r#"
|
||||
n : U8
|
||||
n = 1
|
||||
f = \{} -> (\a -> n)
|
||||
g = f {}
|
||||
g {}
|
||||
"#
|
||||
)
|
||||
}
|
||||
|
||||
// #[ignore]
|
||||
// #[mono_test]
|
||||
// fn static_str_closure() {
|
||||
|
Loading…
Reference in New Issue
Block a user