Apply is-open constraints to nested types

Closes #3459
This commit is contained in:
Ayaz Hafiz 2022-07-21 15:57:41 -04:00
parent 1d4e6acd41
commit d4cf9b8f8d
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
2 changed files with 37 additions and 14 deletions

View file

@ -1653,25 +1653,35 @@ fn open_tag_union(subs: &mut Subs, var: Variable) {
use {Content::*, FlatType::*};
let desc = subs.get(var);
if let Structure(TagUnion(tags, ext)) = desc.content {
if let Structure(EmptyTagUnion) = subs.get_content_without_compacting(ext) {
let new_ext = subs.fresh_unnamed_flex_var();
subs.set_rank(new_ext, desc.rank);
let new_union = Structure(TagUnion(tags, new_ext));
subs.set_content(var, new_union);
match desc.content {
Structure(TagUnion(tags, ext)) => {
if let Structure(EmptyTagUnion) = subs.get_content_without_compacting(ext) {
let new_ext = subs.fresh_unnamed_flex_var();
subs.set_rank(new_ext, desc.rank);
let new_union = Structure(TagUnion(tags, new_ext));
subs.set_content(var, new_union);
}
// Also open up all nested tag unions.
let all_vars = tags.variables().into_iter();
stack.extend(all_vars.flat_map(|slice| subs[slice]).map(|var| subs[var]));
}
// Also open up all nested tag unions.
let all_vars = tags.variables().into_iter();
stack.extend(all_vars.flat_map(|slice| subs[slice]).map(|var| subs[var]));
Structure(Record(fields, _)) => {
// Open up all nested tag unions.
stack.extend(subs.get_subs_slice(fields.variables()));
}
_ => {
// Everything else is not a structural type that can be opened
// (i.e. cannot be matched in a pattern-match)
}
}
// Today, an "open" constraint doesn't affect any types
// other than tag unions. Recursive tag unions are constructed
// at a later time (during occurs checks after tag unions are
// resolved), so that's not handled here either.
// NB: Handle record types here if we add presence constraints
// to their type inference as well.
}
}

View file

@ -7421,10 +7421,23 @@ mod solve_expr {
A _ C -> ""
"#
),
@r#"""
x : [A [B]* [C]*]
"""#
@r#"x : [A [B]* [C]*]"#
allow_errors: true
);
}
#[test]
fn catchall_branch_walk_into_nested_types() {
infer_queries!(
indoc!(
r#"
\x -> when x is
#^
{ a: A { b: B } } -> ""
_ -> ""
"#
),
@r#"x : { a : [A { b : [B]* }*]* }*"#
)
}
}