
#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