summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Scott <ryan.gl.scott@gmail.com>2016-10-06 09:14:49 -0400
committerRyan Scott <ryan.gl.scott@gmail.com>2016-10-06 09:14:49 -0400
commit4a03012aeb4cb6685221b30aea2b1a78145d902b (patch)
tree43c9c13c18d31fa5b421211155355011b0d1403f
parent58ecdf83ff8790b49bdfcba628d189229f81d2a0 (diff)
downloadhaskell-4a03012aeb4cb6685221b30aea2b1a78145d902b.tar.gz
Refactor TcDeriv and TcGenDeriv
Summary: Keeping a promise I made to Simon to clean up these modules. This change splits up the massive `TcDeriv` and `TcGenDeriv` modules into somewhat more manageable pieces. The new modules are: * `TcGenFunctor`: This contains the deriving machinery for `Functor`, `Foldable`, and `Traversable` (which all use the same underlying algorithm). * `TcDerivInfer`: This is the new home for `inferConstraints`, `simplifyInstanceContexts`, and related functions, whose role is to come up with the derived instance context and subsequently simplify it. * `TcDerivUtils`: This is a grab-bag module that contains several error-checking utilities originally in `TcDeriv`, as well as some functions that `TcDeriv` and `TcDerivInfer` both need. The end result is that `TcDeriv` is now less than 1,600 SLOC (originally 2,686 SLOC), and `TcGenDeriv` is now about 2,000 SLOC (originally 2,964). In addition, this also implements a couple of tiny refactorings: * I transformed `type Condition = (DynFlags, TyCon) -> Validity` into `type Condition = DynFlags -> TyCon -> Validity` * I killed the `DerivSpecGeneric` constructor for `DerivSpecMechanism`, and merged its functionality into `DerivSpecStock`. In addition, `hasStockDeriving` now contains key-value pairs for `Generic` and `Generic1`, so they're no longer treated as an awkward special case in `TcDeriv`. Test Plan: ./validate Reviewers: simonpj, austin, bgamari Reviewed By: simonpj Subscribers: thomie, mpickering Differential Revision: https://phabricator.haskell.org/D2568
-rw-r--r--compiler/ghc.cabal.in3
-rw-r--r--compiler/typecheck/TcDeriv.hs1168
-rw-r--r--compiler/typecheck/TcDerivInfer.hs653
-rw-r--r--compiler/typecheck/TcDerivUtils.hs610
-rw-r--r--compiler/typecheck/TcGenDeriv.hs923
-rw-r--r--compiler/typecheck/TcGenFunctor.hs875
-rw-r--r--compiler/typecheck/TcGenGenerics.hs1
7 files changed, 2184 insertions, 2049 deletions
diff --git a/compiler/ghc.cabal.in b/compiler/ghc.cabal.in
index 3d75dae0c1..ab72b455cf 100644
--- a/compiler/ghc.cabal.in
+++ b/compiler/ghc.cabal.in
@@ -405,10 +405,13 @@ Library
TcClassDcl
TcDefaults
TcDeriv
+ TcDerivInfer
+ TcDerivUtils
TcEnv
TcExpr
TcForeign
TcGenDeriv
+ TcGenFunctor
TcGenGenerics
TcHsSyn
TcHsType
diff --git a/compiler/typecheck/TcDeriv.hs b/compiler/typecheck/TcDeriv.hs
index c5c8387196..04202ed79e 100644
--- a/compiler/typecheck/TcDeriv.hs
+++ b/compiler/typecheck/TcDeriv.hs
@@ -7,7 +7,6 @@ Handles @deriving@ clauses on @data@ declarations.
-}
{-# LANGUAGE CPP #-}
-{-# LANGUAGE ImplicitParams #-}
module TcDeriv ( tcDeriving, DerivInfo(..), mkDerivInfos ) where
@@ -18,19 +17,17 @@ import DynFlags
import TcRnMonad
import FamInst
-import TcErrors( reportAllUnsolved )
-import TcValidity( validDerivPred, allDistinctTyVars )
+import TcDerivInfer
+import TcDerivUtils
+import TcValidity( allDistinctTyVars )
import TcClassDcl( tcATDefault, tcMkDeclCtxt )
import TcEnv
import TcGenDeriv -- Deriv stuff
-import TcGenGenerics
import InstEnv
import Inst
import FamInstEnv
import TcHsType
import TcMType
-import TcSimplify
-import TcUnify( buildImplicationFor )
import RnNames( extendGlobalRdrEnvRn )
import RnBinds
@@ -54,7 +51,6 @@ import Var
import VarEnv
import VarSet
import PrelNames
-import THNames ( liftClassKey )
import SrcLoc
import Util
import Outputable
@@ -84,81 +80,6 @@ Overall plan
3. Add the derived bindings, generating InstInfos
-}
--- DerivSpec is purely local to this module
-data DerivSpec theta = DS { ds_loc :: SrcSpan
- , ds_name :: Name -- DFun name
- , ds_tvs :: [TyVar]
- , ds_theta :: theta
- , ds_cls :: Class
- , ds_tys :: [Type]
- , ds_tc :: TyCon
- , ds_overlap :: Maybe OverlapMode
- , ds_mechanism :: DerivSpecMechanism }
- -- This spec implies a dfun declaration of the form
- -- df :: forall tvs. theta => C tys
- -- The Name is the name for the DFun we'll build
- -- The tyvars bind all the variables in the theta
- -- For type families, the tycon in
- -- in ds_tys is the *family* tycon
- -- in ds_tc is the *representation* type
- -- For non-family tycons, both are the same
-
- -- the theta is either the given and final theta, in standalone deriving,
- -- or the not-yet-simplified list of constraints together with their origin
-
- -- ds_mechanism specifies the means by which GHC derives the instance.
- -- See Note [Deriving strategies]
-
-{-
-Example:
-
- newtype instance T [a] = MkT (Tree a) deriving( C s )
-==>
- axiom T [a] = :RTList a
- axiom :RTList a = Tree a
-
- DS { ds_tvs = [a,s], ds_cls = C, ds_tys = [s, T [a]]
- , ds_tc = :RTList, ds_mechanism = DerivSpecNewtype (Tree a) }
--}
-
--- What action to take in order to derive a class instance.
--- See Note [Deriving strategies]
--- NB: DerivSpecMechanism is purely local to this module
-data DerivSpecMechanism
- = DerivSpecStock -- "Standard" classes (except for Generic(1), which is
- -- covered by the special case of DerivSpecGeneric)
- (SrcSpan -> TyCon -> TcM (LHsBinds RdrName, BagDerivStuff))
-
- | DerivSpecGeneric -- -XDeriveGeneric
- (TyCon -> [Type] -> TcM (LHsBinds RdrName, FamInst))
-
- | DerivSpecNewtype -- -XGeneralizedNewtypeDeriving
- Type -- ^ The newtype rep type
-
- | DerivSpecAnyClass -- -XDeriveAnyClass
-
-type DerivContext = Maybe ThetaType
- -- Nothing <=> Vanilla deriving; infer the context of the instance decl
- -- Just theta <=> Standalone deriving: context supplied by programmer
-
--- | A 'PredType' annotated with the origin of the constraint 'CtOrigin',
--- and whether or the constraint deals in types or kinds.
-data PredOrigin = PredOrigin PredType CtOrigin TypeOrKind
-type ThetaOrigin = [PredOrigin]
-
-mkPredOrigin :: CtOrigin -> TypeOrKind -> PredType -> PredOrigin
-mkPredOrigin origin t_or_k pred = PredOrigin pred origin t_or_k
-
-mkThetaOrigin :: CtOrigin -> TypeOrKind -> ThetaType -> ThetaOrigin
-mkThetaOrigin origin t_or_k = map (mkPredOrigin origin t_or_k)
-
-substPredOrigin :: HasCallStack => TCvSubst -> PredOrigin -> PredOrigin
-substPredOrigin subst (PredOrigin pred origin t_or_k)
- = PredOrigin (substTy subst pred) origin t_or_k
-
-substThetaOrigin :: HasCallStack => TCvSubst -> ThetaOrigin -> ThetaOrigin
-substThetaOrigin subst = map (substPredOrigin subst)
-
data EarlyDerivSpec = InferTheta (DerivSpec ThetaOrigin)
| GivenTheta (DerivSpec ThetaType)
-- InferTheta ds => the context for the instance should be inferred
@@ -170,7 +91,7 @@ data EarlyDerivSpec = InferTheta (DerivSpec ThetaOrigin)
--
-- GivenTheta ds => the exact context for the instance is supplied
-- by the programmer; it is ds_theta
- -- See Note [Inferring the instance context]
+ -- See Note [Inferring the instance context] in TcDerivInfer
earlyDSLoc :: EarlyDerivSpec -> SrcSpan
earlyDSLoc (InferTheta spec) = ds_loc spec
@@ -183,83 +104,11 @@ splitEarlyDerivSpec (InferTheta spec : specs) =
splitEarlyDerivSpec (GivenTheta spec : specs) =
case splitEarlyDerivSpec specs of (is, gs) -> (is, spec : gs)
-pprDerivSpec :: Outputable theta => DerivSpec theta -> SDoc
-pprDerivSpec (DS { ds_loc = l, ds_name = n, ds_tvs = tvs,
- ds_cls = c, ds_tys = tys, ds_theta = rhs })
- = hang (text "DerivSpec")
- 2 (vcat [ text "ds_loc =" <+> ppr l
- , text "ds_name =" <+> ppr n
- , text "ds_tvs =" <+> ppr tvs
- , text "ds_cls =" <+> ppr c
- , text "ds_tys =" <+> ppr tys
- , text "ds_theta =" <+> ppr rhs ])
-
-instance Outputable theta => Outputable (DerivSpec theta) where
- ppr = pprDerivSpec
-
instance Outputable EarlyDerivSpec where
ppr (InferTheta spec) = ppr spec <+> text "(Infer)"
ppr (GivenTheta spec) = ppr spec <+> text "(Given)"
-instance Outputable PredOrigin where
- ppr (PredOrigin ty _ _) = ppr ty -- The origin is not so interesting when debugging
-
-{- Note [Inferring the instance context]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-There are two sorts of 'deriving':
-
- * InferTheta: the deriving clause for a data type
- data T a = T1 a deriving( Eq )
- Here we must infer an instance context,
- and generate instance declaration
- instance Eq a => Eq (T a) where ...
-
- * CheckTheta: standalone deriving
- deriving instance Eq a => Eq (T a)
- Here we only need to fill in the bindings;
- the instance context is user-supplied
-
-For a deriving clause (InferTheta) we must figure out the
-instance context (inferConstraints). Suppose we are inferring
-the instance context for
- C t1 .. tn (T s1 .. sm)
-There are two cases
-
- * (T s1 .. sm) :: * (the normal case)
- Then we behave like Eq and guess (C t1 .. tn t)
- for each data constructor arg of type t. More
- details below.
-
- * (T s1 .. sm) :: * -> * (the functor-like case)
- Then we behave like Functor.
-
-In both cases we produce a bunch of un-simplified constraints
-and them simplify them in simplifyInstanceContexts; see
-Note [Simplifying the instance context].
-
-In the functor-like case, we may need to unify some kind variables with * in
-order for the generated instance to be well-kinded. An example from
-Trac #10524:
-
- newtype Compose (f :: k2 -> *) (g :: k1 -> k2) (a :: k1)
- = Compose (f (g a)) deriving Functor
-
-Earlier in the deriving pipeline, GHC unifies the kind of Compose f g
-(k1 -> *) with the kind of Functor's argument (* -> *), so k1 := *. But this
-alone isn't enough, since k2 wasn't unified with *:
-
- instance (Functor (f :: k2 -> *), Functor (g :: * -> k2)) =>
- Functor (Compose f g) where ...
-
-The two Functor constraints are ill-kinded. To ensure this doesn't happen, we:
-
- 1. Collect all of a datatype's subtypes which require functor-like
- constraints.
- 2. For each subtype, create a substitution by unifying the subtype's kind
- with (* -> *).
- 3. Compose all the substitutions into one, then apply that substitution to
- all of the in-scope type variables and the instance types.
-
+{-
Note [Data decl contexts]
~~~~~~~~~~~~~~~~~~~~~~~~~
Consider
@@ -1088,12 +937,7 @@ mk_eqn_stock dflags mtheta cls cls_tys rep_tc go_for_it bale_out
mk_eqn_stock' :: Class -> (DerivSpecMechanism -> TcRn EarlyDerivSpec)
-> TcRn EarlyDerivSpec
mk_eqn_stock' cls go_for_it
- | let ck = classKey cls
- , ck `elem` [genClassKey, gen1ClassKey]
- = let gk = if ck == genClassKey then Gen0 else Gen1
- in go_for_it . DerivSpecGeneric . gen_Generic_binds $ gk
-
- | otherwise = go_for_it $ case hasStockDeriving cls of
+ = go_for_it $ case hasStockDeriving cls of
Just gen_fn -> DerivSpecStock gen_fn
Nothing ->
pprPanic "mk_eqn_stock': Not a stock class!" (ppr cls)
@@ -1119,620 +963,7 @@ mk_eqn_no_mechanism dflags mtheta cls cls_tys rep_tc go_for_it bale_out
CanDerive -> mk_eqn_stock' cls go_for_it
DerivableViaInstance -> go_for_it DerivSpecAnyClass
-
-----------------------
-
-inferConstraints :: [TyVar] -> Class -> [TcType] -> TcType
- -> TyCon -> [TcType]
- -> (ThetaOrigin -> [TyVar] -> [TcType] -> TcM a)
- -> TcM a
--- inferConstraints figures out the constraints needed for the
--- instance declaration generated by a 'deriving' clause on a
--- data type declaration. It also returns the new in-scope type
--- variables and instance types, in case they were changed due to
--- the presence of functor-like constraints.
--- See Note [Inferring the instance context]
-
--- e.g. inferConstraints
--- C Int (T [a]) -- Class and inst_tys
--- :RTList a -- Rep tycon and its arg tys
--- where T [a] ~R :RTList a
---
--- Generate a sufficiently large set of constraints that typechecking the
--- generated method definitions should succeed. This set will be simplified
--- before being used in the instance declaration
-inferConstraints tvs main_cls cls_tys inst_ty rep_tc rep_tc_args mkTheta
- | is_generic -- Generic constraints are easy
- = mkTheta [] tvs inst_tys
-
- | is_generic1 -- Generic1 needs Functor
- = ASSERT( length rep_tc_tvs > 0 ) -- See Note [Getting base classes]
- ASSERT( length cls_tys == 1 ) -- Generic1 has a single kind variable
- do { functorClass <- tcLookupClass functorClassName
- ; con_arg_constraints (get_gen1_constraints functorClass) mkTheta }
-
- | otherwise -- The others are a bit more complicated
- = ASSERT2( equalLength rep_tc_tvs all_rep_tc_args
- , ppr main_cls <+> ppr rep_tc
- $$ ppr rep_tc_tvs $$ ppr all_rep_tc_args )
- con_arg_constraints get_std_constrained_tys
- $ \arg_constraints tvs' inst_tys' ->
- do { traceTc "inferConstraints" $ vcat
- [ ppr main_cls <+> ppr inst_tys'
- , ppr arg_constraints
- ]
- ; mkTheta (stupid_constraints ++ extra_constraints
- ++ sc_constraints ++ arg_constraints)
- tvs' inst_tys' }
- where
- tc_binders = tyConBinders rep_tc
- choose_level bndr
- | isNamedTyConBinder bndr = KindLevel
- | otherwise = TypeLevel
- t_or_ks = map choose_level tc_binders ++ repeat TypeLevel
- -- want to report *kind* errors when possible
-
- -- Constraints arising from the arguments of each constructor
- con_arg_constraints :: (CtOrigin -> TypeOrKind
- -> Type
- -> [(ThetaOrigin, Maybe TCvSubst)])
- -> (ThetaOrigin -> [TyVar] -> [TcType] -> TcM a)
- -> TcM a
- con_arg_constraints get_arg_constraints mkTheta
- = let (predss, mbSubsts) = unzip
- [ preds_and_mbSubst
- | data_con <- tyConDataCons rep_tc
- , (arg_n, arg_t_or_k, arg_ty)
- <- zip3 [1..] t_or_ks $
- dataConInstOrigArgTys data_con all_rep_tc_args
- -- No constraints for unlifted types
- -- See Note [Deriving and unboxed types]
- , not (isUnliftedType arg_ty)
- , let orig = DerivOriginDC data_con arg_n
- , preds_and_mbSubst <- get_arg_constraints orig arg_t_or_k arg_ty
- ]
- preds = concat predss
- -- If the constraints require a subtype to be of kind (* -> *)
- -- (which is the case for functor-like constraints), then we
- -- explicitly unify the subtype's kinds with (* -> *).
- -- See Note [Inferring the instance context]
- subst = foldl' composeTCvSubst
- emptyTCvSubst (catMaybes mbSubsts)
- unmapped_tvs = filter (\v -> v `notElemTCvSubst` subst
- && not (v `isInScope` subst)) tvs
- (subst', _) = mapAccumL substTyVarBndr subst unmapped_tvs
- preds' = substThetaOrigin subst' preds
- inst_tys' = substTys subst' inst_tys
- tvs' = tyCoVarsOfTypesWellScoped inst_tys'
- in mkTheta preds' tvs' inst_tys'
-
- is_generic = main_cls `hasKey` genClassKey
- is_generic1 = main_cls `hasKey` gen1ClassKey
- -- is_functor_like: see Note [Inferring the instance context]
- is_functor_like = typeKind inst_ty `tcEqKind` typeToTypeKind
- || is_generic1 -- Technically, Generic1 requires a type of
- -- kind (k -> *), not (* -> *), but we still
- -- label it "functor-like" to make sure
- -- all_rep_tc_args has all the necessary type
- -- variables it needs to function.
-
- get_gen1_constraints :: Class -> CtOrigin -> TypeOrKind -> Type
- -> [(ThetaOrigin, Maybe TCvSubst)]
- get_gen1_constraints functor_cls orig t_or_k ty
- = mk_functor_like_constraints orig t_or_k functor_cls $
- get_gen1_constrained_tys last_tv ty
-
- get_std_constrained_tys :: CtOrigin -> TypeOrKind -> Type
- -> [(ThetaOrigin, Maybe TCvSubst)]
- get_std_constrained_tys orig t_or_k ty
- | is_functor_like = mk_functor_like_constraints orig t_or_k main_cls $
- deepSubtypesContaining last_tv ty
- | otherwise = [( [mk_cls_pred orig t_or_k main_cls ty]
- , Nothing )]
-
- mk_functor_like_constraints :: CtOrigin -> TypeOrKind
- -> Class -> [Type]
- -> [(ThetaOrigin, Maybe TCvSubst)]
- -- 'cls' is usually main_cls (Functor or Traversable etc), but if
- -- main_cls = Generic1, then 'cls' can be Functor; see get_gen1_constraints
- --
- -- For each type, generate two constraints, [cls ty, kind(ty) ~ (*->*)],
- -- and a kind substitution that results from unifying kind(ty) with * -> *.
- -- If the unification is successful, it will ensure that the resulting
- -- instance is well kinded. If not, the second constraint will result
- -- in an error message which points out the kind mismatch.
- -- See Note [Inferring the instance context]
- mk_functor_like_constraints orig t_or_k cls
- = map $ \ty -> let ki = typeKind ty in
- ( [ mk_cls_pred orig t_or_k cls ty
- , mkPredOrigin orig KindLevel
- (mkPrimEqPred ki typeToTypeKind) ]
- , tcUnifyTy ki typeToTypeKind
- )
-
- rep_tc_tvs = tyConTyVars rep_tc
- last_tv = last rep_tc_tvs
- all_rep_tc_args | is_functor_like = rep_tc_args ++ [mkTyVarTy last_tv]
- | otherwise = rep_tc_args
-
- -- Constraints arising from superclasses
- -- See Note [Superclasses of derived instance]
- cls_tvs = classTyVars main_cls
- inst_tys = cls_tys ++ [inst_ty]
- sc_constraints = ASSERT2( equalLength cls_tvs inst_tys, ppr main_cls <+> ppr rep_tc)
- mkThetaOrigin DerivOrigin TypeLevel $
- substTheta cls_subst (classSCTheta main_cls)
- cls_subst = ASSERT( equalLength cls_tvs inst_tys )
- zipTvSubst cls_tvs inst_tys
-
- -- Stupid constraints
- stupid_constraints = mkThetaOrigin DerivOrigin TypeLevel $
- substTheta tc_subst (tyConStupidTheta rep_tc)
- tc_subst = ASSERT( equalLength rep_tc_tvs all_rep_tc_args )
- zipTvSubst rep_tc_tvs all_rep_tc_args
-
- -- Extra Data constraints
- -- The Data class (only) requires that for
- -- instance (...) => Data (T t1 t2)
- -- IF t1:*, t2:*
- -- THEN (Data t1, Data t2) are among the (...) constraints
- -- Reason: when the IF holds, we generate a method
- -- dataCast2 f = gcast2 f
- -- and we need the Data constraints to typecheck the method
- extra_constraints
- | main_cls `hasKey` dataClassKey
- , all (isLiftedTypeKind . typeKind) rep_tc_args
- = [ mk_cls_pred DerivOrigin t_or_k main_cls ty
- | (t_or_k, ty) <- zip t_or_ks rep_tc_args]
- | otherwise
- = []
-
- mk_cls_pred orig t_or_k cls ty -- Don't forget to apply to cls_tys' too
- = mkPredOrigin orig t_or_k (mkClassPred cls (cls_tys' ++ [ty]))
- cls_tys' | is_generic1 = [] -- In the awkward Generic1 case, cls_tys'
- -- should be empty, since we are applying the
- -- class Functor.
- | otherwise = cls_tys
-
-{- Note [Getting base classes]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Functor and Typeable are defined in package 'base', and that is not available
-when compiling 'ghc-prim'. So we must be careful that 'deriving' for stuff in
-ghc-prim does not use Functor or Typeable implicitly via these lookups.
-
-Note [Deriving and unboxed types]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We have some special hacks to support things like
- data T = MkT Int# deriving ( Show )
-
-Specifically, we use TcGenDeriv.box to box the Int# into an Int
-(which we know how to show), and append a '#'. Parenthesis are not required
-for unboxed values (`MkT -3#` is a valid expression).
-
-Note [Deriving any class]
-~~~~~~~~~~~~~~~~~~~~~~~~~
-Classic uses of a deriving clause, or a standalone-deriving declaration, are
-for:
- * a stock class like Eq or Show, for which GHC knows how to generate
- the instance code
- * a newtype, via the mechanism enabled by GeneralizedNewtypeDeriving
-
-The DeriveAnyClass extension adds a third way to derive instances, based on
-empty instance declarations.
-
-The canonical use case is in combination with GHC.Generics and default method
-signatures. These allow us to have instance declarations being empty, but still
-useful, e.g.
-
- data T a = ...blah..blah... deriving( Generic )
- instance C a => C (T a) -- No 'where' clause
-
-where C is some "random" user-defined class.
-
-This boilerplate code can be replaced by the more compact
-
- data T a = ...blah..blah... deriving( Generic, C )
-
-if DeriveAnyClass is enabled.
-
-This is not restricted to Generics; any class can be derived, simply giving
-rise to an empty instance.
-
-Unfortunately, it is not clear how to determine the context (when using a
-deriving clause; in standalone deriving, the user provides the context).
-GHC uses the same heuristic for figuring out the class context that it uses for
-Eq in the case of *-kinded classes, and for Functor in the case of
-* -> *-kinded classes. That may not be optimal or even wrong. But in such
-cases, standalone deriving can still be used.
--}
-
-------------------------------------------------------------------
--- Check side conditions that dis-allow derivability for particular classes
--- This is *apart* from the newtype-deriving mechanism
---
--- Here we get the representation tycon in case of family instances as it has
--- the data constructors - but we need to be careful to fall back to the
--- family tycon (with indexes) in error messages.
-
-data DerivStatus = CanDerive -- Stock class, can derive
- | DerivableClassError SDoc -- Stock class, but can't do it
- | DerivableViaInstance -- See Note [Deriving any class]
- | NonDerivableClass SDoc -- Non-stock class
-
--- A stock class is one either defined in the Haskell report or for which GHC
--- otherwise knows how to generate code for (possibly requiring the use of a
--- language extension), such as Eq, Ord, Ix, Data, Generic, etc.
-
-checkSideConditions :: DynFlags -> DerivContext -> Class -> [TcType]
- -> TyCon -- tycon
- -> DerivStatus
-checkSideConditions dflags mtheta cls cls_tys rep_tc
- | Just cond <- sideConditions mtheta cls
- = case (cond (dflags, rep_tc)) of
- NotValid err -> DerivableClassError err -- Class-specific error
- IsValid | null (filterOutInvisibleTypes (classTyCon cls) cls_tys)
- -> CanDerive
- -- All stock derivable classes are unary in the sense that
- -- there should be not types in cls_tys (i.e., no type args
- -- other than last). Note that cls_types can contain
- -- invisible types as well (e.g., for Generic1, which is
- -- poly-kinded), so make sure those are not counted.
- | otherwise -> DerivableClassError (classArgsErr cls cls_tys)
- -- e.g. deriving( Eq s )
-
- | Just err <- canDeriveAnyClass dflags rep_tc cls
- = NonDerivableClass err -- DeriveAnyClass does not work
-
- | otherwise
- = DerivableViaInstance -- DeriveAnyClass should work
-
-
-classArgsErr :: Class -> [Type] -> SDoc
-classArgsErr cls cls_tys = quotes (ppr (mkClassPred cls cls_tys)) <+> text "is not a class"
-
-nonUnaryErr :: LHsSigType Name -> SDoc
-nonUnaryErr ct = quotes (ppr ct)
- <+> text "is not a unary constraint, as expected by a deriving clause"
-
-nonStdErr :: Class -> SDoc
-nonStdErr cls =
- quotes (ppr cls)
- <+> text "is not a stock derivable class (Eq, Show, etc.)"
-
-gndNonNewtypeErr :: SDoc
-gndNonNewtypeErr =
- text "GeneralizedNewtypeDeriving cannot be used on non-newtypes"
-
--- Side conditions (whether the datatype must have at least one constructor,
--- required language extensions, etc.) for using GHC's stock deriving
--- mechanism on certain classes (as opposed to classes that require
--- GeneralizedNewtypeDeriving or DeriveAnyClass). Returns Nothing for a
--- class for which stock deriving isn't possible.
---
--- NB: The classes listed below should be in sync with the ones listed in the
--- definition of hasStockDeriving in TcGenDeriv (except for Generic(1),
--- which are handled specially). If you add new class to sideConditions,
--- make sure to update hasStockDeriving as well!
-sideConditions :: DerivContext -> Class -> Maybe Condition
-sideConditions mtheta cls
- | cls_key == eqClassKey = Just (cond_std `andCond` cond_args cls)
- | cls_key == ordClassKey = Just (cond_std `andCond` cond_args cls)
- | cls_key == showClassKey = Just (cond_std `andCond` cond_args cls)
- | cls_key == readClassKey = Just (cond_std `andCond` cond_args cls)
- | cls_key == enumClassKey = Just (cond_std `andCond` cond_isEnumeration)
- | cls_key == ixClassKey = Just (cond_std `andCond` cond_enumOrProduct cls)
- | cls_key == boundedClassKey = Just (cond_std `andCond` cond_enumOrProduct cls)
- | cls_key == dataClassKey = Just (checkFlag LangExt.DeriveDataTypeable `andCond`
- cond_std `andCond`
- cond_args cls)
- | cls_key == functorClassKey = Just (checkFlag LangExt.DeriveFunctor `andCond`
- cond_vanilla `andCond`
- cond_functorOK True False)
- | cls_key == foldableClassKey = Just (checkFlag LangExt.DeriveFoldable `andCond`
- cond_vanilla `andCond`
- cond_functorOK False True)
- -- Functor/Fold/Trav works ok
- -- for rank-n types
- | cls_key == traversableClassKey = Just (checkFlag LangExt.DeriveTraversable `andCond`
- cond_vanilla `andCond`
- cond_functorOK False False)
- | cls_key == genClassKey = Just (checkFlag LangExt.DeriveGeneric `andCond`
- cond_vanilla `andCond`
- cond_RepresentableOk)
- | cls_key == gen1ClassKey = Just (checkFlag LangExt.DeriveGeneric `andCond`
- cond_vanilla `andCond`
- cond_Representable1Ok)
- | cls_key == liftClassKey = Just (checkFlag LangExt.DeriveLift `andCond`
- cond_vanilla `andCond`
- cond_args cls)
- | otherwise = Nothing
- where
- cls_key = getUnique cls
- cond_std = cond_stdOK mtheta False -- Vanilla data constructors, at least one,
- -- and monotype arguments
- cond_vanilla = cond_stdOK mtheta True -- Vanilla data constructors but
- -- allow no data cons or polytype arguments
-
-canDeriveAnyClass :: DynFlags -> TyCon -> Class -> Maybe SDoc
--- Nothing: we can (try to) derive it via an empty instance declaration
--- Just s: we can't, reason s
--- Precondition: the class is not one of the standard ones
-canDeriveAnyClass dflags _tycon clas
- | not (xopt LangExt.DeriveAnyClass dflags)
- = Just (text "Try enabling DeriveAnyClass")
- | not (any (target_kind `tcEqKind`) [ liftedTypeKind, typeToTypeKind ])
- = Just (text "The last argument of class" <+> quotes (ppr clas)
- <+> text "does not have kind * or (* -> *)")
- | otherwise
- = Nothing -- OK!
- where
- -- We are making an instance (C t1 .. tn (T s1 .. sm))
- -- and we can only do so if the kind of C's last argument
- -- is * or (* -> *). Because only then can we make a reasonable
- -- guess at the instance context
- target_kind = tyVarKind (last (classTyVars clas))
-
-typeToTypeKind :: Kind
-typeToTypeKind = liftedTypeKind `mkFunTy` liftedTypeKind
-
-type Condition = (DynFlags, TyCon) -> Validity
- -- TyCon is the *representation* tycon if the data type is an indexed one
- -- Nothing => OK
-
-orCond :: Condition -> Condition -> Condition
-orCond c1 c2 tc
- = case (c1 tc, c2 tc) of
- (IsValid, _) -> IsValid -- c1 succeeds
- (_, IsValid) -> IsValid -- c21 succeeds
- (NotValid x, NotValid y) -> NotValid (x $$ text " or" $$ y)
- -- Both fail
-
-andCond :: Condition -> Condition -> Condition
-andCond c1 c2 tc = c1 tc `andValid` c2 tc
-
-cond_stdOK :: DerivContext -- Says whether this is standalone deriving or not;
- -- if standalone, we just say "yes, go for it"
- -> Bool -- True <=> permissive: allow higher rank
- -- args and no data constructors
- -> Condition
-cond_stdOK (Just _) _ _
- = IsValid -- Don't check these conservative conditions for
- -- standalone deriving; just generate the code
- -- and let the typechecker handle the result
-cond_stdOK Nothing permissive (_, rep_tc)
- | null data_cons
- , not permissive = NotValid (no_cons_why rep_tc $$ suggestion)
- | not (null con_whys) = NotValid (vcat con_whys $$ suggestion)
- | otherwise = IsValid
- where
- suggestion = text "Possible fix: use a standalone deriving declaration instead"
- data_cons = tyConDataCons rep_tc
- con_whys = getInvalids (map check_con data_cons)
-
- check_con :: DataCon -> Validity
- check_con con
- | not (null eq_spec)
- = bad "is a GADT"
- | not (null ex_tvs)
- = bad "has existential type variables in its type"
- | not (null theta)
- = bad "has constraints in its type"
- | not (permissive || all isTauTy (dataConOrigArgTys con))
- = bad "has a higher-rank type"
- | otherwise
- = IsValid
- where
- (_, ex_tvs, eq_spec, theta, _, _) = dataConFullSig con
- bad msg = NotValid (badCon con (text msg))
-
-no_cons_why :: TyCon -> SDoc
-no_cons_why rep_tc = quotes (pprSourceTyCon rep_tc) <+>
- text "must have at least one data constructor"
-
-cond_RepresentableOk :: Condition
-cond_RepresentableOk (_, tc) = canDoGenerics tc
-
-cond_Representable1Ok :: Condition
-cond_Representable1Ok (_, tc) = canDoGenerics1 tc
-
-cond_enumOrProduct :: Class -> Condition
-cond_enumOrProduct cls = cond_isEnumeration `orCond`
- (cond_isProduct `andCond` cond_args cls)
-
-cond_args :: Class -> Condition
--- For some classes (eg Eq, Ord) we allow unlifted arg types
--- by generating specialised code. For others (eg Data) we don't.
-cond_args cls (_, tc)
- = case bad_args of
- [] -> IsValid
- (ty:_) -> NotValid (hang (text "Don't know how to derive" <+> quotes (ppr cls))
- 2 (text "for type" <+> quotes (ppr ty)))
- where
- bad_args = [ arg_ty | con <- tyConDataCons tc
- , arg_ty <- dataConOrigArgTys con
- , isUnliftedType arg_ty
- , not (ok_ty arg_ty) ]
-
- cls_key = classKey cls
- ok_ty arg_ty
- | cls_key == eqClassKey = check_in arg_ty ordOpTbl
- | cls_key == ordClassKey = check_in arg_ty ordOpTbl
- | cls_key == showClassKey = check_in arg_ty boxConTbl
- | cls_key == liftClassKey = check_in arg_ty litConTbl
- | otherwise = False -- Read, Ix etc
-
- check_in :: Type -> [(Type,a)] -> Bool
- check_in arg_ty tbl = any (eqType arg_ty . fst) tbl
-
-
-cond_isEnumeration :: Condition
-cond_isEnumeration (_, rep_tc)
- | isEnumerationTyCon rep_tc = IsValid
- | otherwise = NotValid why
- where
- why = sep [ quotes (pprSourceTyCon rep_tc) <+>
- text "must be an enumeration type"
- , text "(an enumeration consists of one or more nullary, non-GADT constructors)" ]
- -- See Note [Enumeration types] in TyCon
-
-cond_isProduct :: Condition
-cond_isProduct (_, rep_tc)
- | isProductTyCon rep_tc = IsValid
- | otherwise = NotValid why
- where
- why = quotes (pprSourceTyCon rep_tc) <+>
- text "must have precisely one constructor"
-
-cond_functorOK :: Bool -> Bool -> Condition
--- OK for Functor/Foldable/Traversable class
--- Currently: (a) at least one argument
--- (b) don't use argument contravariantly
--- (c) don't use argument in the wrong place, e.g. data T a = T (X a a)
--- (d) optionally: don't use function types
--- (e) no "stupid context" on data type
-cond_functorOK allowFunctions allowExQuantifiedLastTyVar (_, rep_tc)
- | null tc_tvs
- = NotValid (text "Data type" <+> quotes (ppr rep_tc)
- <+> text "must have some type parameters")
-
- | not (null bad_stupid_theta)
- = NotValid (text "Data type" <+> quotes (ppr rep_tc)
- <+> text "must not have a class context:" <+> pprTheta bad_stupid_theta)
-
- | otherwise
- = allValid (map check_con data_cons)
- where
- tc_tvs = tyConTyVars rep_tc
- Just (_, last_tv) = snocView tc_tvs
- bad_stupid_theta = filter is_bad (tyConStupidTheta rep_tc)
- is_bad pred = last_tv `elemVarSet` tyCoVarsOfType pred
-
- data_cons = tyConDataCons rep_tc
- check_con con = allValid (check_universal con : foldDataConArgs (ft_check con) con)
-
- check_universal :: DataCon -> Validity
- check_universal con
- | allowExQuantifiedLastTyVar
- = IsValid -- See Note [DeriveFoldable with ExistentialQuantification]
- -- in TcGenDeriv
- | Just tv <- getTyVar_maybe (last (tyConAppArgs (dataConOrigResTy con)))
- , tv `elem` dataConUnivTyVars con
- , not (tv `elemVarSet` tyCoVarsOfTypes (dataConTheta con))
- = IsValid -- See Note [Check that the type variable is truly universal]
- | otherwise
- = NotValid (badCon con existential)
-
- ft_check :: DataCon -> FFoldType Validity
- ft_check con = FT { ft_triv = IsValid, ft_var = IsValid
- , ft_co_var = NotValid (badCon con covariant)
- , ft_fun = \x y -> if allowFunctions then x `andValid` y
- else NotValid (badCon con functions)
- , ft_tup = \_ xs -> allValid xs
- , ft_ty_app = \_ x -> x
- , ft_bad_app = NotValid (badCon con wrong_arg)
- , ft_forall = \_ x -> x }
-
- existential = text "must be truly polymorphic in the last argument of the data type"
- covariant = text "must not use the type variable in a function argument"
- functions = text "must not contain function types"
- wrong_arg = text "must use the type variable only as the last argument of a data type"
-
-checkFlag :: LangExt.Extension -> Condition
-checkFlag flag (dflags, _)
- | xopt flag dflags = IsValid
- | otherwise = NotValid why
- where
- why = text "You need " <> text flag_str
- <+> text "to derive an instance for this class"
- flag_str = case [ flagSpecName f | f <- xFlags , flagSpecFlag f == flag ] of
- [s] -> s
- other -> pprPanic "checkFlag" (ppr other)
-
-std_class_via_coercible :: Class -> Bool
--- These standard classes can be derived for a newtype
--- using the coercible trick *even if no -XGeneralizedNewtypeDeriving
--- because giving so gives the same results as generating the boilerplate
-std_class_via_coercible clas
- = classKey clas `elem` [eqClassKey, ordClassKey, ixClassKey, boundedClassKey]
- -- Not Read/Show because they respect the type
- -- Not Enum, because newtypes are never in Enum
-
-
-non_coercible_class :: Class -> Bool
--- *Never* derive Read, Show, Typeable, Data, Generic, Generic1, Lift
--- by Coercible, even with -XGeneralizedNewtypeDeriving
--- Also, avoid Traversable, as the Coercible-derived instance and the "normal"-derived
--- instance behave differently if there's a non-lawful Applicative out there.
--- Besides, with roles, Coercible-deriving Traversable is ill-roled.
-non_coercible_class cls
- = classKey cls `elem` ([ readClassKey, showClassKey, dataClassKey
- , genClassKey, gen1ClassKey, typeableClassKey
- , traversableClassKey, liftClassKey ])
-
-badCon :: DataCon -> SDoc -> SDoc
-badCon con msg = text "Constructor" <+> quotes (ppr con) <+> msg
-
{-
-Note [Check that the type variable is truly universal]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-For Functor and Traversable instances, we must check that the *last argument*
-of the type constructor is used truly universally quantified. Example
-
- data T a b where
- T1 :: a -> b -> T a b -- Fine! Vanilla H-98
- T2 :: b -> c -> T a b -- Fine! Existential c, but we can still map over 'b'
- T3 :: b -> T Int b -- Fine! Constraint 'a', but 'b' is still polymorphic
- T4 :: Ord b => b -> T a b -- No! 'b' is constrained
- T5 :: b -> T b b -- No! 'b' is constrained
- T6 :: T a (b,b) -- No! 'b' is constrained
-
-Notice that only the first of these constructors is vanilla H-98. We only
-need to take care about the last argument (b in this case). See Trac #8678.
-Eg. for T1-T3 we can write
-
- fmap f (T1 a b) = T1 a (f b)
- fmap f (T2 b c) = T2 (f b) c
- fmap f (T3 x) = T3 (f x)
-
-We need not perform these checks for Foldable instances, however, since
-functions in Foldable can only consume existentially quantified type variables,
-rather than produce them (as is the case in Functor and Traversable functions.)
-As a result, T can have a derived Foldable instance:
-
- foldr f z (T1 a b) = f b z
- foldr f z (T2 b c) = f b z
- foldr f z (T3 x) = f x z
- foldr f z (T4 x) = f x z
- foldr f z (T5 x) = f x z
- foldr _ z T6 = z
-
-See Note [DeriveFoldable with ExistentialQuantification] in TcGenDeriv.
-
-
-Note [Superclasses of derived instance]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-In general, a derived instance decl needs the superclasses of the derived
-class too. So if we have
- data T a = ...deriving( Ord )
-then the initial context for Ord (T a) should include Eq (T a). Often this is
-redundant; we'll also generate an Ord constraint for each constructor argument,
-and that will probably generate enough constraints to make the Eq (T a) constraint
-be satisfied too. But not always; consider:
-
- data S a = S
- instance Eq (S a)
- instance Ord (S a)
-
- data T a = MkT (S a) deriving( Ord )
- instance Num a => Eq (T a)
-
-The derived instance for (Ord (T a)) must have a (Num a) constraint!
-Similarly consider:
- data T a = MkT deriving( Data )
-Here there *is* no argument field, but we must nevertheless generate
-a context for the Data instances:
- instance Typeable a => Data (T a) where ...
-
************************************************************************
* *
Deriving newtypes
@@ -2005,355 +1236,6 @@ where we're sure that the resulting instance will type-check.
************************************************************************
* *
- Finding the fixed point of deriving equations
-* *
-************************************************************************
-
-Note [Simplifying the instance context]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Consider
-
- data T a b = C1 (Foo a) (Bar b)
- | C2 Int (T b a)
- | C3 (T a a)
- deriving (Eq)
-
-We want to come up with an instance declaration of the form
-
- instance (Ping a, Pong b, ...) => Eq (T a b) where
- x == y = ...
-
-It is pretty easy, albeit tedious, to fill in the code "...". The
-trick is to figure out what the context for the instance decl is,
-namely Ping, Pong and friends.
-
-Let's call the context reqd for the T instance of class C at types
-(a,b, ...) C (T a b). Thus:
-
- Eq (T a b) = (Ping a, Pong b, ...)
-
-Now we can get a (recursive) equation from the data decl. This part
-is done by inferConstraints.
-
- Eq (T a b) = Eq (Foo a) u Eq (Bar b) -- From C1
- u Eq (T b a) u Eq Int -- From C2
- u Eq (T a a) -- From C3
-
-
-Foo and Bar may have explicit instances for Eq, in which case we can
-just substitute for them. Alternatively, either or both may have
-their Eq instances given by deriving clauses, in which case they
-form part of the system of equations.
-
-Now all we need do is simplify and solve the equations, iterating to
-find the least fixpoint. This is done by simplifyInstanceConstraints.
-Notice that the order of the arguments can
-switch around, as here in the recursive calls to T.
-
-Let's suppose Eq (Foo a) = Eq a, and Eq (Bar b) = Ping b.
-
-We start with:
-
- Eq (T a b) = {} -- The empty set
-
-Next iteration:
- Eq (T a b) = Eq (Foo a) u Eq (Bar b) -- From C1
- u Eq (T b a) u Eq Int -- From C2
- u Eq (T a a) -- From C3
-
- After simplification:
- = Eq a u Ping b u {} u {} u {}
- = Eq a u Ping b
-
-Next iteration:
-
- Eq (T a b) = Eq (Foo a) u Eq (Bar b) -- From C1
- u Eq (T b a) u Eq Int -- From C2
- u Eq (T a a) -- From C3
-
- After simplification:
- = Eq a u Ping b
- u (Eq b u Ping a)
- u (Eq a u Ping a)
-
- = Eq a u Ping b u Eq b u Ping a
-
-The next iteration gives the same result, so this is the fixpoint. We
-need to make a canonical form of the RHS to ensure convergence. We do
-this by simplifying the RHS to a form in which
-
- - the classes constrain only tyvars
- - the list is sorted by tyvar (major key) and then class (minor key)
- - no duplicates, of course
-
-Note [Deterministic simplifyInstanceContexts]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Canonicalisation uses nonDetCmpType which is nondeterministic. Sorting
-with nonDetCmpType puts the returned lists in a nondeterministic order.
-If we were to return them, we'd get class constraints in
-nondeterministic order.
-
-Consider:
-
- data ADT a b = Z a b deriving Eq
-
-The generated code could be either:
-
- instance (Eq a, Eq b) => Eq (Z a b) where
-
-Or:
-
- instance (Eq b, Eq a) => Eq (Z a b) where
-
-To prevent the order from being nondeterministic we only
-canonicalize when comparing and return them in the same order as
-simplifyDeriv returned them.
-See also Note [nonDetCmpType nondeterminism]
--}
-
-
-simplifyInstanceContexts :: [DerivSpec ThetaOrigin] -> TcM [DerivSpec ThetaType]
--- Used only for deriving clauses (InferTheta)
--- not for standalone deriving
--- See Note [Simplifying the instance context]
-
-simplifyInstanceContexts [] = return []
-
-simplifyInstanceContexts infer_specs
- = do { traceTc "simplifyInstanceContexts" $ vcat (map pprDerivSpec infer_specs)
- ; iterate_deriv 1 initial_solutions }
- where
- ------------------------------------------------------------------
- -- The initial solutions for the equations claim that each
- -- instance has an empty context; this solution is certainly
- -- in canonical form.
- initial_solutions :: [ThetaType]
- initial_solutions = [ [] | _ <- infer_specs ]
-
- ------------------------------------------------------------------
- -- iterate_deriv calculates the next batch of solutions,
- -- compares it with the current one; finishes if they are the
- -- same, otherwise recurses with the new solutions.
- -- It fails if any iteration fails
- iterate_deriv :: Int -> [ThetaType] -> TcM [DerivSpec ThetaType]
- iterate_deriv n current_solns
- | n > 20 -- Looks as if we are in an infinite loop
- -- This can happen if we have -XUndecidableInstances
- -- (See TcSimplify.tcSimplifyDeriv.)
- = pprPanic "solveDerivEqns: probable loop"
- (vcat (map pprDerivSpec infer_specs) $$ ppr current_solns)
- | otherwise
- = do { -- Extend the inst info from the explicit instance decls
- -- with the current set of solutions, and simplify each RHS
- inst_specs <- zipWithM newDerivClsInst current_solns infer_specs
- ; new_solns <- checkNoErrs $
- extendLocalInstEnv inst_specs $
- mapM gen_soln infer_specs
-
- ; if (current_solns `eqSolution` new_solns) then
- return [ spec { ds_theta = soln }
- | (spec, soln) <- zip infer_specs current_solns ]
- else
- iterate_deriv (n+1) new_solns }
-
- eqSolution a b = eqListBy (eqListBy eqType) (canSolution a) (canSolution b)
- -- Canonicalise for comparison
- -- See Note [Deterministic simplifyInstanceContexts]
- canSolution = map (sortBy nonDetCmpType)
- ------------------------------------------------------------------
- gen_soln :: DerivSpec ThetaOrigin -> TcM ThetaType
- gen_soln (DS { ds_loc = loc, ds_tvs = tyvars
- , ds_cls = clas, ds_tys = inst_tys, ds_theta = deriv_rhs })
- = setSrcSpan loc $
- addErrCtxt (derivInstCtxt the_pred) $
- do { theta <- simplifyDeriv the_pred tyvars deriv_rhs
- -- checkValidInstance tyvars theta clas inst_tys
- -- Not necessary; see Note [Exotic derived instance contexts]
-
- ; traceTc "TcDeriv" (ppr deriv_rhs $$ ppr theta)
- -- Claim: the result instance declaration is guaranteed valid
- -- Hence no need to call:
- -- checkValidInstance tyvars theta clas inst_tys
- ; return theta }
- where
- the_pred = mkClassPred clas inst_tys
-
-------------------------------------------------------------------
-newDerivClsInst :: ThetaType -> DerivSpec theta -> TcM ClsInst
-newDerivClsInst theta (DS { ds_name = dfun_name, ds_overlap = overlap_mode
- , ds_tvs = tvs, ds_cls = clas, ds_tys = tys })
- = newClsInst overlap_mode dfun_name tvs theta clas tys
-
-extendLocalInstEnv :: [ClsInst] -> TcM a -> TcM a
--- Add new locally-defined instances; don't bother to check
--- for functional dependency errors -- that'll happen in TcInstDcls
-extendLocalInstEnv dfuns thing_inside
- = do { env <- getGblEnv
- ; let inst_env' = extendInstEnvList (tcg_inst_env env) dfuns
- env' = env { tcg_inst_env = inst_env' }
- ; setGblEnv env' thing_inside }
-
-{-
-***********************************************************************************
-* *
-* Simplify derived constraints
-* *
-***********************************************************************************
--}
-
--- | Given @instance (wanted) => C inst_ty@, simplify 'wanted' as much
--- as possible. Fail if not possible.
-simplifyDeriv :: PredType -- ^ @C inst_ty@, head of the instance we are
- -- deriving. Only used for SkolemInfo.
- -> [TyVar] -- ^ The tyvars bound by @inst_ty@.
- -> ThetaOrigin -- ^ @wanted@ constraints, i.e. @['PredOrigin']@.
- -> TcM ThetaType -- ^ Needed constraints (after simplification),
- -- i.e. @['PredType']@.
-simplifyDeriv pred tvs theta
- = do { (skol_subst, tvs_skols) <- tcInstSkolTyVars tvs -- Skolemize
- -- The constraint solving machinery
- -- expects *TcTyVars* not TyVars.
- -- We use *non-overlappable* (vanilla) skolems
- -- See Note [Overlap and deriving]
-
- ; let skol_set = mkVarSet tvs_skols
- skol_info = DerivSkol pred
- doc = text "deriving" <+> parens (ppr pred)
- mk_ct (PredOrigin t o t_or_k)
- = newWanted o (Just t_or_k) (substTy skol_subst t)
-
- -- Generate the wanted constraints with the skolemized variables
- ; (wanted, tclvl) <- pushTcLevelM (mapM mk_ct theta)
-
- ; traceTc "simplifyDeriv inputs" $
- vcat [ pprTvBndrs tvs $$ ppr theta $$ ppr wanted, doc ]
- -- Simplify the constraints
- ; residual_wanted <- simplifyWantedsTcM wanted
- -- Result is zonked
-
- -- Split the resulting constraints into bad and good constraints,
- -- building an @unsolved :: WantedConstraints@ representing all
- -- the constraints we can't just shunt to the predicates.
- -- See Note [Exotic derived instance contexts]
- ; let residual_simple = wc_simple residual_wanted
- (bad, good) = partitionBagWith get_good residual_simple
- unsolved = residual_wanted { wc_simple = bad }
-
- -- See Note [Exotic derived instance contexts]
-
- get_good :: Ct -> Either Ct PredType
- get_good ct | validDerivPred skol_set p
- , isWantedCt ct
- = Right p
- -- NB re 'isWantedCt': residual_wanted may contain
- -- unsolved CtDerived and we stick them into the
- -- bad set so that reportUnsolved may decide what
- -- to do with them
- | otherwise
- = Left ct
- where p = ctPred ct
-
- ; traceTc "simplifyDeriv outputs" $
- vcat [ ppr tvs_skols, ppr residual_simple, ppr good, ppr bad ]
-
- -- If we are deferring type errors, simply ignore any insoluble
- -- constraints. They'll come up again when we typecheck the
- -- generated instance declaration
- ; defer <- goptM Opt_DeferTypeErrors
- ; (implic, _) <- buildImplicationFor tclvl skol_info tvs_skols [] unsolved
- -- The buildImplicationFor is just to bind the skolems,
- -- in case they are mentioned in error messages
- -- See Trac #11347
- -- Report the (bad) unsolved constraints
- ; unless defer (reportAllUnsolved (mkImplicWC implic))
-
-
- -- Return the good unsolved constraints (unskolemizing on the way out.)
- ; let min_theta = mkMinimalBySCs (bagToList good)
- subst_skol = zipTvSubst tvs_skols $ mkTyVarTys tvs
- -- The reverse substitution (sigh)
- ; return (substTheta subst_skol min_theta) }
-
-{-
-Note [Overlap and deriving]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Consider some overlapping instances:
- data Show a => Show [a] where ..
- data Show [Char] where ...
-
-Now a data type with deriving:
- data T a = MkT [a] deriving( Show )
-
-We want to get the derived instance
- instance Show [a] => Show (T a) where...
-and NOT
- instance Show a => Show (T a) where...
-so that the (Show (T Char)) instance does the Right Thing
-
-It's very like the situation when we're inferring the type
-of a function
- f x = show [x]
-and we want to infer
- f :: Show [a] => a -> String
-
-BOTTOM LINE: use vanilla, non-overlappable skolems when inferring
- the context for the derived instance.
- Hence tcInstSkolTyVars not tcInstSuperSkolTyVars
-
-Note [Exotic derived instance contexts]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-In a 'derived' instance declaration, we *infer* the context. It's a
-bit unclear what rules we should apply for this; the Haskell report is
-silent. Obviously, constraints like (Eq a) are fine, but what about
- data T f a = MkT (f a) deriving( Eq )
-where we'd get an Eq (f a) constraint. That's probably fine too.
-
-One could go further: consider
- data T a b c = MkT (Foo a b c) deriving( Eq )
- instance (C Int a, Eq b, Eq c) => Eq (Foo a b c)
-
-Notice that this instance (just) satisfies the Paterson termination
-conditions. Then we *could* derive an instance decl like this:
-
- instance (C Int a, Eq b, Eq c) => Eq (T a b c)
-even though there is no instance for (C Int a), because there just
-*might* be an instance for, say, (C Int Bool) at a site where we
-need the equality instance for T's.
-
-However, this seems pretty exotic, and it's quite tricky to allow
-this, and yet give sensible error messages in the (much more common)
-case where we really want that instance decl for C.
-
-So for now we simply require that the derived instance context
-should have only type-variable constraints.
-
-Here is another example:
- data Fix f = In (f (Fix f)) deriving( Eq )
-Here, if we are prepared to allow -XUndecidableInstances we
-could derive the instance
- instance Eq (f (Fix f)) => Eq (Fix f)
-but this is so delicate that I don't think it should happen inside
-'deriving'. If you want this, write it yourself!
-
-NB: if you want to lift this condition, make sure you still meet the
-termination conditions! If not, the deriving mechanism generates
-larger and larger constraints. Example:
- data Succ a = S a
- data Seq a = Cons a (Seq (Succ a)) | Nil deriving Show
-
-Note the lack of a Show instance for Succ. First we'll generate
- instance (Show (Succ a), Show a) => Show (Seq a)
-and then
- instance (Show (Succ (Succ a)), Show (Succ a), Show a) => Show (Seq a)
-and so on. Instead we want to complain of no instance for (Show (Succ a)).
-
-The bottom line
-~~~~~~~~~~~~~~~
-Allow constraints which consist only of type variables, with no repeats.
-
-
-************************************************************************
-* *
\subsection[TcDeriv-normal-binds]{Bindings for the various classes}
* *
************************************************************************
@@ -2475,8 +1357,8 @@ doDerivInstErrorChecks clas clas_inst mechanism
; when (safeInferOn dflags) (recordUnsafeInfer emptyBag) } }
where
exotic_mechanism = case mechanism of
- DerivSpecGeneric _ -> False
- _ -> True
+ DerivSpecStock{} -> False
+ _ -> True
gen_inst_err = hang (text ("Generic instances can only be derived in "
++ "Safe Haskell using the stock strategy.") $+$
@@ -2490,18 +1372,11 @@ genDerivStuff :: DerivSpecMechanism -> SrcSpan -> Class
-> TcM (LHsBinds RdrName, BagDerivStuff)
genDerivStuff mechanism loc clas tycon inst_tys tyvars
= case mechanism of
- -- Special case for DeriveGeneric, since it's monadic
- DerivSpecGeneric gen_fn -> do
- -- TODO NSF: correctly identify when we're building Both instead of One
- (binds, faminst) <- gen_fn tycon inst_tys
- return (binds, unitBag (DerivFamInst faminst))
-
- -- The rest of the stock derivers
- DerivSpecStock gen_fn -> gen_fn loc tycon
-
- -- If there isn't compiler support for deriving the class, our last
- -- resort is -XDeriveAnyClass (since -XGeneralizedNewtypeDeriving
- -- fell through).
+ -- Try a stock deriver
+ DerivSpecStock gen_fn -> gen_fn loc tycon inst_tys
+
+ -- If there isn't a stock deriver, our last resort is -XDeriveAnyClass
+ -- (since -XGeneralizedNewtypeDeriving fell through).
DerivSpecAnyClass -> do
let mini_env = mkVarEnv (classTyVars clas `zip` inst_tys)
mini_subst = mkTvSubst (mkInScopeSet (mkVarSet tyvars)) mini_env
@@ -2622,6 +1497,19 @@ ask for a particular DerivStrategy (using the algorithm linked to above).
************************************************************************
-}
+nonUnaryErr :: LHsSigType Name -> SDoc
+nonUnaryErr ct = quotes (ppr ct)
+ <+> text "is not a unary constraint, as expected by a deriving clause"
+
+nonStdErr :: Class -> SDoc
+nonStdErr cls =
+ quotes (ppr cls)
+ <+> text "is not a stock derivable class (Eq, Show, etc.)"
+
+gndNonNewtypeErr :: SDoc
+gndNonNewtypeErr =
+ text "GeneralizedNewtypeDeriving cannot be used on non-newtypes"
+
derivingNullaryErr :: MsgDoc
derivingNullaryErr = text "Cannot derive instances for nullary classes"
@@ -2672,10 +1560,6 @@ standaloneCtxt :: LHsSigType Name -> SDoc
standaloneCtxt ty = hang (text "In the stand-alone deriving instance for")
2 (quotes (ppr ty))
-derivInstCtxt :: PredType -> MsgDoc
-derivInstCtxt pred
- = text "When deriving the instance for" <+> parens (ppr pred)
-
unboxedTyConErr :: String -> MsgDoc
unboxedTyConErr thing =
text "The last argument of the instance cannot be an unboxed" <+> text thing
diff --git a/compiler/typecheck/TcDerivInfer.hs b/compiler/typecheck/TcDerivInfer.hs
new file mode 100644
index 0000000000..63ff90489f
--- /dev/null
+++ b/compiler/typecheck/TcDerivInfer.hs
@@ -0,0 +1,653 @@
+{-
+(c) The University of Glasgow 2006
+(c) The GRASP/AQUA Project, Glasgow University, 1992-1998
+
+
+Functions for inferring (and simplifying) the context for derived instances.
+-}
+
+{-# LANGUAGE CPP #-}
+
+module TcDerivInfer (inferConstraints, simplifyInstanceContexts) where
+
+#include "HsVersions.h"
+
+import Bag
+import Class
+import DataCon
+import DynFlags
+import ErrUtils
+import Inst
+import Outputable
+import PrelNames
+import TcDerivUtils
+import TcEnv
+import TcErrors (reportAllUnsolved)
+import TcGenFunctor
+import TcGenGenerics
+import TcMType
+import TcRnMonad
+import TcType
+import TyCon
+import Type
+import TcSimplify
+import TcValidity (validDerivPred)
+import TcUnify (buildImplicationFor)
+import Unify (tcUnifyTy)
+import Util
+import VarSet
+
+import Control.Monad
+import Data.List
+import Data.Maybe
+
+----------------------
+
+inferConstraints :: [TyVar] -> Class -> [TcType] -> TcType
+ -> TyCon -> [TcType]
+ -> (ThetaOrigin -> [TyVar] -> [TcType] -> TcM a)
+ -> TcM a
+-- inferConstraints figures out the constraints needed for the
+-- instance declaration generated by a 'deriving' clause on a
+-- data type declaration. It also returns the new in-scope type
+-- variables and instance types, in case they were changed due to
+-- the presence of functor-like constraints.
+-- See Note [Inferring the instance context]
+
+-- e.g. inferConstraints
+-- C Int (T [a]) -- Class and inst_tys
+-- :RTList a -- Rep tycon and its arg tys
+-- where T [a] ~R :RTList a
+--
+-- Generate a sufficiently large set of constraints that typechecking the
+-- generated method definitions should succeed. This set will be simplified
+-- before being used in the instance declaration
+inferConstraints tvs main_cls cls_tys inst_ty rep_tc rep_tc_args mkTheta
+ | is_generic -- Generic constraints are easy
+ = mkTheta [] tvs inst_tys
+
+ | is_generic1 -- Generic1 needs Functor
+ = ASSERT( length rep_tc_tvs > 0 ) -- See Note [Getting base classes]
+ ASSERT( length cls_tys == 1 ) -- Generic1 has a single kind variable
+ do { functorClass <- tcLookupClass functorClassName
+ ; con_arg_constraints (get_gen1_constraints functorClass) mkTheta }
+
+ | otherwise -- The others are a bit more complicated
+ = ASSERT2( equalLength rep_tc_tvs all_rep_tc_args
+ , ppr main_cls <+> ppr rep_tc
+ $$ ppr rep_tc_tvs $$ ppr all_rep_tc_args )
+ con_arg_constraints get_std_constrained_tys
+ $ \arg_constraints tvs' inst_tys' ->
+ do { traceTc "inferConstraints" $ vcat
+ [ ppr main_cls <+> ppr inst_tys'
+ , ppr arg_constraints
+ ]
+ ; mkTheta (stupid_constraints ++ extra_constraints
+ ++ sc_constraints ++ arg_constraints)
+ tvs' inst_tys' }
+ where
+ tc_binders = tyConBinders rep_tc
+ choose_level bndr
+ | isNamedTyConBinder bndr = KindLevel
+ | otherwise = TypeLevel
+ t_or_ks = map choose_level tc_binders ++ repeat TypeLevel
+ -- want to report *kind* errors when possible
+
+ -- Constraints arising from the arguments of each constructor
+ con_arg_constraints :: (CtOrigin -> TypeOrKind
+ -> Type
+ -> [(ThetaOrigin, Maybe TCvSubst)])
+ -> (ThetaOrigin -> [TyVar] -> [TcType] -> TcM a)
+ -> TcM a
+ con_arg_constraints get_arg_constraints mkTheta
+ = let (predss, mbSubsts) = unzip
+ [ preds_and_mbSubst
+ | data_con <- tyConDataCons rep_tc
+ , (arg_n, arg_t_or_k, arg_ty)
+ <- zip3 [1..] t_or_ks $
+ dataConInstOrigArgTys data_con all_rep_tc_args
+ -- No constraints for unlifted types
+ -- See Note [Deriving and unboxed types]
+ , not (isUnliftedType arg_ty)
+ , let orig = DerivOriginDC data_con arg_n
+ , preds_and_mbSubst <- get_arg_constraints orig arg_t_or_k arg_ty
+ ]
+ preds = concat predss
+ -- If the constraints require a subtype to be of kind (* -> *)
+ -- (which is the case for functor-like constraints), then we
+ -- explicitly unify the subtype's kinds with (* -> *).
+ -- See Note [Inferring the instance context]
+ subst = foldl' composeTCvSubst
+ emptyTCvSubst (catMaybes mbSubsts)
+ unmapped_tvs = filter (\v -> v `notElemTCvSubst` subst
+ && not (v `isInScope` subst)) tvs
+ (subst', _) = mapAccumL substTyVarBndr subst unmapped_tvs
+ preds' = substThetaOrigin subst' preds
+ inst_tys' = substTys subst' inst_tys
+ tvs' = tyCoVarsOfTypesWellScoped inst_tys'
+ in mkTheta preds' tvs' inst_tys'
+
+ is_generic = main_cls `hasKey` genClassKey
+ is_generic1 = main_cls `hasKey` gen1ClassKey
+ -- is_functor_like: see Note [Inferring the instance context]
+ is_functor_like = typeKind inst_ty `tcEqKind` typeToTypeKind
+ || is_generic1 -- Technically, Generic1 requires a type of
+ -- kind (k -> *), not (* -> *), but we still
+ -- label it "functor-like" to make sure
+ -- all_rep_tc_args has all the necessary type
+ -- variables it needs to function.
+
+ get_gen1_constraints :: Class -> CtOrigin -> TypeOrKind -> Type
+ -> [(ThetaOrigin, Maybe TCvSubst)]
+ get_gen1_constraints functor_cls orig t_or_k ty
+ = mk_functor_like_constraints orig t_or_k functor_cls $
+ get_gen1_constrained_tys last_tv ty
+
+ get_std_constrained_tys :: CtOrigin -> TypeOrKind -> Type
+ -> [(ThetaOrigin, Maybe TCvSubst)]
+ get_std_constrained_tys orig t_or_k ty
+ | is_functor_like = mk_functor_like_constraints orig t_or_k main_cls $
+ deepSubtypesContaining last_tv ty
+ | otherwise = [( [mk_cls_pred orig t_or_k main_cls ty]
+ , Nothing )]
+
+ mk_functor_like_constraints :: CtOrigin -> TypeOrKind
+ -> Class -> [Type]
+ -> [(ThetaOrigin, Maybe TCvSubst)]
+ -- 'cls' is usually main_cls (Functor or Traversable etc), but if
+ -- main_cls = Generic1, then 'cls' can be Functor; see get_gen1_constraints
+ --
+ -- For each type, generate two constraints, [cls ty, kind(ty) ~ (*->*)],
+ -- and a kind substitution that results from unifying kind(ty) with * -> *.
+ -- If the unification is successful, it will ensure that the resulting
+ -- instance is well kinded. If not, the second constraint will result
+ -- in an error message which points out the kind mismatch.
+ -- See Note [Inferring the instance context]
+ mk_functor_like_constraints orig t_or_k cls
+ = map $ \ty -> let ki = typeKind ty in
+ ( [ mk_cls_pred orig t_or_k cls ty
+ , mkPredOrigin orig KindLevel
+ (mkPrimEqPred ki typeToTypeKind) ]
+ , tcUnifyTy ki typeToTypeKind
+ )
+
+ rep_tc_tvs = tyConTyVars rep_tc
+ last_tv = last rep_tc_tvs
+ all_rep_tc_args | is_functor_like = rep_tc_args ++ [mkTyVarTy last_tv]
+ | otherwise = rep_tc_args
+
+ -- Constraints arising from superclasses
+ -- See Note [Superclasses of derived instance]
+ cls_tvs = classTyVars main_cls
+ inst_tys = cls_tys ++ [inst_ty]
+ sc_constraints = ASSERT2( equalLength cls_tvs inst_tys, ppr main_cls <+> ppr rep_tc)
+ mkThetaOrigin DerivOrigin TypeLevel $
+ substTheta cls_subst (classSCTheta main_cls)
+ cls_subst = ASSERT( equalLength cls_tvs inst_tys )
+ zipTvSubst cls_tvs inst_tys
+
+ -- Stupid constraints
+ stupid_constraints = mkThetaOrigin DerivOrigin TypeLevel $
+ substTheta tc_subst (tyConStupidTheta rep_tc)
+ tc_subst = ASSERT( equalLength rep_tc_tvs all_rep_tc_args )
+ zipTvSubst rep_tc_tvs all_rep_tc_args
+
+ -- Extra Data constraints
+ -- The Data class (only) requires that for
+ -- instance (...) => Data (T t1 t2)
+ -- IF t1:*, t2:*
+ -- THEN (Data t1, Data t2) are among the (...) constraints
+ -- Reason: when the IF holds, we generate a method
+ -- dataCast2 f = gcast2 f
+ -- and we need the Data constraints to typecheck the method
+ extra_constraints
+ | main_cls `hasKey` dataClassKey
+ , all (isLiftedTypeKind . typeKind) rep_tc_args
+ = [ mk_cls_pred DerivOrigin t_or_k main_cls ty
+ | (t_or_k, ty) <- zip t_or_ks rep_tc_args]
+ | otherwise
+ = []
+
+ mk_cls_pred orig t_or_k cls ty -- Don't forget to apply to cls_tys' too
+ = mkPredOrigin orig t_or_k (mkClassPred cls (cls_tys' ++ [ty]))
+ cls_tys' | is_generic1 = [] -- In the awkward Generic1 case, cls_tys'
+ -- should be empty, since we are applying the
+ -- class Functor.
+ | otherwise = cls_tys
+
+typeToTypeKind :: Kind
+typeToTypeKind = liftedTypeKind `mkFunTy` liftedTypeKind
+
+{-
+Note [Inferring the instance context]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+There are two sorts of 'deriving':
+
+ * InferTheta: the deriving clause for a data type
+ data T a = T1 a deriving( Eq )
+ Here we must infer an instance context,
+ and generate instance declaration
+ instance Eq a => Eq (T a) where ...
+
+ * CheckTheta: standalone deriving
+ deriving instance Eq a => Eq (T a)
+ Here we only need to fill in the bindings;
+ the instance context is user-supplied
+
+For a deriving clause (InferTheta) we must figure out the
+instance context (inferConstraints). Suppose we are inferring
+the instance context for
+ C t1 .. tn (T s1 .. sm)
+There are two cases
+
+ * (T s1 .. sm) :: * (the normal case)
+ Then we behave like Eq and guess (C t1 .. tn t)
+ for each data constructor arg of type t. More
+ details below.
+
+ * (T s1 .. sm) :: * -> * (the functor-like case)
+ Then we behave like Functor.
+
+In both cases we produce a bunch of un-simplified constraints
+and them simplify them in simplifyInstanceContexts; see
+Note [Simplifying the instance context].
+
+In the functor-like case, we may need to unify some kind variables with * in
+order for the generated instance to be well-kinded. An example from
+Trac #10524:
+
+ newtype Compose (f :: k2 -> *) (g :: k1 -> k2) (a :: k1)
+ = Compose (f (g a)) deriving Functor
+
+Earlier in the deriving pipeline, GHC unifies the kind of Compose f g
+(k1 -> *) with the kind of Functor's argument (* -> *), so k1 := *. But this
+alone isn't enough, since k2 wasn't unified with *:
+
+ instance (Functor (f :: k2 -> *), Functor (g :: * -> k2)) =>
+ Functor (Compose f g) where ...
+
+The two Functor constraints are ill-kinded. To ensure this doesn't happen, we:
+
+ 1. Collect all of a datatype's subtypes which require functor-like
+ constraints.
+ 2. For each subtype, create a substitution by unifying the subtype's kind
+ with (* -> *).
+ 3. Compose all the substitutions into one, then apply that substitution to
+ all of the in-scope type variables and the instance types.
+
+Note [Getting base classes]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Functor and Typeable are defined in package 'base', and that is not available
+when compiling 'ghc-prim'. So we must be careful that 'deriving' for stuff in
+ghc-prim does not use Functor or Typeable implicitly via these lookups.
+
+Note [Deriving and unboxed types]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+We have some special hacks to support things like
+ data T = MkT Int# deriving ( Show )
+
+Specifically, we use TcGenDeriv.box to box the Int# into an Int
+(which we know how to show), and append a '#'. Parenthesis are not required
+for unboxed values (`MkT -3#` is a valid expression).
+
+Note [Superclasses of derived instance]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In general, a derived instance decl needs the superclasses of the derived
+class too. So if we have
+ data T a = ...deriving( Ord )
+then the initial context for Ord (T a) should include Eq (T a). Often this is
+redundant; we'll also generate an Ord constraint for each constructor argument,
+and that will probably generate enough constraints to make the Eq (T a) constraint
+be satisfied too. But not always; consider:
+
+ data S a = S
+ instance Eq (S a)
+ instance Ord (S a)
+
+ data T a = MkT (S a) deriving( Ord )
+ instance Num a => Eq (T a)
+
+The derived instance for (Ord (T a)) must have a (Num a) constraint!
+Similarly consider:
+ data T a = MkT deriving( Data )
+Here there *is* no argument field, but we must nevertheless generate
+a context for the Data instances:
+ instance Typeable a => Data (T a) where ...
+
+************************************************************************
+* *
+ Finding the fixed point of deriving equations
+* *
+************************************************************************
+
+Note [Simplifying the instance context]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider
+
+ data T a b = C1 (Foo a) (Bar b)
+ | C2 Int (T b a)
+ | C3 (T a a)
+ deriving (Eq)
+
+We want to come up with an instance declaration of the form
+
+ instance (Ping a, Pong b, ...) => Eq (T a b) where
+ x == y = ...
+
+It is pretty easy, albeit tedious, to fill in the code "...". The
+trick is to figure out what the context for the instance decl is,
+namely Ping, Pong and friends.
+
+Let's call the context reqd for the T instance of class C at types
+(a,b, ...) C (T a b). Thus:
+
+ Eq (T a b) = (Ping a, Pong b, ...)
+
+Now we can get a (recursive) equation from the data decl. This part
+is done by inferConstraints.
+
+ Eq (T a b) = Eq (Foo a) u Eq (Bar b) -- From C1
+ u Eq (T b a) u Eq Int -- From C2
+ u Eq (T a a) -- From C3
+
+
+Foo and Bar may have explicit instances for Eq, in which case we can
+just substitute for them. Alternatively, either or both may have
+their Eq instances given by deriving clauses, in which case they
+form part of the system of equations.
+
+Now all we need do is simplify and solve the equations, iterating to
+find the least fixpoint. This is done by simplifyInstanceConstraints.
+Notice that the order of the arguments can
+switch around, as here in the recursive calls to T.
+
+Let's suppose Eq (Foo a) = Eq a, and Eq (Bar b) = Ping b.
+
+We start with:
+
+ Eq (T a b) = {} -- The empty set
+
+Next iteration:
+ Eq (T a b) = Eq (Foo a) u Eq (Bar b) -- From C1
+ u Eq (T b a) u Eq Int -- From C2
+ u Eq (T a a) -- From C3
+
+ After simplification:
+ = Eq a u Ping b u {} u {} u {}
+ = Eq a u Ping b
+
+Next iteration:
+
+ Eq (T a b) = Eq (Foo a) u Eq (Bar b) -- From C1
+ u Eq (T b a) u Eq Int -- From C2
+ u Eq (T a a) -- From C3
+
+ After simplification:
+ = Eq a u Ping b
+ u (Eq b u Ping a)
+ u (Eq a u Ping a)
+
+ = Eq a u Ping b u Eq b u Ping a
+
+The next iteration gives the same result, so this is the fixpoint. We
+need to make a canonical form of the RHS to ensure convergence. We do
+this by simplifying the RHS to a form in which
+
+ - the classes constrain only tyvars
+ - the list is sorted by tyvar (major key) and then class (minor key)
+ - no duplicates, of course
+
+Note [Deterministic simplifyInstanceContexts]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Canonicalisation uses nonDetCmpType which is nondeterministic. Sorting
+with nonDetCmpType puts the returned lists in a nondeterministic order.
+If we were to return them, we'd get class constraints in
+nondeterministic order.
+
+Consider:
+
+ data ADT a b = Z a b deriving Eq
+
+The generated code could be either:
+
+ instance (Eq a, Eq b) => Eq (Z a b) where
+
+Or:
+
+ instance (Eq b, Eq a) => Eq (Z a b) where
+
+To prevent the order from being nondeterministic we only
+canonicalize when comparing and return them in the same order as
+simplifyDeriv returned them.
+See also Note [nonDetCmpType nondeterminism]
+-}
+
+
+simplifyInstanceContexts :: [DerivSpec ThetaOrigin] -> TcM [DerivSpec ThetaType]
+-- Used only for deriving clauses (InferTheta)
+-- not for standalone deriving
+-- See Note [Simplifying the instance context]
+
+simplifyInstanceContexts [] = return []
+
+simplifyInstanceContexts infer_specs
+ = do { traceTc "simplifyInstanceContexts" $ vcat (map pprDerivSpec infer_specs)
+ ; iterate_deriv 1 initial_solutions }
+ where
+ ------------------------------------------------------------------
+ -- The initial solutions for the equations claim that each
+ -- instance has an empty context; this solution is certainly
+ -- in canonical form.
+ initial_solutions :: [ThetaType]
+ initial_solutions = [ [] | _ <- infer_specs ]
+
+ ------------------------------------------------------------------
+ -- iterate_deriv calculates the next batch of solutions,
+ -- compares it with the current one; finishes if they are the
+ -- same, otherwise recurses with the new solutions.
+ -- It fails if any iteration fails
+ iterate_deriv :: Int -> [ThetaType] -> TcM [DerivSpec ThetaType]
+ iterate_deriv n current_solns
+ | n > 20 -- Looks as if we are in an infinite loop
+ -- This can happen if we have -XUndecidableInstances
+ -- (See TcSimplify.tcSimplifyDeriv.)
+ = pprPanic "solveDerivEqns: probable loop"
+ (vcat (map pprDerivSpec infer_specs) $$ ppr current_solns)
+ | otherwise
+ = do { -- Extend the inst info from the explicit instance decls
+ -- with the current set of solutions, and simplify each RHS
+ inst_specs <- zipWithM newDerivClsInst current_solns infer_specs
+ ; new_solns <- checkNoErrs $
+ extendLocalInstEnv inst_specs $
+ mapM gen_soln infer_specs
+
+ ; if (current_solns `eqSolution` new_solns) then
+ return [ spec { ds_theta = soln }
+ | (spec, soln) <- zip infer_specs current_solns ]
+ else
+ iterate_deriv (n+1) new_solns }
+
+ eqSolution a b = eqListBy (eqListBy eqType) (canSolution a) (canSolution b)
+ -- Canonicalise for comparison
+ -- See Note [Deterministic simplifyInstanceContexts]
+ canSolution = map (sortBy nonDetCmpType)
+ ------------------------------------------------------------------
+ gen_soln :: DerivSpec ThetaOrigin -> TcM ThetaType
+ gen_soln (DS { ds_loc = loc, ds_tvs = tyvars
+ , ds_cls = clas, ds_tys = inst_tys, ds_theta = deriv_rhs })
+ = setSrcSpan loc $
+ addErrCtxt (derivInstCtxt the_pred) $
+ do { theta <- simplifyDeriv the_pred tyvars deriv_rhs
+ -- checkValidInstance tyvars theta clas inst_tys
+ -- Not necessary; see Note [Exotic derived instance contexts]
+
+ ; traceTc "TcDeriv" (ppr deriv_rhs $$ ppr theta)
+ -- Claim: the result instance declaration is guaranteed valid
+ -- Hence no need to call:
+ -- checkValidInstance tyvars theta clas inst_tys
+ ; return theta }
+ where
+ the_pred = mkClassPred clas inst_tys
+
+derivInstCtxt :: PredType -> MsgDoc
+derivInstCtxt pred
+ = text "When deriving the instance for" <+> parens (ppr pred)
+
+{-
+***********************************************************************************
+* *
+* Simplify derived constraints
+* *
+***********************************************************************************
+-}
+
+-- | Given @instance (wanted) => C inst_ty@, simplify 'wanted' as much
+-- as possible. Fail if not possible.
+simplifyDeriv :: PredType -- ^ @C inst_ty@, head of the instance we are
+ -- deriving. Only used for SkolemInfo.
+ -> [TyVar] -- ^ The tyvars bound by @inst_ty@.
+ -> ThetaOrigin -- ^ @wanted@ constraints, i.e. @['PredOrigin']@.
+ -> TcM ThetaType -- ^ Needed constraints (after simplification),
+ -- i.e. @['PredType']@.
+simplifyDeriv pred tvs theta
+ = do { (skol_subst, tvs_skols) <- tcInstSkolTyVars tvs -- Skolemize
+ -- The constraint solving machinery
+ -- expects *TcTyVars* not TyVars.
+ -- We use *non-overlappable* (vanilla) skolems
+ -- See Note [Overlap and deriving]
+
+ ; let skol_set = mkVarSet tvs_skols
+ skol_info = DerivSkol pred
+ doc = text "deriving" <+> parens (ppr pred)
+ mk_ct (PredOrigin t o t_or_k)
+ = newWanted o (Just t_or_k) (substTy skol_subst t)
+
+ -- Generate the wanted constraints with the skolemized variables
+ ; (wanted, tclvl) <- pushTcLevelM (mapM mk_ct theta)
+
+ ; traceTc "simplifyDeriv inputs" $
+ vcat [ pprTvBndrs tvs $$ ppr theta $$ ppr wanted, doc ]
+ -- Simplify the constraints
+ ; residual_wanted <- simplifyWantedsTcM wanted
+ -- Result is zonked
+
+ -- Split the resulting constraints into bad and good constraints,
+ -- building an @unsolved :: WantedConstraints@ representing all
+ -- the constraints we can't just shunt to the predicates.
+ -- See Note [Exotic derived instance contexts]
+ ; let residual_simple = wc_simple residual_wanted
+ (bad, good) = partitionBagWith get_good residual_simple
+ unsolved = residual_wanted { wc_simple = bad }
+
+ -- See Note [Exotic derived instance contexts]
+
+ get_good :: Ct -> Either Ct PredType
+ get_good ct | validDerivPred skol_set p
+ , isWantedCt ct
+ = Right p
+ -- NB re 'isWantedCt': residual_wanted may contain
+ -- unsolved CtDerived and we stick them into the
+ -- bad set so that reportUnsolved may decide what
+ -- to do with them
+ | otherwise
+ = Left ct
+ where p = ctPred ct
+
+ ; traceTc "simplifyDeriv outputs" $
+ vcat [ ppr tvs_skols, ppr residual_simple, ppr good, ppr bad ]
+
+ -- If we are deferring type errors, simply ignore any insoluble
+ -- constraints. They'll come up again when we typecheck the
+ -- generated instance declaration
+ ; defer <- goptM Opt_DeferTypeErrors
+ ; (implic, _) <- buildImplicationFor tclvl skol_info tvs_skols [] unsolved
+ -- The buildImplicationFor is just to bind the skolems,
+ -- in case they are mentioned in error messages
+ -- See Trac #11347
+ -- Report the (bad) unsolved constraints
+ ; unless defer (reportAllUnsolved (mkImplicWC implic))
+
+
+ -- Return the good unsolved constraints (unskolemizing on the way out.)
+ ; let min_theta = mkMinimalBySCs (bagToList good)
+ subst_skol = zipTvSubst tvs_skols $ mkTyVarTys tvs
+ -- The reverse substitution (sigh)
+ ; return (substTheta subst_skol min_theta) }
+
+{-
+Note [Overlap and deriving]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider some overlapping instances:
+ data Show a => Show [a] where ..
+ data Show [Char] where ...
+
+Now a data type with deriving:
+ data T a = MkT [a] deriving( Show )
+
+We want to get the derived instance
+ instance Show [a] => Show (T a) where...
+and NOT
+ instance Show a => Show (T a) where...
+so that the (Show (T Char)) instance does the Right Thing
+
+It's very like the situation when we're inferring the type
+of a function
+ f x = show [x]
+and we want to infer
+ f :: Show [a] => a -> String
+
+BOTTOM LINE: use vanilla, non-overlappable skolems when inferring
+ the context for the derived instance.
+ Hence tcInstSkolTyVars not tcInstSuperSkolTyVars
+
+Note [Exotic derived instance contexts]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In a 'derived' instance declaration, we *infer* the context. It's a
+bit unclear what rules we should apply for this; the Haskell report is
+silent. Obviously, constraints like (Eq a) are fine, but what about
+ data T f a = MkT (f a) deriving( Eq )
+where we'd get an Eq (f a) constraint. That's probably fine too.
+
+One could go further: consider
+ data T a b c = MkT (Foo a b c) deriving( Eq )
+ instance (C Int a, Eq b, Eq c) => Eq (Foo a b c)
+
+Notice that this instance (just) satisfies the Paterson termination
+conditions. Then we *could* derive an instance decl like this:
+
+ instance (C Int a, Eq b, Eq c) => Eq (T a b c)
+even though there is no instance for (C Int a), because there just
+*might* be an instance for, say, (C Int Bool) at a site where we
+need the equality instance for T's.
+
+However, this seems pretty exotic, and it's quite tricky to allow
+this, and yet give sensible error messages in the (much more common)
+case where we really want that instance decl for C.
+
+So for now we simply require that the derived instance context
+should have only type-variable constraints.
+
+Here is another example:
+ data Fix f = In (f (Fix f)) deriving( Eq )
+Here, if we are prepared to allow -XUndecidableInstances we
+could derive the instance
+ instance Eq (f (Fix f)) => Eq (Fix f)
+but this is so delicate that I don't think it should happen inside
+'deriving'. If you want this, write it yourself!
+
+NB: if you want to lift this condition, make sure you still meet the
+termination conditions! If not, the deriving mechanism generates
+larger and larger constraints. Example:
+ data Succ a = S a
+ data Seq a = Cons a (Seq (Succ a)) | Nil deriving Show
+
+Note the lack of a Show instance for Succ. First we'll generate
+ instance (Show (Succ a), Show a) => Show (Seq a)
+and then
+ instance (Show (Succ (Succ a)), Show (Succ a), Show a) => Show (Seq a)
+and so on. Instead we want to complain of no instance for (Show (Succ a)).
+
+The bottom line
+~~~~~~~~~~~~~~~
+Allow constraints which consist only of type variables, with no repeats.
+-}
diff --git a/compiler/typecheck/TcDerivUtils.hs b/compiler/typecheck/TcDerivUtils.hs
new file mode 100644
index 0000000000..9eef9f1738
--- /dev/null
+++ b/compiler/typecheck/TcDerivUtils.hs
@@ -0,0 +1,610 @@
+{-
+(c) The University of Glasgow 2006
+(c) The GRASP/AQUA Project, Glasgow University, 1992-1998
+
+
+Error-checking and other utilities for @deriving@ clauses or declarations.
+-}
+
+{-# LANGUAGE ImplicitParams #-}
+
+module TcDerivUtils (
+ DerivSpec(..), pprDerivSpec, DerivSpecMechanism(..),
+ DerivContext, DerivStatus(..),
+ PredOrigin(..), ThetaOrigin, mkPredOrigin,
+ mkThetaOrigin, substPredOrigin, substThetaOrigin,
+ checkSideConditions, hasStockDeriving,
+ canDeriveAnyClass,
+ std_class_via_coercible, non_coercible_class,
+ newDerivClsInst, extendLocalInstEnv
+ ) where
+
+import Bag
+import BasicTypes
+import Class
+import DataCon
+import DynFlags
+import ErrUtils
+import HscTypes (lookupFixity, mi_fix)
+import HsSyn
+import Inst
+import InstEnv
+import LoadIface (loadInterfaceForName)
+import Module (getModule)
+import Name
+import Outputable
+import PrelNames
+import RdrName
+import SrcLoc
+import TcGenDeriv
+import TcGenFunctor
+import TcGenGenerics
+import TcRnMonad
+import TcType
+import THNames (liftClassKey)
+import TyCon
+import Type
+import Util
+import VarSet
+
+import qualified GHC.LanguageExtensions as LangExt
+import ListSetOps (assocMaybe)
+
+data DerivSpec theta = DS { ds_loc :: SrcSpan
+ , ds_name :: Name -- DFun name
+ , ds_tvs :: [TyVar]
+ , ds_theta :: theta
+ , ds_cls :: Class
+ , ds_tys :: [Type]
+ , ds_tc :: TyCon
+ , ds_overlap :: Maybe OverlapMode
+ , ds_mechanism :: DerivSpecMechanism }
+ -- This spec implies a dfun declaration of the form
+ -- df :: forall tvs. theta => C tys
+ -- The Name is the name for the DFun we'll build
+ -- The tyvars bind all the variables in the theta
+ -- For type families, the tycon in
+ -- in ds_tys is the *family* tycon
+ -- in ds_tc is the *representation* type
+ -- For non-family tycons, both are the same
+
+ -- the theta is either the given and final theta, in standalone deriving,
+ -- or the not-yet-simplified list of constraints together with their origin
+
+ -- ds_mechanism specifies the means by which GHC derives the instance.
+ -- See Note [Deriving strategies] in TcDeriv
+
+{-
+Example:
+
+ newtype instance T [a] = MkT (Tree a) deriving( C s )
+==>
+ axiom T [a] = :RTList a
+ axiom :RTList a = Tree a
+
+ DS { ds_tvs = [a,s], ds_cls = C, ds_tys = [s, T [a]]
+ , ds_tc = :RTList, ds_mechanism = DerivSpecNewtype (Tree a) }
+-}
+
+pprDerivSpec :: Outputable theta => DerivSpec theta -> SDoc
+pprDerivSpec (DS { ds_loc = l, ds_name = n, ds_tvs = tvs,
+ ds_cls = c, ds_tys = tys, ds_theta = rhs })
+ = hang (text "DerivSpec")
+ 2 (vcat [ text "ds_loc =" <+> ppr l
+ , text "ds_name =" <+> ppr n
+ , text "ds_tvs =" <+> ppr tvs
+ , text "ds_cls =" <+> ppr c
+ , text "ds_tys =" <+> ppr tys
+ , text "ds_theta =" <+> ppr rhs ])
+
+instance Outputable theta => Outputable (DerivSpec theta) where
+ ppr = pprDerivSpec
+
+-- What action to take in order to derive a class instance.
+-- See Note [Deriving strategies] in TcDeriv
+-- NB: DerivSpecMechanism is purely local to this module
+data DerivSpecMechanism
+ = DerivSpecStock -- "Standard" classes
+ (SrcSpan -> TyCon -> [Type] -> TcM (LHsBinds RdrName, BagDerivStuff))
+
+ | DerivSpecNewtype -- -XGeneralizedNewtypeDeriving
+ Type -- ^ The newtype rep type
+
+ | DerivSpecAnyClass -- -XDeriveAnyClass
+
+type DerivContext = Maybe ThetaType
+ -- Nothing <=> Vanilla deriving; infer the context of the instance decl
+ -- Just theta <=> Standalone deriving: context supplied by programmer
+
+data DerivStatus = CanDerive -- Stock class, can derive
+ | DerivableClassError SDoc -- Stock class, but can't do it
+ | DerivableViaInstance -- See Note [Deriving any class]
+ | NonDerivableClass SDoc -- Non-stock class
+
+-- A stock class is one either defined in the Haskell report or for which GHC
+-- otherwise knows how to generate code for (possibly requiring the use of a
+-- language extension), such as Eq, Ord, Ix, Data, Generic, etc.
+
+-- | A 'PredType' annotated with the origin of the constraint 'CtOrigin',
+-- and whether or the constraint deals in types or kinds.
+data PredOrigin = PredOrigin PredType CtOrigin TypeOrKind
+type ThetaOrigin = [PredOrigin]
+
+instance Outputable PredOrigin where
+ ppr (PredOrigin ty _ _) = ppr ty -- The origin is not so interesting when debugging
+
+mkPredOrigin :: CtOrigin -> TypeOrKind -> PredType -> PredOrigin
+mkPredOrigin origin t_or_k pred = PredOrigin pred origin t_or_k
+
+mkThetaOrigin :: CtOrigin -> TypeOrKind -> ThetaType -> ThetaOrigin
+mkThetaOrigin origin t_or_k = map (mkPredOrigin origin t_or_k)
+
+substPredOrigin :: HasCallStack => TCvSubst -> PredOrigin -> PredOrigin
+substPredOrigin subst (PredOrigin pred origin t_or_k)
+ = PredOrigin (substTy subst pred) origin t_or_k
+
+substThetaOrigin :: HasCallStack => TCvSubst -> ThetaOrigin -> ThetaOrigin
+substThetaOrigin subst = map (substPredOrigin subst)
+
+{-
+************************************************************************
+* *
+ Class deriving diagnostics
+* *
+************************************************************************
+
+Only certain blessed classes can be used in a deriving clause (without the
+assistance of GeneralizedNewtypeDeriving or DeriveAnyClass). These classes
+are listed below in the definition of hasStockDeriving. The sideConditions
+function determines the criteria that needs to be met in order for a particular
+class to be able to be derived successfully.
+
+A class might be able to be used in a deriving clause if -XDeriveAnyClass
+is willing to support it. The canDeriveAnyClass function checks if this is the
+case.
+-}
+
+hasStockDeriving :: Class
+ -> Maybe (SrcSpan
+ -> TyCon
+ -> [Type]
+ -> TcM (LHsBinds RdrName, BagDerivStuff))
+hasStockDeriving clas
+ = assocMaybe gen_list (getUnique clas)
+ where
+ gen_list :: [(Unique, SrcSpan
+ -> TyCon
+ -> [Type]
+ -> TcM (LHsBinds RdrName, BagDerivStuff))]
+ gen_list = [ (eqClassKey, simple gen_Eq_binds)
+ , (ordClassKey, simple gen_Ord_binds)
+ , (enumClassKey, simple gen_Enum_binds)
+ , (boundedClassKey, simple gen_Bounded_binds)
+ , (ixClassKey, simple gen_Ix_binds)
+ , (showClassKey, with_fix_env gen_Show_binds)
+ , (readClassKey, with_fix_env gen_Read_binds)
+ , (dataClassKey, simpleM gen_Data_binds)
+ , (functorClassKey, simple gen_Functor_binds)
+ , (foldableClassKey, simple gen_Foldable_binds)
+ , (traversableClassKey, simple gen_Traversable_binds)
+ , (liftClassKey, simple gen_Lift_binds)
+ , (genClassKey, generic (gen_Generic_binds Gen0))
+ , (gen1ClassKey, generic (gen_Generic_binds Gen1)) ]
+
+ simple gen_fn loc tc _
+ = return (gen_fn loc tc)
+
+ simpleM gen_fn loc tc _
+ = gen_fn loc tc
+
+ with_fix_env gen_fn loc tc _
+ = do { fix_env <- getDataConFixityFun tc
+ ; return (gen_fn fix_env loc tc) }
+
+ generic gen_fn _ tc inst_tys
+ = do { (binds, faminst) <- gen_fn tc inst_tys
+ ; return (binds, unitBag (DerivFamInst faminst)) }
+
+getDataConFixityFun :: TyCon -> TcM (Name -> Fixity)
+-- If the TyCon is locally defined, we want the local fixity env;
+-- but if it is imported (which happens for standalone deriving)
+-- we need to get the fixity env from the interface file
+-- c.f. RnEnv.lookupFixity, and Trac #9830
+getDataConFixityFun tc
+ = do { this_mod <- getModule
+ ; if nameIsLocalOrFrom this_mod name
+ then do { fix_env <- getFixityEnv
+ ; return (lookupFixity fix_env) }
+ else do { iface <- loadInterfaceForName doc name
+ -- Should already be loaded!
+ ; return (mi_fix iface . nameOccName) } }
+ where
+ name = tyConName tc
+ doc = text "Data con fixities for" <+> ppr name
+
+------------------------------------------------------------------
+-- Check side conditions that dis-allow derivability for particular classes
+-- This is *apart* from the newtype-deriving mechanism
+--
+-- Here we get the representation tycon in case of family instances as it has
+-- the data constructors - but we need to be careful to fall back to the
+-- family tycon (with indexes) in error messages.
+
+checkSideConditions :: DynFlags -> DerivContext -> Class -> [TcType]
+ -> TyCon -- tycon
+ -> DerivStatus
+checkSideConditions dflags mtheta cls cls_tys rep_tc
+ | Just cond <- sideConditions mtheta cls
+ = case (cond dflags rep_tc) of
+ NotValid err -> DerivableClassError err -- Class-specific error
+ IsValid | null (filterOutInvisibleTypes (classTyCon cls) cls_tys)
+ -> CanDerive
+ -- All stock derivable classes are unary in the sense that
+ -- there should be not types in cls_tys (i.e., no type args
+ -- other than last). Note that cls_types can contain
+ -- invisible types as well (e.g., for Generic1, which is
+ -- poly-kinded), so make sure those are not counted.
+ | otherwise -> DerivableClassError (classArgsErr cls cls_tys)
+ -- e.g. deriving( Eq s )
+
+ | Just err <- canDeriveAnyClass dflags rep_tc cls
+ = NonDerivableClass err -- DeriveAnyClass does not work
+
+ | otherwise
+ = DerivableViaInstance -- DeriveAnyClass should work
+
+classArgsErr :: Class -> [Type] -> SDoc
+classArgsErr cls cls_tys = quotes (ppr (mkClassPred cls cls_tys)) <+> text "is not a class"
+
+-- Side conditions (whether the datatype must have at least one constructor,
+-- required language extensions, etc.) for using GHC's stock deriving
+-- mechanism on certain classes (as opposed to classes that require
+-- GeneralizedNewtypeDeriving or DeriveAnyClass). Returns Nothing for a
+-- class for which stock deriving isn't possible.
+sideConditions :: DerivContext -> Class -> Maybe Condition
+sideConditions mtheta cls
+ | cls_key == eqClassKey = Just (cond_std `andCond` cond_args cls)
+ | cls_key == ordClassKey = Just (cond_std `andCond` cond_args cls)
+ | cls_key == showClassKey = Just (cond_std `andCond` cond_args cls)
+ | cls_key == readClassKey = Just (cond_std `andCond` cond_args cls)
+ | cls_key == enumClassKey = Just (cond_std `andCond` cond_isEnumeration)
+ | cls_key == ixClassKey = Just (cond_std `andCond` cond_enumOrProduct cls)
+ | cls_key == boundedClassKey = Just (cond_std `andCond` cond_enumOrProduct cls)
+ | cls_key == dataClassKey = Just (checkFlag LangExt.DeriveDataTypeable `andCond`
+ cond_std `andCond`
+ cond_args cls)
+ | cls_key == functorClassKey = Just (checkFlag LangExt.DeriveFunctor `andCond`
+ cond_vanilla `andCond`
+ cond_functorOK True False)
+ | cls_key == foldableClassKey = Just (checkFlag LangExt.DeriveFoldable `andCond`
+ cond_vanilla `andCond`
+ cond_functorOK False True)
+ -- Functor/Fold/Trav works ok
+ -- for rank-n types
+ | cls_key == traversableClassKey = Just (checkFlag LangExt.DeriveTraversable `andCond`
+ cond_vanilla `andCond`
+ cond_functorOK False False)
+ | cls_key == genClassKey = Just (checkFlag LangExt.DeriveGeneric `andCond`
+ cond_vanilla `andCond`
+ cond_RepresentableOk)
+ | cls_key == gen1ClassKey = Just (checkFlag LangExt.DeriveGeneric `andCond`
+ cond_vanilla `andCond`
+ cond_Representable1Ok)
+ | cls_key == liftClassKey = Just (checkFlag LangExt.DeriveLift `andCond`
+ cond_vanilla `andCond`
+ cond_args cls)
+ | otherwise = Nothing
+ where
+ cls_key = getUnique cls
+ cond_std = cond_stdOK mtheta False -- Vanilla data constructors, at least one,
+ -- and monotype arguments
+ cond_vanilla = cond_stdOK mtheta True -- Vanilla data constructors but
+ -- allow no data cons or polytype arguments
+
+canDeriveAnyClass :: DynFlags -> TyCon -> Class -> Maybe SDoc
+-- Nothing: we can (try to) derive it via an empty instance declaration
+-- Just s: we can't, reason s
+-- Precondition: the class is not one of the standard ones
+canDeriveAnyClass dflags _tycon clas
+ | not (xopt LangExt.DeriveAnyClass dflags)
+ = Just (text "Try enabling DeriveAnyClass")
+ | not (any (target_kind `tcEqKind`) [ liftedTypeKind, typeToTypeKind ])
+ = Just (text "The last argument of class" <+> quotes (ppr clas)
+ <+> text "does not have kind * or (* -> *)")
+ | otherwise
+ = Nothing -- OK!
+ where
+ -- We are making an instance (C t1 .. tn (T s1 .. sm))
+ -- and we can only do so if the kind of C's last argument
+ -- is * or (* -> *). Because only then can we make a reasonable
+ -- guess at the instance context
+ target_kind = tyVarKind (last (classTyVars clas))
+
+typeToTypeKind :: Kind
+typeToTypeKind = liftedTypeKind `mkFunTy` liftedTypeKind
+
+type Condition = DynFlags -> TyCon -> Validity
+ -- TyCon is the *representation* tycon if the data type is an indexed one
+ -- Nothing => OK
+
+orCond :: Condition -> Condition -> Condition
+orCond c1 c2 dflags tc
+ = case (c1 dflags tc, c2 dflags tc) of
+ (IsValid, _) -> IsValid -- c1 succeeds
+ (_, IsValid) -> IsValid -- c21 succeeds
+ (NotValid x, NotValid y) -> NotValid (x $$ text " or" $$ y)
+ -- Both fail
+
+andCond :: Condition -> Condition -> Condition
+andCond c1 c2 dflags tc = c1 dflags tc `andValid` c2 dflags tc
+
+cond_stdOK :: DerivContext -- Says whether this is standalone deriving or not;
+ -- if standalone, we just say "yes, go for it"
+ -> Bool -- True <=> permissive: allow higher rank
+ -- args and no data constructors
+ -> Condition
+cond_stdOK (Just _) _ _ _
+ = IsValid -- Don't check these conservative conditions for
+ -- standalone deriving; just generate the code
+ -- and let the typechecker handle the result
+cond_stdOK Nothing permissive _ rep_tc
+ | null data_cons
+ , not permissive = NotValid (no_cons_why rep_tc $$ suggestion)
+ | not (null con_whys) = NotValid (vcat con_whys $$ suggestion)
+ | otherwise = IsValid
+ where
+ suggestion = text "Possible fix: use a standalone deriving declaration instead"
+ data_cons = tyConDataCons rep_tc
+ con_whys = getInvalids (map check_con data_cons)
+
+ check_con :: DataCon -> Validity
+ check_con con
+ | not (null eq_spec)
+ = bad "is a GADT"
+ | not (null ex_tvs)
+ = bad "has existential type variables in its type"
+ | not (null theta)
+ = bad "has constraints in its type"
+ | not (permissive || all isTauTy (dataConOrigArgTys con))
+ = bad "has a higher-rank type"
+ | otherwise
+ = IsValid
+ where
+ (_, ex_tvs, eq_spec, theta, _, _) = dataConFullSig con
+ bad msg = NotValid (badCon con (text msg))
+
+no_cons_why :: TyCon -> SDoc
+no_cons_why rep_tc = quotes (pprSourceTyCon rep_tc) <+>
+ text "must have at least one data constructor"
+
+cond_RepresentableOk :: Condition
+cond_RepresentableOk _ tc = canDoGenerics tc
+
+cond_Representable1Ok :: Condition
+cond_Representable1Ok _ tc = canDoGenerics1 tc
+
+cond_enumOrProduct :: Class -> Condition
+cond_enumOrProduct cls = cond_isEnumeration `orCond`
+ (cond_isProduct `andCond` cond_args cls)
+
+cond_args :: Class -> Condition
+-- For some classes (eg Eq, Ord) we allow unlifted arg types
+-- by generating specialised code. For others (eg Data) we don't.
+cond_args cls _ tc
+ = case bad_args of
+ [] -> IsValid
+ (ty:_) -> NotValid (hang (text "Don't know how to derive" <+> quotes (ppr cls))
+ 2 (text "for type" <+> quotes (ppr ty)))
+ where
+ bad_args = [ arg_ty | con <- tyConDataCons tc
+ , arg_ty <- dataConOrigArgTys con
+ , isUnliftedType arg_ty
+ , not (ok_ty arg_ty) ]
+
+ cls_key = classKey cls
+ ok_ty arg_ty
+ | cls_key == eqClassKey = check_in arg_ty ordOpTbl
+ | cls_key == ordClassKey = check_in arg_ty ordOpTbl
+ | cls_key == showClassKey = check_in arg_ty boxConTbl
+ | cls_key == liftClassKey = check_in arg_ty litConTbl
+ | otherwise = False -- Read, Ix etc
+
+ check_in :: Type -> [(Type,a)] -> Bool
+ check_in arg_ty tbl = any (eqType arg_ty . fst) tbl
+
+
+cond_isEnumeration :: Condition
+cond_isEnumeration _ rep_tc
+ | isEnumerationTyCon rep_tc = IsValid
+ | otherwise = NotValid why
+ where
+ why = sep [ quotes (pprSourceTyCon rep_tc) <+>
+ text "must be an enumeration type"
+ , text "(an enumeration consists of one or more nullary, non-GADT constructors)" ]
+ -- See Note [Enumeration types] in TyCon
+
+cond_isProduct :: Condition
+cond_isProduct _ rep_tc
+ | isProductTyCon rep_tc = IsValid
+ | otherwise = NotValid why
+ where
+ why = quotes (pprSourceTyCon rep_tc) <+>
+ text "must have precisely one constructor"
+
+cond_functorOK :: Bool -> Bool -> Condition
+-- OK for Functor/Foldable/Traversable class
+-- Currently: (a) at least one argument
+-- (b) don't use argument contravariantly
+-- (c) don't use argument in the wrong place, e.g. data T a = T (X a a)
+-- (d) optionally: don't use function types
+-- (e) no "stupid context" on data type
+cond_functorOK allowFunctions allowExQuantifiedLastTyVar _ rep_tc
+ | null tc_tvs
+ = NotValid (text "Data type" <+> quotes (ppr rep_tc)
+ <+> text "must have some type parameters")
+
+ | not (null bad_stupid_theta)
+ = NotValid (text "Data type" <+> quotes (ppr rep_tc)
+ <+> text "must not have a class context:" <+> pprTheta bad_stupid_theta)
+
+ | otherwise
+ = allValid (map check_con data_cons)
+ where
+ tc_tvs = tyConTyVars rep_tc
+ Just (_, last_tv) = snocView tc_tvs
+ bad_stupid_theta = filter is_bad (tyConStupidTheta rep_tc)
+ is_bad pred = last_tv `elemVarSet` tyCoVarsOfType pred
+
+ data_cons = tyConDataCons rep_tc
+ check_con con = allValid (check_universal con : foldDataConArgs (ft_check con) con)
+
+ check_universal :: DataCon -> Validity
+ check_universal con
+ | allowExQuantifiedLastTyVar
+ = IsValid -- See Note [DeriveFoldable with ExistentialQuantification]
+ -- in TcGenFunctor
+ | Just tv <- getTyVar_maybe (last (tyConAppArgs (dataConOrigResTy con)))
+ , tv `elem` dataConUnivTyVars con
+ , not (tv `elemVarSet` tyCoVarsOfTypes (dataConTheta con))
+ = IsValid -- See Note [Check that the type variable is truly universal]
+ | otherwise
+ = NotValid (badCon con existential)
+
+ ft_check :: DataCon -> FFoldType Validity
+ ft_check con = FT { ft_triv = IsValid, ft_var = IsValid
+ , ft_co_var = NotValid (badCon con covariant)
+ , ft_fun = \x y -> if allowFunctions then x `andValid` y
+ else NotValid (badCon con functions)
+ , ft_tup = \_ xs -> allValid xs
+ , ft_ty_app = \_ x -> x
+ , ft_bad_app = NotValid (badCon con wrong_arg)
+ , ft_forall = \_ x -> x }
+
+ existential = text "must be truly polymorphic in the last argument of the data type"
+ covariant = text "must not use the type variable in a function argument"
+ functions = text "must not contain function types"
+ wrong_arg = text "must use the type variable only as the last argument of a data type"
+
+checkFlag :: LangExt.Extension -> Condition
+checkFlag flag dflags _
+ | xopt flag dflags = IsValid
+ | otherwise = NotValid why
+ where
+ why = text "You need " <> text flag_str
+ <+> text "to derive an instance for this class"
+ flag_str = case [ flagSpecName f | f <- xFlags , flagSpecFlag f == flag ] of
+ [s] -> s
+ other -> pprPanic "checkFlag" (ppr other)
+
+std_class_via_coercible :: Class -> Bool
+-- These standard classes can be derived for a newtype
+-- using the coercible trick *even if no -XGeneralizedNewtypeDeriving
+-- because giving so gives the same results as generating the boilerplate
+std_class_via_coercible clas
+ = classKey clas `elem` [eqClassKey, ordClassKey, ixClassKey, boundedClassKey]
+ -- Not Read/Show because they respect the type
+ -- Not Enum, because newtypes are never in Enum
+
+
+non_coercible_class :: Class -> Bool
+-- *Never* derive Read, Show, Typeable, Data, Generic, Generic1, Lift
+-- by Coercible, even with -XGeneralizedNewtypeDeriving
+-- Also, avoid Traversable, as the Coercible-derived instance and the "normal"-derived
+-- instance behave differently if there's a non-lawful Applicative out there.
+-- Besides, with roles, Coercible-deriving Traversable is ill-roled.
+non_coercible_class cls
+ = classKey cls `elem` ([ readClassKey, showClassKey, dataClassKey
+ , genClassKey, gen1ClassKey, typeableClassKey
+ , traversableClassKey, liftClassKey ])
+
+badCon :: DataCon -> SDoc -> SDoc
+badCon con msg = text "Constructor" <+> quotes (ppr con) <+> msg
+
+------------------------------------------------------------------
+
+newDerivClsInst :: ThetaType -> DerivSpec theta -> TcM ClsInst
+newDerivClsInst theta (DS { ds_name = dfun_name, ds_overlap = overlap_mode
+ , ds_tvs = tvs, ds_cls = clas, ds_tys = tys })
+ = newClsInst overlap_mode dfun_name tvs theta clas tys
+
+extendLocalInstEnv :: [ClsInst] -> TcM a -> TcM a
+-- Add new locally-defined instances; don't bother to check
+-- for functional dependency errors -- that'll happen in TcInstDcls
+extendLocalInstEnv dfuns thing_inside
+ = do { env <- getGblEnv
+ ; let inst_env' = extendInstEnvList (tcg_inst_env env) dfuns
+ env' = env { tcg_inst_env = inst_env' }
+ ; setGblEnv env' thing_inside }
+
+{-
+Note [Deriving any class]
+~~~~~~~~~~~~~~~~~~~~~~~~~
+Classic uses of a deriving clause, or a standalone-deriving declaration, are
+for:
+ * a stock class like Eq or Show, for which GHC knows how to generate
+ the instance code
+ * a newtype, via the mechanism enabled by GeneralizedNewtypeDeriving
+
+The DeriveAnyClass extension adds a third way to derive instances, based on
+empty instance declarations.
+
+The canonical use case is in combination with GHC.Generics and default method
+signatures. These allow us to have instance declarations being empty, but still
+useful, e.g.
+
+ data T a = ...blah..blah... deriving( Generic )
+ instance C a => C (T a) -- No 'where' clause
+
+where C is some "random" user-defined class.
+
+This boilerplate code can be replaced by the more compact
+
+ data T a = ...blah..blah... deriving( Generic, C )
+
+if DeriveAnyClass is enabled.
+
+This is not restricted to Generics; any class can be derived, simply giving
+rise to an empty instance.
+
+Unfortunately, it is not clear how to determine the context (when using a
+deriving clause; in standalone deriving, the user provides the context).
+GHC uses the same heuristic for figuring out the class context that it uses for
+Eq in the case of *-kinded classes, and for Functor in the case of
+* -> *-kinded classes. That may not be optimal or even wrong. But in such
+cases, standalone deriving can still be used.
+
+Note [Check that the type variable is truly universal]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+For Functor and Traversable instances, we must check that the *last argument*
+of the type constructor is used truly universally quantified. Example
+
+ data T a b where
+ T1 :: a -> b -> T a b -- Fine! Vanilla H-98
+ T2 :: b -> c -> T a b -- Fine! Existential c, but we can still map over 'b'
+ T3 :: b -> T Int b -- Fine! Constraint 'a', but 'b' is still polymorphic
+ T4 :: Ord b => b -> T a b -- No! 'b' is constrained
+ T5 :: b -> T b b -- No! 'b' is constrained
+ T6 :: T a (b,b) -- No! 'b' is constrained
+
+Notice that only the first of these constructors is vanilla H-98. We only
+need to take care about the last argument (b in this case). See Trac #8678.
+Eg. for T1-T3 we can write
+
+ fmap f (T1 a b) = T1 a (f b)
+ fmap f (T2 b c) = T2 (f b) c
+ fmap f (T3 x) = T3 (f x)
+
+We need not perform these checks for Foldable instances, however, since
+functions in Foldable can only consume existentially quantified type variables,
+rather than produce them (as is the case in Functor and Traversable functions.)
+As a result, T can have a derived Foldable instance:
+
+ foldr f z (T1 a b) = f b z
+ foldr f z (T2 b c) = f b z
+ foldr f z (T3 x) = f x z
+ foldr f z (T4 x) = f x z
+ foldr f z (T5 x) = f x z
+ foldr _ z T6 = z
+
+See Note [DeriveFoldable with ExistentialQuantification] in TcGenFunctor.
+-}
diff --git a/compiler/typecheck/TcGenDeriv.hs b/compiler/typecheck/TcGenDeriv.hs
index 0a5fbb0cf9..6c44d0db81 100644
--- a/compiler/typecheck/TcGenDeriv.hs
+++ b/compiler/typecheck/TcGenDeriv.hs
@@ -18,26 +18,28 @@ This is where we do all the grimy bindings' generation.
module TcGenDeriv (
BagDerivStuff, DerivStuff(..),
- hasStockDeriving,
- FFoldType(..), functorLikeTraverse,
- deepSubtypesContaining, foldDataConArgs,
- mkCoerceClassMethEqn,
+ gen_Eq_binds,
+ gen_Ord_binds,
+ gen_Enum_binds,
+ gen_Bounded_binds,
+ gen_Ix_binds,
+ gen_Show_binds,
+ gen_Read_binds,
+ gen_Data_binds,
+ gen_Lift_binds,
gen_Newtype_binds,
+ mkCoerceClassMethEqn,
genAuxBinds,
ordOpTbl, boxConTbl, litConTbl,
- mkRdrFunBind
+ mkRdrFunBind, error_Expr
) where
#include "HsVersions.h"
-
-import LoadIface( loadInterfaceForName )
-import HscTypes( lookupFixity, mi_fix )
import TcRnMonad
import HsSyn
import RdrName
import BasicTypes
-import Module( getModule )
import DataCon
import Name
import Fingerprint
@@ -59,10 +61,8 @@ import TysPrim
import TysWiredIn
import Type
import Class
-import TyCoRep
import VarSet
import VarEnv
-import State
import Util
import Var
import Outputable
@@ -72,9 +72,7 @@ import Pair
import Bag
import StaticFlags( opt_PprStyle_Debug )
-import ListSetOps ( assocMaybe )
import Data.List ( partition, intersperse )
-import Data.Maybe ( catMaybes, isJust )
type BagDerivStuff = Bag DerivStuff
@@ -95,72 +93,6 @@ data DerivStuff -- Please add this auxiliary stuff
-- New top-level auxiliary bindings
| DerivHsBind (LHsBind RdrName, LSig RdrName) -- Also used for SYB
-{-
-************************************************************************
-* *
- Class deriving diagnostics
-* *
-************************************************************************
-
-Only certain blessed classes can be used in a deriving clause (without the
-assistance of GeneralizedNewtypeDeriving or DeriveAnyClass). These classes
-are listed below in the definition of hasStockDeriving (with the exception
-of Generic and Generic1, which are handled separately in TcGenGenerics).
-
-A class might be able to be used in a deriving clause if -XDeriveAnyClass
-is willing to support it. The canDeriveAnyClass function in TcDeriv checks
-if this is the case.
--}
-
--- NB: The classes listed below should be in sync with the ones listed in
--- the definition of sideConditions in TcDeriv (except for Generic(1), as
--- noted above). If you add a new class to hasStockDeriving, make sure to
--- update sideConditions as well!
-hasStockDeriving :: Class
- -> Maybe (SrcSpan
- -> TyCon
- -> TcM (LHsBinds RdrName, BagDerivStuff))
-hasStockDeriving clas
- = assocMaybe gen_list (getUnique clas)
- where
- gen_list :: [(Unique, SrcSpan -> TyCon -> TcM (LHsBinds RdrName, BagDerivStuff))]
- gen_list = [ (eqClassKey, simple gen_Eq_binds)
- , (ordClassKey, simple gen_Ord_binds)
- , (enumClassKey, simple gen_Enum_binds)
- , (boundedClassKey, simple gen_Bounded_binds)
- , (ixClassKey, simple gen_Ix_binds)
- , (showClassKey, with_fix_env gen_Show_binds)
- , (readClassKey, with_fix_env gen_Read_binds)
- , (dataClassKey, gen_Data_binds)
- , (functorClassKey, simple gen_Functor_binds)
- , (foldableClassKey, simple gen_Foldable_binds)
- , (traversableClassKey, simple gen_Traversable_binds)
- , (liftClassKey, simple gen_Lift_binds) ]
-
- simple gen_fn loc tc
- = return (gen_fn loc tc)
-
- with_fix_env gen_fn loc tc
- = do { fix_env <- getDataConFixityFun tc
- ; return (gen_fn fix_env loc tc) }
-
-getDataConFixityFun :: TyCon -> TcM (Name -> Fixity)
--- If the TyCon is locally defined, we want the local fixity env;
--- but if it is imported (which happens for standalone deriving)
--- we need to get the fixity env from the interface file
--- c.f. RnEnv.lookupFixity, and Trac #9830
-getDataConFixityFun tc
- = do { this_mod <- getModule
- ; if nameIsLocalOrFrom this_mod name
- then do { fix_env <- getFixityEnv
- ; return (lookupFixity fix_env) }
- else do { iface <- loadInterfaceForName doc name
- -- Should already be loaded!
- ; return (mi_fix iface . nameOccName) } }
- where
- name = tyConName tc
- doc = text "Data con fixities for" <+> ppr name
-
{-
************************************************************************
@@ -1533,589 +1465,6 @@ geDouble_RDR = varQual_RDR gHC_PRIM (fsLit ">=##")
{-
************************************************************************
* *
- Functor instances
-
- see http://www.mail-archive.com/haskell-prime@haskell.org/msg02116.html
-
-* *
-************************************************************************
-
-For the data type:
-
- data T a = T1 Int a | T2 (T a)
-
-We generate the instance:
-
- instance Functor T where
- fmap f (T1 b1 a) = T1 b1 (f a)
- fmap f (T2 ta) = T2 (fmap f ta)
-
-Notice that we don't simply apply 'fmap' to the constructor arguments.
-Rather
- - Do nothing to an argument whose type doesn't mention 'a'
- - Apply 'f' to an argument of type 'a'
- - Apply 'fmap f' to other arguments
-That's why we have to recurse deeply into the constructor argument types,
-rather than just one level, as we typically do.
-
-What about types with more than one type parameter? In general, we only
-derive Functor for the last position:
-
- data S a b = S1 [b] | S2 (a, T a b)
- instance Functor (S a) where
- fmap f (S1 bs) = S1 (fmap f bs)
- fmap f (S2 (p,q)) = S2 (a, fmap f q)
-
-However, we have special cases for
- - tuples
- - functions
-
-More formally, we write the derivation of fmap code over type variable
-'a for type 'b as ($fmap 'a 'b). In this general notation the derived
-instance for T is:
-
- instance Functor T where
- fmap f (T1 x1 x2) = T1 ($(fmap 'a 'b1) x1) ($(fmap 'a 'a) x2)
- fmap f (T2 x1) = T2 ($(fmap 'a '(T a)) x1)
-
- $(fmap 'a 'b) = \x -> x -- when b does not contain a
- $(fmap 'a 'a) = f
- $(fmap 'a '(b1,b2)) = \x -> case x of (x1,x2) -> ($(fmap 'a 'b1) x1, $(fmap 'a 'b2) x2)
- $(fmap 'a '(T b1 b2)) = fmap $(fmap 'a 'b2) -- when a only occurs in the last parameter, b2
- $(fmap 'a '(b -> c)) = \x b -> $(fmap 'a' 'c) (x ($(cofmap 'a 'b) b))
-
-For functions, the type parameter 'a can occur in a contravariant position,
-which means we need to derive a function like:
-
- cofmap :: (a -> b) -> (f b -> f a)
-
-This is pretty much the same as $fmap, only without the $(cofmap 'a 'a) case:
-
- $(cofmap 'a 'b) = \x -> x -- when b does not contain a
- $(cofmap 'a 'a) = error "type variable in contravariant position"
- $(cofmap 'a '(b1,b2)) = \x -> case x of (x1,x2) -> ($(cofmap 'a 'b1) x1, $(cofmap 'a 'b2) x2)
- $(cofmap 'a '[b]) = map $(cofmap 'a 'b)
- $(cofmap 'a '(T b1 b2)) = fmap $(cofmap 'a 'b2) -- when a only occurs in the last parameter, b2
- $(cofmap 'a '(b -> c)) = \x b -> $(cofmap 'a' 'c) (x ($(fmap 'a 'c) b))
-
-Note that the code produced by $(fmap _ _) is always a higher order function,
-with type `(a -> b) -> (g a -> g b)` for some g. When we need to do pattern
-matching on the type, this means create a lambda function (see the (,) case above).
-The resulting code for fmap can look a bit weird, for example:
-
- data X a = X (a,Int)
- -- generated instance
- instance Functor X where
- fmap f (X x) = (\y -> case y of (x1,x2) -> X (f x1, (\z -> z) x2)) x
-
-The optimizer should be able to simplify this code by simple inlining.
-
-An older version of the deriving code tried to avoid these applied
-lambda functions by producing a meta level function. But the function to
-be mapped, `f`, is a function on the code level, not on the meta level,
-so it was eta expanded to `\x -> [| f $x |]`. This resulted in too much eta expansion.
-It is better to produce too many lambdas than to eta expand, see ticket #7436.
--}
-
-gen_Functor_binds :: SrcSpan -> TyCon -> (LHsBinds RdrName, BagDerivStuff)
-gen_Functor_binds loc tycon
- = (unitBag fmap_bind, emptyBag)
- where
- data_cons = tyConDataCons tycon
- fun_name = L loc fmap_RDR
- fmap_bind = mkRdrFunBind fun_name eqns
-
- fmap_eqn con = evalState (match_for_con [f_Pat] con =<< parts) bs_RDRs
- where
- parts = sequence $ foldDataConArgs ft_fmap con
-
- eqns | null data_cons = [mkSimpleMatch (FunRhs fun_name Prefix)
- [nlWildPat, nlWildPat]
- (error_Expr "Void fmap")]
- | otherwise = map fmap_eqn data_cons
-
- ft_fmap :: FFoldType (State [RdrName] (LHsExpr RdrName))
- ft_fmap = FT { ft_triv = mkSimpleLam $ \x -> return x
- -- fmap f = \x -> x
- , ft_var = return f_Expr
- -- fmap f = f
- , ft_fun = \g h -> do
- gg <- g
- hh <- h
- mkSimpleLam2 $ \x b -> return $
- nlHsApp hh (nlHsApp x (nlHsApp gg b))
- -- fmap f = \x b -> h (x (g b))
- , ft_tup = \t gs -> do
- gg <- sequence gs
- mkSimpleLam $ mkSimpleTupleCase match_for_con t gg
- -- fmap f = \x -> case x of (a1,a2,..) -> (g1 a1,g2 a2,..)
- , ft_ty_app = \_ g -> nlHsApp fmap_Expr <$> g
- -- fmap f = fmap g
- , ft_forall = \_ g -> g
- , ft_bad_app = panic "in other argument"
- , ft_co_var = panic "contravariant" }
-
- -- Con a1 a2 ... -> Con (f1 a1) (f2 a2) ...
- match_for_con :: [LPat RdrName] -> DataCon -> [LHsExpr RdrName]
- -> State [RdrName] (LMatch RdrName (LHsExpr RdrName))
- match_for_con = mkSimpleConMatch CaseAlt $
- \con_name xs -> return $ nlHsApps con_name xs -- Con x1 x2 ..
-
-{-
-Utility functions related to Functor deriving.
-
-Since several things use the same pattern of traversal, this is abstracted into functorLikeTraverse.
-This function works like a fold: it makes a value of type 'a' in a bottom up way.
--}
-
--- Generic traversal for Functor deriving
--- See Note [FFoldType and functorLikeTraverse]
-data FFoldType a -- Describes how to fold over a Type in a functor like way
- = FT { ft_triv :: a
- -- ^ Does not contain variable
- , ft_var :: a
- -- ^ The variable itself
- , ft_co_var :: a
- -- ^ The variable itself, contravariantly
- , ft_fun :: a -> a -> a
- -- ^ Function type
- , ft_tup :: TyCon -> [a] -> a
- -- ^ Tuple type
- , ft_ty_app :: Type -> a -> a
- -- ^ Type app, variable only in last argument
- , ft_bad_app :: a
- -- ^ Type app, variable other than in last argument
- , ft_forall :: TcTyVar -> a -> a
- -- ^ Forall type
- }
-
-functorLikeTraverse :: forall a.
- TyVar -- ^ Variable to look for
- -> FFoldType a -- ^ How to fold
- -> Type -- ^ Type to process
- -> a
-functorLikeTraverse var (FT { ft_triv = caseTrivial, ft_var = caseVar
- , ft_co_var = caseCoVar, ft_fun = caseFun
- , ft_tup = caseTuple, ft_ty_app = caseTyApp
- , ft_bad_app = caseWrongArg, ft_forall = caseForAll })
- ty
- = fst (go False ty)
- where
- go :: Bool -- Covariant or contravariant context
- -> Type
- -> (a, Bool) -- (result of type a, does type contain var)
-
- go co ty | Just ty' <- coreView ty = go co ty'
- go co (TyVarTy v) | v == var = (if co then caseCoVar else caseVar,True)
- go co (FunTy x y) | isPredTy x = go co y
- | xc || yc = (caseFun xr yr,True)
- where (xr,xc) = go (not co) x
- (yr,yc) = go co y
- go co (AppTy x y) | xc = (caseWrongArg, True)
- | yc = (caseTyApp x yr, True)
- where (_, xc) = go co x
- (yr,yc) = go co y
- go co ty@(TyConApp con args)
- | not (or xcs) = (caseTrivial, False) -- Variable does not occur
- -- At this point we know that xrs, xcs is not empty,
- -- and at least one xr is True
- | isTupleTyCon con = (caseTuple con xrs, True)
- | or (init xcs) = (caseWrongArg, True) -- T (..var..) ty
- | Just (fun_ty, _) <- splitAppTy_maybe ty -- T (..no var..) ty
- = (caseTyApp fun_ty (last xrs), True)
- | otherwise = (caseWrongArg, True) -- Non-decomposable (eg type function)
- where
- -- When folding over an unboxed tuple, we must explicitly drop the
- -- runtime rep arguments, or else GHC will generate twice as many
- -- variables in a unboxed tuple pattern match and expression as it
- -- actually needs. See Trac #12399
- (xrs,xcs) = unzip (map (go co) (dropRuntimeRepArgs args))
- go co (ForAllTy (TvBndr v vis) x)
- | isVisibleArgFlag vis = panic "unexpected visible binder"
- | v /= var && xc = (caseForAll v xr,True)
- where (xr,xc) = go co x
-
- go _ _ = (caseTrivial,False)
-
--- Return all syntactic subterms of ty that contain var somewhere
--- These are the things that should appear in instance constraints
-deepSubtypesContaining :: TyVar -> Type -> [TcType]
-deepSubtypesContaining tv
- = functorLikeTraverse tv
- (FT { ft_triv = []
- , ft_var = []
- , ft_fun = (++)
- , ft_tup = \_ xs -> concat xs
- , ft_ty_app = (:)
- , ft_bad_app = panic "in other argument"
- , ft_co_var = panic "contravariant"
- , ft_forall = \v xs -> filterOut ((v `elemVarSet`) . tyCoVarsOfType) xs })
-
-
-foldDataConArgs :: FFoldType a -> DataCon -> [a]
--- Fold over the arguments of the datacon
-foldDataConArgs ft con
- = map foldArg (dataConOrigArgTys con)
- where
- foldArg
- = case getTyVar_maybe (last (tyConAppArgs (dataConOrigResTy con))) of
- Just tv -> functorLikeTraverse tv ft
- Nothing -> const (ft_triv ft)
- -- If we are deriving Foldable for a GADT, there is a chance that the last
- -- type variable in the data type isn't actually a type variable at all.
- -- (for example, this can happen if the last type variable is refined to
- -- be a concrete type such as Int). If the last type variable is refined
- -- to be a specific type, then getTyVar_maybe will return Nothing.
- -- See Note [DeriveFoldable with ExistentialQuantification]
- --
- -- The kind checks have ensured the last type parameter is of kind *.
-
--- Make a HsLam using a fresh variable from a State monad
-mkSimpleLam :: (LHsExpr RdrName -> State [RdrName] (LHsExpr RdrName))
- -> State [RdrName] (LHsExpr RdrName)
--- (mkSimpleLam fn) returns (\x. fn(x))
-mkSimpleLam lam = do
- (n:names) <- get
- put names
- body <- lam (nlHsVar n)
- return (mkHsLam [nlVarPat n] body)
-
-mkSimpleLam2 :: (LHsExpr RdrName -> LHsExpr RdrName
- -> State [RdrName] (LHsExpr RdrName))
- -> State [RdrName] (LHsExpr RdrName)
-mkSimpleLam2 lam = do
- (n1:n2:names) <- get
- put names
- body <- lam (nlHsVar n1) (nlHsVar n2)
- return (mkHsLam [nlVarPat n1,nlVarPat n2] body)
-
--- "Con a1 a2 a3 -> fold [x1 a1, x2 a2, x3 a3]"
---
--- @mkSimpleConMatch fold extra_pats con insides@ produces a match clause in
--- which the LHS pattern-matches on @extra_pats@, followed by a match on the
--- constructor @con@ and its arguments. The RHS folds (with @fold@) over @con@
--- and its arguments, applying an expression (from @insides@) to each of the
--- respective arguments of @con@.
-mkSimpleConMatch :: Monad m => HsMatchContext RdrName
- -> (RdrName -> [LHsExpr RdrName] -> m (LHsExpr RdrName))
- -> [LPat RdrName]
- -> DataCon
- -> [LHsExpr RdrName]
- -> m (LMatch RdrName (LHsExpr RdrName))
-mkSimpleConMatch ctxt fold extra_pats con insides = do
- let con_name = getRdrName con
- let vars_needed = takeList insides as_RDRs
- let pat = nlConVarPat con_name vars_needed
- rhs <- fold con_name (zipWith nlHsApp insides (map nlHsVar vars_needed))
- return $ mkMatch ctxt (extra_pats ++ [pat]) rhs
- (noLoc emptyLocalBinds)
-
--- "Con a1 a2 a3 -> fmap (\b2 -> Con a1 b2 a3) (traverse f a2)"
---
--- @mkSimpleConMatch2 fold extra_pats con insides@ behaves very similarly to
--- 'mkSimpleConMatch', with two key differences:
---
--- 1. @insides@ is a @[Maybe (LHsExpr RdrName)]@ instead of a
--- @[LHsExpr RdrName]@. This is because it filters out the expressions
--- corresponding to arguments whose types do not mention the last type
--- variable in a derived 'Foldable' or 'Traversable' instance (i.e., the
--- 'Nothing' elements of @insides@).
---
--- 2. @fold@ takes an expression as its first argument instead of a
--- constructor name. This is because it uses a specialized
--- constructor function expression that only takes as many parameters as
--- there are argument types that mention the last type variable.
---
--- See Note [Generated code for DeriveFoldable and DeriveTraversable]
-mkSimpleConMatch2 :: Monad m
- => HsMatchContext RdrName
- -> (LHsExpr RdrName -> [LHsExpr RdrName]
- -> m (LHsExpr RdrName))
- -> [LPat RdrName]
- -> DataCon
- -> [Maybe (LHsExpr RdrName)]
- -> m (LMatch RdrName (LHsExpr RdrName))
-mkSimpleConMatch2 ctxt fold extra_pats con insides = do
- let con_name = getRdrName con
- vars_needed = takeList insides as_RDRs
- pat = nlConVarPat con_name vars_needed
- -- Make sure to zip BEFORE invoking catMaybes. We want the variable
- -- indicies in each expression to match up with the argument indices
- -- in con_expr (defined below).
- exps = catMaybes $ zipWith (\i v -> (`nlHsApp` v) <$> i)
- insides (map nlHsVar vars_needed)
- -- An element of argTysTyVarInfo is True if the constructor argument
- -- with the same index has a type which mentions the last type
- -- variable.
- argTysTyVarInfo = map isJust insides
- (asWithTyVar, asWithoutTyVar) = partitionByList argTysTyVarInfo as_RDRs
-
- con_expr
- | null asWithTyVar = nlHsApps con_name $ map nlHsVar asWithoutTyVar
- | otherwise =
- let bs = filterByList argTysTyVarInfo bs_RDRs
- vars = filterByLists argTysTyVarInfo
- (map nlHsVar bs_RDRs)
- (map nlHsVar as_RDRs)
- in mkHsLam (map nlVarPat bs) (nlHsApps con_name vars)
-
- rhs <- fold con_expr exps
- return $ mkMatch ctxt (extra_pats ++ [pat]) rhs
- (noLoc emptyLocalBinds)
-
--- "case x of (a1,a2,a3) -> fold [x1 a1, x2 a2, x3 a3]"
-mkSimpleTupleCase :: Monad m => ([LPat RdrName] -> DataCon -> [a]
- -> m (LMatch RdrName (LHsExpr RdrName)))
- -> TyCon -> [a] -> LHsExpr RdrName -> m (LHsExpr RdrName)
-mkSimpleTupleCase match_for_con tc insides x
- = do { let data_con = tyConSingleDataCon tc
- ; match <- match_for_con [] data_con insides
- ; return $ nlHsCase x [match] }
-
-{-
-************************************************************************
-* *
- Foldable instances
-
- see http://www.mail-archive.com/haskell-prime@haskell.org/msg02116.html
-
-* *
-************************************************************************
-
-Deriving Foldable instances works the same way as Functor instances,
-only Foldable instances are not possible for function types at all.
-Given (data T a = T a a (T a) deriving Foldable), we get:
-
- instance Foldable T where
- foldr f z (T x1 x2 x3) =
- $(foldr 'a 'a) x1 ( $(foldr 'a 'a) x2 ( $(foldr 'a '(T a)) x3 z ) )
-
--XDeriveFoldable is different from -XDeriveFunctor in that it filters out
-arguments to the constructor that would produce useless code in a Foldable
-instance. For example, the following datatype:
-
- data Foo a = Foo Int a Int deriving Foldable
-
-would have the following generated Foldable instance:
-
- instance Foldable Foo where
- foldr f z (Foo x1 x2 x3) = $(foldr 'a 'a) x2
-
-since neither of the two Int arguments are folded over.
-
-The cases are:
-
- $(foldr 'a 'a) = f
- $(foldr 'a '(b1,b2)) = \x z -> case x of (x1,x2) -> $(foldr 'a 'b1) x1 ( $(foldr 'a 'b2) x2 z )
- $(foldr 'a '(T b1 b2)) = \x z -> foldr $(foldr 'a 'b2) z x -- when a only occurs in the last parameter, b2
-
-Note that the arguments to the real foldr function are the wrong way around,
-since (f :: a -> b -> b), while (foldr f :: b -> t a -> b).
-
-One can envision a case for types that don't contain the last type variable:
-
- $(foldr 'a 'b) = \x z -> z -- when b does not contain a
-
-But this case will never materialize, since the aforementioned filtering
-removes all such types from consideration.
-See Note [Generated code for DeriveFoldable and DeriveTraversable].
-
-Foldable instances differ from Functor and Traversable instances in that
-Foldable instances can be derived for data types in which the last type
-variable is existentially quantified. In particular, if the last type variable
-is refined to a more specific type in a GADT:
-
- data GADT a where
- G :: a ~ Int => a -> G Int
-
-then the deriving machinery does not attempt to check that the type a contains
-Int, since it is not syntactically equal to a type variable. That is, the
-derived Foldable instance for GADT is:
-
- instance Foldable GADT where
- foldr _ z (GADT _) = z
-
-See Note [DeriveFoldable with ExistentialQuantification].
-
--}
-
-gen_Foldable_binds :: SrcSpan -> TyCon -> (LHsBinds RdrName, BagDerivStuff)
-gen_Foldable_binds loc tycon
- = (listToBag [foldr_bind, foldMap_bind], emptyBag)
- where
- data_cons = tyConDataCons tycon
-
- foldr_bind = mkRdrFunBind (L loc foldable_foldr_RDR) eqns
- eqns = map foldr_eqn data_cons
- foldr_eqn con
- = evalState (match_foldr z_Expr [f_Pat,z_Pat] con =<< parts) bs_RDRs
- where
- parts = sequence $ foldDataConArgs ft_foldr con
-
- foldMap_bind = mkRdrFunBind (L loc foldMap_RDR) (map foldMap_eqn data_cons)
- foldMap_eqn con
- = evalState (match_foldMap [f_Pat] con =<< parts) bs_RDRs
- where
- parts = sequence $ foldDataConArgs ft_foldMap con
-
- -- Yields 'Just' an expression if we're folding over a type that mentions
- -- the last type parameter of the datatype. Otherwise, yields 'Nothing'.
- -- See Note [FFoldType and functorLikeTraverse]
- ft_foldr :: FFoldType (State [RdrName] (Maybe (LHsExpr RdrName)))
- ft_foldr
- = FT { ft_triv = return Nothing
- -- foldr f = \x z -> z
- , ft_var = return $ Just f_Expr
- -- foldr f = f
- , ft_tup = \t g -> do
- gg <- sequence g
- lam <- mkSimpleLam2 $ \x z ->
- mkSimpleTupleCase (match_foldr z) t gg x
- return (Just lam)
- -- foldr f = (\x z -> case x of ...)
- , ft_ty_app = \_ g -> do
- gg <- g
- mapM (\gg' -> mkSimpleLam2 $ \x z -> return $
- nlHsApps foldable_foldr_RDR [gg',z,x]) gg
- -- foldr f = (\x z -> foldr g z x)
- , ft_forall = \_ g -> g
- , ft_co_var = panic "contravariant"
- , ft_fun = panic "function"
- , ft_bad_app = panic "in other argument" }
-
- match_foldr :: LHsExpr RdrName
- -> [LPat RdrName]
- -> DataCon
- -> [Maybe (LHsExpr RdrName)]
- -> State [RdrName] (LMatch RdrName (LHsExpr RdrName))
- match_foldr z = mkSimpleConMatch2 LambdaExpr $ \_ xs -> return (mkFoldr xs)
- where
- -- g1 v1 (g2 v2 (.. z))
- mkFoldr :: [LHsExpr RdrName] -> LHsExpr RdrName
- mkFoldr = foldr nlHsApp z
-
- -- See Note [FFoldType and functorLikeTraverse]
- ft_foldMap :: FFoldType (State [RdrName] (Maybe (LHsExpr RdrName)))
- ft_foldMap
- = FT { ft_triv = return Nothing
- -- foldMap f = \x -> mempty
- , ft_var = return (Just f_Expr)
- -- foldMap f = f
- , ft_tup = \t g -> do
- gg <- sequence g
- lam <- mkSimpleLam $ mkSimpleTupleCase match_foldMap t gg
- return (Just lam)
- -- foldMap f = \x -> case x of (..,)
- , ft_ty_app = \_ g -> fmap (nlHsApp foldMap_Expr) <$> g
- -- foldMap f = foldMap g
- , ft_forall = \_ g -> g
- , ft_co_var = panic "contravariant"
- , ft_fun = panic "function"
- , ft_bad_app = panic "in other argument" }
-
- match_foldMap :: [LPat RdrName]
- -> DataCon
- -> [Maybe (LHsExpr RdrName)]
- -> State [RdrName] (LMatch RdrName (LHsExpr RdrName))
- match_foldMap = mkSimpleConMatch2 CaseAlt $ \_ xs -> return (mkFoldMap xs)
- where
- -- mappend v1 (mappend v2 ..)
- mkFoldMap :: [LHsExpr RdrName] -> LHsExpr RdrName
- mkFoldMap [] = mempty_Expr
- mkFoldMap xs = foldr1 (\x y -> nlHsApps mappend_RDR [x,y]) xs
-
-{-
-************************************************************************
-* *
- Traversable instances
-
- see http://www.mail-archive.com/haskell-prime@haskell.org/msg02116.html
-* *
-************************************************************************
-
-Again, Traversable is much like Functor and Foldable.
-
-The cases are:
-
- $(traverse 'a 'a) = f
- $(traverse 'a '(b1,b2)) = \x -> case x of (x1,x2) -> (,) <$> $(traverse 'a 'b1) x1 <*> $(traverse 'a 'b2) x2
- $(traverse 'a '(T b1 b2)) = traverse $(traverse 'a 'b2) -- when a only occurs in the last parameter, b2
-
-Like -XDeriveFoldable, -XDeriveTraversable filters out arguments whose types
-do not mention the last type parameter. Therefore, the following datatype:
-
- data Foo a = Foo Int a Int
-
-would have the following derived Traversable instance:
-
- instance Traversable Foo where
- traverse f (Foo x1 x2 x3) =
- fmap (\b2 -> Foo x1 b2 x3) ( $(traverse 'a 'a) x2 )
-
-since the two Int arguments do not produce any effects in a traversal.
-
-One can envision a case for types that do not mention the last type parameter:
-
- $(traverse 'a 'b) = pure -- when b does not contain a
-
-But this case will never materialize, since the aforementioned filtering
-removes all such types from consideration.
-See Note [Generated code for DeriveFoldable and DeriveTraversable].
--}
-
-gen_Traversable_binds :: SrcSpan -> TyCon -> (LHsBinds RdrName, BagDerivStuff)
-gen_Traversable_binds loc tycon
- = (unitBag traverse_bind, emptyBag)
- where
- data_cons = tyConDataCons tycon
-
- traverse_bind = mkRdrFunBind (L loc traverse_RDR) eqns
- eqns = map traverse_eqn data_cons
- traverse_eqn con
- = evalState (match_for_con [f_Pat] con =<< parts) bs_RDRs
- where
- parts = sequence $ foldDataConArgs ft_trav con
-
- -- Yields 'Just' an expression if we're folding over a type that mentions
- -- the last type parameter of the datatype. Otherwise, yields 'Nothing'.
- -- See Note [FFoldType and functorLikeTraverse]
- ft_trav :: FFoldType (State [RdrName] (Maybe (LHsExpr RdrName)))
- ft_trav
- = FT { ft_triv = return Nothing
- -- traverse f = pure x
- , ft_var = return (Just f_Expr)
- -- traverse f = f x
- , ft_tup = \t gs -> do
- gg <- sequence gs
- lam <- mkSimpleLam $ mkSimpleTupleCase match_for_con t gg
- return (Just lam)
- -- traverse f = \x -> case x of (a1,a2,..) ->
- -- (,,) <$> g1 a1 <*> g2 a2 <*> ..
- , ft_ty_app = \_ g -> fmap (nlHsApp traverse_Expr) <$> g
- -- traverse f = traverse g
- , ft_forall = \_ g -> g
- , ft_co_var = panic "contravariant"
- , ft_fun = panic "function"
- , ft_bad_app = panic "in other argument" }
-
- -- Con a1 a2 ... -> fmap (\b1 b2 ... -> Con b1 b2 ...) (g1 a1)
- -- <*> g2 a2 <*> ...
- match_for_con :: [LPat RdrName]
- -> DataCon
- -> [Maybe (LHsExpr RdrName)]
- -> State [RdrName] (LMatch RdrName (LHsExpr RdrName))
- match_for_con = mkSimpleConMatch2 CaseAlt $
- \con xs -> return (mkApCon con xs)
- where
- -- fmap (\b1 b2 ... -> Con b1 b2 ...) x1 <*> x2 <*> ..
- mkApCon :: LHsExpr RdrName -> [LHsExpr RdrName] -> LHsExpr RdrName
- mkApCon con [] = nlHsApps pure_RDR [con]
- mkApCon con (x:xs) = foldl appAp (nlHsApps fmap_RDR [con,x]) xs
- where appAp x y = nlHsApps ap_RDR [x,y]
-
-{-
-************************************************************************
-* *
Lift instances
* *
************************************************************************
@@ -2228,7 +1577,7 @@ to say how it should be instantiated. Recall
coerce :: Coeercible a b => a -> b
By giving it explicit type arguments we deal with the case where
-'op' has a higher rank type, and so we must instantiae 'coerce' with
+'op' has a higher rank type, and so we must instantiate 'coerce' with
a polytype. E.g.
class C a where op :: forall b. a -> b -> b
newtype T x = MkT <rep-ty>
@@ -2649,31 +1998,22 @@ as_RDRs = [ mkVarUnqual (mkFastString ("a"++show i)) | i <- [(1::Int) ..
bs_RDRs = [ mkVarUnqual (mkFastString ("b"++show i)) | i <- [(1::Int) .. ] ]
cs_RDRs = [ mkVarUnqual (mkFastString ("c"++show i)) | i <- [(1::Int) .. ] ]
-a_Expr, b_Expr, c_Expr, f_Expr, z_Expr, ltTag_Expr, eqTag_Expr, gtTag_Expr,
- false_Expr, true_Expr, fmap_Expr,
- mempty_Expr, foldMap_Expr, traverse_Expr :: LHsExpr RdrName
+a_Expr, b_Expr, c_Expr, ltTag_Expr, eqTag_Expr, gtTag_Expr, false_Expr,
+ true_Expr :: LHsExpr RdrName
a_Expr = nlHsVar a_RDR
b_Expr = nlHsVar b_RDR
c_Expr = nlHsVar c_RDR
-f_Expr = nlHsVar f_RDR
-z_Expr = nlHsVar z_RDR
ltTag_Expr = nlHsVar ltTag_RDR
eqTag_Expr = nlHsVar eqTag_RDR
gtTag_Expr = nlHsVar gtTag_RDR
false_Expr = nlHsVar false_RDR
true_Expr = nlHsVar true_RDR
-fmap_Expr = nlHsVar fmap_RDR
--- pure_Expr = nlHsVar pure_RDR
-mempty_Expr = nlHsVar mempty_RDR
-foldMap_Expr = nlHsVar foldMap_RDR
-traverse_Expr = nlHsVar traverse_RDR
-a_Pat, b_Pat, c_Pat, d_Pat, f_Pat, k_Pat, z_Pat :: LPat RdrName
+a_Pat, b_Pat, c_Pat, d_Pat, k_Pat, z_Pat :: LPat RdrName
a_Pat = nlVarPat a_RDR
b_Pat = nlVarPat b_RDR
c_Pat = nlVarPat c_RDR
d_Pat = nlVarPat d_RDR
-f_Pat = nlVarPat f_RDR
k_Pat = nlVarPat k_RDR
z_Pat = nlVarPat z_RDR
@@ -2704,7 +2044,7 @@ mkAuxBinderName parent occ_fun
parent_stable_hash =
let Fingerprint high low = fingerprintString parent_stable
in toBase62 high ++ toBase62Padded low
- -- See Note [Base 62 encoding 128-bit integers]
+ -- See Note [Base 62 encoding 128-bit integers] in Encoding
parent_occ = nameOccName parent
@@ -2730,235 +2070,4 @@ To make the symbol names short we take a base62 hash of the full name.
In the past we used the *unique* from the parent, but that's not stable across
recompilations as uniques are nondeterministic.
-
-Note [DeriveFoldable with ExistentialQuantification]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Functor and Traversable instances can only be derived for data types whose
-last type parameter is truly universally polymorphic. For example:
-
- data T a b where
- T1 :: b -> T a b -- YES, b is unconstrained
- T2 :: Ord b => b -> T a b -- NO, b is constrained by (Ord b)
- T3 :: b ~ Int => b -> T a b -- NO, b is constrained by (b ~ Int)
- T4 :: Int -> T a Int -- NO, this is just like T3
- T5 :: Ord a => a -> b -> T a b -- YES, b is unconstrained, even
- -- though a is existential
- T6 :: Int -> T Int b -- YES, b is unconstrained
-
-For Foldable instances, however, we can completely lift the constraint that
-the last type parameter be truly universally polymorphic. This means that T
-(as defined above) can have a derived Foldable instance:
-
- instance Foldable (T a) where
- foldr f z (T1 b) = f b z
- foldr f z (T2 b) = f b z
- foldr f z (T3 b) = f b z
- foldr f z (T4 b) = z
- foldr f z (T5 a b) = f b z
- foldr f z (T6 a) = z
-
- foldMap f (T1 b) = f b
- foldMap f (T2 b) = f b
- foldMap f (T3 b) = f b
- foldMap f (T4 b) = mempty
- foldMap f (T5 a b) = f b
- foldMap f (T6 a) = mempty
-
-In a Foldable instance, it is safe to fold over an occurrence of the last type
-parameter that is not truly universally polymorphic. However, there is a bit
-of subtlety in determining what is actually an occurrence of a type parameter.
-T3 and T4, as defined above, provide one example:
-
- data T a b where
- ...
- T3 :: b ~ Int => b -> T a b
- T4 :: Int -> T a Int
- ...
-
- instance Foldable (T a) where
- ...
- foldr f z (T3 b) = f b z
- foldr f z (T4 b) = z
- ...
- foldMap f (T3 b) = f b
- foldMap f (T4 b) = mempty
- ...
-
-Notice that the argument of T3 is folded over, whereas the argument of T4 is
-not. This is because we only fold over constructor arguments that
-syntactically mention the universally quantified type parameter of that
-particular data constructor. See foldDataConArgs for how this is implemented.
-
-As another example, consider the following data type. The argument of each
-constructor has the same type as the last type parameter:
-
- data E a where
- E1 :: (a ~ Int) => a -> E a
- E2 :: Int -> E Int
- E3 :: (a ~ Int) => a -> E Int
- E4 :: (a ~ Int) => Int -> E a
-
-Only E1's argument is an occurrence of a universally quantified type variable
-that is syntactically equivalent to the last type parameter, so only E1's
-argument will be be folded over in a derived Foldable instance.
-
-See Trac #10447 for the original discussion on this feature. Also see
-https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/DeriveFunctor
-for a more in-depth explanation.
-
-Note [FFoldType and functorLikeTraverse]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Deriving Functor, Foldable, and Traversable all require generating expressions
-which perform an operation on each argument of a data constructor depending
-on the argument's type. In particular, a generated operation can be different
-depending on whether the type mentions the last type variable of the datatype
-(e.g., if you have data T a = MkT a Int, then a generated foldr expresion would
-fold over the first argument of MkT, but not the second).
-
-This pattern is abstracted with the FFoldType datatype, which provides hooks
-for the user to specify how a constructor argument should be folded when it
-has a type with a particular "shape". The shapes are as follows (assume that
-a is the last type variable in a given datatype):
-
-* ft_triv: The type does not mention the last type variable at all.
- Examples: Int, b
-
-* ft_var: The type is syntactically equal to the last type variable.
- Moreover, the type appears in a covariant position (see
- the Deriving Functor instances section of the users' guide
- for an in-depth explanation of covariance vs. contravariance).
- Example: a (covariantly)
-
-* ft_co_var: The type is syntactically equal to the last type variable.
- Moreover, the type appears in a contravariant position.
- Example: a (contravariantly)
-
-* ft_fun: A function type which mentions the last type variable in
- the argument position, result position or both.
- Examples: a -> Int, Int -> a, Maybe a -> [a]
-
-* ft_tup: A tuple type which mentions the last type variable in at least
- one of its fields. The TyCon argument of ft_tup represents the
- particular tuple's type constructor.
- Examples: (a, Int), (Maybe a, [a], Either a Int), (# Int, a #)
-
-* ft_ty_app: A type is being applied to the last type parameter, where the
- applied type does not mention the last type parameter (if it
- did, it would fall under ft_bad_app). The Type argument to
- ft_ty_app represents the applied type.
-
- Note that functions, tuples, and foralls are distinct cases
- and take precedence of ft_ty_app. (For example, (Int -> a) would
- fall under (ft_fun Int a), not (ft_ty_app ((->) Int) a).
- Examples: Maybe a, Either b a
-
-* ft_bad_app: A type application uses the last type parameter in a position
- other than the last argument. This case is singled out because
- Functor, Foldable, and Traversable instances cannot be derived
- for datatypes containing arguments with such types.
- Examples: Either a Int, Const a b
-
-* ft_forall: A forall'd type mentions the last type parameter on its right-
- hand side (and is not quantified on the left-hand side). This
- case is present mostly for plumbing purposes.
- Example: forall b. Either b a
-
-If FFoldType describes a strategy for folding subcomponents of a Type, then
-functorLikeTraverse is the function that applies that strategy to the entirety
-of a Type, returning the final folded-up result.
-
-foldDataConArgs applies functorLikeTraverse to every argument type of a
-constructor, returning a list of the fold results. This makes foldDataConArgs
-a natural way to generate the subexpressions in a generated fmap, foldr,
-foldMap, or traverse definition (the subexpressions must then be combined in
-a method-specific fashion to form the final generated expression).
-
-Deriving Generic1 also does validity checking by looking for the last type
-variable in certain positions of a constructor's argument types, so it also
-uses foldDataConArgs. See Note [degenerate use of FFoldType] in TcGenGenerics.
-
-Note [Generated code for DeriveFoldable and DeriveTraversable]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We adapt the algorithms for -XDeriveFoldable and -XDeriveTraversable based on
-that of -XDeriveFunctor. However, there an important difference between deriving
-the former two typeclasses and the latter one, which is best illustrated by the
-following scenario:
-
- data WithInt a = WithInt a Int# deriving (Functor, Foldable, Traversable)
-
-The generated code for the Functor instance is straightforward:
-
- instance Functor WithInt where
- fmap f (WithInt a i) = WithInt (f a) i
-
-But if we use too similar of a strategy for deriving the Foldable and
-Traversable instances, we end up with this code:
-
- instance Foldable WithInt where
- foldMap f (WithInt a i) = f a <> mempty
-
- instance Traversable WithInt where
- traverse f (WithInt a i) = fmap WithInt (f a) <*> pure i
-
-This is unsatisfying for two reasons:
-
-1. The Traversable instance doesn't typecheck! Int# is of kind #, but pure
- expects an argument whose type is of kind *. This effectively prevents
- Traversable from being derived for any datatype with an unlifted argument
- type (Trac #11174).
-
-2. The generated code contains superfluous expressions. By the Monoid laws,
- we can reduce (f a <> mempty) to (f a), and by the Applicative laws, we can
- reduce (fmap WithInt (f a) <*> pure i) to (fmap (\b -> WithInt b i) (f a)).
-
-We can fix both of these issues by incorporating a slight twist to the usual
-algorithm that we use for -XDeriveFunctor. The differences can be summarized
-as follows:
-
-1. In the generated expression, we only fold over arguments whose types
- mention the last type parameter. Any other argument types will simply
- produce useless 'mempty's or 'pure's, so they can be safely ignored.
-
-2. In the case of -XDeriveTraversable, instead of applying ConName,
- we apply (\b_i ... b_k -> ConName a_1 ... a_n), where
-
- * ConName has n arguments
- * {b_i, ..., b_k} is a subset of {a_1, ..., a_n} whose indices correspond
- to the arguments whose types mention the last type parameter. As a
- consequence, taking the difference of {a_1, ..., a_n} and
- {b_i, ..., b_k} yields the all the argument values of ConName whose types
- do not mention the last type parameter. Note that [i, ..., k] is a
- strictly increasing—but not necessarily consecutive—integer sequence.
-
- For example, the datatype
-
- data Foo a = Foo Int a Int a
-
- would generate the following Traversable instance:
-
- instance Traversable Foo where
- traverse f (Foo a1 a2 a3 a4) =
- fmap (\b2 b4 -> Foo a1 b2 a3 b4) (f a2) <*> f a4
-
-Technically, this approach would also work for -XDeriveFunctor as well, but we
-decide not to do so because:
-
-1. There's not much benefit to generating, e.g., ((\b -> WithInt b i) (f a))
- instead of (WithInt (f a) i).
-
-2. There would be certain datatypes for which the above strategy would
- generate Functor code that would fail to typecheck. For example:
-
- data Bar f a = Bar (forall f. Functor f => f a) deriving Functor
-
- With the conventional algorithm, it would generate something like:
-
- fmap f (Bar a) = Bar (fmap f a)
-
- which typechecks. But with the strategy mentioned above, it would generate:
-
- fmap f (Bar a) = (\b -> Bar b) (fmap f a)
-
- which does not typecheck, since GHC cannot unify the rank-2 type variables
- in the types of b and (fmap f a).
-}
diff --git a/compiler/typecheck/TcGenFunctor.hs b/compiler/typecheck/TcGenFunctor.hs
new file mode 100644
index 0000000000..c57740324e
--- /dev/null
+++ b/compiler/typecheck/TcGenFunctor.hs
@@ -0,0 +1,875 @@
+{-
+(c) The University of Glasgow 2011
+
+
+The deriving code for the Functor, Foldable, and Traversable classes
+(equivalent to the code in TcGenDeriv, for other classes)
+-}
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module TcGenFunctor (
+ FFoldType(..), functorLikeTraverse,
+ deepSubtypesContaining, foldDataConArgs,
+
+ gen_Functor_binds, gen_Foldable_binds, gen_Traversable_binds
+ ) where
+
+import Bag
+import DataCon
+import FastString
+import HsSyn
+import Panic
+import PrelNames
+import RdrName
+import SrcLoc
+import State
+import TcGenDeriv
+import TcType
+import TyCon
+import TyCoRep
+import Type
+import Util
+import Var
+import VarSet
+
+import Data.Maybe (catMaybes, isJust)
+
+{-
+************************************************************************
+* *
+ Functor instances
+
+ see http://www.mail-archive.com/haskell-prime@haskell.org/msg02116.html
+
+* *
+************************************************************************
+
+For the data type:
+
+ data T a = T1 Int a | T2 (T a)
+
+We generate the instance:
+
+ instance Functor T where
+ fmap f (T1 b1 a) = T1 b1 (f a)
+ fmap f (T2 ta) = T2 (fmap f ta)
+
+Notice that we don't simply apply 'fmap' to the constructor arguments.
+Rather
+ - Do nothing to an argument whose type doesn't mention 'a'
+ - Apply 'f' to an argument of type 'a'
+ - Apply 'fmap f' to other arguments
+That's why we have to recurse deeply into the constructor argument types,
+rather than just one level, as we typically do.
+
+What about types with more than one type parameter? In general, we only
+derive Functor for the last position:
+
+ data S a b = S1 [b] | S2 (a, T a b)
+ instance Functor (S a) where
+ fmap f (S1 bs) = S1 (fmap f bs)
+ fmap f (S2 (p,q)) = S2 (a, fmap f q)
+
+However, we have special cases for
+ - tuples
+ - functions
+
+More formally, we write the derivation of fmap code over type variable
+'a for type 'b as ($fmap 'a 'b). In this general notation the derived
+instance for T is:
+
+ instance Functor T where
+ fmap f (T1 x1 x2) = T1 ($(fmap 'a 'b1) x1) ($(fmap 'a 'a) x2)
+ fmap f (T2 x1) = T2 ($(fmap 'a '(T a)) x1)
+
+ $(fmap 'a 'b) = \x -> x -- when b does not contain a
+ $(fmap 'a 'a) = f
+ $(fmap 'a '(b1,b2)) = \x -> case x of (x1,x2) -> ($(fmap 'a 'b1) x1, $(fmap 'a 'b2) x2)
+ $(fmap 'a '(T b1 b2)) = fmap $(fmap 'a 'b2) -- when a only occurs in the last parameter, b2
+ $(fmap 'a '(b -> c)) = \x b -> $(fmap 'a' 'c) (x ($(cofmap 'a 'b) b))
+
+For functions, the type parameter 'a can occur in a contravariant position,
+which means we need to derive a function like:
+
+ cofmap :: (a -> b) -> (f b -> f a)
+
+This is pretty much the same as $fmap, only without the $(cofmap 'a 'a) case:
+
+ $(cofmap 'a 'b) = \x -> x -- when b does not contain a
+ $(cofmap 'a 'a) = error "type variable in contravariant position"
+ $(cofmap 'a '(b1,b2)) = \x -> case x of (x1,x2) -> ($(cofmap 'a 'b1) x1, $(cofmap 'a 'b2) x2)
+ $(cofmap 'a '[b]) = map $(cofmap 'a 'b)
+ $(cofmap 'a '(T b1 b2)) = fmap $(cofmap 'a 'b2) -- when a only occurs in the last parameter, b2
+ $(cofmap 'a '(b -> c)) = \x b -> $(cofmap 'a' 'c) (x ($(fmap 'a 'c) b))
+
+Note that the code produced by $(fmap _ _) is always a higher order function,
+with type `(a -> b) -> (g a -> g b)` for some g. When we need to do pattern
+matching on the type, this means create a lambda function (see the (,) case above).
+The resulting code for fmap can look a bit weird, for example:
+
+ data X a = X (a,Int)
+ -- generated instance
+ instance Functor X where
+ fmap f (X x) = (\y -> case y of (x1,x2) -> X (f x1, (\z -> z) x2)) x
+
+The optimizer should be able to simplify this code by simple inlining.
+
+An older version of the deriving code tried to avoid these applied
+lambda functions by producing a meta level function. But the function to
+be mapped, `f`, is a function on the code level, not on the meta level,
+so it was eta expanded to `\x -> [| f $x |]`. This resulted in too much eta expansion.
+It is better to produce too many lambdas than to eta expand, see ticket #7436.
+-}
+
+gen_Functor_binds :: SrcSpan -> TyCon -> (LHsBinds RdrName, BagDerivStuff)
+gen_Functor_binds loc tycon
+ = (unitBag fmap_bind, emptyBag)
+ where
+ data_cons = tyConDataCons tycon
+ fun_name = L loc fmap_RDR
+ fmap_bind = mkRdrFunBind fun_name eqns
+
+ fmap_eqn con = evalState (match_for_con [f_Pat] con =<< parts) bs_RDRs
+ where
+ parts = sequence $ foldDataConArgs ft_fmap con
+
+ eqns | null data_cons = [mkSimpleMatch (FunRhs fun_name Prefix)
+ [nlWildPat, nlWildPat]
+ (error_Expr "Void fmap")]
+ | otherwise = map fmap_eqn data_cons
+
+ ft_fmap :: FFoldType (State [RdrName] (LHsExpr RdrName))
+ ft_fmap = FT { ft_triv = mkSimpleLam $ \x -> return x
+ -- fmap f = \x -> x
+ , ft_var = return f_Expr
+ -- fmap f = f
+ , ft_fun = \g h -> do
+ gg <- g
+ hh <- h
+ mkSimpleLam2 $ \x b -> return $
+ nlHsApp hh (nlHsApp x (nlHsApp gg b))
+ -- fmap f = \x b -> h (x (g b))
+ , ft_tup = \t gs -> do
+ gg <- sequence gs
+ mkSimpleLam $ mkSimpleTupleCase match_for_con t gg
+ -- fmap f = \x -> case x of (a1,a2,..) -> (g1 a1,g2 a2,..)
+ , ft_ty_app = \_ g -> nlHsApp fmap_Expr <$> g
+ -- fmap f = fmap g
+ , ft_forall = \_ g -> g
+ , ft_bad_app = panic "in other argument"
+ , ft_co_var = panic "contravariant" }
+
+ -- Con a1 a2 ... -> Con (f1 a1) (f2 a2) ...
+ match_for_con :: [LPat RdrName] -> DataCon -> [LHsExpr RdrName]
+ -> State [RdrName] (LMatch RdrName (LHsExpr RdrName))
+ match_for_con = mkSimpleConMatch CaseAlt $
+ \con_name xs -> return $ nlHsApps con_name xs -- Con x1 x2 ..
+
+{-
+Utility functions related to Functor deriving.
+
+Since several things use the same pattern of traversal, this is abstracted into functorLikeTraverse.
+This function works like a fold: it makes a value of type 'a' in a bottom up way.
+-}
+
+-- Generic traversal for Functor deriving
+-- See Note [FFoldType and functorLikeTraverse]
+data FFoldType a -- Describes how to fold over a Type in a functor like way
+ = FT { ft_triv :: a
+ -- ^ Does not contain variable
+ , ft_var :: a
+ -- ^ The variable itself
+ , ft_co_var :: a
+ -- ^ The variable itself, contravariantly
+ , ft_fun :: a -> a -> a
+ -- ^ Function type
+ , ft_tup :: TyCon -> [a] -> a
+ -- ^ Tuple type
+ , ft_ty_app :: Type -> a -> a
+ -- ^ Type app, variable only in last argument
+ , ft_bad_app :: a
+ -- ^ Type app, variable other than in last argument
+ , ft_forall :: TcTyVar -> a -> a
+ -- ^ Forall type
+ }
+
+functorLikeTraverse :: forall a.
+ TyVar -- ^ Variable to look for
+ -> FFoldType a -- ^ How to fold
+ -> Type -- ^ Type to process
+ -> a
+functorLikeTraverse var (FT { ft_triv = caseTrivial, ft_var = caseVar
+ , ft_co_var = caseCoVar, ft_fun = caseFun
+ , ft_tup = caseTuple, ft_ty_app = caseTyApp
+ , ft_bad_app = caseWrongArg, ft_forall = caseForAll })
+ ty
+ = fst (go False ty)
+ where
+ go :: Bool -- Covariant or contravariant context
+ -> Type
+ -> (a, Bool) -- (result of type a, does type contain var)
+
+ go co ty | Just ty' <- coreView ty = go co ty'
+ go co (TyVarTy v) | v == var = (if co then caseCoVar else caseVar,True)
+ go co (FunTy x y) | isPredTy x = go co y
+ | xc || yc = (caseFun xr yr,True)
+ where (xr,xc) = go (not co) x
+ (yr,yc) = go co y
+ go co (AppTy x y) | xc = (caseWrongArg, True)
+ | yc = (caseTyApp x yr, True)
+ where (_, xc) = go co x
+ (yr,yc) = go co y
+ go co ty@(TyConApp con args)
+ | not (or xcs) = (caseTrivial, False) -- Variable does not occur
+ -- At this point we know that xrs, xcs is not empty,
+ -- and at least one xr is True
+ | isTupleTyCon con = (caseTuple con xrs, True)
+ | or (init xcs) = (caseWrongArg, True) -- T (..var..) ty
+ | Just (fun_ty, _) <- splitAppTy_maybe ty -- T (..no var..) ty
+ = (caseTyApp fun_ty (last xrs), True)
+ | otherwise = (caseWrongArg, True) -- Non-decomposable (eg type function)
+ where
+ -- When folding over an unboxed tuple, we must explicitly drop the
+ -- runtime rep arguments, or else GHC will generate twice as many
+ -- variables in a unboxed tuple pattern match and expression as it
+ -- actually needs. See Trac #12399
+ (xrs,xcs) = unzip (map (go co) (dropRuntimeRepArgs args))
+ go co (ForAllTy (TvBndr v vis) x)
+ | isVisibleArgFlag vis = panic "unexpected visible binder"
+ | v /= var && xc = (caseForAll v xr,True)
+ where (xr,xc) = go co x
+
+ go _ _ = (caseTrivial,False)
+
+-- Return all syntactic subterms of ty that contain var somewhere
+-- These are the things that should appear in instance constraints
+deepSubtypesContaining :: TyVar -> Type -> [TcType]
+deepSubtypesContaining tv
+ = functorLikeTraverse tv
+ (FT { ft_triv = []
+ , ft_var = []
+ , ft_fun = (++)
+ , ft_tup = \_ xs -> concat xs
+ , ft_ty_app = (:)
+ , ft_bad_app = panic "in other argument"
+ , ft_co_var = panic "contravariant"
+ , ft_forall = \v xs -> filterOut ((v `elemVarSet`) . tyCoVarsOfType) xs })
+
+
+foldDataConArgs :: FFoldType a -> DataCon -> [a]
+-- Fold over the arguments of the datacon
+foldDataConArgs ft con
+ = map foldArg (dataConOrigArgTys con)
+ where
+ foldArg
+ = case getTyVar_maybe (last (tyConAppArgs (dataConOrigResTy con))) of
+ Just tv -> functorLikeTraverse tv ft
+ Nothing -> const (ft_triv ft)
+ -- If we are deriving Foldable for a GADT, there is a chance that the last
+ -- type variable in the data type isn't actually a type variable at all.
+ -- (for example, this can happen if the last type variable is refined to
+ -- be a concrete type such as Int). If the last type variable is refined
+ -- to be a specific type, then getTyVar_maybe will return Nothing.
+ -- See Note [DeriveFoldable with ExistentialQuantification]
+ --
+ -- The kind checks have ensured the last type parameter is of kind *.
+
+-- Make a HsLam using a fresh variable from a State monad
+mkSimpleLam :: (LHsExpr RdrName -> State [RdrName] (LHsExpr RdrName))
+ -> State [RdrName] (LHsExpr RdrName)
+-- (mkSimpleLam fn) returns (\x. fn(x))
+mkSimpleLam lam = do
+ (n:names) <- get
+ put names
+ body <- lam (nlHsVar n)
+ return (mkHsLam [nlVarPat n] body)
+
+mkSimpleLam2 :: (LHsExpr RdrName -> LHsExpr RdrName
+ -> State [RdrName] (LHsExpr RdrName))
+ -> State [RdrName] (LHsExpr RdrName)
+mkSimpleLam2 lam = do
+ (n1:n2:names) <- get
+ put names
+ body <- lam (nlHsVar n1) (nlHsVar n2)
+ return (mkHsLam [nlVarPat n1,nlVarPat n2] body)
+
+-- "Con a1 a2 a3 -> fold [x1 a1, x2 a2, x3 a3]"
+--
+-- @mkSimpleConMatch fold extra_pats con insides@ produces a match clause in
+-- which the LHS pattern-matches on @extra_pats@, followed by a match on the
+-- constructor @con@ and its arguments. The RHS folds (with @fold@) over @con@
+-- and its arguments, applying an expression (from @insides@) to each of the
+-- respective arguments of @con@.
+mkSimpleConMatch :: Monad m => HsMatchContext RdrName
+ -> (RdrName -> [LHsExpr RdrName] -> m (LHsExpr RdrName))
+ -> [LPat RdrName]
+ -> DataCon
+ -> [LHsExpr RdrName]
+ -> m (LMatch RdrName (LHsExpr RdrName))
+mkSimpleConMatch ctxt fold extra_pats con insides = do
+ let con_name = getRdrName con
+ let vars_needed = takeList insides as_RDRs
+ let pat = nlConVarPat con_name vars_needed
+ rhs <- fold con_name (zipWith nlHsApp insides (map nlHsVar vars_needed))
+ return $ mkMatch ctxt (extra_pats ++ [pat]) rhs
+ (noLoc emptyLocalBinds)
+
+-- "Con a1 a2 a3 -> fmap (\b2 -> Con a1 b2 a3) (traverse f a2)"
+--
+-- @mkSimpleConMatch2 fold extra_pats con insides@ behaves very similarly to
+-- 'mkSimpleConMatch', with two key differences:
+--
+-- 1. @insides@ is a @[Maybe (LHsExpr RdrName)]@ instead of a
+-- @[LHsExpr RdrName]@. This is because it filters out the expressions
+-- corresponding to arguments whose types do not mention the last type
+-- variable in a derived 'Foldable' or 'Traversable' instance (i.e., the
+-- 'Nothing' elements of @insides@).
+--
+-- 2. @fold@ takes an expression as its first argument instead of a
+-- constructor name. This is because it uses a specialized
+-- constructor function expression that only takes as many parameters as
+-- there are argument types that mention the last type variable.
+--
+-- See Note [Generated code for DeriveFoldable and DeriveTraversable]
+mkSimpleConMatch2 :: Monad m
+ => HsMatchContext RdrName
+ -> (LHsExpr RdrName -> [LHsExpr RdrName]
+ -> m (LHsExpr RdrName))
+ -> [LPat RdrName]
+ -> DataCon
+ -> [Maybe (LHsExpr RdrName)]
+ -> m (LMatch RdrName (LHsExpr RdrName))
+mkSimpleConMatch2 ctxt fold extra_pats con insides = do
+ let con_name = getRdrName con
+ vars_needed = takeList insides as_RDRs
+ pat = nlConVarPat con_name vars_needed
+ -- Make sure to zip BEFORE invoking catMaybes. We want the variable
+ -- indicies in each expression to match up with the argument indices
+ -- in con_expr (defined below).
+ exps = catMaybes $ zipWith (\i v -> (`nlHsApp` v) <$> i)
+ insides (map nlHsVar vars_needed)
+ -- An element of argTysTyVarInfo is True if the constructor argument
+ -- with the same index has a type which mentions the last type
+ -- variable.
+ argTysTyVarInfo = map isJust insides
+ (asWithTyVar, asWithoutTyVar) = partitionByList argTysTyVarInfo as_RDRs
+
+ con_expr
+ | null asWithTyVar = nlHsApps con_name $ map nlHsVar asWithoutTyVar
+ | otherwise =
+ let bs = filterByList argTysTyVarInfo bs_RDRs
+ vars = filterByLists argTysTyVarInfo
+ (map nlHsVar bs_RDRs)
+ (map nlHsVar as_RDRs)
+ in mkHsLam (map nlVarPat bs) (nlHsApps con_name vars)
+
+ rhs <- fold con_expr exps
+ return $ mkMatch ctxt (extra_pats ++ [pat]) rhs
+ (noLoc emptyLocalBinds)
+
+-- "case x of (a1,a2,a3) -> fold [x1 a1, x2 a2, x3 a3]"
+mkSimpleTupleCase :: Monad m => ([LPat RdrName] -> DataCon -> [a]
+ -> m (LMatch RdrName (LHsExpr RdrName)))
+ -> TyCon -> [a] -> LHsExpr RdrName -> m (LHsExpr RdrName)
+mkSimpleTupleCase match_for_con tc insides x
+ = do { let data_con = tyConSingleDataCon tc
+ ; match <- match_for_con [] data_con insides
+ ; return $ nlHsCase x [match] }
+
+{-
+************************************************************************
+* *
+ Foldable instances
+
+ see http://www.mail-archive.com/haskell-prime@haskell.org/msg02116.html
+
+* *
+************************************************************************
+
+Deriving Foldable instances works the same way as Functor instances,
+only Foldable instances are not possible for function types at all.
+Given (data T a = T a a (T a) deriving Foldable), we get:
+
+ instance Foldable T where
+ foldr f z (T x1 x2 x3) =
+ $(foldr 'a 'a) x1 ( $(foldr 'a 'a) x2 ( $(foldr 'a '(T a)) x3 z ) )
+
+-XDeriveFoldable is different from -XDeriveFunctor in that it filters out
+arguments to the constructor that would produce useless code in a Foldable
+instance. For example, the following datatype:
+
+ data Foo a = Foo Int a Int deriving Foldable
+
+would have the following generated Foldable instance:
+
+ instance Foldable Foo where
+ foldr f z (Foo x1 x2 x3) = $(foldr 'a 'a) x2
+
+since neither of the two Int arguments are folded over.
+
+The cases are:
+
+ $(foldr 'a 'a) = f
+ $(foldr 'a '(b1,b2)) = \x z -> case x of (x1,x2) -> $(foldr 'a 'b1) x1 ( $(foldr 'a 'b2) x2 z )
+ $(foldr 'a '(T b1 b2)) = \x z -> foldr $(foldr 'a 'b2) z x -- when a only occurs in the last parameter, b2
+
+Note that the arguments to the real foldr function are the wrong way around,
+since (f :: a -> b -> b), while (foldr f :: b -> t a -> b).
+
+One can envision a case for types that don't contain the last type variable:
+
+ $(foldr 'a 'b) = \x z -> z -- when b does not contain a
+
+But this case will never materialize, since the aforementioned filtering
+removes all such types from consideration.
+See Note [Generated code for DeriveFoldable and DeriveTraversable].
+
+Foldable instances differ from Functor and Traversable instances in that
+Foldable instances can be derived for data types in which the last type
+variable is existentially quantified. In particular, if the last type variable
+is refined to a more specific type in a GADT:
+
+ data GADT a where
+ G :: a ~ Int => a -> G Int
+
+then the deriving machinery does not attempt to check that the type a contains
+Int, since it is not syntactically equal to a type variable. That is, the
+derived Foldable instance for GADT is:
+
+ instance Foldable GADT where
+ foldr _ z (GADT _) = z
+
+See Note [DeriveFoldable with ExistentialQuantification].
+
+-}
+
+gen_Foldable_binds :: SrcSpan -> TyCon -> (LHsBinds RdrName, BagDerivStuff)
+gen_Foldable_binds loc tycon
+ = (listToBag [foldr_bind, foldMap_bind], emptyBag)
+ where
+ data_cons = tyConDataCons tycon
+
+ foldr_bind = mkRdrFunBind (L loc foldable_foldr_RDR) eqns
+ eqns = map foldr_eqn data_cons
+ foldr_eqn con
+ = evalState (match_foldr z_Expr [f_Pat,z_Pat] con =<< parts) bs_RDRs
+ where
+ parts = sequence $ foldDataConArgs ft_foldr con
+
+ foldMap_bind = mkRdrFunBind (L loc foldMap_RDR) (map foldMap_eqn data_cons)
+ foldMap_eqn con
+ = evalState (match_foldMap [f_Pat] con =<< parts) bs_RDRs
+ where
+ parts = sequence $ foldDataConArgs ft_foldMap con
+
+ -- Yields 'Just' an expression if we're folding over a type that mentions
+ -- the last type parameter of the datatype. Otherwise, yields 'Nothing'.
+ -- See Note [FFoldType and functorLikeTraverse]
+ ft_foldr :: FFoldType (State [RdrName] (Maybe (LHsExpr RdrName)))
+ ft_foldr
+ = FT { ft_triv = return Nothing
+ -- foldr f = \x z -> z
+ , ft_var = return $ Just f_Expr
+ -- foldr f = f
+ , ft_tup = \t g -> do
+ gg <- sequence g
+ lam <- mkSimpleLam2 $ \x z ->
+ mkSimpleTupleCase (match_foldr z) t gg x
+ return (Just lam)
+ -- foldr f = (\x z -> case x of ...)
+ , ft_ty_app = \_ g -> do
+ gg <- g
+ mapM (\gg' -> mkSimpleLam2 $ \x z -> return $
+ nlHsApps foldable_foldr_RDR [gg',z,x]) gg
+ -- foldr f = (\x z -> foldr g z x)
+ , ft_forall = \_ g -> g
+ , ft_co_var = panic "contravariant"
+ , ft_fun = panic "function"
+ , ft_bad_app = panic "in other argument" }
+
+ match_foldr :: LHsExpr RdrName
+ -> [LPat RdrName]
+ -> DataCon
+ -> [Maybe (LHsExpr RdrName)]
+ -> State [RdrName] (LMatch RdrName (LHsExpr RdrName))
+ match_foldr z = mkSimpleConMatch2 LambdaExpr $ \_ xs -> return (mkFoldr xs)
+ where
+ -- g1 v1 (g2 v2 (.. z))
+ mkFoldr :: [LHsExpr RdrName] -> LHsExpr RdrName
+ mkFoldr = foldr nlHsApp z
+
+ -- See Note [FFoldType and functorLikeTraverse]
+ ft_foldMap :: FFoldType (State [RdrName] (Maybe (LHsExpr RdrName)))
+ ft_foldMap
+ = FT { ft_triv = return Nothing
+ -- foldMap f = \x -> mempty
+ , ft_var = return (Just f_Expr)
+ -- foldMap f = f
+ , ft_tup = \t g -> do
+ gg <- sequence g
+ lam <- mkSimpleLam $ mkSimpleTupleCase match_foldMap t gg
+ return (Just lam)
+ -- foldMap f = \x -> case x of (..,)
+ , ft_ty_app = \_ g -> fmap (nlHsApp foldMap_Expr) <$> g
+ -- foldMap f = foldMap g
+ , ft_forall = \_ g -> g
+ , ft_co_var = panic "contravariant"
+ , ft_fun = panic "function"
+ , ft_bad_app = panic "in other argument" }
+
+ match_foldMap :: [LPat RdrName]
+ -> DataCon
+ -> [Maybe (LHsExpr RdrName)]
+ -> State [RdrName] (LMatch RdrName (LHsExpr RdrName))
+ match_foldMap = mkSimpleConMatch2 CaseAlt $ \_ xs -> return (mkFoldMap xs)
+ where
+ -- mappend v1 (mappend v2 ..)
+ mkFoldMap :: [LHsExpr RdrName] -> LHsExpr RdrName
+ mkFoldMap [] = mempty_Expr
+ mkFoldMap xs = foldr1 (\x y -> nlHsApps mappend_RDR [x,y]) xs
+
+{-
+************************************************************************
+* *
+ Traversable instances
+
+ see http://www.mail-archive.com/haskell-prime@haskell.org/msg02116.html
+* *
+************************************************************************
+
+Again, Traversable is much like Functor and Foldable.
+
+The cases are:
+
+ $(traverse 'a 'a) = f
+ $(traverse 'a '(b1,b2)) = \x -> case x of (x1,x2) -> (,) <$> $(traverse 'a 'b1) x1 <*> $(traverse 'a 'b2) x2
+ $(traverse 'a '(T b1 b2)) = traverse $(traverse 'a 'b2) -- when a only occurs in the last parameter, b2
+
+Like -XDeriveFoldable, -XDeriveTraversable filters out arguments whose types
+do not mention the last type parameter. Therefore, the following datatype:
+
+ data Foo a = Foo Int a Int
+
+would have the following derived Traversable instance:
+
+ instance Traversable Foo where
+ traverse f (Foo x1 x2 x3) =
+ fmap (\b2 -> Foo x1 b2 x3) ( $(traverse 'a 'a) x2 )
+
+since the two Int arguments do not produce any effects in a traversal.
+
+One can envision a case for types that do not mention the last type parameter:
+
+ $(traverse 'a 'b) = pure -- when b does not contain a
+
+But this case will never materialize, since the aforementioned filtering
+removes all such types from consideration.
+See Note [Generated code for DeriveFoldable and DeriveTraversable].
+-}
+
+gen_Traversable_binds :: SrcSpan -> TyCon -> (LHsBinds RdrName, BagDerivStuff)
+gen_Traversable_binds loc tycon
+ = (unitBag traverse_bind, emptyBag)
+ where
+ data_cons = tyConDataCons tycon
+
+ traverse_bind = mkRdrFunBind (L loc traverse_RDR) eqns
+ eqns = map traverse_eqn data_cons
+ traverse_eqn con
+ = evalState (match_for_con [f_Pat] con =<< parts) bs_RDRs
+ where
+ parts = sequence $ foldDataConArgs ft_trav con
+
+ -- Yields 'Just' an expression if we're folding over a type that mentions
+ -- the last type parameter of the datatype. Otherwise, yields 'Nothing'.
+ -- See Note [FFoldType and functorLikeTraverse]
+ ft_trav :: FFoldType (State [RdrName] (Maybe (LHsExpr RdrName)))
+ ft_trav
+ = FT { ft_triv = return Nothing
+ -- traverse f = pure x
+ , ft_var = return (Just f_Expr)
+ -- traverse f = f x
+ , ft_tup = \t gs -> do
+ gg <- sequence gs
+ lam <- mkSimpleLam $ mkSimpleTupleCase match_for_con t gg
+ return (Just lam)
+ -- traverse f = \x -> case x of (a1,a2,..) ->
+ -- (,,) <$> g1 a1 <*> g2 a2 <*> ..
+ , ft_ty_app = \_ g -> fmap (nlHsApp traverse_Expr) <$> g
+ -- traverse f = traverse g
+ , ft_forall = \_ g -> g
+ , ft_co_var = panic "contravariant"
+ , ft_fun = panic "function"
+ , ft_bad_app = panic "in other argument" }
+
+ -- Con a1 a2 ... -> fmap (\b1 b2 ... -> Con b1 b2 ...) (g1 a1)
+ -- <*> g2 a2 <*> ...
+ match_for_con :: [LPat RdrName]
+ -> DataCon
+ -> [Maybe (LHsExpr RdrName)]
+ -> State [RdrName] (LMatch RdrName (LHsExpr RdrName))
+ match_for_con = mkSimpleConMatch2 CaseAlt $
+ \con xs -> return (mkApCon con xs)
+ where
+ -- fmap (\b1 b2 ... -> Con b1 b2 ...) x1 <*> x2 <*> ..
+ mkApCon :: LHsExpr RdrName -> [LHsExpr RdrName] -> LHsExpr RdrName
+ mkApCon con [] = nlHsApps pure_RDR [con]
+ mkApCon con (x:xs) = foldl appAp (nlHsApps fmap_RDR [con,x]) xs
+ where appAp x y = nlHsApps ap_RDR [x,y]
+
+-----------------------------------------------------------------------
+
+f_Expr, z_Expr, fmap_Expr, mempty_Expr, foldMap_Expr,
+ traverse_Expr :: LHsExpr RdrName
+f_Expr = nlHsVar f_RDR
+z_Expr = nlHsVar z_RDR
+fmap_Expr = nlHsVar fmap_RDR
+mempty_Expr = nlHsVar mempty_RDR
+foldMap_Expr = nlHsVar foldMap_RDR
+traverse_Expr = nlHsVar traverse_RDR
+
+f_RDR, z_RDR :: RdrName
+f_RDR = mkVarUnqual (fsLit "f")
+z_RDR = mkVarUnqual (fsLit "z")
+
+as_RDRs, bs_RDRs :: [RdrName]
+as_RDRs = [ mkVarUnqual (mkFastString ("a"++show i)) | i <- [(1::Int) .. ] ]
+bs_RDRs = [ mkVarUnqual (mkFastString ("b"++show i)) | i <- [(1::Int) .. ] ]
+
+f_Pat, z_Pat :: LPat RdrName
+f_Pat = nlVarPat f_RDR
+z_Pat = nlVarPat z_RDR
+
+{-
+Note [DeriveFoldable with ExistentialQuantification]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Functor and Traversable instances can only be derived for data types whose
+last type parameter is truly universally polymorphic. For example:
+
+ data T a b where
+ T1 :: b -> T a b -- YES, b is unconstrained
+ T2 :: Ord b => b -> T a b -- NO, b is constrained by (Ord b)
+ T3 :: b ~ Int => b -> T a b -- NO, b is constrained by (b ~ Int)
+ T4 :: Int -> T a Int -- NO, this is just like T3
+ T5 :: Ord a => a -> b -> T a b -- YES, b is unconstrained, even
+ -- though a is existential
+ T6 :: Int -> T Int b -- YES, b is unconstrained
+
+For Foldable instances, however, we can completely lift the constraint that
+the last type parameter be truly universally polymorphic. This means that T
+(as defined above) can have a derived Foldable instance:
+
+ instance Foldable (T a) where
+ foldr f z (T1 b) = f b z
+ foldr f z (T2 b) = f b z
+ foldr f z (T3 b) = f b z
+ foldr f z (T4 b) = z
+ foldr f z (T5 a b) = f b z
+ foldr f z (T6 a) = z
+
+ foldMap f (T1 b) = f b
+ foldMap f (T2 b) = f b
+ foldMap f (T3 b) = f b
+ foldMap f (T4 b) = mempty
+ foldMap f (T5 a b) = f b
+ foldMap f (T6 a) = mempty
+
+In a Foldable instance, it is safe to fold over an occurrence of the last type
+parameter that is not truly universally polymorphic. However, there is a bit
+of subtlety in determining what is actually an occurrence of a type parameter.
+T3 and T4, as defined above, provide one example:
+
+ data T a b where
+ ...
+ T3 :: b ~ Int => b -> T a b
+ T4 :: Int -> T a Int
+ ...
+
+ instance Foldable (T a) where
+ ...
+ foldr f z (T3 b) = f b z
+ foldr f z (T4 b) = z
+ ...
+ foldMap f (T3 b) = f b
+ foldMap f (T4 b) = mempty
+ ...
+
+Notice that the argument of T3 is folded over, whereas the argument of T4 is
+not. This is because we only fold over constructor arguments that
+syntactically mention the universally quantified type parameter of that
+particular data constructor. See foldDataConArgs for how this is implemented.
+
+As another example, consider the following data type. The argument of each
+constructor has the same type as the last type parameter:
+
+ data E a where
+ E1 :: (a ~ Int) => a -> E a
+ E2 :: Int -> E Int
+ E3 :: (a ~ Int) => a -> E Int
+ E4 :: (a ~ Int) => Int -> E a
+
+Only E1's argument is an occurrence of a universally quantified type variable
+that is syntactically equivalent to the last type parameter, so only E1's
+argument will be be folded over in a derived Foldable instance.
+
+See Trac #10447 for the original discussion on this feature. Also see
+https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/DeriveFunctor
+for a more in-depth explanation.
+
+Note [FFoldType and functorLikeTraverse]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Deriving Functor, Foldable, and Traversable all require generating expressions
+which perform an operation on each argument of a data constructor depending
+on the argument's type. In particular, a generated operation can be different
+depending on whether the type mentions the last type variable of the datatype
+(e.g., if you have data T a = MkT a Int, then a generated foldr expresion would
+fold over the first argument of MkT, but not the second).
+
+This pattern is abstracted with the FFoldType datatype, which provides hooks
+for the user to specify how a constructor argument should be folded when it
+has a type with a particular "shape". The shapes are as follows (assume that
+a is the last type variable in a given datatype):
+
+* ft_triv: The type does not mention the last type variable at all.
+ Examples: Int, b
+
+* ft_var: The type is syntactically equal to the last type variable.
+ Moreover, the type appears in a covariant position (see
+ the Deriving Functor instances section of the users' guide
+ for an in-depth explanation of covariance vs. contravariance).
+ Example: a (covariantly)
+
+* ft_co_var: The type is syntactically equal to the last type variable.
+ Moreover, the type appears in a contravariant position.
+ Example: a (contravariantly)
+
+* ft_fun: A function type which mentions the last type variable in
+ the argument position, result position or both.
+ Examples: a -> Int, Int -> a, Maybe a -> [a]
+
+* ft_tup: A tuple type which mentions the last type variable in at least
+ one of its fields. The TyCon argument of ft_tup represents the
+ particular tuple's type constructor.
+ Examples: (a, Int), (Maybe a, [a], Either a Int), (# Int, a #)
+
+* ft_ty_app: A type is being applied to the last type parameter, where the
+ applied type does not mention the last type parameter (if it
+ did, it would fall under ft_bad_app). The Type argument to
+ ft_ty_app represents the applied type.
+
+ Note that functions, tuples, and foralls are distinct cases
+ and take precedence of ft_ty_app. (For example, (Int -> a) would
+ fall under (ft_fun Int a), not (ft_ty_app ((->) Int) a).
+ Examples: Maybe a, Either b a
+
+* ft_bad_app: A type application uses the last type parameter in a position
+ other than the last argument. This case is singled out because
+ Functor, Foldable, and Traversable instances cannot be derived
+ for datatypes containing arguments with such types.
+ Examples: Either a Int, Const a b
+
+* ft_forall: A forall'd type mentions the last type parameter on its right-
+ hand side (and is not quantified on the left-hand side). This
+ case is present mostly for plumbing purposes.
+ Example: forall b. Either b a
+
+If FFoldType describes a strategy for folding subcomponents of a Type, then
+functorLikeTraverse is the function that applies that strategy to the entirety
+of a Type, returning the final folded-up result.
+
+foldDataConArgs applies functorLikeTraverse to every argument type of a
+constructor, returning a list of the fold results. This makes foldDataConArgs
+a natural way to generate the subexpressions in a generated fmap, foldr,
+foldMap, or traverse definition (the subexpressions must then be combined in
+a method-specific fashion to form the final generated expression).
+
+Deriving Generic1 also does validity checking by looking for the last type
+variable in certain positions of a constructor's argument types, so it also
+uses foldDataConArgs. See Note [degenerate use of FFoldType] in TcGenGenerics.
+
+Note [Generated code for DeriveFoldable and DeriveTraversable]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+We adapt the algorithms for -XDeriveFoldable and -XDeriveTraversable based on
+that of -XDeriveFunctor. However, there an important difference between deriving
+the former two typeclasses and the latter one, which is best illustrated by the
+following scenario:
+
+ data WithInt a = WithInt a Int# deriving (Functor, Foldable, Traversable)
+
+The generated code for the Functor instance is straightforward:
+
+ instance Functor WithInt where
+ fmap f (WithInt a i) = WithInt (f a) i
+
+But if we use too similar of a strategy for deriving the Foldable and
+Traversable instances, we end up with this code:
+
+ instance Foldable WithInt where
+ foldMap f (WithInt a i) = f a <> mempty
+
+ instance Traversable WithInt where
+ traverse f (WithInt a i) = fmap WithInt (f a) <*> pure i
+
+This is unsatisfying for two reasons:
+
+1. The Traversable instance doesn't typecheck! Int# is of kind #, but pure
+ expects an argument whose type is of kind *. This effectively prevents
+ Traversable from being derived for any datatype with an unlifted argument
+ type (Trac #11174).
+
+2. The generated code contains superfluous expressions. By the Monoid laws,
+ we can reduce (f a <> mempty) to (f a), and by the Applicative laws, we can
+ reduce (fmap WithInt (f a) <*> pure i) to (fmap (\b -> WithInt b i) (f a)).
+
+We can fix both of these issues by incorporating a slight twist to the usual
+algorithm that we use for -XDeriveFunctor. The differences can be summarized
+as follows:
+
+1. In the generated expression, we only fold over arguments whose types
+ mention the last type parameter. Any other argument types will simply
+ produce useless 'mempty's or 'pure's, so they can be safely ignored.
+
+2. In the case of -XDeriveTraversable, instead of applying ConName,
+ we apply (\b_i ... b_k -> ConName a_1 ... a_n), where
+
+ * ConName has n arguments
+ * {b_i, ..., b_k} is a subset of {a_1, ..., a_n} whose indices correspond
+ to the arguments whose types mention the last type parameter. As a
+ consequence, taking the difference of {a_1, ..., a_n} and
+ {b_i, ..., b_k} yields the all the argument values of ConName whose types
+ do not mention the last type parameter. Note that [i, ..., k] is a
+ strictly increasing—but not necessarily consecutive—integer sequence.
+
+ For example, the datatype
+
+ data Foo a = Foo Int a Int a
+
+ would generate the following Traversable instance:
+
+ instance Traversable Foo where
+ traverse f (Foo a1 a2 a3 a4) =
+ fmap (\b2 b4 -> Foo a1 b2 a3 b4) (f a2) <*> f a4
+
+Technically, this approach would also work for -XDeriveFunctor as well, but we
+decide not to do so because:
+
+1. There's not much benefit to generating, e.g., ((\b -> WithInt b i) (f a))
+ instead of (WithInt (f a) i).
+
+2. There would be certain datatypes for which the above strategy would
+ generate Functor code that would fail to typecheck. For example:
+
+ data Bar f a = Bar (forall f. Functor f => f a) deriving Functor
+
+ With the conventional algorithm, it would generate something like:
+
+ fmap f (Bar a) = Bar (fmap f a)
+
+ which typechecks. But with the strategy mentioned above, it would generate:
+
+ fmap f (Bar a) = (\b -> Bar b) (fmap f a)
+
+ which does not typecheck, since GHC cannot unify the rank-2 type variables
+ in the types of b and (fmap f a).
+-}
diff --git a/compiler/typecheck/TcGenGenerics.hs b/compiler/typecheck/TcGenGenerics.hs
index 5757e98592..0c65f686c2 100644
--- a/compiler/typecheck/TcGenGenerics.hs
+++ b/compiler/typecheck/TcGenGenerics.hs
@@ -17,6 +17,7 @@ import HsSyn
import Type
import TcType
import TcGenDeriv
+import TcGenFunctor
import DataCon
import TyCon
import FamInstEnv ( FamInst, FamFlavor(..), mkSingleCoAxiom )