fix recursion issue in type inference

This commit is contained in:
Folkert 2020-09-07 16:35:49 +02:00
parent 0a034c474a
commit 4522fe14fc
4 changed files with 86 additions and 31 deletions

View file

@ -555,9 +555,7 @@ mod gen_primitives {
Nil -> 0
Cons _ rest -> 1 + length rest
wrapper = { list: nil }
length wrapper.list
length nil + length nil
"#
),
0,
@ -611,8 +609,7 @@ mod gen_primitives {
Cons _ rest -> 1 + length rest
# TODO actually calculate twice
2 * length one
length one + length one
"#
),
2,

View file

@ -1848,4 +1848,58 @@ mod test_mono {
),
)
}
#[test]
fn linked_list_length_twice() {
compiles_to_ir(
indoc!(
r#"
LinkedList a : [ Nil, Cons a (LinkedList a) ]
nil : LinkedList Int
nil = Nil
length : LinkedList a -> Int
length = \list ->
when list is
Nil -> 0
Cons _ rest -> 1 + length rest
length nil + length nil
"#
),
indoc!(
r#"
procedure Num.14 (#Attr.2, #Attr.3):
let Test.14 = lowlevel NumAdd #Attr.2 #Attr.3;
ret Test.14;
procedure Test.2 (Test.4):
let Test.16 = true;
let Test.17 = 1i64;
let Test.18 = Index 0 Test.4;
let Test.19 = lowlevel Eq Test.17 Test.18;
let Test.15 = lowlevel And Test.19 Test.16;
if Test.15 then
dec Test.4;
let Test.10 = 0i64;
ret Test.10;
else
let Test.5 = Index 2 Test.4;
dec Test.4;
let Test.12 = 1i64;
let Test.13 = CallByName Test.2 Test.5;
let Test.11 = CallByName Num.14 Test.12 Test.13;
ret Test.11;
let Test.9 = 1i64;
let Test.1 = Nil Test.9;
let Test.7 = CallByName Test.2 Test.1;
let Test.8 = CallByName Test.2 Test.1;
let Test.6 = CallByName Num.14 Test.7 Test.8;
ret Test.6;
"#
),
)
}
}

View file

@ -2005,7 +2005,7 @@ mod solve_uniq_expr {
toAs
"#
),
"Attr Shared (Attr Shared (Attr a q -> Attr b p), Attr (* | a | b) (ListA (Attr b p) (Attr a q)) -> Attr * (ConsList (Attr b p)))"
"Attr Shared (Attr Shared (Attr a q -> Attr b p), Attr (c | a | b) (ListA (Attr b p) (Attr a q)) -> Attr * (ConsList (Attr b p)))"
);
}
@ -2039,7 +2039,7 @@ mod solve_uniq_expr {
toAs
"#
),
"Attr Shared (Attr Shared (Attr a q -> Attr b p), Attr (* | a | b) (ListA (Attr b p) (Attr a q)) -> Attr * (ConsList (Attr b p)))"
"Attr Shared (Attr Shared (Attr a q -> Attr b p), Attr (c | a | b) (ListA (Attr b p) (Attr a q)) -> Attr * (ConsList (Attr b p)))"
);
}
@ -2789,7 +2789,7 @@ mod solve_uniq_expr {
cheapestOpen
"#
),
"Attr * (Attr * (Attr Shared position -> Attr * Float), Attr (* | * | * | *) (Model (Attr Shared position)) -> Attr * (Result (Attr Shared position) (Attr * [ KeyNotFound ]*)))"
"Attr * (Attr * (Attr Shared position -> Attr * Float), Attr (* | * | a | b) (Model (Attr Shared position)) -> Attr * (Result (Attr Shared position) (Attr * [ KeyNotFound ]*)))"
)
});
}

View file

@ -581,8 +581,8 @@ fn unify_shared_tags(
if let Some(rvar) = recursion_var {
match attr_wrapped {
None => {
if expected == rvar {
if actual == rvar {
if subs.equivalent(expected, rvar) {
if subs.equivalent(actual, rvar) {
problems.extend(unify_pool(subs, pool, expected, actual));
} else {
problems.extend(unify_pool(subs, pool, actual, ctx.second));
@ -610,8 +610,8 @@ fn unify_shared_tags(
}
}
Some((_expected_uvar, inner_expected, _actual_uvar, inner_actual)) => {
if inner_expected == rvar {
if inner_actual == rvar {
if subs.equivalent(inner_expected, rvar) {
if subs.equivalent(inner_actual, rvar) {
problems.extend(unify_pool(subs, pool, actual, expected));
} else {
problems.extend(unify_pool(subs, pool, inner_actual, ctx.second));
@ -747,7 +747,7 @@ fn unify_flat_type(
ctx,
union1,
union2,
(None, Some(*recursion_var)),
(Some(*recursion_var), None),
)
}
@ -774,7 +774,11 @@ fn unify_flat_type(
(Boolean(b1), Boolean(b2)) => {
use Bool::*;
match (b1, b2) {
let b1 = b1.simplify(subs);
let b2 = b2.simplify(subs);
match (&b1, &b2) {
(Shared, Shared) => merge(subs, ctx, Structure(left.clone())),
(Shared, Container(cvar, mvars)) => {
let mut outcome = vec![];