X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2Ftypecheck%2FTcDeriv.lhs;h=de06136b7117ca87707456b1cfaeaf1bc127ffec;hb=ebec49fed627b7dd17e297ddc79a9c677a2ce538;hp=dc9bf3e5e4fe7e42e2bb217b2bf4e98627cacdca;hpb=f098cfb236c17bcb3c46e39f9b1d7d8d8ca86003;p=ghc-hetmet.git diff --git a/compiler/typecheck/TcDeriv.lhs b/compiler/typecheck/TcDeriv.lhs index dc9bf3e..de06136 100644 --- a/compiler/typecheck/TcDeriv.lhs +++ b/compiler/typecheck/TcDeriv.lhs @@ -269,7 +269,9 @@ tcDeriving tycl_decls inst_decls deriv_decls = recoverM (return ([], emptyValBindsOut)) $ do { -- Fish the "deriving"-related information out of the TcEnv -- And make the necessary "equations". - ; early_specs <- makeDerivSpecs tycl_decls inst_decls deriv_decls + is_boot <- tcIsHsBoot + ; traceTc (text "tcDeriving" <+> ppr is_boot) + ; early_specs <- makeDerivSpecs is_boot tycl_decls inst_decls deriv_decls ; overlap_flag <- getOverlapFlag ; let (infer_specs, given_specs) = splitEithers early_specs @@ -280,7 +282,6 @@ tcDeriving tycl_decls inst_decls deriv_decls ; insts2 <- mapM (genInst overlap_flag) final_specs - ; is_boot <- tcIsHsBoot -- Generate the generic to/from functions from each type declaration ; gen_binds <- mkGenericBinds is_boot ; (inst_info, rn_binds) <- renameDeriv is_boot gen_binds (insts1 ++ insts2) @@ -307,8 +308,8 @@ renameDeriv is_boot gen_binds insts | otherwise = discardWarnings $ -- Discard warnings about unused bindings etc - do { (rn_gen, dus_gen) <- setOptM Opt_PatternSignatures $ -- Type signatures in patterns - -- are used in the generic binds + do { (rn_gen, dus_gen) <- setOptM Opt_ScopedTypeVariables $ -- Type signatures in patterns + -- are used in the generic binds rnTopBinds (ValBindsIn gen_binds []) ; keepAliveSetTc (duDefs dus_gen) -- Mark these guys to be kept alive @@ -387,23 +388,37 @@ or} has just one data constructor (e.g., tuples). all those. \begin{code} -makeDerivSpecs :: [LTyClDecl Name] +makeDerivSpecs :: Bool + -> [LTyClDecl Name] -> [LInstDecl Name] -> [LDerivDecl Name] -> TcM [EarlyDerivSpec] -makeDerivSpecs tycl_decls inst_decls deriv_decls - = do { eqns1 <- mapAndRecoverM deriveTyData $ - extractTyDataPreds tycl_decls ++ - [ pd -- traverse assoc data families - | L _ (InstDecl _ _ _ ats) <- inst_decls - , pd <- extractTyDataPreds ats ] +makeDerivSpecs is_boot tycl_decls inst_decls deriv_decls + | is_boot -- No 'deriving' at all in hs-boot files + = do { mapM_ add_deriv_err deriv_locs + ; return [] } + | otherwise + = do { eqns1 <- mapAndRecoverM deriveTyData all_tydata ; eqns2 <- mapAndRecoverM deriveStandalone deriv_decls ; return (catMaybes (eqns1 ++ eqns2)) } where - extractTyDataPreds decls = - [(p, d) | d@(L _ (TyData {tcdDerivs = Just preds})) <- decls, p <- preds] + extractTyDataPreds decls + = [(p, d) | d@(L _ (TyData {tcdDerivs = Just preds})) <- decls, p <- preds] + + 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 ] + + deriv_locs = map (getLoc . snd) all_tydata + ++ map getLoc deriv_decls + add_deriv_err loc = setSrcSpan loc $ + addErr (hang (ptext (sLit "Deriving not permitted in hs-boot file")) + 2 (ptext (sLit "Use an instance declaration instead"))) ------------------------------------------------------------------ deriveStandalone :: LDerivDecl Name -> TcM (Maybe EarlyDerivSpec) @@ -554,13 +569,13 @@ mkDataTypeEqn :: InstOrigin -> Bool -> [Var] -> Class -> [Type] mkDataTypeEqn orig mayDeriveDataTypeable tvs cls cls_tys tycon tc_args rep_tc rep_tc_args mtheta - | Just err <- checkSideConditions mayDeriveDataTypeable cls cls_tys rep_tc + = case checkSideConditions mayDeriveDataTypeable cls cls_tys rep_tc of -- NB: pass the *representation* tycon to checkSideConditions - = baleOut (derivingThingErr cls cls_tys (mkTyConApp tycon tc_args) err) - - | otherwise - = ASSERT( null cls_tys ) - mk_data_eqn orig tvs cls tycon tc_args rep_tc rep_tc_args mtheta + CanDerive -> mk_data_eqn orig tvs cls tycon tc_args rep_tc rep_tc_args mtheta + NonDerivableClass -> bale_out (nonStdErr cls) + DerivableClassError msg -> bale_out msg + where + bale_out msg = baleOut (derivingThingErr cls cls_tys (mkTyConApp tycon tc_args) msg) mk_data_eqn, mk_typeable_eqn :: InstOrigin -> [TyVar] -> Class @@ -633,17 +648,25 @@ mk_typeable_eqn orig tvs cls tycon tc_args rep_tc _rep_tc_args mtheta -- the data constructors - but we need to be careful to fall back to the -- family tycon (with indexes) in error messages. -checkSideConditions :: Bool -> Class -> [TcType] -> TyCon -> Maybe SDoc +data DerivStatus = CanDerive + | NonDerivableClass + | DerivableClassError SDoc + +checkSideConditions :: Bool -> Class -> [TcType] -> TyCon -> DerivStatus checkSideConditions mayDeriveDataTypeable cls cls_tys rep_tc | notNull cls_tys - = Just ty_args_why -- e.g. deriving( Foo s ) + = DerivableClassError ty_args_why -- e.g. deriving( Foo s ) | otherwise = case sideConditions cls of - Just cond -> cond (mayDeriveDataTypeable, rep_tc) - Nothing -> Just non_std_why + Nothing -> NonDerivableClass + Just cond -> case (cond (mayDeriveDataTypeable, rep_tc)) of + Nothing -> CanDerive + Just err -> DerivableClassError err where ty_args_why = quotes (ppr (mkClassPred cls cls_tys)) <+> ptext (sLit "is not a class") - non_std_why = quotes (ppr cls) <+> ptext (sLit "is not a derivable class") + +nonStdErr :: Class -> SDoc +nonStdErr cls = quotes (ppr cls) <+> ptext (sLit "is not a derivable class") sideConditions :: Class -> Maybe Condition sideConditions cls @@ -799,17 +822,20 @@ mkNewTypeEqn orig mayDeriveDataTypeable newtype_deriving tvs ; return (if isJust mtheta then Just (Right spec) else Just (Left spec)) } - | isNothing mb_std_err -- Use the standard H98 method - = mk_data_eqn orig tvs cls tycon tc_args rep_tycon rep_tc_args mtheta - - -- Otherwise we can't derive - | newtype_deriving = baleOut cant_derive_err -- Too hard - | otherwise = baleOut std_err -- Just complain about being a non-std instance + | otherwise + = case check_conditions of + CanDerive -> mk_data_eqn orig tvs cls tycon tc_args rep_tycon rep_tc_args mtheta + -- Use the standard H98 method + DerivableClassError msg -> bale_out msg -- Error with standard class + NonDerivableClass -- Must use newtype deriving + | newtype_deriving -> bale_out cant_derive_err -- Too hard, even with newtype deriving + | otherwise -> bale_out non_std_err -- Try newtype deriving! where - mb_std_err = checkSideConditions mayDeriveDataTypeable cls cls_tys rep_tycon - std_err = derivingThingErr cls cls_tys tc_app $ - vcat [fromJust mb_std_err, - ptext (sLit "Try -XGeneralizedNewtypeDeriving for GHC's newtype-deriving extension")] + check_conditions = checkSideConditions mayDeriveDataTypeable cls cls_tys rep_tycon + bale_out msg = baleOut (derivingThingErr cls cls_tys tc_app msg) + + non_std_err = nonStdErr cls $$ + ptext (sLit "Try -XGeneralizedNewtypeDeriving for GHC's newtype-deriving extension") -- Here is the plan for newtype derivings. We see -- newtype T a1...an = MkT (t ak+1...an) deriving (.., C s1 .. sm, ...) @@ -943,22 +969,21 @@ mkNewTypeEqn orig mayDeriveDataTypeable newtype_deriving tvs -- (d) in case of newtype family instances, the eta-dropped -- arguments must be type variables (not more complex indexes) - cant_derive_err = derivingThingErr cls cls_tys tc_app - (vcat [ptext (sLit "even with cunning newtype deriving:"), - if isRecursiveTyCon tycon then - ptext (sLit "the newtype may be recursive") - else empty, - if not right_arity then - quotes (ppr (mkClassPred cls cls_tys)) <+> ptext (sLit "does not have arity 1") - else empty, - if not (n_tyargs_to_keep >= 0) then - ptext (sLit "the type constructor has wrong kind") - else if not (n_args_to_keep >= 0) then - ptext (sLit "the representation type has wrong kind") - else if not eta_ok then - ptext (sLit "the eta-reduction property does not hold") - else empty - ]) + cant_derive_err = vcat [ptext (sLit "even with cunning newtype deriving:"), + if isRecursiveTyCon tycon then + ptext (sLit "the newtype may be recursive") + else empty, + if not right_arity then + quotes (ppr (mkClassPred cls cls_tys)) <+> ptext (sLit "does not have arity 1") + else empty, + if not (n_tyargs_to_keep >= 0) then + ptext (sLit "the type constructor has wrong kind") + else if not (n_args_to_keep >= 0) then + ptext (sLit "the representation type has wrong kind") + else if not eta_ok then + ptext (sLit "the eta-reduction property does not hold") + else empty + ] \end{code}