specialize rigids

This commit is contained in:
Folkert 2020-10-12 23:58:39 +02:00
parent 973a632c25
commit edc0717a7d
3 changed files with 117 additions and 21 deletions

View file

@ -1326,12 +1326,8 @@ pub fn specialize_all<'a>(
pending.clone(), pending.clone(),
partial_proc, partial_proc,
) { ) {
Ok((proc, layout)) if outside_layout != layout => {
println!("Layouts don't match for function {:?}", proc.name,);
dbg!(outside_layout, layout, &pending.solved_type);
panic!();
}
Ok((proc, layout)) => { Ok((proc, layout)) => {
debug_assert_eq!(outside_layout, layout);
procs.specialized.remove(&(name, outside_layout)); procs.specialized.remove(&(name, outside_layout));
procs.specialized.insert((name, layout), Done(proc)); procs.specialized.insert((name, layout), Done(proc));
} }
@ -1490,7 +1486,7 @@ fn specialize_solved_type<'a>(
) -> Result<(Proc<'a>, Layout<'a>), LayoutProblem> { ) -> Result<(Proc<'a>, Layout<'a>), LayoutProblem> {
// add the specializations that other modules require of us // add the specializations that other modules require of us
use roc_constrain::module::{to_type, FreeVars}; use roc_constrain::module::{to_type, FreeVars};
use roc_solve::solve::insert_type_into_subs; use roc_solve::solve::{insert_type_into_subs, instantiate_rigids};
use roc_types::subs::VarStore; use roc_types::subs::VarStore;
let snapshot = env.subs.snapshot(); let snapshot = env.subs.snapshot();
@ -1509,6 +1505,9 @@ fn specialize_solved_type<'a>(
let fn_var = insert_type_into_subs(env.subs, &normal_type); let fn_var = insert_type_into_subs(env.subs, &normal_type);
// make sure rigid variables in the annotation are converted to flex variables
instantiate_rigids(env.subs, partial_proc.annotation);
match specialize_external(env, procs, proc_name, layout_cache, fn_var, partial_proc) { match specialize_external(env, procs, proc_name, layout_cache, fn_var, partial_proc) {
Ok(proc) => { Ok(proc) => {
let layout = layout_cache let layout = layout_cache
@ -2726,15 +2725,24 @@ pub fn from_can<'a>(
_ => unreachable!(), _ => unreachable!(),
} }
} }
let rest = from_can(env, cont.value, procs, layout_cache);
return with_hole( let mut rest = from_can(env, cont.value, procs, layout_cache);
env,
def.loc_expr.value, // a variable is aliased
procs, if let roc_can::expr::Expr::Var(original) = def.loc_expr.value {
layout_cache, substitute_in_exprs(env.arena, &mut rest, *symbol, original);
*symbol,
env.arena.alloc(rest), return rest;
); } else {
return with_hole(
env,
def.loc_expr.value,
procs,
layout_cache,
*symbol,
env.arena.alloc(rest),
);
}
} }
// this may be a destructure pattern // this may be a destructure pattern
@ -2744,6 +2752,7 @@ pub fn from_can<'a>(
let hole = env let hole = env
.arena .arena
.alloc(from_can(env, cont.value, procs, layout_cache)); .alloc(from_can(env, cont.value, procs, layout_cache));
with_hole(env, def.loc_expr.value, procs, layout_cache, symbol, hole) with_hole(env, def.loc_expr.value, procs, layout_cache, symbol, hole)
} else { } else {
let context = crate::exhaustive::Context::BadDestruct; let context = crate::exhaustive::Context::BadDestruct;

View file

@ -875,7 +875,8 @@ mod test_mono {
indoc!( indoc!(
r#" r#"
let Test.0 = 5i64; let Test.0 = 5i64;
ret Test.0; let Test.2 = 3i64;
ret Test.2;
"# "#
), ),
); );
@ -1751,14 +1752,14 @@ mod test_mono {
nonEmpty : List Int nonEmpty : List Int
nonEmpty = nonEmpty =
[ 1, 1, -4, 1, 2 ] [ 1, 1, -4, 1, 2 ]
greaterThanOne : Int -> Bool greaterThanOne : Int -> Bool
greaterThanOne = \i -> greaterThanOne = \i ->
i > 0 i > 0
List.map nonEmpty greaterThanOne List.map nonEmpty greaterThanOne
main {} main {}
"# "#
), ),
@ -1920,4 +1921,89 @@ mod test_mono {
), ),
) )
} }
#[test]
fn rigids() {
compiles_to_ir(
indoc!(
r#"
swap : Int, Int, List a -> List a
swap = \i, j, list ->
when Pair (List.get list i) (List.get list j) is
Pair (Ok atI) (Ok atJ) ->
foo = atJ
list
|> List.set i foo
|> List.set j atI
_ ->
[]
swap 0 0 [0x1]
"#
),
indoc!(
r#"
procedure List.3 (#Attr.2, #Attr.3):
let Test.43 = lowlevel ListLen #Attr.2;
let Test.39 = lowlevel NumLt #Attr.3 Test.43;
if Test.39 then
let Test.41 = 1i64;
let Test.42 = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
let Test.40 = Ok Test.41 Test.42;
ret Test.40;
else
let Test.37 = 0i64;
let Test.38 = Struct {};
let Test.36 = Err Test.37 Test.38;
ret Test.36;
procedure List.4 (#Attr.2, #Attr.3, #Attr.4):
let Test.19 = lowlevel ListLen #Attr.2;
let Test.17 = lowlevel NumLt #Attr.3 Test.19;
if Test.17 then
let Test.18 = lowlevel ListSet #Attr.2 #Attr.3 #Attr.4;
ret Test.18;
else
ret #Attr.2;
procedure Test.0 (Test.2, Test.3, Test.4):
let Test.34 = CallByName List.3 Test.4 Test.2;
let Test.35 = CallByName List.3 Test.4 Test.3;
let Test.13 = Struct {Test.34, Test.35};
let Test.24 = true;
let Test.26 = 1i64;
let Test.25 = Index 0 Test.13;
let Test.27 = Index 0 Test.25;
let Test.33 = lowlevel Eq Test.26 Test.27;
let Test.31 = lowlevel And Test.33 Test.24;
let Test.29 = 1i64;
let Test.28 = Index 1 Test.13;
let Test.30 = Index 0 Test.28;
let Test.32 = lowlevel Eq Test.29 Test.30;
let Test.23 = lowlevel And Test.32 Test.31;
if Test.23 then
let Test.21 = Index 0 Test.13;
let Test.5 = Index 1 Test.21;
let Test.20 = Index 1 Test.13;
let Test.6 = Index 1 Test.20;
let Test.15 = CallByName List.4 Test.4 Test.2 Test.6;
let Test.14 = CallByName List.4 Test.15 Test.3 Test.5;
ret Test.14;
else
dec Test.4;
let Test.22 = Array [];
ret Test.22;
let Test.9 = 0i64;
let Test.10 = 0i64;
let Test.12 = 1i64;
let Test.11 = Array [Test.12];
let Test.8 = CallByName Test.0 Test.9 Test.10 Test.11;
ret Test.8;
"#
),
)
}
} }

View file

@ -1,10 +1,11 @@
interface Utils exposes [ swap ] imports [] interface Utils exposes [ swap ] imports []
swap : Int, Int, List a -> List a
swap = \i, j, list -> swap = \i, j, list ->
when Pair (List.get list i) (List.get list j) is when Pair (List.get list i) (List.get list j) is
Pair (Ok atI) (Ok atJ) -> Pair (Ok atI) (Ok atJ) ->
list list
|> List.set i atJ |> List.set i atJ
|> List.set j atI |> List.set j atI
_ -> _ ->