diff options
author | Ryan Scott <ryan.gl.scott@gmail.com> | 2018-06-04 21:20:02 -0400 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2018-06-04 22:37:19 -0400 |
commit | 8ed8b037fee9611b1c4ef49adb6cf50bbd929a27 (patch) | |
tree | ff3907f0412085a78e694597c1bdba700740403f /testsuite/tests/deriving/should_fail | |
parent | 85309a3cda367425cca727dfa45e5e6c63b47391 (diff) | |
download | haskell-8ed8b037fee9611b1c4ef49adb6cf50bbd929a27.tar.gz |
Introduce DerivingVia
This implements the `DerivingVia` proposal put forth in
https://github.com/ghc-proposals/ghc-proposals/pull/120.
This introduces the `DerivingVia` deriving strategy. This is a
generalization of `GeneralizedNewtypeDeriving` that permits the user
to specify the type to `coerce` from.
The major change in this patch is the introduction of the
`ViaStrategy` constructor to `DerivStrategy`, which takes a type
as a field. As a result, `DerivStrategy` is no longer a simple
enumeration type, but rather something that must be renamed and
typechecked. The process by which this is done is explained more
thoroughly in section 3 of this paper
( https://www.kosmikus.org/DerivingVia/deriving-via-paper.pdf ),
although I have inlined the relevant parts into Notes where possible.
There are some knock-on changes as well. I took the opportunity to
do some refactoring of code in `TcDeriv`, especially the
`mkNewTypeEqn` function, since it was bundling all of the logic for
(1) deriving instances for newtypes and
(2) `GeneralizedNewtypeDeriving`
into one huge broth. `DerivingVia` reuses much of part (2), so that
was factored out as much as possible.
Bumps the Haddock submodule.
Test Plan: ./validate
Reviewers: simonpj, bgamari, goldfire, alanz
Subscribers: alanz, goldfire, rwbarton, thomie, mpickering, carter
GHC Trac Issues: #15178
Differential Revision: https://phabricator.haskell.org/D4684
Diffstat (limited to 'testsuite/tests/deriving/should_fail')
9 files changed, 94 insertions, 0 deletions
diff --git a/testsuite/tests/deriving/should_fail/all.T b/testsuite/tests/deriving/should_fail/all.T index f1d8261e4b..0cc85ea4aa 100644 --- a/testsuite/tests/deriving/should_fail/all.T +++ b/testsuite/tests/deriving/should_fail/all.T @@ -74,3 +74,7 @@ test('T14728b', normal, compile_fail, ['']) test('T14916', normal, compile_fail, ['']) test('T15073', [extra_files(['T15073a.hs'])], multimod_compile_fail, ['T15073', '-v0']) +test('deriving-via-fail', normal, compile_fail, ['']) +test('deriving-via-fail2', normal, compile_fail, ['']) +test('deriving-via-fail3', normal, compile_fail, ['']) +test('deriving-via-fail4', normal, compile_fail, ['']) diff --git a/testsuite/tests/deriving/should_fail/deriving-via-fail.hs b/testsuite/tests/deriving/should_fail/deriving-via-fail.hs new file mode 100644 index 0000000000..fbae1e7d13 --- /dev/null +++ b/testsuite/tests/deriving/should_fail/deriving-via-fail.hs @@ -0,0 +1,19 @@ +{-# LANGUAGE DerivingVia #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE StandaloneDeriving #-} +module DerivingViaFail where + +import Control.Category +import Data.Functor.Identity + +newtype Foo1 a = Foo1 a deriving Show via (Identity b) + +newtype Foo2 a b = Foo2 (a -> b) + deriving Category + via fooo + +data Foo3 deriving Eq via (forall a. a) + +newtype Foo4 a = Foo4 a +deriving via (Identity b) + instance Show (Foo4 a) diff --git a/testsuite/tests/deriving/should_fail/deriving-via-fail.stderr b/testsuite/tests/deriving/should_fail/deriving-via-fail.stderr new file mode 100644 index 0000000000..51907e02cf --- /dev/null +++ b/testsuite/tests/deriving/should_fail/deriving-via-fail.stderr @@ -0,0 +1,16 @@ + +deriving-via-fail.hs:9:34: error: + Type variable ‘b’ is bound in the ‘via’ type ‘(Identity b)’ + but is not mentioned in the derived class ‘Show’, which is illegal + +deriving-via-fail.hs:12:12: error: + Type variable ‘fooo’ is bound in the ‘via’ type ‘fooo’ + but is not mentioned in the derived class ‘Category’, which is illegal + +deriving-via-fail.hs:15:20: error: + Type variable ‘a’ is bound in the ‘via’ type ‘(forall a. a)’ + but is not mentioned in the derived class ‘Eq’, which is illegal + +deriving-via-fail.hs:19:12: error: + Type variable ‘b’ is bound in the ‘via’ type ‘(Identity b)’ + but is not mentioned in the derived instance ‘Show (Foo4 a)’, which is illegal diff --git a/testsuite/tests/deriving/should_fail/deriving-via-fail2.hs b/testsuite/tests/deriving/should_fail/deriving-via-fail2.hs new file mode 100644 index 0000000000..e9a456d048 --- /dev/null +++ b/testsuite/tests/deriving/should_fail/deriving-via-fail2.hs @@ -0,0 +1,7 @@ +{-# LANGUAGE DerivingVia #-} +{-# LANGUAGE StandaloneDeriving #-} +module DerivingViaFail2 where + +class C a +data A = A +deriving via Maybe instance C A diff --git a/testsuite/tests/deriving/should_fail/deriving-via-fail2.stderr b/testsuite/tests/deriving/should_fail/deriving-via-fail2.stderr new file mode 100644 index 0000000000..d5692ad6b2 --- /dev/null +++ b/testsuite/tests/deriving/should_fail/deriving-via-fail2.stderr @@ -0,0 +1,6 @@ + +deriving-via-fail2.hs:7:1: error: + • Cannot derive instance via ‘Maybe’ + Class ‘C’ expects an argument of kind ‘*’, + but ‘Maybe’ has kind ‘* -> *’ + • In the stand-alone deriving instance for ‘C A’ diff --git a/testsuite/tests/deriving/should_fail/deriving-via-fail3.hs b/testsuite/tests/deriving/should_fail/deriving-via-fail3.hs new file mode 100644 index 0000000000..ad8e0be542 --- /dev/null +++ b/testsuite/tests/deriving/should_fail/deriving-via-fail3.hs @@ -0,0 +1,3 @@ +module DerivingViaFail3 where + +data F deriving Eq via F diff --git a/testsuite/tests/deriving/should_fail/deriving-via-fail3.stderr b/testsuite/tests/deriving/should_fail/deriving-via-fail3.stderr new file mode 100644 index 0000000000..f2af73a01f --- /dev/null +++ b/testsuite/tests/deriving/should_fail/deriving-via-fail3.stderr @@ -0,0 +1,4 @@ + +deriving-via-fail3.hs:3:1: error: + Illegal deriving strategy: via + Use DerivingVia to enable this extension diff --git a/testsuite/tests/deriving/should_fail/deriving-via-fail4.hs b/testsuite/tests/deriving/should_fail/deriving-via-fail4.hs new file mode 100644 index 0000000000..1436d994c0 --- /dev/null +++ b/testsuite/tests/deriving/should_fail/deriving-via-fail4.hs @@ -0,0 +1,17 @@ +{-# LANGUAGE DerivingVia #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE ScopedTypeVariables #-} +module DerivingViaFail4 where + +class C a b where + c :: a -> b -> Bool + +instance C a a where + c _ _ = True + +newtype F1 = F1 Int + deriving Eq via Char + +newtype F2 a = MkF2 a + deriving (C a) via (forall a. a) diff --git a/testsuite/tests/deriving/should_fail/deriving-via-fail4.stderr b/testsuite/tests/deriving/should_fail/deriving-via-fail4.stderr new file mode 100644 index 0000000000..caa2bfe93b --- /dev/null +++ b/testsuite/tests/deriving/should_fail/deriving-via-fail4.stderr @@ -0,0 +1,18 @@ + +deriving-via-fail4.hs:14:12: error: + • Couldn't match representation of type ‘Int’ with that of ‘Char’ + arising from the coercion of the method ‘==’ + from type ‘Char -> Char -> Bool’ to type ‘F1 -> F1 -> Bool’ + • When deriving the instance for (Eq F1) + +deriving-via-fail4.hs:17:13: error: + • Couldn't match representation of type ‘a1’ with that of ‘a’ + arising from the coercion of the method ‘c’ + from type ‘a -> a -> Bool’ to type ‘a -> F2 a1 -> Bool’ + ‘a1’ is a rigid type variable bound by + the deriving clause for ‘C a (F2 a1)’ + at deriving-via-fail4.hs:17:13-15 + ‘a’ is a rigid type variable bound by + the deriving clause for ‘C a (F2 a1)’ + at deriving-via-fail4.hs:17:13-15 + • When deriving the instance for (C a (F2 a1)) |