mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 15:21:12 +00:00
specialize rigids
This commit is contained in:
parent
973a632c25
commit
edc0717a7d
3 changed files with 117 additions and 21 deletions
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue