Audit shady uses of tcSplitSigmaTy
When fixing #12918 (closed), I ended up needing to introduce a helper function called tcSplitNestedSigmaTys, which is quite similar to tcSplitSigmaTy, except that it attempts to look through as many nested foralls as possible. (See the documentation for tcSplitNestedSigmaTys here).
In the process, I accidentally discovered a bug! First, consider this program:
{-# LANGUAGE RankNTypes #-}
module Bug where
class C a where
op :: forall b c. (Monoid b, Monoid c, Eq a) => a -> b -> c
This should be (and is) rejected, since we're trying to constrain a with Eq in op, but we don't have -XConstraintedClassMethods enabled. But what about this equivalent program?
{-# LANGUAGE RankNTypes #-}
module Bug where
class C a where
op :: forall b. Monoid b => forall c. Monoid c => Eq a => a -> b -> c
By the same logic, this should also be rejected. But in GHC 8.0.2, it wasn't! That's because we were checking for the presence of constrained class variables using tcSplitSigmaTy, which only gives you Monoid b as the constraint, totally ignoring the bogus constraint inside of forall c. Monoid c => Eq a => a -> b -> c.
When I fixed #12918 (closed) (a seemingly unrelated task), I ended up replacing that very use of tcSplitSigmaTy with tcSplitNestedSigmaTys. Now it gives you (Monoid b, Monoid c, Eq a) as expected when checking the constraints, and the second program is now rightly rejected on GHC HEAD.
But I fear that there may be many more bogus uses of tcSplitSigmaTy. I should go through and try flushing out bugs of a similar caliber, and see if subbing in tcSplitNestedSigmaTys fixes these bugs.
Trac metadata
| Trac field | Value |
|---|---|
| Version | 8.1 |
| Type | Task |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler (Type checker) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture |