diff --git a/crates/compiler/constrain/src/pattern.rs b/crates/compiler/constrain/src/pattern.rs index d90374fb2d..b23240e76c 100644 --- a/crates/compiler/constrain/src/pattern.rs +++ b/crates/compiler/constrain/src/pattern.rs @@ -676,6 +676,17 @@ pub fn constrain_pattern( RecordField::Optional(pat_type) } DestructType::Required => { + // Named destructures like + // {foo} -> ... + // are equivalent to wildcards on the type of `foo`, so if `foo` is a tag + // union, we must add a constraint to ensure that this destructure opens it + // up. + if could_be_a_tag_union(types, pat_type_index) { + state + .delayed_is_open_constraints + .push(constraints.is_open_type(pat_type_index)); + } + // No extra constraints necessary. RecordField::Demanded(pat_type) } diff --git a/crates/compiler/uitest/tests/exhaustive/open_union_under_record.txt b/crates/compiler/uitest/tests/exhaustive/open_union_under_record.txt new file mode 100644 index 0000000000..f53e922986 --- /dev/null +++ b/crates/compiler/uitest/tests/exhaustive/open_union_under_record.txt @@ -0,0 +1,16 @@ +# +opt infer:print_only_under_alias + +app "test" provides [limitedKind] to "./platform" + +Kind : [ A, B, C ] +Data : {kind: Kind} + +limitedKind : Data -> Str +limitedKind = \data -> + when data is +# ^^^^ { kind : [A, B, C] } + {kind: A} -> "A is special" + {kind} -> when kind is + B -> "B" + C -> "C" + _ -> ""