Skip to content

Pattern match checker should suggest constructors in the range of view pattern instead of the domain

Consider

data D = InternalConstructorIDon'tWannaHearAbout Int Bool Char

predicate :: D -> Bool
predicate (InternalConstructorIDon'tWannaHearAbout i b c) = i >= 0 && b

foo :: D -> Int
foo (predicate -> False) = 3

Today, we'll report

test.hs:12:1: warning: [-Wincomplete-patterns]
    Pattern match(es) are non-exhaustive
    In an equation for ‘foo’: Patterns of type ‘D’ not matched: _
   |
12 | foo (predicate -> False) = 3
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

and that is rather unhelpful. GHC 9.0 (and I'd expect 9.2 to do so, too) even repported

test.hs:12:1: warning: [-Wincomplete-patterns]
    Pattern match(es) are non-exhaustive
    In an equation for ‘foo’:
        Patterns not matched: InternalConstructorIDon'tWannaHearAbout _ _ _
   |
12 | foo (predicate -> False) = 3
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

mentioning the unhelpful constructor of D.

Proposal

If there's a view pattern involved, try to report missed patterns in the range of that pattern instead:

test.hs:12:1: warning: [-Wincomplete-patterns]
    Pattern match(es) are non-exhaustive
    In an equation for ‘foo’:
        Patterns not matched: predicate -> True
   |
12 | foo (predicate -> False) = 3
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Open question: What should happen if both view patterns and regular patterns are used? Should we report patterns in the range or the domain? Not sure. In effect, we are trying to decide from which COMPLETE set to report: Either the one from the range (Bool) or the one from the domain (D).

(In that way, this ticket is related to #20311 where @sheaf first reported this example. We probably never want to report patterns from the domain if it's comprised of non-exported constructors.)

Challenges

We'd have to identify which pattern variable is associated with the range of a view pat, to be able to "un-desugar" in our reporting mechanism later on.

I don't have time to work on this, but I'd be happy to advise.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information