summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/typecheck/TcDeriv.hs8
-rw-r--r--docs/users_guide/8.2.1-notes.rst22
-rw-r--r--docs/users_guide/glasgow_exts.rst13
-rw-r--r--testsuite/tests/deriving/should_compile/T12814.hs9
-rw-r--r--testsuite/tests/deriving/should_compile/all.T1
-rw-r--r--testsuite/tests/deriving/should_fail/T3621.hs3
-rw-r--r--testsuite/tests/deriving/should_fail/T3621.stderr15
-rw-r--r--testsuite/tests/indexed-types/should_compile/T6088.hs (renamed from testsuite/tests/indexed-types/should_fail/T6088.hs)4
-rw-r--r--testsuite/tests/indexed-types/should_compile/all.T1
-rw-r--r--testsuite/tests/indexed-types/should_fail/T6088.stderr5
-rw-r--r--testsuite/tests/indexed-types/should_fail/all.T1
11 files changed, 60 insertions, 22 deletions
diff --git a/compiler/typecheck/TcDeriv.hs b/compiler/typecheck/TcDeriv.hs
index 0ff70fda79..837f4e8a2d 100644
--- a/compiler/typecheck/TcDeriv.hs
+++ b/compiler/typecheck/TcDeriv.hs
@@ -1271,9 +1271,9 @@ mkNewTypeEqn dflags overlap_mode tvs
-- and constraints to coerce each individual method
meth_theta :: [PredOrigin]
meths = classMethods cls
- meth_theta = rep_pred_o : coercible_constraints
--- meth_theta | null meths = [] -- No methods => no constraints (Trac #12814)
--- | otherwise = rep_pred_o : coercible_constraints
+ meth_theta | null meths = [] -- No methods => no constraints
+ -- (Trac #12814)
+ | otherwise = rep_pred_o : coercible_constraints
coercible_constraints
= [ mkPredOrigin (DerivOriginCoerce meth t1 t2) TypeLevel
(mkReprPrimEqPred t1 t2)
@@ -1415,7 +1415,7 @@ However, we must watch out for three things:
with the former definition of C, you'd end up with something like this:
- instance C a x => C a (Foo x) where
+ instance C a (Foo x) where
type T a = T ???
This T family instance doesn't mention the newtype (or its representation
diff --git a/docs/users_guide/8.2.1-notes.rst b/docs/users_guide/8.2.1-notes.rst
index 7504a70796..748bc80985 100644
--- a/docs/users_guide/8.2.1-notes.rst
+++ b/docs/users_guide/8.2.1-notes.rst
@@ -61,6 +61,28 @@ Compiler
:ref:`GeneralizedNewtypeDeriving and associated type families
<gnd-and-associated-types>`.
+- :ghc-flag:`-XGeneralizedNewtypeDeriving` will no longer infer constraints
+ when deriving a class with no methods. That is, this code: ::
+
+ class Throws e
+ newtype Id a = MkId a
+ deriving Throws
+
+ will now generate this instance: ::
+
+ instance Throws (Id a)
+
+ instead of this instance: ::
+
+ instance Throws a => Throws (Id a)
+
+ This change was motivated by the fact that the latter code has a strictly
+ redundant ``Throws a`` constraint, so it would emit a warning when compiled
+ with :ghc-flag:`-Wredundant-constraints`. The latter instance could still
+ be derived if so desired using :ghc-flag:`-XStandaloneDeriving`: ::
+
+ deriving instance Throws a => Throws (Id a)
+
- Add warning flag :ghc-flag:`-Wcpp-undef` which passes ``-Wundef`` to the C
pre-processor causing the pre-processor to warn on uses of the ``#if``
directive on undefined identifiers.
diff --git a/docs/users_guide/glasgow_exts.rst b/docs/users_guide/glasgow_exts.rst
index 38afb3b675..9cda16a970 100644
--- a/docs/users_guide/glasgow_exts.rst
+++ b/docs/users_guide/glasgow_exts.rst
@@ -3971,6 +3971,11 @@ Then the derived instance declaration is of the form ::
instance C t1..tj t => C t1..tj (T v1...vk)
+Note that if ``C`` does not contain any class methods, the instance context
+is wholly unnecessary, and as such GHC will instead generate: ::
+
+ instance C t1..tj (T v1..vk)
+
As an example which does *not* work, consider ::
newtype NonMonad m s = NonMonad (State s m s) deriving Monad
@@ -4018,7 +4023,7 @@ associated type families. Here is an example: ::
The derived ``HasRing`` instance would look like ::
- instance HasRing a => HasRing (L1Norm a) where
+ instance HasRing (L1Norm a) where
type Ring (L1Norm a) = Ring a
To be precise, if the class being derived is of the form ::
@@ -4051,7 +4056,7 @@ then you can derive a ``C c_1 c_2 ... c_(m-1)`` instance for
For the derived ``Bad Int`` instance, GHC would need to generate something
like this: ::
- instance Bad Int a => Bad Int (Foo a) where
+ instance Bad Int (Foo a) where
type B Int = B ???
Now we're stuck, since we have no way to refer to ``a`` on the right-hand
@@ -4088,6 +4093,10 @@ If both of these conditions are met, GHC will generate this instance: ::
type Tk tk_1 tk_2 ... (N n_1 n_2 ... n_q) ... tk_p
= Tk tk_1 tk_2 ... <rep-type> ... tk_p
+Again, if ``C`` contains no class methods, the instance context will be
+redundant, so GHC will instead generate
+``instance C c_1 c_2 ... c_(m-1) (N n_1 n_2 ... n_q)``.
+
Beware that in some cases, you may need to enable the
:ghc-flag:`-XUndecidableInstances` extension in order to use this feature.
Here's a pathological case that illustrates why this might happen: ::
diff --git a/testsuite/tests/deriving/should_compile/T12814.hs b/testsuite/tests/deriving/should_compile/T12814.hs
new file mode 100644
index 0000000000..4acb23218f
--- /dev/null
+++ b/testsuite/tests/deriving/should_compile/T12814.hs
@@ -0,0 +1,9 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE TypeFamilies #-}
+module T12814 where
+
+class C a where
+ type T a
+
+newtype Identity a = Identity a
+ deriving C
diff --git a/testsuite/tests/deriving/should_compile/all.T b/testsuite/tests/deriving/should_compile/all.T
index 39a765a16f..fd4bb54e82 100644
--- a/testsuite/tests/deriving/should_compile/all.T
+++ b/testsuite/tests/deriving/should_compile/all.T
@@ -79,3 +79,4 @@ test('T12399', normal, compile, [''])
test('T12583', normal, compile, [''])
test('T12616', normal, compile, [''])
test('T12688', normal, compile, [''])
+test('T12814', normal, compile, ['-Wredundant-constraints'])
diff --git a/testsuite/tests/deriving/should_fail/T3621.hs b/testsuite/tests/deriving/should_fail/T3621.hs
index 36ac195f2b..19786a4ec4 100644
--- a/testsuite/tests/deriving/should_fail/T3621.hs
+++ b/testsuite/tests/deriving/should_fail/T3621.hs
@@ -3,7 +3,7 @@ module T3621 where
-- This one is ok, even though the deriving clause mentions 'a'
-- which is not a parameter of 'T'
-class C a b
+class C a b
instance C a S
data S = MkS
@@ -12,6 +12,7 @@ newtype T = MkT S deriving( C a )
-- But this one fails, and should fail
class (Monad m) => MonadState s m | m -> s where
+ state :: (s -> (a, s)) -> m a
newtype State s a = State { runState :: s -> (a, s) }
instance Functor (State s) where {}
diff --git a/testsuite/tests/deriving/should_fail/T3621.stderr b/testsuite/tests/deriving/should_fail/T3621.stderr
index 67b949e754..88004bb230 100644
--- a/testsuite/tests/deriving/should_fail/T3621.stderr
+++ b/testsuite/tests/deriving/should_fail/T3621.stderr
@@ -1,8 +1,9 @@
-T3621.hs:23:43:
- No instance for (MonadState state (State s))
- arising from the 'deriving' clause of a data type declaration
- Possible fix:
- use a standalone 'deriving instance' declaration,
- so you can specify the instance context yourself
- When deriving the instance for (MonadState state (WrappedState s))
+T3621.hs:24:43: error:
+ • No instance for (MonadState state (State s))
+ arising from the 'deriving' clause of a data type declaration
+ Possible fix:
+ use a standalone 'deriving instance' declaration,
+ so you can specify the instance context yourself
+ • When deriving the instance for (MonadState
+ state (WrappedState s))
diff --git a/testsuite/tests/indexed-types/should_fail/T6088.hs b/testsuite/tests/indexed-types/should_compile/T6088.hs
index 2c9a592eae..ab54c72be4 100644
--- a/testsuite/tests/indexed-types/should_fail/T6088.hs
+++ b/testsuite/tests/indexed-types/should_compile/T6088.hs
@@ -1,5 +1,5 @@
{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE EmptyDataDecls #-}
module T6088 where
@@ -15,4 +15,4 @@ instance (Pos n ~ True) => C (A n)
newtype B n = B (A n) deriving (C)
-- This should work, giving
- -- instance (Pos n ~ True) => C (B n)
+ -- instance C (B n)
diff --git a/testsuite/tests/indexed-types/should_compile/all.T b/testsuite/tests/indexed-types/should_compile/all.T
index 05c9ad3d41..b093128a41 100644
--- a/testsuite/tests/indexed-types/should_compile/all.T
+++ b/testsuite/tests/indexed-types/should_compile/all.T
@@ -200,6 +200,7 @@ test('Overlap14', normal, compile, [''])
test('T7156', normal, compile, [''])
test('T5591a', normal, compile, [''])
test('T5591b', normal, compile, [''])
+test('T6088', normal, compile, [''])
test('T7280', normal, compile, [''])
test('T7474', normal, compile, [''])
test('T7489', normal, compile, [''])
diff --git a/testsuite/tests/indexed-types/should_fail/T6088.stderr b/testsuite/tests/indexed-types/should_fail/T6088.stderr
deleted file mode 100644
index c910ec60d6..0000000000
--- a/testsuite/tests/indexed-types/should_fail/T6088.stderr
+++ /dev/null
@@ -1,5 +0,0 @@
-
-T6088.hs:16:33: error:
- Couldn't match type ‘Pos n’ with ‘True’
- arising from the 'deriving' clause of a data type declaration
- When deriving the instance for (C (B n))
diff --git a/testsuite/tests/indexed-types/should_fail/all.T b/testsuite/tests/indexed-types/should_fail/all.T
index f4f8c8d2c9..4b0e994610 100644
--- a/testsuite/tests/indexed-types/should_fail/all.T
+++ b/testsuite/tests/indexed-types/should_fail/all.T
@@ -129,7 +129,6 @@ test('T9580', normal, multimod_compile_fail, ['T9580', ''])
test('T9662', normal, compile_fail, [''])
test('T7862', normal, compile, [''])
test('T9896', normal, compile_fail, [''])
-test('T6088', normal, compile_fail, [''])
test('T8550', normal, compile_fail, [''])
test('T9554', normal, compile_fail, [''])
test('T10141', normal, compile_fail, [''])