Skip to content

Pattern-match warnings for datatypes with COMPLETE sets break abstraction

Here's a file:

{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ViewPatterns #-}
module Bug (Boolean(F, TooGoodToBeTrue), catchAll) where

data Boolean = F | T
  deriving Eq

pattern TooGoodToBeTrue :: Boolean
pattern TooGoodToBeTrue <- ((== T) -> True)
  where
    TooGoodToBeTrue = T
{-# COMPLETE F, TooGoodToBeTrue #-}

catchAll :: Boolean -> Int
catchAll F               = 0
-- catchAll TooGoodToBeTrue = 1

If you compile this with -Wall, the warning will warn about T, not TooGoodToBeTrue (the other conlike in the COMPLETE set):

$ /opt/ghc/8.2.1/bin/ghc -fforce-recomp -Wall Bug.hs
[1 of 1] Compiling Bug              ( Bug.hs, Bug.o )

Bug.hs:15:1: warning: [-Wincomplete-patterns]
    Pattern match(es) are non-exhaustive
    In an equation for ‘catchAll’: Patterns not matched: T
   |
15 | catchAll F               = 0
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Perhaps this isn't so bad, since it's intra-module. But the problem persists even across modules:

module Foo where

import Bug

catchAll2 :: Boolean -> Int
catchAll2 F               = 0
-- catchAll2 TooGoodToBeTrue = 1
$ /opt/ghc/8.2.1/bin/ghc -fforce-recomp -c Bug.hs
$ /opt/ghc/8.2.1/bin/ghc -fforce-recomp -c -Wall Foo.hs

Foo.hs:6:1: warning: [-Wincomplete-patterns]
    Pattern match(es) are non-exhaustive
    In an equation for ‘catchAll2’: Patterns not matched: Bug.T
  |
6 | catchAll2 F               = 0
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

This one is really bad, since it's warning about Bug.T, which should be hidden!

Trac metadata
Trac field Value
Version 8.0.1
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information