I’m trying to write a simple Haskell function that distinguishes between an empty list and a non-empty list. However, when I compile the code with -Werror=incomplete-patterns enabled, I get an error. It looks like OverloadedLists, and RebindableSyntax no longer work together.
data Wombat = K Wombat Wombat | ...instance IsLit Wombat where type Item Wombat = Int toList w = ...<maybe big>...nullWombat :: Wombat -> Boolnull [] = Truenull (K x y) = ...
we would not be surprised at a pattern match warning, because null turns into
null w = case toList @Wombat w of [] -> True _ -> case x of K x y -> ... _ -> error "not covered"
Not having such a warning would require GHC to figure out that the [] restul from toList deals will all constructors of w other than K.
But here we are in the very special case of toList called at type [a], where it is the identity function.
It seems plausible that the pattern match checker might have built-in knowledge of this, and treat toList @[type] x just the same way it treats x. Yes, that's ad-hoc, but everything the pattern match checker is on a best-efforts basis.
This is unrelated to whether or not we want to look through the definition of toList. We would detect both
null(toList->[])=Truenull(toList->(_:_))=False
null[]=Truenull(_:_)=False
as complete. The former is the desugaring under -XOverloadedLists, the latter is the vanilla desugaring. It is only with -XRebindableSyntax that we get the weird desugaring
Why are we expanding [] differently to (_:_)? That's the bug here. If we fix it, we won't see any warnings, I believe (try removing -XRebindableSyntax in the reproducer to test).
Ah, the problem is that [] is desugared as a ListPat while (_:_) is a ConPat.
In the absence of -XRebindableSyntax, we have a special code path in Pmc.Desugar.desugarPat, but that is deactivated in case of -XRebindableSyntax.
Perhaps instead of deactivating that code path completely, we could see whether the expansion is the vanilla GHC.Exts.toList which amounts to inlining it.
Because [] is built-in syntax, expanded by OverloadedLists (as is [a,b,c]), while _:_ is just a regular old data constructor, like Just x which has no relationship with OverloadedLists.
I don't see how deactivating code paths can help with that.
It looks like this is actually a regression. In GHC 8.4.4, the false positive warning doesn't happen, but you do still get the warning on my modified one where it really is incomplete.