diff options
-rw-r--r-- | compiler/typecheck/TcDeriv.hs | 8 | ||||
-rw-r--r-- | docs/users_guide/8.2.1-notes.rst | 22 | ||||
-rw-r--r-- | docs/users_guide/glasgow_exts.rst | 13 | ||||
-rw-r--r-- | testsuite/tests/deriving/should_compile/T12814.hs | 9 | ||||
-rw-r--r-- | testsuite/tests/deriving/should_compile/all.T | 1 | ||||
-rw-r--r-- | testsuite/tests/deriving/should_fail/T3621.hs | 3 | ||||
-rw-r--r-- | testsuite/tests/deriving/should_fail/T3621.stderr | 15 | ||||
-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.T | 1 | ||||
-rw-r--r-- | testsuite/tests/indexed-types/should_fail/T6088.stderr | 5 | ||||
-rw-r--r-- | testsuite/tests/indexed-types/should_fail/all.T | 1 |
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, ['']) |