mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 21:39:07 +00:00
Merge pull request #5440 from roc-lang/i5429
Implement openness constraints under records
This commit is contained in:
commit
af3ee5e5f1
4 changed files with 50 additions and 6 deletions
|
@ -448,8 +448,9 @@ pub fn find_type_def_symbols(
|
||||||
As(actual, _, _) => {
|
As(actual, _, _) => {
|
||||||
stack.push(&actual.value);
|
stack.push(&actual.value);
|
||||||
}
|
}
|
||||||
Tuple { elems: _, ext: _ } => {
|
Tuple { elems, ext } => {
|
||||||
todo!("find_type_def_symbols: Tuple");
|
stack.extend(elems.iter().map(|t| &t.value));
|
||||||
|
stack.extend(ext.iter().map(|t| &t.value));
|
||||||
}
|
}
|
||||||
Record { fields, ext } => {
|
Record { fields, ext } => {
|
||||||
let mut inner_stack = Vec::with_capacity(fields.items.len());
|
let mut inner_stack = Vec::with_capacity(fields.items.len());
|
||||||
|
|
|
@ -512,13 +512,13 @@ pub fn constrain_pattern(
|
||||||
let expected =
|
let expected =
|
||||||
constraints.push_pat_expected_type(PExpected::NoExpectation(pat_type_index));
|
constraints.push_pat_expected_type(PExpected::NoExpectation(pat_type_index));
|
||||||
|
|
||||||
let (guard_var, loc_guard) = typ;
|
let (guard_var, loc_pattern) = typ;
|
||||||
let elem_type = {
|
let elem_type = {
|
||||||
let guard_type = constraints.push_variable(*guard_var);
|
let guard_type = constraints.push_variable(*guard_var);
|
||||||
let expected_pat = constraints.push_pat_expected_type(PExpected::ForReason(
|
let expected_pat = constraints.push_pat_expected_type(PExpected::ForReason(
|
||||||
PReason::PatternGuard,
|
PReason::PatternGuard,
|
||||||
pat_type_index,
|
pat_type_index,
|
||||||
loc_guard.region,
|
loc_pattern.region,
|
||||||
));
|
));
|
||||||
|
|
||||||
state.constraints.push(constraints.pattern_presence(
|
state.constraints.push(constraints.pattern_presence(
|
||||||
|
@ -533,8 +533,8 @@ pub fn constrain_pattern(
|
||||||
types,
|
types,
|
||||||
constraints,
|
constraints,
|
||||||
env,
|
env,
|
||||||
&loc_guard.value,
|
&loc_pattern.value,
|
||||||
loc_guard.region,
|
loc_pattern.region,
|
||||||
expected,
|
expected,
|
||||||
state,
|
state,
|
||||||
);
|
);
|
||||||
|
@ -676,6 +676,17 @@ pub fn constrain_pattern(
|
||||||
RecordField::Optional(pat_type)
|
RecordField::Optional(pat_type)
|
||||||
}
|
}
|
||||||
DestructType::Required => {
|
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.
|
// No extra constraints necessary.
|
||||||
RecordField::Demanded(pat_type)
|
RecordField::Demanded(pat_type)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
|
_ -> ""
|
|
@ -0,0 +1,16 @@
|
||||||
|
# +opt infer:print_only_under_alias
|
||||||
|
|
||||||
|
app "test" provides [limitedKind] to "./platform"
|
||||||
|
|
||||||
|
Kind : [ A, B, C ]
|
||||||
|
Data : ({}, Kind)
|
||||||
|
|
||||||
|
limitedKind : Data -> Str
|
||||||
|
limitedKind = \data ->
|
||||||
|
when data is
|
||||||
|
# ^^^^ ( {}, [A, B, C] )*
|
||||||
|
({}, A) -> "A is special"
|
||||||
|
({}, kind) -> when kind is
|
||||||
|
B -> "B"
|
||||||
|
C -> "C"
|
||||||
|
_ -> ""
|
Loading…
Add table
Add a link
Reference in a new issue