[GHC] #14546: -Woverlapping-patterns warns on wrong patterns for Int
GHC
ghc-devs at haskell.org
Thu Nov 30 09:20:16 UTC 2017
#14546: -Woverlapping-patterns warns on wrong patterns for Int
-------------------------------------+-------------------------------------
Reporter: Lemming | Owner: (none)
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 8.2.2
(Type checker) |
Keywords: | Operating System: Unknown/Multiple
Architecture: | Type of failure: Incorrect
Unknown/Multiple | error/warning at compile-time
Test Case: | Blocked By:
Blocking: | Related Tickets:
Differential Rev(s): | Wiki Page:
-------------------------------------+-------------------------------------
GHC-8.0 introduced a new warning on redundant pattern matches in `case`
clauses.
But there is something strange.
{{{
$ cat RedundantCase.hs
main :: IO ()
main = do
case 0::Int of
0 -> putStrLn "A"
1 -> putStrLn "B"
_ -> putStrLn "C"
case 0::Int of
0 -> putStrLn "A"
1 -> putStrLn "B"
2 -> putStrLn "C"
case 0::Integer of
0 -> putStrLn "A"
1 -> putStrLn "B"
_ -> putStrLn "C"
case 0::Integer of
0 -> putStrLn "A"
1 -> putStrLn "B"
2 -> putStrLn "C"
case 0::Integer of
1 -> putStrLn "B"
2 -> putStrLn "C"
let dummy :: Integer
dummy = 0
case dummy of
0 -> putStrLn "A"
1 -> putStrLn "B"
_ -> putStrLn "C"
case "foo" of
"foo" -> putStrLn "A"
"bar" -> putStrLn "B"
"baz" -> putStrLn "C"
if True
then putStrLn "X"
else putStrLn "Y"
}}}
{{{
$ ghc-8.2.2 -Wall RedundantCase.hs
[1 of 1] Compiling Main ( RedundantCase.hs, RedundantCase.o )
RedundantCase.hs:4:7: warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: 0 -> ...
|
4 | 0 -> putStrLn "A"
| ^^^^^^^^^^^^^^^^^
RedundantCase.hs:5:7: warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: 1 -> ...
|
5 | 1 -> putStrLn "B"
| ^^^^^^^^^^^^^^^^^
RedundantCase.hs:8:4: warning: [-Wincomplete-patterns]
Pattern match(es) are non-exhaustive
In a case alternative: Patterns not matched: 0
|
8 | case 0::Int of
| ^^^^^^^^^^^^^^...
RedundantCase.hs:9:7: warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: 0 -> ...
|
9 | 0 -> putStrLn "A"
| ^^^^^^^^^^^^^^^^^
RedundantCase.hs:10:7: warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: 1 -> ...
|
10 | 1 -> putStrLn "B"
| ^^^^^^^^^^^^^^^^^
RedundantCase.hs:11:7: warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: 2 -> ...
|
11 | 2 -> putStrLn "C"
| ^^^^^^^^^^^^^^^^^
RedundantCase.hs:15:7: warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: 1 -> ...
|
15 | 1 -> putStrLn "B"
| ^^^^^^^^^^^^^^^^^
RedundantCase.hs:16:7: warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: _ -> ...
|
16 | _ -> putStrLn "C"
| ^^^^^^^^^^^^^^^^^
RedundantCase.hs:20:7: warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: 1 -> ...
|
20 | 1 -> putStrLn "B"
| ^^^^^^^^^^^^^^^^^
RedundantCase.hs:21:7: warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: 2 -> ...
|
21 | 2 -> putStrLn "C"
| ^^^^^^^^^^^^^^^^^
RedundantCase.hs:23:4: warning: [-Wincomplete-patterns]
Pattern match(es) are non-exhaustive
In a case alternative: Patterns not matched: 0
|
23 | case 0::Integer of
| ^^^^^^^^^^^^^^^^^^...
RedundantCase.hs:24:7: warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: 1 -> ...
|
24 | 1 -> putStrLn "B"
| ^^^^^^^^^^^^^^^^^
RedundantCase.hs:25:7: warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: 2 -> ...
|
25 | 2 -> putStrLn "C"
| ^^^^^^^^^^^^^^^^^
RedundantCase.hs:34:4: warning: [-Wincomplete-patterns]
Pattern match(es) are non-exhaustive
In a case alternative:
Patterns not matched:
[]
(p:_) where p is not one of {'b', 'f'}
['b']
('b':p:_) where p is not one of {'a'}
...
|
34 | case "foo" of
| ^^^^^^^^^^^^^...
Linking RedundantCase ...
}}}
In the first case it warns about the wrong patterns,
in the second case it warns about all patterns and a non-exhaustive
pattern list.
In the following three cases using `Integer` the warnings seem to be
correct.
The next case shows that I can suppress the warning if I hide the constant
nature of the case selector a bit.
Then a case on a `String` - GHC does not seem to try to detect redundant
pattern matches
but falls back to a general test on exhaustive pattern lists.
Finally, in a constant `case` on `Bool` I can avoid the warning using a
plain `if-then-else`.
Now I wonder what the purpose of the warning is at all.
First I thought that it wants to warn me, that the patterns overlap,
i.e. pattern `_` contains the already handled case `0`.
This does not seem to be the purpose of the warning - and such overlapping
patterns are pretty common, aren't they?
Second thought: GHC wants to warn me about redundant patterns in the
presence of a constant case selector.
But then, it does so with varying degrees of success: For `Integer` it
works, but not for `Int` or `String`.
Is it really only about constant case selectors?
Then, not only some pattern matches are redundant but the whole `case`
clause is redundant.
Then again, can't we assume that the programmer wrote such a `case` clause
by intend?
At least, this is how I use a `case` clause with constant selector: as a
type-safe way to out-comment alternative implementations.
Thus my question: Where is this warning useful?
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14546>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list