X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2Ftypecheck%2FTcDeriv.lhs;h=03638b100d5819a1ada2e050afb4ee38d2bd274e;hb=94696a96b799ae942e8dfe4edb2c74268b9fccee;hp=3aecc43dc35483afb0663d814aef3027bf4ee36f;hpb=55e0ee453646be887a27a3fe6b4559d8182bf9fe;p=ghc-hetmet.git diff --git a/compiler/typecheck/TcDeriv.lhs b/compiler/typecheck/TcDeriv.lhs index 3aecc43..03638b1 100644 --- a/compiler/typecheck/TcDeriv.lhs +++ b/compiler/typecheck/TcDeriv.lhs @@ -393,9 +393,11 @@ deriveStandalone (L loc (DerivDecl deriv_ty)) <+> text "theta:" <+> ppr theta <+> text "tau:" <+> ppr tau) ; (cls, inst_tys) <- checkValidInstHead tau + ; checkValidInstance tvs theta cls inst_tys + -- C.f. TcInstDcls.tcLocalInstDecl1 + ; let cls_tys = take (length inst_tys - 1) inst_tys inst_ty = last inst_tys - ; traceTc (text "standalone deriving;" <+> text "class:" <+> ppr cls <+> text "class types:" <+> ppr cls_tys @@ -432,24 +434,24 @@ mkEqnHelp :: InstOrigin -> [TyVar] -> Class -> [Type] -> Type -> TcRn (Maybe EarlyDerivSpec) mkEqnHelp orig tvs cls cls_tys tc_app mtheta | Just (tycon, tc_args) <- tcSplitTyConApp_maybe tc_app - = do { + , isAlgTyCon tycon -- Check for functions, primitive types etc + = do { (rep_tc, rep_tc_args) <- tcLookupFamInstExact tycon tc_args + -- Be careful to test rep_tc here: in the case of families, + -- we want to check the instance tycon, not the family tycon + -- For standalone deriving (mtheta /= Nothing), -- check that all the data constructors are in scope -- By this time we know that the thing is algebraic -- because we've called checkInstHead in derivingStandalone - rdr_env <- getGlobalRdrEnv - ; let hidden_data_cons = filter not_in_scope (tyConDataCons tycon) - not_in_scope dc = null (lookupGRE_Name rdr_env (dataConName dc)) - ; checkTc (isNothing mtheta || null hidden_data_cons) + ; rdr_env <- getGlobalRdrEnv + ; let hidden_data_cons = isAbstractTyCon rep_tc || any not_in_scope (tyConDataCons rep_tc) + not_in_scope dc = null (lookupGRE_Name rdr_env (dataConName dc)) + ; checkTc (isNothing mtheta || not hidden_data_cons) (derivingHiddenErr tycon) ; mayDeriveDataTypeable <- doptM Opt_DeriveDataTypeable ; newtype_deriving <- doptM Opt_GeneralizedNewtypeDeriving - ; (rep_tc, rep_tc_args) <- tcLookupFamInstExact tycon tc_args - - -- Be careful to test rep_tc here: in the case of families, we want - -- to check the instance tycon, not the family tycon ; if isDataTyCon rep_tc then mkDataTypeEqn orig mayDeriveDataTypeable tvs cls cls_tys tycon tc_args rep_tc rep_tc_args mtheta @@ -459,15 +461,35 @@ mkEqnHelp orig tvs cls cls_tys tc_app mtheta tycon tc_args rep_tc rep_tc_args mtheta } | otherwise = baleOut (derivingThingErr cls cls_tys tc_app - (ptext (sLit "Last argument of the instance must be a type application"))) + (ptext (sLit "The last argument of the instance must be a data or newtype application"))) baleOut :: Message -> TcM (Maybe a) baleOut err = do { addErrTc err; return Nothing } \end{code} -Auxiliary lookup wrapper which requires that looked up family instances are -not type instances. If called with a vanilla tycon, the old type application -is simply returned. +Note [Looking up family instances for deriving] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +tcLookupFamInstExact is an auxiliary lookup wrapper which requires +that looked-up family instances exist. If called with a vanilla +tycon, the old type application is simply returned. + +If we have + data instance F () = ... deriving Eq + data instance F () = ... deriving Eq +then tcLookupFamInstExact will be confused by the two matches; +but that can't happen because tcInstDecls1 doesn't call tcDeriving +if there are any overlaps. + +There are two other things that might go wrong with the lookup. +First, we might see a standalone deriving clause + deriving Eq (F ()) +when there is no data instance F () in scope. + +Note that it's OK to have + data instance F [a] = ... + deriving Eq (F [(a,b)]) +where the match is not exact; the same holds for ordinary data types +with standalone deriving declrations. \begin{code} tcLookupFamInstExact :: TyCon -> [Type] -> TcM (TyCon, [Type]) @@ -477,18 +499,14 @@ tcLookupFamInstExact tycon tys | otherwise = do { maybeFamInst <- tcLookupFamInst tycon tys ; case maybeFamInst of - Nothing -> famInstNotFound tycon tys False - Just famInst@(_, rep_tys) - | not variable_only_subst -> famInstNotFound tycon tys True - | otherwise -> return famInst - where - tvs = map (Type.getTyVar - "TcDeriv.tcLookupFamInstExact") - rep_tys - variable_only_subst = all Type.isTyVarTy rep_tys && - sizeVarSet (mkVarSet tvs) == length tvs - -- renaming may have no repetitions + Nothing -> famInstNotFound tycon tys + Just famInst -> return famInst } + +famInstNotFound :: TyCon -> [Type] -> TcM a +famInstNotFound tycon tys + = failWithTc (ptext (sLit "No family instance for") + <+> quotes (pprTypeApp tycon (ppr tycon) tys)) \end{code} @@ -955,7 +973,7 @@ inferInstanceContexts oflag infer_specs iterate_deriv :: Int -> [ThetaType] -> TcM [DerivSpec] iterate_deriv n current_solns | n > 20 -- Looks as if we are in an infinite loop - -- This can happen if we have -fallow-undecidable-instances + -- This can happen if we have -XUndecidableInstances -- (See TcSimplify.tcSimplifyDeriv.) = pprPanic "solveDerivEqns: probable loop" (vcat (map pprDerivSpec infer_specs) $$ ppr current_solns) @@ -1182,12 +1200,4 @@ badDerivedPred pred = vcat [ptext (sLit "Can't derive instances where the instance context mentions"), ptext (sLit "type variables that are not data type parameters"), nest 2 (ptext (sLit "Offending constraint:") <+> ppr pred)] - -famInstNotFound :: TyCon -> [Type] -> Bool -> TcM a -famInstNotFound tycon tys notExact - = failWithTc (msg <+> quotes (pprTypeApp tycon (ppr tycon) tys)) - where - msg = ptext $ if notExact - then sLit "No family instance exactly matching" - else sLit "More than one family instance for" \end{code}