mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +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 = 0
|
||||||
/// [ A, .., B ] -> patterns = [A, B], rest = 1
|
/// [ A, .., B ] -> patterns = [A, B], rest = 1
|
||||||
/// [ A, B, .. ] -> patterns = [A, B], rest = 2
|
/// [ A, B, .. ] -> patterns = [A, B], rest = 2
|
||||||
pub opt_rest: Option<(usize, Option<Symbol>)>,
|
pub opt_rest: Option<(usize, Option<Loc<Symbol>>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ListPatterns {
|
impl ListPatterns {
|
||||||
|
@ -793,7 +793,8 @@ pub fn canonicalize_pattern<'a>(
|
||||||
pattern_as.identifier.value,
|
pattern_as.identifier.value,
|
||||||
) {
|
) {
|
||||||
Ok(symbol) => {
|
Ok(symbol) => {
|
||||||
rest_name = Some(symbol);
|
rest_name =
|
||||||
|
Some(Loc::at(pattern_as.identifier.region, symbol));
|
||||||
}
|
}
|
||||||
Err(pattern) => {
|
Err(pattern) => {
|
||||||
opt_erroneous = Some(pattern);
|
opt_erroneous = Some(pattern);
|
||||||
|
@ -997,6 +998,10 @@ impl<'a> BindingsFromPattern<'a> {
|
||||||
| OpaqueNotInScope(..) => (),
|
| OpaqueNotInScope(..) => (),
|
||||||
List { patterns, .. } => {
|
List { patterns, .. } => {
|
||||||
stack.extend(patterns.patterns.iter().rev().map(Pattern));
|
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)
|
constraints.push_type(types, typ)
|
||||||
};
|
};
|
||||||
let typ = Loc::at(annotation.region, annotation_index);
|
let typ = Loc::at(annotation.region, annotation_index);
|
||||||
headers.insert(rest, typ);
|
headers.insert(rest.value, typ);
|
||||||
|
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
|
@ -735,7 +735,7 @@ pub fn constrain_pattern(
|
||||||
|
|
||||||
if let Some((_, Some(rest))) = opt_rest {
|
if let Some((_, Some(rest))) = opt_rest {
|
||||||
state.headers.insert(
|
state.headers.insert(
|
||||||
*rest,
|
rest.value,
|
||||||
Loc {
|
Loc {
|
||||||
region,
|
region,
|
||||||
value: *constraints[expected].get_type_ref(),
|
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!(
|
test_report!(
|
||||||
flip_flop_catch_all_branches_not_exhaustive,
|
flip_flop_catch_all_branches_not_exhaustive,
|
||||||
indoc!(
|
indoc!(
|
||||||
|
|
|
@ -1084,7 +1084,9 @@ fn from_can_pattern_help<'a>(
|
||||||
list_layout,
|
list_layout,
|
||||||
element_layout,
|
element_layout,
|
||||||
elements: mono_patterns,
|
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