diff options
author | Simon Peyton Jones <simonpj@microsoft.com> | 2018-09-13 11:23:53 +0100 |
---|---|---|
committer | Simon Peyton Jones <simonpj@microsoft.com> | 2018-09-13 11:35:00 +0100 |
commit | bd76875ae6ad0cdd734564dddfb9ab88a6de9579 (patch) | |
tree | dddaeaf707a06f3e4b34d462978a20f89c12b0f6 /testsuite/tests/quantified-constraints | |
parent | 291b0f89703f28631a381549e1838aa06195d011 (diff) | |
download | haskell-bd76875ae6ad0cdd734564dddfb9ab88a6de9579.tar.gz |
Allow (~) in the head of a quantified constraints
Since the introduction of quantified constraints, GHC has rejected
a quantified constraint with (~) in the head, thus
f :: (forall a. blah => a ~ ty) => stuff
I am frankly dubious that this is ever useful. But /is/ necessary for
Coercible (representation equality version of (~)) and it does no harm
to allow it for (~) as well. Plus, our users are asking for it
(Trac #15359, #15625).
It was really only excluded by accident, so
this patch lifts the restriction. See TcCanonical
Note [Equality superclasses in quantified constraints]
There are a number of wrinkles:
* If the context of the quantified constraint is empty, we
can get trouble when we get down to unboxed equality (a ~# b)
or (a ~R# b), as Trac #15625 showed. This is even more of
a corner case, but it produced an outright crash, so I elaborated
the superclass machinery in TcCanonical.makeStrictSuperClasses
to add a void argument in this case. See
Note [Equality superclasses in quantified constraints]
* The restriction on (~) was in TcValidity.checkValidInstHead.
In lifting the restriction I discovered an old special case for
(~), namely
| clas_nm `elem` [ heqTyConName, eqTyConName]
, nameModule clas_nm /= this_mod
This was (solely) to support the strange instance
instance a ~~ b => a ~ b
in Data.Type.Equality. But happily that is no longer
with us, since
commit f265008fb6f70830e7e92ce563f6d83833cef071
Refactor (~) to reduce the suerpclass stack
So I removed the special case.
* I found that the Core invariants on when we could have
co = <expr>
were entirely not written down. (Getting this wrong ws
the proximate source of the crash in Trac #15625. So
- Documented them better in CoreSyn
Note [CoreSyn type and coercion invariant],
- Modified CoreOpt and CoreLint to match
- Modified CoreUtils.bindNonRec to match
- Made MkCore.mkCoreLet use bindNonRec, rather
than duplicate its logic
- Made Simplify.rebuildCase case-to-let respect
Note [CoreSyn type and coercion invariant],
Diffstat (limited to 'testsuite/tests/quantified-constraints')
-rw-r--r-- | testsuite/tests/quantified-constraints/T15359.hs | 12 | ||||
-rw-r--r-- | testsuite/tests/quantified-constraints/T15359a.hs | 14 | ||||
-rw-r--r-- | testsuite/tests/quantified-constraints/T15625.hs | 16 | ||||
-rw-r--r-- | testsuite/tests/quantified-constraints/T15625a.hs | 20 | ||||
-rw-r--r-- | testsuite/tests/quantified-constraints/all.T | 4 |
5 files changed, 66 insertions, 0 deletions
diff --git a/testsuite/tests/quantified-constraints/T15359.hs b/testsuite/tests/quantified-constraints/T15359.hs new file mode 100644 index 0000000000..7ef1cc5572 --- /dev/null +++ b/testsuite/tests/quantified-constraints/T15359.hs @@ -0,0 +1,12 @@ +{-# LANGUAGE MultiParamTypeClasses, GADTs, RankNTypes, + ConstraintKinds, QuantifiedConstraints #-} + +module T15359 where + +class C a b + +data Dict c where + Dict :: c => Dict c + +foo :: (forall a b. C a b => a ~ b) => Dict (C a b) -> a -> b +foo Dict x = x diff --git a/testsuite/tests/quantified-constraints/T15359a.hs b/testsuite/tests/quantified-constraints/T15359a.hs new file mode 100644 index 0000000000..6ec5f861a8 --- /dev/null +++ b/testsuite/tests/quantified-constraints/T15359a.hs @@ -0,0 +1,14 @@ +{-# LANGUAGE MultiParamTypeClasses, GADTs, RankNTypes, + ConstraintKinds, QuantifiedConstraints, + UndecidableInstances #-} + +module T15359a where + +class C a b +class a ~ b => D a b + +data Dict c where + Dict :: c => Dict c + +foo :: (forall a b. C a b => D a b) => Dict (C a b) -> a -> b +foo Dict x = x diff --git a/testsuite/tests/quantified-constraints/T15625.hs b/testsuite/tests/quantified-constraints/T15625.hs new file mode 100644 index 0000000000..8fe092da98 --- /dev/null +++ b/testsuite/tests/quantified-constraints/T15625.hs @@ -0,0 +1,16 @@ +{-# Language GADTs, MultiParamTypeClasses, QuantifiedConstraints #-} + +module T15625 where + +import Data.Coerce + +class a ~ b => Equal a b + +test1 :: (forall b. a ~ b) => a +test1 = False + +test2 :: (forall b. Equal a b) => a +test2 = False + +test3 :: (forall b. Coercible a b) => a +test3 = coerce False diff --git a/testsuite/tests/quantified-constraints/T15625a.hs b/testsuite/tests/quantified-constraints/T15625a.hs new file mode 100644 index 0000000000..ca049cb19d --- /dev/null +++ b/testsuite/tests/quantified-constraints/T15625a.hs @@ -0,0 +1,20 @@ +{-# Language RankNTypes, ConstraintKinds, QuantifiedConstraints, + PolyKinds, GADTs, MultiParamTypeClasses, + DataKinds, FlexibleInstances #-} + +module T15625a where + +import Data.Kind + +type Cat ob = ob -> ob -> Type + +data KLEISLI (m :: Type -> Type) :: Cat (KL_kind m) where + MkKLEISLI :: (a -> m b) -> KLEISLI(m) (KL a) (KL b) + +data KL_kind (m :: Type -> Type) = KL Type + +class (a ~ KL xx) => AsKL a xx +instance (a ~ KL xx) => AsKL a xx + +ekki__ :: Monad m => (forall xx. AsKL a xx) => KLEISLI m a a +ekki__ = MkKLEISLI undefined diff --git a/testsuite/tests/quantified-constraints/all.T b/testsuite/tests/quantified-constraints/all.T index 833a667ea9..1e2eca8358 100644 --- a/testsuite/tests/quantified-constraints/all.T +++ b/testsuite/tests/quantified-constraints/all.T @@ -16,3 +16,7 @@ test('T15290a', normal, compile_fail, ['']) test('T15290b', normal, compile_fail, ['']) test('T15316', normal, compile_fail, ['']) test('T15334', normal, compile_fail, ['']) +test('T15359', normal, compile, ['']) +test('T15359a', normal, compile, ['']) +test('T15625', normal, compile, ['']) +test('T15625a', normal, compile, ['']) |