; let aux_binds = listToBag $ map (genAuxBind loc) $
rm_dups [] $ concat deriv_aux_binds
; rn_aux_lhs <- rnTopBindsLHS emptyFsEnv (ValBindsIn aux_binds [])
- ; let aux_names = map unLoc (collectHsValBinders rn_aux_lhs)
+ ; let aux_names = collectHsValBinders rn_aux_lhs
; bindLocalNames aux_names $
do { (rn_aux, dus_aux) <- rnTopBindsRHS (mkNameSet aux_names) rn_aux_lhs
| otherwise = rm_dups (b:acc) bs
- rn_inst_info (InstInfo { iSpec = inst, iBinds = NewTypeDerived co })
- = return (InstInfo { iSpec = inst, iBinds = NewTypeDerived co }, emptyFVs)
+ rn_inst_info :: InstInfo RdrName -> TcM (InstInfo Name, FreeVars)
+ rn_inst_info info@(InstInfo { iBinds = NewTypeDerived coi tc })
+ = return ( info { iBinds = NewTypeDerived coi tc }
+ , mkFVs (map dataConName (tyConDataCons tc)))
+ -- See Note [Newtype deriving and unused constructors]
rn_inst_info (InstInfo { iSpec = inst, iBinds = VanillaInst binds sigs standalone_deriv })
= -- Bring the right type variables into
-- The predicate tyConHasGenerics finds both of these
\end{code}
+Note [Newtype deriving and unused constructors]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider this (see Trac #1954):
+
+ module Bug(P) where
+ newtype P a = MkP (IO a) deriving Monad
+
+If you compile with -fwarn-unused-binds you do not expect the warning
+"Defined but not used: data consructor MkP". Yet the newtype deriving
+code does not explicitly mention MkP, but it should behave as if you
+had written
+ instance Monad P where
+ return x = MkP (return x)
+ ...etc...
+
+So we want to signal a user of the data constructor 'MkP'. That's
+what we do in rn_inst_info, and it's the only reason we have the TyCon
+stored in NewTypeDerived.
+
%************************************************************************
%* *
all_tydata :: [(LHsType Name, LTyClDecl Name)]
-- Derived predicate paired with its data type declaration
- all_tydata = extractTyDataPreds tycl_decls ++
- [ pd -- Traverse assoc data families
- | L _ (InstDecl _ _ _ ats) <- inst_decls
- , pd <- extractTyDataPreds ats ]
+ all_tydata = extractTyDataPreds (instDeclATs inst_decls ++ tycl_decls)
deriv_locs = map (getLoc . snd) all_tydata
++ map getLoc deriv_decls
newtype S a = MkS [a]
-- :CoS :: S ~ [] -- Eta-reduced
- instance Eq [a] => Eq (S a) -- by coercion sym (Eq (coMkS a)) : Eq [a] ~ Eq (S a)
- instance Monad [] => Monad S -- by coercion sym (Monad coMkS) : Monad [] ~ Monad S
+ instance Eq [a] => Eq (S a) -- by coercion sym (Eq (:CoS a)) : Eq [a] ~ Eq (S a)
+ instance Monad [] => Monad S -- by coercion sym (Monad :CoS) : Monad [] ~ Monad S
When type familes are involved it's trickier:
-- 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 cls inst_tys rep_tc rep_tc_args
+inferConstraints _ cls inst_tys rep_tc rep_tc_args
= ASSERT2( equalLength rep_tc_tvs all_rep_tc_args, ppr cls <+> ppr rep_tc )
stupid_constraints ++ extra_constraints
++ sc_constraints ++ con_arg_constraints
stupid_constraints = substTheta subst (tyConStupidTheta rep_tc)
subst = zipTopTvSubst rep_tc_tvs all_rep_tc_args
- -- Extra constraints
+ -- Extra Data constraints
-- The Data class (only) requires that for
- -- instance (...) => Data (T a b)
- -- then (Data a, Data b) are among the (...) constraints
- -- Reason: that's what you need to typecheck the method
- -- dataCast1 f = gcast1 f
+ -- 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
- | cls `hasKey` dataClassKey = [mkClassPred cls [mkTyVarTy tv] | tv <- tvs]
- | otherwise = []
+ | cls `hasKey` dataClassKey
+ , all (isLiftedTypeKind . typeKind) rep_tc_args
+ = [mkClassPred cls [ty] | ty <- rep_tc_args]
+ | otherwise
+ = []
------------------------------------------------------------------
-- Check side conditions that dis-allow derivability for particular classes
functions = ptext (sLit "contains function types")
wrong_arg = ptext (sLit "uses the type variable in an argument other than the last")
-checkFlag :: DynFlag -> Condition
+checkFlag :: ExtensionFlag -> Condition
checkFlag flag (dflags, _)
| dopt flag dflags = Nothing
| otherwise = Just why
weird_preds = [pred | pred <- theta, not (tyVarsOfPred pred `subVarSet` tv_set)]
; mapM_ (addErrTc . badDerivedPred) weird_preds
+ ; traceTc (text "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
genInst standalone_deriv oflag spec
| ds_newtype spec
= return (InstInfo { iSpec = mkInstance oflag (ds_theta spec) spec
- , iBinds = NewTypeDerived co }, [])
+ , iBinds = NewTypeDerived co rep_tycon }, [])
| otherwise
= do { let loc = getSrcSpan (ds_name spec)