I'm attempting to pattern match on a pair of lists. I believe that I have covered all possible permutations, but the compiler says I have not. Here is my code:
when (left, right) is
([], _) -> #1
(_, []) -> #2
([l], [r]) -> #3
([l], [r, .. as rs]) -> #4
([l, .. as ls], [r]) -> #5
([l, .. as ls], [r, .. as rs]) -> #6
So, since I have a pair of lists, each list may be 0,1..N elements. So the permutations are:
0,0 : covered by #1
0,1 : covered by #1
0,N : covered by #1
1,0 : covered by #2
1,1 : covered by #3
1,N : covered by #4
N,0 : covered by #2
N,1 : covered by #5
N,N : covered by #6
Yet compiler says:
This when does not cover all the possibilities:
...
Other possibilities include:
( [_, ..], _ )
The case described by the compiler would be covered by # 2, 5, and 6. - [(N,0), (N,1), (N,N)], which is exhaustive for the cases described in the error.
I can't help more, but to say yes, this seem exhaustive.
I threw a (_, _) -> crash "..." on my code, and it compiles, but that makes me pretty squeamish.. :rolling_eyes:
Maybe exhaustiveness checking struggles with overlapping patterns? Right now the patterns are not disjoint since [42]
would be matched by both [x]
and [x, .. as xs]
(with xs = []
). What happens if you change the length=N cases to use a pattern that matches on the first two elements?
Yeah, I think bug
As far as the [x]
overlapping with [x, ..]
goes, I need to differentiate between [x]
and [x, ..]
. Originally, I didn't have cases 2, 3, or 4. They were only added because the compiler was the same error message and I though, oh, maybe Roc doesn't match ..
on empty lists...
I can try throwing in an extra var in the N
cases, but since originally I didn't have the 1
cases, I don't expect a change.
I'll try to find a min repro for this tomorrow. My guess would be its struggling to determine exhaustiveness on a tuple of lists.
Yeah, that makes sense. Not sure what we did for exhaustiveness of records and if it is fully implemented. A tuple is just a weird record
Right.. makes sense. Just a record with place-value identifiers instead of names. Hmm... be interesting to see if I can break things with records too.
Thats a good point too... assuming records don't break in this way, that would be a much better work around than the (_, _) -> crash
I threw on the end of my when block.
Actually... do records have any kind of equivalent pattern matching? I can't even imagine what that syntax would look like...
when { left, right } is
#... ?
when {x : 1} is
{x: 2} -> "2"
{x: 1} -> "1"
{x: _} -> "eh"
```
Ahhh, of course! :sweat_smile:
Okay, I can confirm that records are subject to the exact same exhaustiveness checking bug, plus one more:
In the following example the compiler says that the second pattern is redundant, when it is obviously not.
when { lhs: left, rhs: right } is
{ lhs: [] } -> right
{ rhs: [] } -> left
# ...
Can you make an issue for that @Ian McLerran?
Yep, sure can!
Okay, issue filed here.
Thanks :)
Last updated: Jul 06 2025 at 12:14 UTC