#include "HsVersions.h"
-import HsSyn ( HsBinds(..), TyClDecl(..), MonoBinds(..),
- andMonoBindList )
-import RdrHsSyn ( RdrNameMonoBinds )
-import RnHsSyn ( RenamedHsBinds, RenamedTyClDecl, RenamedHsPred )
+import HsSyn
import CmdLineOpts ( DynFlag(..) )
-import Generics ( mkGenericBinds )
+import Generics ( mkTyConGenericBinds )
import TcRnMonad
-import TcEnv ( newDFunName,
- InstInfo(..), pprInstInfo, InstBindings(..),
- pprInstInfoDetails, tcLookupTyCon, tcExtendTyVarEnv
+import TcEnv ( newDFunName, pprInstInfoDetails,
+ InstInfo(..), InstBindings(..),
+ tcLookupClass, tcLookupTyCon, tcExtendTyVarEnv
)
import TcGenDeriv -- Deriv stuff
import InstEnv ( simpleDFunClassTyCon, extendInstEnv )
-import TcHsType ( tcHsPred )
+import TcHsType ( tcHsDeriv )
import TcSimplify ( tcSimplifyDeriv )
-import RnBinds ( rnMethodBinds, rnTopMonoBinds )
+import RnBinds ( rnMethodBinds, rnTopBinds )
import RnEnv ( bindLocalNames )
-import TcRnMonad ( thenM, returnM, mapAndUnzipM )
-import HscTypes ( DFunId, FixityEnv, typeEnvTyCons )
+import HscTypes ( DFunId, FixityEnv )
-import BasicTypes ( NewOrData(..) )
import Class ( className, classArity, classKey, classTyVars, classSCTheta, Class )
import Subst ( mkTyVarSubst, substTheta )
import ErrUtils ( dumpIfSet_dyn )
import MkId ( mkDictFunId )
-import DataCon ( dataConOrigArgTys, isNullaryDataCon, isExistentialDataCon )
+import DataCon ( isNullaryDataCon, isExistentialDataCon, dataConOrigArgTys )
import Maybes ( catMaybes )
+import RdrName ( RdrName )
import Name ( Name, getSrcLoc )
import NameSet ( NameSet, emptyNameSet, duDefs )
-import Unique ( Unique, getUnique )
-
-import TyCon ( tyConTyVars, tyConDataCons, tyConArity,
- tyConTheta, isProductTyCon, isDataTyCon,
+import Kind ( splitKindFunTys )
+import TyCon ( tyConTyVars, tyConDataCons, tyConArity, tyConHasGenerics,
+ tyConTheta, isProductTyCon, isDataTyCon, newTyConRhs,
isEnumerationTyCon, isRecursiveTyCon, TyCon
)
-import TcType ( TcType, ThetaType, mkTyVarTy, mkTyVarTys, mkTyConApp,
- getClassPredTys_maybe, tcTyConAppTyCon,
- isUnLiftedType, mkClassPred, tyVarsOfTypes, tcSplitFunTys, isTypeKind,
+import TcType ( TcType, ThetaType, mkTyVarTys, mkTyConApp, tcTyConAppTyCon,
+ isUnLiftedType, mkClassPred, tyVarsOfTypes, isArgTypeKind,
tcEqTypes, tcSplitAppTys, mkAppTys, tcSplitDFunTy )
import Var ( TyVar, tyVarKind, idType, varName )
import VarSet ( mkVarSet, subVarSet )
import PrelNames
+import SrcLoc ( srcLocSpan, Located(..) )
import Util ( zipWithEqual, sortLt, notNull )
-import ListSetOps ( removeDups, assoc )
+import ListSetOps ( removeDups, assocMaybe )
import Outputable
+import Bag
\end{code}
%************************************************************************
gives rise to the constraints for that context -- or at least the thinned
version. So now all classes are "offending".
+[Newtype deriving]
+~~~~~~~~~~~~~~~~~~
+Consider this:
+ class C a b
+ instance C [a] Char
+ newtype T = T Char deriving( C [a] )
+
+Notice the free 'a' in the deriving. We have to fill this out to
+ newtype T = T Char deriving( forall a. C [a] )
+
+And then translate it to:
+ instance C [a] Char => C [a] T where ...
+
+
%************************************************************************
%************************************************************************
\begin{code}
-tcDeriving :: [RenamedTyClDecl] -- All type constructors
+tcDeriving :: [LTyClDecl Name] -- All type constructors
-> TcM ([InstInfo], -- The generated "instance decls"
- RenamedHsBinds, -- Extra generated top-level bindings
+ [HsBindGroup Name], -- Extra generated top-level bindings
NameSet) -- Binders to keep alive
tcDeriving tycl_decls
- = recoverM (returnM ([], EmptyBinds, emptyNameSet)) $
+ = recoverM (returnM ([], [], emptyNameSet)) $
do { -- Fish the "deriving"-related information out of the TcEnv
-- and make the necessary "equations".
; (ordinary_eqns, newtype_inst_info) <- makeDerivEqns tycl_decls
-- before tacking the "ordinary" ones
-- Generate the generic to/from functions from each type declaration
- ; tcg_env <- getGblEnv
- ; let gen_binds = mkGenericBinds (typeEnvTyCons (tcg_type_env tcg_env))
+ ; gen_binds <- mkGenericBinds tycl_decls
; let inst_info = newtype_inst_info ++ ordinary_inst_info
-- Rename these extra bindings, discarding warnings about unused bindings etc
+ -- Set -fglasgow exts so that we can have type signatures in patterns,
+ -- which is used in the generic binds
; (rn_binds, gen_bndrs)
- <- discardWarnings $ do
- { (rn_deriv, _dus1) <- rnTopMonoBinds deriv_binds []
- ; (rn_gen, dus_gen) <- rnTopMonoBinds gen_binds []
- ; return (rn_deriv `ThenBinds` rn_gen, duDefs dus_gen) }
+ <- discardWarnings $ setOptM Opt_GlasgowExts $ do
+ { (rn_deriv, _dus1) <- rnTopBinds deriv_binds []
+ ; (rn_gen, dus_gen) <- rnTopBinds gen_binds []
+ ; return (rn_deriv ++ rn_gen, duDefs dus_gen) }
; dflags <- getDOpts
; returnM (inst_info, rn_binds, gen_bndrs)
}
where
- ddump_deriving :: [InstInfo] -> RenamedHsBinds -> SDoc
+ ddump_deriving :: [InstInfo] -> [HsBindGroup Name] -> SDoc
ddump_deriving inst_infos extra_binds
- = vcat (map ppr_info inst_infos) $$ ppr extra_binds
-
- ppr_info inst_info = pprInstInfo inst_info $$
- nest 4 (pprInstInfoDetails inst_info)
- -- pprInstInfo doesn't print much: only the type
+ = vcat (map pprInstInfoDetails inst_infos) $$ vcat (map ppr extra_binds)
-----------------------------------------
deriveOrdinaryStuff [] -- Short cut
- = returnM ([], EmptyMonoBinds)
+ = returnM ([], emptyBag)
deriveOrdinaryStuff eqns
= do { -- Take the equation list and solve it, to deliver a list of
; extra_binds <- genTaggeryBinds new_dfuns
-- Done
- ; returnM (inst_infos, andMonoBindList (extra_binds : aux_binds_s)) }
+ ; returnM (inst_infos, unionManyBags (extra_binds : aux_binds_s))
+ }
+
+-----------------------------------------
+mkGenericBinds tycl_decls
+ = do { tcs <- mapM tcLookupTyCon
+ [ tc_name |
+ L _ (TyData { tcdLName = L _ tc_name }) <- tycl_decls]
+ -- We are only interested in the data type declarations
+ ; return (unionManyBags [ mkTyConGenericBinds tc |
+ tc <- tcs, tyConHasGenerics tc ]) }
+ -- And then only in the ones whose 'has-generics' flag is on
\end{code}
all those.
\begin{code}
-makeDerivEqns :: [RenamedTyClDecl]
+makeDerivEqns :: [LTyClDecl Name]
-> TcM ([DerivEqn], -- Ordinary derivings
[InstInfo]) -- Special newtype derivings
returnM (catMaybes maybe_ordinaries, catMaybes maybe_newtypes)
where
------------------------------------------------------------------
- derive_these :: [(NewOrData, Name, RenamedHsPred)]
+ derive_these :: [(NewOrData, Name, LHsType Name)]
-- Find the (nd, TyCon, Pred) pairs that must be `derived'
- -- NB: only source-language decls have deriving, no imported ones do
derive_these = [ (nd, tycon, pred)
- | TyData {tcdND = nd, tcdName = tycon, tcdDerivs = Just preds} <- tycl_decls,
+ | L _ (TyData { tcdND = nd, tcdLName = L _ tycon,
+ tcdDerivs = Just preds }) <- tycl_decls,
pred <- preds ]
------------------------------------------------------------------
- mk_eqn :: (NewOrData, Name, RenamedHsPred) -> TcM (Maybe DerivEqn, Maybe InstInfo)
+ mk_eqn :: (NewOrData, Name, LHsType Name) -> TcM (Maybe DerivEqn, Maybe InstInfo)
-- We swizzle the tyvars and datacons out of the tycon
-- to make the rest of the equation
+ --
+ -- The "deriv_ty" is a LHsType to take account of the fact that for newtype derivign
+ -- we allow deriving (forall a. C [a]).
- mk_eqn (new_or_data, tycon_name, pred)
+ mk_eqn (new_or_data, tycon_name, hs_deriv_ty)
= tcLookupTyCon tycon_name `thenM` \ tycon ->
- addSrcLoc (getSrcLoc tycon) $
+ addSrcSpan (srcLocSpan (getSrcLoc tycon)) $
addErrCtxt (derivCtxt Nothing tycon) $
tcExtendTyVarEnv (tyConTyVars tycon) $ -- Deriving preds may (now) mention
-- the type variables for the type constructor
- tcHsPred pred `thenM` \ pred' ->
- case getClassPredTys_maybe pred' of
- Nothing -> bale_out (malformedPredErr tycon pred)
- Just (clas, tys) -> doptM Opt_GlasgowExts `thenM` \ gla_exts ->
- mk_eqn_help gla_exts new_or_data tycon clas tys
+ tcHsDeriv hs_deriv_ty `thenM` \ (deriv_tvs, clas, tys) ->
+ doptM Opt_GlasgowExts `thenM` \ gla_exts ->
+ mk_eqn_help gla_exts new_or_data tycon deriv_tvs clas tys
------------------------------------------------------------------
- mk_eqn_help gla_exts DataType tycon clas tys
- | Just err <- checkSideConditions gla_exts clas tycon tys
- = bale_out (derivingThingErr clas tys tycon tyvars err)
+ mk_eqn_help gla_exts DataType tycon deriv_tvs clas tys
+ | Just err <- checkSideConditions gla_exts tycon deriv_tvs clas tys
+ = bale_out (derivingThingErr clas tys tycon (tyConTyVars tycon) err)
| otherwise
- = new_dfun_name clas tycon `thenM` \ dfun_name ->
- returnM (Just (dfun_name, clas, tycon, tyvars, constraints), Nothing)
- where
- tyvars = tyConTyVars tycon
- constraints = extra_constraints ++ ordinary_constraints
- -- "extra_constraints": see note [Data decl contexts] above
- extra_constraints = tyConTheta tycon
-
- ordinary_constraints
- | clas `hasKey` typeableClassKey -- For the Typeable class, the constraints
- -- don't involve the constructor ags, only
- -- the tycon tyvars
- -- e.g. data T a b = ...
- -- we want
- -- instance (Typeable a, Typable b)
- -- => Typeable (T a b) where
- = [mkClassPred clas [mkTyVarTy tv] | tv <- tyvars]
- | otherwise
- = [ mkClassPred clas [arg_ty]
- | data_con <- tyConDataCons tycon,
- arg_ty <- dataConOrigArgTys data_con,
- -- Use the same type variables
- -- as the type constructor,
- -- hence no need to instantiate
- not (isUnLiftedType arg_ty) -- No constraints for unlifted types?
- ]
-
- mk_eqn_help gla_exts NewType tycon clas tys
- | can_derive_via_isomorphism && (gla_exts || standard_class gla_exts clas)
+ = do { eqn <- mkDataTypeEqn tycon clas
+ ; returnM (Just eqn, Nothing) }
+
+ mk_eqn_help gla_exts NewType tycon deriv_tvs clas tys
+ | can_derive_via_isomorphism && (gla_exts || std_class_via_iso clas)
= -- Go ahead and use the isomorphism
traceTc (text "newtype deriving:" <+> ppr tycon <+> ppr rep_tys) `thenM_`
new_dfun_name clas tycon `thenM` \ dfun_name ->
returnM (Nothing, Just (InstInfo { iDFunId = mk_dfun dfun_name,
iBinds = NewTypeDerived rep_tys }))
- | standard_class gla_exts clas
- = mk_eqn_help gla_exts DataType tycon clas tys -- Go via bale-out route
+ | std_class gla_exts clas
+ = mk_eqn_help gla_exts DataType tycon deriv_tvs clas tys -- Go via bale-out route
| otherwise -- Non-standard instance
= bale_out (if gla_exts then
where
-- Here is the plan for newtype derivings. We see
-- newtype T a1...an = T (t ak...an) deriving (.., C s1 .. sm, ...)
- -- where aj...an do not occur free in t, and the (C s1 ... sm) is a
- -- *partial applications* of class C with the last parameter missing
+ -- where t is a type,
+ -- ak...an is a suffix of a1..an
+ -- ak...an do not occur free in t,
+ -- (C s1 ... sm) is a *partial applications* of class C
+ -- with the last parameter missing
--
-- We generate the instances
- -- instance C s1 .. sm (t ak...aj) => C s1 .. sm (T a1...aj)
- -- where T a1...aj is the partial application of the LHS of the correct kind
+ -- instance C s1 .. sm (t ak...ap) => C s1 .. sm (T a1...ap)
+ -- where T a1...ap is the partial application of the LHS of the correct kind
+ -- and p >= k
--
-- Running example: newtype T s a = MkT (ST s a) deriving( Monad )
-- instance Monad (ST s) => Monad (T s) where
-- fail = coerce ... (fail @ ST s)
+ -- (Actually we don't need the coerce, because non-rec newtypes are transparent
clas_tyvars = classTyVars clas
kind = tyVarKind (last clas_tyvars)
-- Kind of the thing we want to instance
-- e.g. argument kind of Monad, *->*
- (arg_kinds, _) = tcSplitFunTys kind
+ (arg_kinds, _) = splitKindFunTys kind
n_args_to_drop = length arg_kinds
-- Want to drop 1 arg from (T s a) and (ST s a)
-- to get instance Monad (ST s) => Monad (T s)
-- Note [newtype representation]
- -- We must not use newTyConRep to get the representation
- -- type, because that looks through all intermediate newtypes
- -- To get the RHS of *this* newtype, just look at the data
- -- constructor. For example
+ -- Need newTyConRhs *not* newTyConRep to get the representation
+ -- type, because the latter looks through all intermediate newtypes
+ -- For example
-- newtype B = MkB Int
-- newtype A = MkA B deriving( Num )
-- We want the Num instance of B, *not* the Num instance of Int,
-- when making the Num instance of A!
- tyvars = tyConTyVars tycon
- rep_ty = head (dataConOrigArgTys (head (tyConDataCons tycon)))
+ (tc_tvs, rep_ty) = newTyConRhs tycon
(rep_fn, rep_ty_args) = tcSplitAppTys rep_ty
n_tyvars_to_keep = tyConArity tycon - n_args_to_drop
- tyvars_to_drop = drop n_tyvars_to_keep tyvars
- tyvars_to_keep = take n_tyvars_to_keep tyvars
+ tyvars_to_drop = drop n_tyvars_to_keep tc_tvs
+ tyvars_to_keep = take n_tyvars_to_keep tc_tvs
n_args_to_keep = length rep_ty_args - n_args_to_drop
args_to_drop = drop n_args_to_keep rep_ty_args
-- If there are no tyvars, there's no need
-- to abstract over the dictionaries we need
- dict_args | null tyvars = []
- | otherwise = rep_pred : sc_theta
+ dict_tvs = deriv_tvs ++ tc_tvs
+ dict_args | null dict_tvs = []
+ | otherwise = rep_pred : sc_theta
-- Finally! Here's where we build the dictionary Id
- mk_dfun dfun_name = mkDictFunId dfun_name tyvars dict_args clas inst_tys
+ mk_dfun dfun_name = mkDictFunId dfun_name dict_tvs dict_args clas inst_tys
-------------------------------------------------------------------
-- Figuring out whether we can only do this newtype-deriving thing
-- newtype A = MkA [A]
-- Don't want
-- instance Eq [A] => Eq A !!
-
-- Here's a recursive newtype that's actually OK
-- newtype S1 = S1 [T1 ()]
-- newtype T1 a = T1 (StateT S1 IO a ) deriving( Monad )
-- It's currently rejected. Oh well.
+ -- In fact we generate an instance decl that has method of form
+ -- meth @ instTy = meth @ repTy
+ -- (no coerce's). We'd need a coerce if we wanted to handle
+ -- recursive newtypes too
-- Check that eta reduction is OK
-- (a) the dropped-off args are identical
ptext SLIT("Try -fglasgow-exts for GHC's newtype-deriving extension")])
bale_out err = addErrTc err `thenM_` returnM (Nothing, Nothing)
- standard_class gla_exts clas = key `elem` derivableClassKeys
- || (gla_exts && (key == typeableClassKey || key == dataClassKey))
- where
- key = classKey clas
-
+std_class gla_exts clas
+ = key `elem` derivableClassKeys
+ || (gla_exts && (key == typeableClassKey || key == dataClassKey))
+ where
+ key = classKey clas
+
+std_class_via_iso clas -- These standard classes can be derived for a newtype
+ -- using the isomorphism trick *even if no -fglasgow-exts*
+ = classKey clas `elem` [eqClassKey, ordClassKey, ixClassKey, boundedClassKey]
+ -- Not Read/Show because they respect the type
+ -- Not Enum, becuase newtypes are never in Enum
new_dfun_name clas tycon -- Just a simple wrapper
-- a suitable string; hence the empty type arg list
------------------------------------------------------------------
+mkDataTypeEqn :: TyCon -> Class -> TcM DerivEqn
+mkDataTypeEqn tycon clas
+ | clas `hasKey` typeableClassKey
+ = -- The Typeable class is special in several ways
+ -- data T a b = ... deriving( Typeable )
+ -- gives
+ -- instance Typeable2 T where ...
+ -- Notice that:
+ -- 1. There are no constraints in the instance
+ -- 2. There are no type variables either
+ -- 3. The actual class we want to generate isn't necessarily
+ -- Typeable; it depends on the arity of the type
+ do { real_clas <- tcLookupClass (typeableClassNames !! tyConArity tycon)
+ ; dfun_name <- new_dfun_name real_clas tycon
+ ; return (dfun_name, real_clas, tycon, [], []) }
+
+ | otherwise
+ = do { dfun_name <- new_dfun_name clas tycon
+ ; return (dfun_name, clas, tycon, tyvars, constraints) }
+ where
+ tyvars = tyConTyVars tycon
+ constraints = extra_constraints ++ ordinary_constraints
+ extra_constraints = tyConTheta tycon
+ -- "extra_constraints": see note [Data decl contexts] above
+
+ ordinary_constraints
+ = [ mkClassPred clas [arg_ty]
+ | data_con <- tyConDataCons tycon,
+ arg_ty <- dataConOrigArgTys data_con,
+ -- Use the same type variables
+ -- as the type constructor,
+ -- hence no need to instantiate
+ not (isUnLiftedType arg_ty) -- No constraints for unlifted types?
+ ]
+
+
+------------------------------------------------------------------
-- Check side conditions that dis-allow derivability for particular classes
-- This is *apart* from the newtype-deriving mechanism
-checkSideConditions :: Bool -> Class -> TyCon -> [TcType] -> Maybe SDoc
-checkSideConditions gla_exts clas tycon tys
- | notNull tys
+checkSideConditions :: Bool -> TyCon -> [TyVar] -> Class -> [TcType] -> Maybe SDoc
+checkSideConditions gla_exts tycon deriv_tvs clas tys
+ | notNull deriv_tvs || notNull tys
= Just ty_args_why -- e.g. deriving( Foo s )
| otherwise
= case [cond | (key,cond) <- sideConditions, key == getUnique clas] of
[cond] -> cond (gla_exts, tycon)
other -> pprPanic "checkSideConditions" (ppr clas)
where
- ty_args_why = quotes (ppr (mkClassPred clas tys)) <+> ptext SLIT("is not a class")
+ ty_args_why = quotes (ppr (mkClassPred clas tys)) <+> ptext SLIT("is not a class")
non_std_why clas = quotes (ppr clas) <+> ptext SLIT("is not a derivable class")
(enumClassKey, cond_std `andCond` cond_isEnumeration),
(ixClassKey, cond_std `andCond` (cond_isEnumeration `orCond` cond_isProduct)),
(boundedClassKey, cond_std `andCond` (cond_isEnumeration `orCond` cond_isProduct)),
- (typeableClassKey, cond_glaExts `andCond` cond_allTypeKind),
+ (typeableClassKey, cond_glaExts `andCond` cond_typeableOK),
(dataClassKey, cond_glaExts `andCond` cond_std)
]
where
why = quotes (ppr tycon) <+> ptext SLIT("has more than one constructor")
-cond_allTypeKind :: Condition
-cond_allTypeKind (gla_exts, tycon)
- | all (isTypeKind . tyVarKind) (tyConTyVars tycon) = Nothing
- | otherwise = Just why
+cond_typeableOK :: Condition
+-- OK for Typeable class
+-- Currently: (a) args all of kind *
+-- (b) 7 or fewer args
+cond_typeableOK (gla_exts, tycon)
+ | tyConArity tycon > 7 = Just too_many
+ | not (all (isArgTypeKind . tyVarKind) (tyConTyVars tycon)) = Just bad_kind
+ | otherwise = Nothing
where
- why = quotes (ppr tycon) <+> ptext SLIT("is parameterised over arguments of kind other than `*'")
+ too_many = quotes (ppr tycon) <+> ptext SLIT("has too many arguments")
+ bad_kind = quotes (ppr tycon) <+> ptext SLIT("has arguments of kind other than `*'")
cond_glaExts :: Condition
cond_glaExts (gla_exts, tycon) | gla_exts = Nothing
------------------------------------------------------------------
gen_soln (_, clas, tc,tyvars,deriv_rhs)
- = addSrcLoc (getSrcLoc tc) $
+ = addSrcSpan (srcLocSpan (getSrcLoc tc)) $
addErrCtxt (derivCtxt (Just clas) tc) $
tcSimplifyDeriv tyvars deriv_rhs `thenM` \ theta ->
returnM (sortLt (<) theta) -- Canonicalise before returning the soluction
\item
We use the renamer!!! Reason: we're supposed to be
-producing @RenamedMonoBinds@ for the methods, but that means
+producing @LHsBinds Name@ for the methods, but that means
producing correctly-uniquified code on the fly. This is entirely
possible (the @TcM@ monad has a @UniqueSupply@), but it is painful.
-So, instead, we produce @RdrNameMonoBinds@ then heave 'em through
+So, instead, we produce @MonoBinds RdrName@ then heave 'em through
the renamer. What a great hack!
\end{itemize}
\begin{code}
-- Generate the InstInfo for the required instance,
-- plus any auxiliary bindings required
-genInst :: DFunId -> TcM (InstInfo, RdrNameMonoBinds)
+genInst :: DFunId -> TcM (InstInfo, LHsBinds RdrName)
genInst dfun
= getFixityEnv `thenM` \ fix_env ->
let
(tyvars,_,clas,[ty]) = tcSplitDFunTy (idType dfun)
clas_nm = className clas
tycon = tcTyConAppTyCon ty
- (meth_binds, aux_binds) = assoc "gen_bind:bad derived class"
- gen_list (getUnique clas) fix_env tycon
+ (meth_binds, aux_binds) = genDerivBinds clas fix_env tycon
in
-- Bring the right type variables into
-- scope, and rename the method binds
returnM (InstInfo { iDFunId = dfun, iBinds = VanillaInst rn_meth_binds [] },
aux_binds)
-gen_list :: [(Unique, FixityEnv -> TyCon -> (RdrNameMonoBinds, RdrNameMonoBinds))]
-gen_list = [(eqClassKey, no_aux_binds (ignore_fix_env gen_Eq_binds))
- ,(ordClassKey, no_aux_binds (ignore_fix_env gen_Ord_binds))
- ,(enumClassKey, no_aux_binds (ignore_fix_env gen_Enum_binds))
- ,(boundedClassKey, no_aux_binds (ignore_fix_env gen_Bounded_binds))
- ,(ixClassKey, no_aux_binds (ignore_fix_env gen_Ix_binds))
- ,(typeableClassKey,no_aux_binds (ignore_fix_env gen_Typeable_binds))
- ,(showClassKey, no_aux_binds gen_Show_binds)
- ,(readClassKey, no_aux_binds gen_Read_binds)
- ,(dataClassKey, gen_Data_binds)
- ]
-
- -- no_aux_binds is used for generators that don't
- -- need to produce any auxiliary bindings
-no_aux_binds f fix_env tc = (f fix_env tc, EmptyMonoBinds)
-ignore_fix_env f fix_env tc = f tc
+genDerivBinds clas fix_env tycon
+ | className clas `elem` typeableClassNames
+ = (gen_Typeable_binds tycon, emptyBag)
+
+ | otherwise
+ = case assocMaybe gen_list (getUnique clas) of
+ Just gen_fn -> gen_fn fix_env tycon
+ Nothing -> pprPanic "genDerivBinds: bad derived class" (ppr clas)
+ where
+ gen_list :: [(Unique, FixityEnv -> TyCon -> (LHsBinds RdrName, LHsBinds RdrName))]
+ gen_list = [(eqClassKey, no_aux_binds (ignore_fix_env gen_Eq_binds))
+ ,(ordClassKey, no_aux_binds (ignore_fix_env gen_Ord_binds))
+ ,(enumClassKey, no_aux_binds (ignore_fix_env gen_Enum_binds))
+ ,(boundedClassKey, no_aux_binds (ignore_fix_env gen_Bounded_binds))
+ ,(ixClassKey, no_aux_binds (ignore_fix_env gen_Ix_binds))
+ ,(typeableClassKey,no_aux_binds (ignore_fix_env gen_Typeable_binds))
+ ,(showClassKey, no_aux_binds gen_Show_binds)
+ ,(readClassKey, no_aux_binds gen_Read_binds)
+ ,(dataClassKey, gen_Data_binds)
+ ]
+
+ -- no_aux_binds is used for generators that don't
+ -- need to produce any auxiliary bindings
+ no_aux_binds f fix_env tc = (f fix_env tc, emptyBag)
+ ignore_fix_env f fix_env tc = f tc
\end{code}
If we have a @tag2con@ function, we also generate a @maxtag@ constant.
\begin{code}
-genTaggeryBinds :: [DFunId] -> TcM RdrNameMonoBinds
+genTaggeryBinds :: [DFunId] -> TcM (LHsBinds RdrName)
genTaggeryBinds dfuns
= do { names_so_far <- foldlM do_con2tag [] tycons_of_interest
; nm_alist_etc <- foldlM do_tag2con names_so_far tycons_of_interest
- ; return (andMonoBindList (map gen_tag_n_con_monobind nm_alist_etc)) }
+ ; return (listToBag (map gen_tag_n_con_monobind nm_alist_etc)) }
where
all_CTs = map simpleDFunClassTyCon dfuns
all_tycons = map snd all_CTs
where
pred = mkClassPred clas (tys ++ [mkTyConApp tycon (mkTyVarTys tyvars)])
-malformedPredErr tycon pred = ptext SLIT("Illegal deriving item") <+> ppr pred
-
derivCtxt :: Maybe Class -> TyCon -> SDoc
derivCtxt maybe_cls tycon
= ptext SLIT("When deriving") <+> cls <+> ptext SLIT("for type") <+> quotes (ppr tycon)