X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=compiler%2Ftypecheck%2FFamInst.lhs;h=e2da7952a92291d4cd6d8e1f7faa7a6650b218e3;hp=8e8df882d32d3f44a5022cadde3e1ae3f32c9bf8;hb=d2ce0f52d42edf32bb9f13796e6ba6edba8bd516;hpb=f5e36de375d03a0af3858c4222690bbaa5f8a1ee diff --git a/compiler/typecheck/FamInst.lhs b/compiler/typecheck/FamInst.lhs index 8e8df88..e2da795 100644 --- a/compiler/typecheck/FamInst.lhs +++ b/compiler/typecheck/FamInst.lhs @@ -2,7 +2,7 @@ The @FamInst@ type: family instance heads \begin{code} module FamInst ( - checkFamInstConsistency, tcExtendLocalFamInstEnv + checkFamInstConsistency, tcExtendLocalFamInstEnv, tcGetFamInstEnvs ) where import HscTypes @@ -11,17 +11,16 @@ import TcMType import TcType import TcRnMonad import TyCon -import Type import Name import Module import SrcLoc import Outputable -import LazyUniqFM +import UniqFM import FiniteMap import FastString -import Maybe -import Monad +import Maybes +import Control.Monad \end{code} @@ -36,6 +35,16 @@ check whether the instances in the two modules are consistent, *unless* we can be certain that the instances of the two modules have already been checked for consistency during the compilation of modules that we import. +Why do we need to check? Consider + module X1 where module X2 where + data T1 data T2 + type instance F T1 b = Int type instance F a T2 = Char + f1 :: F T1 a -> Int f2 :: Char -> F a T2 + f1 x = x f2 x = x + +Now if we import both X1 and X2 we could make (f2 . f1) :: Int -> Char. +Notice that neither instance is an orphan. + How do we know which pairs of modules have already been checked? Any pair of modules where both modules occur in the `HscTypes.dep_finsts' set (of the `HscTypes.Dependencies') of one of our directly imported modules must have @@ -107,8 +116,8 @@ checkFamInstConsistency famInstMods directlyImpMods -- already loaded in the EPS or they are in the HPT. -- check modInstsEnv (ModulePair m1 m2) - = let { instEnv1 = fromJust . lookupModuleEnv modInstsEnv $ m1 - ; instEnv2 = fromJust . lookupModuleEnv modInstsEnv $ m2 + = let { instEnv1 = (expectJust "checkFamInstConsistency") . lookupModuleEnv modInstsEnv $ m1 + ; instEnv2 = (expectJust "checkFamInstConsistency") . lookupModuleEnv modInstsEnv $ m2 ; insts1 = famInstEnvElts instEnv1 } in @@ -168,38 +177,14 @@ checkForConflicts inst_envs famInst -- (since we do unification). -- We use tcInstSkolType because we don't want to allocate -- fresh *meta* type variables. - ; let { tycon = famInstTyCon famInst - ; ty = case tyConFamInst_maybe tycon of - Nothing -> panic "FamInst.checkForConflicts" - Just (tc, tys) -> tc `mkTyConApp` tys - } - ; (_, _, tau') <- tcInstSkolType FamInstSkol ty - - ; let (fam, tys') = tcSplitTyConApp tau' - - ; let { matches = lookupFamInstEnvUnify inst_envs fam tys' - ; conflicts = [ conflictingFamInst - | match@((conflictingFamInst, _), _) <- matches - , conflicting tycon match - ] - } + + ; skol_tvs <- tcInstSkolTyVars FamInstSkol + (tyConTyVars (famInstTyCon famInst)) + ; let conflicts = lookupFamInstEnvConflicts inst_envs famInst skol_tvs ; unless (null conflicts) $ - conflictInstErr famInst (head conflicts) + conflictInstErr famInst (fst (head conflicts)) } where - -- * In the case of data family instances, any overlap is fundamentally a - -- conflict (as these instances imply injective type mappings). - -- * In the case of type family instances, overlap is admitted as long as - -- the right-hand sides of the overlapping rules coincide under the - -- overlap substitution. We require that they are syntactically equal; - -- anything else would be difficult to test for at this stage. - conflicting tycon1 ((famInst2, _), subst) - | isAlgTyCon tycon1 = True - | otherwise = not (rhs1 `tcEqType` rhs2) - where - tycon2 = famInstTyCon famInst2 - rhs1 = substTy subst $ synTyConType tycon1 - rhs2 = substTy subst $ synTyConType tycon2 conflictInstErr :: FamInst -> FamInst -> TcRn () conflictInstErr famInst conflictingFamInst @@ -212,4 +197,17 @@ addFamInstLoc famInst thing_inside = setSrcSpan (mkSrcSpan loc loc) thing_inside where loc = getSrcLoc famInst +\end{code} + +\begin{code} + +tcGetFamInstEnvs :: TcM (FamInstEnv, FamInstEnv) +-- Gets both the external-package inst-env +-- and the home-pkg inst env (includes module being compiled) +tcGetFamInstEnvs + = do { eps <- getEps; env <- getGblEnv + ; return (eps_fam_inst_env eps, tcg_fam_inst_env env) + } + + \end{code}