mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 11:52:19 +00:00
fix and test as pattern type inference
This commit is contained in:
parent
57f2233278
commit
c2ddeb0de0
3 changed files with 150 additions and 41 deletions
|
@ -781,8 +781,29 @@ pub fn canonicalize_pattern<'a>(
|
|||
malformed_pattern(env, problem, region)
|
||||
}
|
||||
|
||||
As(_pattern, _pattern_as) => {
|
||||
todo!();
|
||||
As(loc_pattern, pattern_as) => {
|
||||
let can_subpattern = canonicalize_pattern(
|
||||
env,
|
||||
var_store,
|
||||
scope,
|
||||
output,
|
||||
pattern_type,
|
||||
&loc_pattern.value,
|
||||
loc_pattern.region,
|
||||
permit_shadows,
|
||||
);
|
||||
|
||||
match canonicalize_pattern_symbol(
|
||||
env,
|
||||
scope,
|
||||
output,
|
||||
region,
|
||||
permit_shadows,
|
||||
pattern_as.identifier.value,
|
||||
) {
|
||||
Ok(symbol) => Pattern::As(Box::new(can_subpattern), symbol),
|
||||
Err(pattern) => pattern,
|
||||
}
|
||||
}
|
||||
|
||||
Malformed(_str) => {
|
||||
|
|
|
@ -125,12 +125,23 @@ fn headers_from_annotation_help(
|
|||
_ => false,
|
||||
},
|
||||
|
||||
List { .. } => {
|
||||
// There are no interesting headers to introduce for list patterns, since the only
|
||||
// exhaustive list pattern is
|
||||
// \[..] -> <body>
|
||||
// which does not introduce any symbols.
|
||||
false
|
||||
List { patterns, .. } => {
|
||||
if let Some((_, Some(rest))) = patterns.opt_rest {
|
||||
let annotation_index = {
|
||||
let typ = types.from_old_type(annotation.value);
|
||||
constraints.push_type(types, typ)
|
||||
};
|
||||
let typ = Loc::at(annotation.region, annotation_index);
|
||||
headers.insert(rest, typ);
|
||||
|
||||
false
|
||||
} else {
|
||||
// There are no interesting headers to introduce for list patterns, since the only
|
||||
// exhaustive list pattern is
|
||||
// \[..] -> <body>
|
||||
// which does not introduce any symbols.
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
AppliedTag {
|
||||
|
@ -203,32 +214,6 @@ fn headers_from_annotation_help(
|
|||
}
|
||||
}
|
||||
|
||||
fn constrain_pattern_symbol(
|
||||
types: &mut Types,
|
||||
constraints: &mut Constraints,
|
||||
region: Region,
|
||||
expected: PExpectedTypeIndex,
|
||||
state: &mut PatternState,
|
||||
symbol: Symbol,
|
||||
) {
|
||||
let expected = &constraints[expected];
|
||||
let type_index = *expected.get_type_ref();
|
||||
|
||||
if could_be_a_tag_union(types, type_index) {
|
||||
state
|
||||
.delayed_is_open_constraints
|
||||
.push(constraints.is_open_type(type_index));
|
||||
}
|
||||
|
||||
state.headers.insert(
|
||||
symbol,
|
||||
Loc {
|
||||
region,
|
||||
value: type_index,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// This accepts PatternState (rather than returning it) so that the caller can
|
||||
/// initialize the Vecs in PatternState using with_capacity
|
||||
/// based on its knowledge of their lengths.
|
||||
|
@ -261,11 +246,34 @@ pub fn constrain_pattern(
|
|||
}
|
||||
|
||||
Identifier(symbol) | Shadowed(_, _, symbol) => {
|
||||
constrain_pattern_symbol(types, constraints, region, expected, state, *symbol);
|
||||
let type_index = *constraints[expected].get_type_ref();
|
||||
|
||||
if could_be_a_tag_union(types, type_index) {
|
||||
state
|
||||
.delayed_is_open_constraints
|
||||
.push(constraints.is_open_type(type_index));
|
||||
}
|
||||
|
||||
state.headers.insert(
|
||||
*symbol,
|
||||
Loc {
|
||||
region,
|
||||
value: type_index,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
As(subpattern, symbol) => {
|
||||
constrain_pattern_symbol(types, constraints, region, expected, state, *symbol);
|
||||
// NOTE: we don't use `could_be_a_tag_union` here. The `PATTERN as name` should
|
||||
// just use the type of the PATTERN, and not influence what type is inferred for PATTERN
|
||||
|
||||
state.headers.insert(
|
||||
*symbol,
|
||||
Loc {
|
||||
region,
|
||||
value: *constraints[expected].get_type_ref(),
|
||||
},
|
||||
);
|
||||
|
||||
constrain_pattern(
|
||||
types,
|
||||
|
@ -599,14 +607,20 @@ pub fn constrain_pattern(
|
|||
List {
|
||||
list_var,
|
||||
elem_var,
|
||||
patterns:
|
||||
ListPatterns {
|
||||
patterns,
|
||||
opt_rest: _,
|
||||
},
|
||||
patterns: ListPatterns { patterns, opt_rest },
|
||||
} => {
|
||||
let elem_var_index = constraints.push_variable(*elem_var);
|
||||
|
||||
if let Some((_, Some(rest))) = opt_rest {
|
||||
state.headers.insert(
|
||||
*rest,
|
||||
Loc {
|
||||
region,
|
||||
value: *constraints[expected].get_type_ref(),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
for loc_pat in patterns.iter() {
|
||||
let expected = constraints.push_pat_expected_type(PExpected::ForReason(
|
||||
PReason::ListElem,
|
||||
|
|
|
@ -8581,4 +8581,78 @@ mod solve_expr {
|
|||
@"polyDbg : a -[[polyDbg(1)]]-> a"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pattern_as_uses_inferred_type() {
|
||||
infer_queries!(
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" provides [main] to "./platform"
|
||||
|
||||
main = when A "foo" is
|
||||
A _ as a -> a
|
||||
# ^
|
||||
b -> b
|
||||
# ^
|
||||
"#
|
||||
),
|
||||
@r###"
|
||||
a : [A Str]*
|
||||
b : [A Str]*
|
||||
"###
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pattern_as_does_not_narrow() {
|
||||
infer_queries!(
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" provides [main] to "./platform"
|
||||
|
||||
input : [A Str, B Str]
|
||||
input = A "foo"
|
||||
|
||||
drop : a -> {}
|
||||
drop = \_ -> {}
|
||||
|
||||
main = when input is
|
||||
# ^^^^^
|
||||
A _ as a -> drop a
|
||||
# ^
|
||||
B _ as b -> drop b
|
||||
# ^
|
||||
"#
|
||||
),
|
||||
@r###"
|
||||
input : [A Str, B Str]
|
||||
a : [A Str, B Str]
|
||||
b : [A Str, B Str]
|
||||
"###
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pattern_as_list() {
|
||||
infer_queries!(
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" provides [main] to "./platform"
|
||||
|
||||
input : List Str
|
||||
input = [ "foo", "bar" ]
|
||||
|
||||
main = when input is
|
||||
# ^^^^^
|
||||
[ _first, .. as rest ] -> 1 + List.len rest
|
||||
# ^^^^
|
||||
[] -> 0
|
||||
"#
|
||||
),
|
||||
@r###"
|
||||
input : List Str
|
||||
rest : List Str
|
||||
"###
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue