mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 03:42:17 +00:00
Handle multi pattern unbound list rest variables
This commit is contained in:
parent
03eadc2e0f
commit
f4551978ce
4 changed files with 35 additions and 5 deletions
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -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))),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue