Fix bug in unification of tag args in polymorphic contexts

This commit is contained in:
Joshua Warner 2022-12-25 14:34:28 -08:00
parent f0b3c3eb08
commit 8abd5cf605
No known key found for this signature in database
GPG key ID: 89AD497003F93FDD
3 changed files with 69 additions and 1 deletions

View file

@ -0,0 +1,35 @@
procedure Bool.11 (#Attr.2, #Attr.3):
let Bool.23 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.23;
procedure Str.3 (#Attr.2, #Attr.3):
let Str.266 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.266;
procedure Test.2 (Test.7):
let Test.24 : Str = ".trace(\"";
let Test.26 : Str = "\")";
let Test.25 : Str = CallByName Str.3 Test.7 Test.26;
dec Test.26;
let Test.23 : Str = CallByName Str.3 Test.24 Test.25;
dec Test.25;
let Test.22 : [<r>C List *self, C Str] = TagId(1) Test.23;
let Test.21 : List [<r>C List *self, C Str] = Array [Test.22];
let Test.8 : [<r>C List *self, C Str] = TagId(0) Test.21;
let Test.20 : List [<r>C List *self, C Str] = Array [Test.8];
let Test.19 : [<r>C List *self, C Str] = TagId(0) Test.20;
ret Test.19;
procedure Test.3 ():
let Test.18 : Str = "interface_header";
let Test.17 : [<r>C List *self, C Str] = CallByName Test.2 Test.18;
ret Test.17;
procedure Test.0 ():
let Test.14 : [<r>C List *self, C Str] = CallByName Test.3;
let Test.16 : Str = "";
let Test.15 : [<r>C List *self, C Str] = TagId(1) Test.16;
let Test.13 : Int1 = CallByName Bool.11 Test.14 Test.15;
dec Test.15;
dec Test.14;
ret Test.13;

View file

@ -1925,6 +1925,28 @@ fn encode_derived_tag_one_field_string() {
)
}
#[mono_test(no_check)]
fn polymorphic_expression_unification() {
indoc!(
r#"
app "test" provides [main] to "./platform"
RenderTree : [
Text Str,
Indent (List RenderTree),
]
parseFunction : Str -> RenderTree
parseFunction = \name ->
last = Indent [Text ".trace(\"\(name)\")" ]
Indent [last]
values = parseFunction "interface_header"
main = values == Text ""
"#
)
}
#[mono_test]
fn encode_derived_tag_two_payloads_string() {
indoc!(

View file

@ -2979,7 +2979,18 @@ fn unify_flat_type<M: MetaCollector>(
let mut outcome = unify_zip_slices(env, pool, *l_args, *r_args, ctx.mode);
if outcome.mismatches.is_empty() {
outcome.union(merge(env, ctx, Structure(Apply(*r_symbol, *r_args))));
let chosen_args = SubsSlice::reserve_into_subs(env.subs, l_args.len());
for ((store, var1), var2) in chosen_args
.into_iter()
.zip(l_args.into_iter())
.zip(r_args.into_iter())
{
let var1 = env.subs[var1];
let var2 = env.subs[var2];
env.subs[store] = choose_merged_var(env.subs, var1, var2);
}
outcome.union(merge(env, ctx, Structure(Apply(*r_symbol, chosen_args))));
}
outcome