[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