mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 16:44:33 +00:00
Spread list tests can never touch exact-sized bounds tests
When compiling a pattern match like ``` [] -> .. [_] -> .. [_, ..] -> .. ``` to a decision tree, we must make sure that the last test (len >= 1) does not touch the branch reached by the second test (len == 1). It is enough to ban (len >=) tests from ever touching exact-sized list patterns, because a spread test (len >=) can never reach an exact-sized test. On the other hand, an exact-sized test can reach a spread pattern, because in ``` [_, _] -> .. [..] -> .. ``` the last branch generates tests for patterns `[]` and `[_]`, and we would like those patterns to be covered by the spread test (len >= 0)! Closes #4685
This commit is contained in:
parent
b6a96ebb85
commit
759127660d
3 changed files with 62 additions and 62 deletions
|
@ -425,6 +425,7 @@ fn flatten<'a>(
|
|||
/// variables to "how to get their value". So a pattern like (Just (x,_)) will give
|
||||
/// us something like ("x" => value.0.0)
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Match {
|
||||
Exact(Label),
|
||||
GuardOnly,
|
||||
|
@ -795,7 +796,22 @@ fn to_relevant_branch_help<'a>(
|
|||
elements,
|
||||
element_layout: _,
|
||||
} => match test {
|
||||
IsListLen { bound: _, len } if my_arity.covers_length(*len as _) => {
|
||||
IsListLen {
|
||||
bound: test_bound,
|
||||
len,
|
||||
} if my_arity.covers_length(*len as _)
|
||||
// Spread tests [_, ..] can only match spread tests, not exact-sized bounds [_].
|
||||
//
|
||||
// On the other hand, exact-sized tests [_] can match spread bounds [_, ..],
|
||||
// because each spread bound generates 0 or more exact-sized tests.
|
||||
//
|
||||
// See exhaustiveness checking of lists for more details on the tests generated
|
||||
// for spread bounds.
|
||||
&& !matches!(
|
||||
(test_bound, my_arity),
|
||||
(ListLenBound::AtLeast, ListArity::Exact(..))
|
||||
) =>
|
||||
{
|
||||
let sub_positions = elements.into_iter().enumerate().map(|(index, elem_pat)| {
|
||||
let mut new_path = path.to_vec();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue