Handle multi pattern unbound list rest variables

This commit is contained in:
JRI98 2024-06-21 17:01:49 +01:00
parent 03eadc2e0f
commit f4551978ce
No known key found for this signature in database
GPG key ID: F83B29916FF13F24
4 changed files with 35 additions and 5 deletions

View file

@ -207,7 +207,7 @@ pub struct ListPatterns {
/// [ .., A, B ] -> patterns = [A, B], rest = 0
/// [ A, .., B ] -> patterns = [A, B], rest = 1
/// [ A, B, .. ] -> patterns = [A, B], rest = 2
pub opt_rest: Option<(usize, Option<Symbol>)>,
pub opt_rest: Option<(usize, Option<Loc<Symbol>>)>,
}
impl ListPatterns {
@ -793,7 +793,8 @@ pub fn canonicalize_pattern<'a>(
pattern_as.identifier.value,
) {
Ok(symbol) => {
rest_name = Some(symbol);
rest_name =
Some(Loc::at(pattern_as.identifier.region, symbol));
}
Err(pattern) => {
opt_erroneous = Some(pattern);
@ -997,6 +998,10 @@ impl<'a> BindingsFromPattern<'a> {
| OpaqueNotInScope(..) => (),
List { patterns, .. } => {
stack.extend(patterns.patterns.iter().rev().map(Pattern));
if let Some((_, Some(rest_sym))) = &patterns.opt_rest {
return Some((rest_sym.value, rest_sym.region));
}
}
}
}

View file

@ -141,7 +141,7 @@ fn headers_from_annotation_help(
constraints.push_type(types, typ)
};
let typ = Loc::at(annotation.region, annotation_index);
headers.insert(rest, typ);
headers.insert(rest.value, typ);
false
} else {
@ -735,7 +735,7 @@ pub fn constrain_pattern(
if let Some((_, Some(rest))) = opt_rest {
state.headers.insert(
*rest,
rest.value,
Loc {
region,
value: *constraints[expected].get_type_ref(),

View file

@ -10501,6 +10501,29 @@ In roc, functions are always written as a lambda, like{}
"###
);
test_report!(
issue_6825,
indoc!(
r#"
when [] is
[] | [_, .. as rest] if List.isEmpty rest -> []
_ -> []
"#
),
@r###"
NAME NOT BOUND IN ALL PATTERNS in /code/proj/Main.roc
`rest` is not bound in all patterns of this `when` branch
5 [] | [_, .. as rest] if List.isEmpty rest -> []
^^^^
Identifiers introduced in a `when` branch must be bound in all patterns
of the branch. Otherwise, the program would crash when it tries to use
an identifier that wasn't bound!
"###
);
test_report!(
flip_flop_catch_all_branches_not_exhaustive,
indoc!(

View file

@ -1084,7 +1084,9 @@ fn from_can_pattern_help<'a>(
list_layout,
element_layout,
elements: mono_patterns,
opt_rest: patterns.opt_rest,
opt_rest: patterns
.opt_rest
.map(|(i, name)| (i, name.map(|s| s.value))),
})
}
}