Do not permit inferred-open-in-output-position extension variables to grow

Closes #4852
Closes #4845
This commit is contained in:
Ayaz Hafiz 2023-01-13 11:53:30 -06:00
parent c9460ecf3f
commit 2f74d0b1b9
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
2 changed files with 197 additions and 10 deletions

View file

@ -2405,14 +2405,22 @@ fn close_uninhabited_extended_union(subs: &mut Subs, mut var: Variable) {
}
}
enum UnifySides<T, U> {
Left(T, U),
Right(U, T),
}
#[must_use]
fn unify_tag_ext<M: MetaCollector>(
env: &mut Env,
pool: &mut Pool,
ext: TagExt,
var: Variable,
vars: UnifySides<TagExt, Variable>,
mode: Mode,
) -> Outcome<M> {
let (ext, var, flip_for_unify) = match vars {
UnifySides::Left(ext, var) => (ext, var, false),
UnifySides::Right(var, ext) => (ext, var, true),
};
let legal_unification = match ext {
TagExt::Openness(_) => {
// Openness extensions can either unify with empty tag unions (marking them as closed),
@ -2434,12 +2442,24 @@ fn unify_tag_ext<M: MetaCollector>(
TagExt::Any(_) => true,
};
if legal_unification {
unify_pool(env, pool, ext.var(), var, mode)
if flip_for_unify {
unify_pool(env, pool, var, ext.var(), mode)
} else {
unify_pool(env, pool, ext.var(), var, mode)
}
} else {
mismatch!()
}
}
#[must_use]
fn merge_tag_exts(ext1: TagExt, ext2: TagExt) -> TagExt {
match (ext1, ext2) {
(_, TagExt::Openness(v)) | (TagExt::Openness(v), _) => TagExt::Openness(v),
(TagExt::Any(v), TagExt::Any(_)) => TagExt::Any(v),
}
}
#[allow(clippy::too_many_arguments)]
#[must_use]
fn unify_tag_unions<M: MetaCollector>(
@ -2509,7 +2529,7 @@ fn unify_tag_unions<M: MetaCollector>(
ctx,
shared_tags,
OtherTags2::Empty,
ext1,
merge_tag_exts(ext1, ext2),
recursion_var,
);
@ -2538,7 +2558,8 @@ fn unify_tag_unions<M: MetaCollector>(
ext1 = new_ext;
}
let ext_outcome = unify_tag_ext(env, pool, ext1, extra_tags_in_2, ctx.mode);
let ext_outcome =
unify_tag_ext(env, pool, UnifySides::Left(ext1, extra_tags_in_2), ctx.mode);
if !ext_outcome.mismatches.is_empty() {
return ext_outcome;
@ -2590,7 +2611,12 @@ fn unify_tag_unions<M: MetaCollector>(
ext2 = new_ext;
}
let ext_outcome = unify_tag_ext(env, pool, ext2, extra_tags_in_1, ctx.mode);
let ext_outcome = unify_tag_ext(
env,
pool,
UnifySides::Right(extra_tags_in_1, ext2),
ctx.mode,
);
if !ext_outcome.mismatches.is_empty() {
return ext_outcome;
@ -2659,7 +2685,7 @@ fn unify_tag_unions<M: MetaCollector>(
let mut total_outcome = Outcome::default();
let snapshot = env.subs.snapshot();
let ext1_outcome = unify_tag_ext(env, pool, ext1, sub2, ctx.mode);
let ext1_outcome = unify_tag_ext(env, pool, UnifySides::Left(ext1, sub2), ctx.mode);
if !ext1_outcome.mismatches.is_empty() {
env.subs.rollback_to(snapshot);
return ext1_outcome;
@ -2667,7 +2693,7 @@ fn unify_tag_unions<M: MetaCollector>(
total_outcome.union(ext1_outcome);
if ctx.mode.is_eq() {
let ext2_outcome = unify_tag_ext(env, pool, ext2, sub1, ctx.mode);
let ext2_outcome = unify_tag_ext(env, pool, UnifySides::Right(sub1, ext2), ctx.mode);
if !ext2_outcome.mismatches.is_empty() {
env.subs.rollback_to(snapshot);
return ext2_outcome;