Commit af77089b authored by Simon Peyton Jones's avatar Simon Peyton Jones
Browse files

Fix DeriveAnyClass (Trac #9968)

The main issue concerned things like

   data T a = MkT a deriving( C Int )

which is supposed to generate

   instance C Int (T a) where {}

But the 'Int' argument (called cls_tys in the code) wasn't
even being passed to inferConstraints and mk_data_eqn, so it
really had no chance.   DeriveAnyClass came along after this
code was written!

Anyway I did quite a bit of tidying up in inferConstraints.

Also I discovered that this case was not covered at all

   data T a b = MkT a b deriving( Bifunctor )

What constraints should we generate for the instance context?
We can deal with classes whose last arg has kind *, like Eq, Ord;
or (* -> *), like Functor, Traversable.  But we really don't have
a story for classes whose last arg has kind (* -> * -> *).

So I augmented checkSideConditions to check for that and give
a sensible error message.

ToDo: update the user manual.
parent 31bddc42
This diff is collapsed.
......@@ -18,7 +18,7 @@ This is where we do all the grimy bindings' generation.
module TcGenDeriv (
BagDerivStuff, DerivStuff(..),
hasBuiltinDeriving, canDeriveAnyClass,
FFoldType(..), functorLikeTraverse,
deepSubtypesContaining, foldDataConArgs,
......@@ -133,19 +133,6 @@ hasBuiltinDeriving dflags fix_env clas = assocMaybe gen_list (getUnique clas)
, (traversableClassKey, gen_Traversable_binds)
, (liftClassKey, gen_Lift_binds) ]
-- Nothing: we can (try to) derive it via Generics
-- Just s: we can't, reason s
canDeriveAnyClass :: DynFlags -> TyCon -> Class -> Maybe SDoc
canDeriveAnyClass dflags _tycon clas =
let b `orElse` s = if b then Nothing else Just (ptext (sLit s))
Just m <> _ = Just m
Nothing <> n = n
-- We can derive a given class for a given tycon via Generics iff
in -- 1) The class is not a "standard" class (like Show, Functor, etc.)
(not (getUnique clas `elem` standardClassKeys) `orElse` "")
-- 2) Opt_DeriveAnyClass is on
<> (xopt Opt_DeriveAnyClass dflags `orElse` "Try enabling DeriveAnyClass")
* *
{-# LANGUAGE DeriveAnyClass, MultiParamTypeClasses #-}
module T9968 where
class C a b
data X = X deriving (C Int)
......@@ -58,3 +58,4 @@ test('T10561', normal, compile_fail, [''])
test('T10487', extra_clean(['T10487_M.o', 'T10487_M.hi']), multimod_compile, ['T10487', '-v0'])
test('T11148', normal, run_command,
['$MAKE -s --no-print-directory T11148'])
test('T9968', normal, compile, [''])
{-# LANGUAGE DeriveAnyClass #-}
module T9968 where
import Data.Bifunctor
data Blah a b = A a | B b
deriving (Bifunctor)
T9968a.hs:8:13: error:
• Can't make a derived instance of ‘Bifunctor Blah’:
‘Bifunctor’ is not a standard derivable class (Eq, Show, etc.)
The last argument of class ‘Bifunctor’ does not have kind * or (* -> *)
• In the data declaration for ‘Blah’
......@@ -58,3 +58,5 @@ test('T9687', normal, compile_fail, [''])
test('T8984', normal, compile_fail, [''])
test('T10524', normal, compile_fail, [''])
test('T9968a', normal, compile_fail, [''])
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment