X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2Ftypes%2FInstEnv.lhs;h=49b49b83e15b80af8dd974827030fe6d1122c6df;hb=d24fc63ae1a193917d35ef3d4e31aba4e283267d;hp=e7b4f47a490b07d1cc6eda94ef99b91240700aad;hpb=3b1438a9757639d7f37f10e1237e2369ca0ebe4a;p=ghc-hetmet.git diff --git a/compiler/types/InstEnv.lhs b/compiler/types/InstEnv.lhs index e7b4f47..49b49b8 100644 --- a/compiler/types/InstEnv.lhs +++ b/compiler/types/InstEnv.lhs @@ -7,13 +7,6 @@ The bits common to TcInstDcls and TcDeriv. \begin{code} -{-# OPTIONS -w #-} --- The above warning supression flag is a temporary kludge. --- While working on this module you are encouraged to remove it and fix --- any warnings in the module. See --- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings --- for details - module InstEnv ( DFunId, OverlapFlag(..), Instance(..), pprInstance, pprInstanceHdr, pprInstances, @@ -22,7 +15,7 @@ module InstEnv ( InstEnv, emptyInstEnv, extendInstEnv, extendInstEnvList, lookupInstEnv, instEnvElts, - classInstances, + classInstances, instanceBindFun, instanceCantMatch, roughMatchTcs ) where @@ -34,13 +27,12 @@ import VarSet import Name import TcType import TyCon -import TcGadt import Unify import Outputable import BasicTypes import UniqFM import Id -import SrcLoc +import FastString import Data.Maybe ( isJust, isNothing ) \end{code} @@ -67,7 +59,7 @@ data Instance -- INVARIANT: is_dfun Id has type -- forall is_tvs. (...) => is_cls is_tys - , is_dfun :: DFunId + , is_dfun :: DFunId -- See Note [Haddock assumptions] , is_flag :: OverlapFlag -- See detailed comments with -- the decl of BasicTypes.OverlapFlag } @@ -107,7 +99,20 @@ However, note that: (This is so that we can use the matching substitution to instantiate the dfun's context.) +Note [Haddock assumptions] +~~~~~~~~~~~~~~~~~~~~~~~~~~ +For normal user-written instances, Haddock relies on + + * the SrcSpan of + * the Name of + * the is_dfun of + * an Instance +being equal to + + * the SrcSpan of + * the instance head type of + * the InstDecl used to construct the Instance. \begin{code} instanceDFunId :: Instance -> DFunId @@ -124,7 +129,7 @@ setInstanceDFunId ispec dfun -- are ok; hence the assert ispec { is_dfun = dfun, is_tvs = mkVarSet tvs, is_tys = tys } where - (tvs, _, _, tys) = tcSplitDFunTy (idType dfun) + (tvs, _, tys) = tcSplitDFunTy (idType dfun) instanceRoughTcs :: Instance -> [Maybe Name] instanceRoughTcs = is_tcs @@ -139,25 +144,29 @@ instance Outputable Instance where pprInstance :: Instance -> SDoc -- Prints the Instance as an instance declaration -pprInstance ispec@(Instance { is_flag = flag }) +pprInstance ispec = hang (pprInstanceHdr ispec) - 2 (ptext SLIT("--") <+> pprNameLoc (getName ispec)) + 2 (ptext (sLit "--") <+> pprNameLoc (getName ispec)) -- * pprInstanceHdr is used in VStudio to populate the ClassView tree pprInstanceHdr :: Instance -> SDoc -- Prints the Instance as an instance declaration pprInstanceHdr ispec@(Instance { is_flag = flag }) - = ptext SLIT("instance") <+> ppr flag - <+> sep [pprThetaArrow theta, pprClassPred clas tys] + = ptext (sLit "instance") <+> ppr flag + <+> sep [pprThetaArrow theta, ppr res_ty] where - (_, theta, clas, tys) = instanceHead ispec + (_, theta, res_ty) = tcSplitSigmaTy (idType (is_dfun ispec)) -- Print without the for-all, which the programmer doesn't write pprInstances :: [Instance] -> SDoc pprInstances ispecs = vcat (map pprInstance ispecs) -instanceHead :: Instance -> ([TyVar], [PredType], Class, [Type]) -instanceHead ispec = tcSplitDFunTy (idType (is_dfun ispec)) +instanceHead :: Instance -> ([TyVar], ThetaType, Class, [Type]) +instanceHead ispec + = (tvs, theta, cls, tys) + where + (tvs, theta, tau) = tcSplitSigmaTy (idType (is_dfun ispec)) + (cls, tys) = tcSplitDFunHead tau mkLocalInstance :: DFunId -> OverlapFlag -> Instance -- Used for local instances, where we can safely pull on the DFunId @@ -166,7 +175,7 @@ mkLocalInstance dfun oflag is_tvs = mkVarSet tvs, is_tys = tys, is_cls = className cls, is_tcs = roughMatchTcs tys } where - (tvs, _, cls, tys) = tcSplitDFunTy (idType dfun) + (tvs, cls, tys) = tcSplitDFunTy (idType dfun) mkImportedInstance :: Name -> [Maybe Name] -> DFunId -> OverlapFlag -> Instance @@ -177,7 +186,7 @@ mkImportedInstance cls mb_tcs dfun oflag is_tvs = mkVarSet tvs, is_tys = tys, is_cls = cls, is_tcs = mb_tcs } where - (tvs, _, _, tys) = tcSplitDFunTy (idType dfun) + (tvs, _, tys) = tcSplitDFunTy (idType dfun) roughMatchTcs :: [Type] -> [Maybe Name] roughMatchTcs tys = map rough tys @@ -191,7 +200,7 @@ instanceCantMatch :: [Maybe Name] -> [Maybe Name] -> Bool -- possibly be instantiated to actual, nor vice versa; -- False is non-committal instanceCantMatch (Just t : ts) (Just a : as) = t/=a || instanceCantMatch ts as -instanceCantMatch ts as = False -- Safe +instanceCantMatch _ _ = False -- Safe \end{code} @@ -378,12 +387,12 @@ extendInstEnv inst_env ins_item@(Instance { is_cls = cls_nm, is_tcs = mb_tcs }) add (ClsIE cur_insts cur_tyvar) _ = ClsIE (ins_item : cur_insts) (ins_tyvar || cur_tyvar) ins_tyvar = not (any isJust mb_tcs) -\end{code} +\end{code} %************************************************************************ %* * -\subsection{Looking up an instance} + Looking up an instance %* * %************************************************************************ @@ -489,31 +498,11 @@ lookupInstEnv (pkg_ie, home_ie) cls tys ) -- Unification will break badly if the variables overlap -- They shouldn't because we allocate separate uniques for them - case tcUnifyTys bind_fn tpl_tys tys of + case tcUnifyTys instanceBindFun tpl_tys tys of Just _ -> find ms (item:us) rest - Nothing -> find ms us rest + Nothing -> find ms us rest --------------- -bind_fn tv | isTcTyVar tv && isExistentialTyVar tv = Skolem - | otherwise = BindMe - -- The key_tys can contain skolem constants, and we can guarantee that those - -- are never going to be instantiated to anything, so we should not involve - -- them in the unification test. Example: - -- class Foo a where { op :: a -> Int } - -- instance Foo a => Foo [a] -- NB overlap - -- instance Foo [Int] -- NB overlap - -- data T = forall a. Foo a => MkT a - -- f :: T -> Int - -- f (MkT x) = op [x,x] - -- The op [x,x] means we need (Foo [a]). Without the filterVarSet we'd - -- complain, saying that the choice of instance depended on the instantiation - -- of 'a'; but of course it isn't *going* to be instantiated. - -- - -- We do this only for pattern-bound skolems. For example we reject - -- g :: forall a => [a] -> Int - -- g x = op x - -- on the grounds that the correct instance depends on the instantiation of 'a' - --------------- insert_overlapping :: InstMatch -> [InstMatch] -> [InstMatch] -- Add a new solution, knocking out strictly less specific ones @@ -539,6 +528,43 @@ insert_overlapping new_item (item:items) where overlap_ok = case is_flag instB of NoOverlap -> False - other -> True + _ -> True +\end{code} + + +%************************************************************************ +%* * + Binding decisions +%* * +%************************************************************************ + +\begin{code} +instanceBindFun :: TyVar -> BindFlag +instanceBindFun tv | isTcTyVar tv && isExistentialTyVar tv = Skolem + | otherwise = BindMe + -- Note [Binding when looking up instances] \end{code} +Note [Binding when looking up instances] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +When looking up in the instance environment, or family-instance environment, +we are careful about multiple matches, as described above in +Note [Overlapping instances] + +The key_tys can contain skolem constants, and we can guarantee that those +are never going to be instantiated to anything, so we should not involve +them in the unification test. Example: + class Foo a where { op :: a -> Int } + instance Foo a => Foo [a] -- NB overlap + instance Foo [Int] -- NB overlap + data T = forall a. Foo a => MkT a + f :: T -> Int + f (MkT x) = op [x,x] +The op [x,x] means we need (Foo [a]). Without the filterVarSet we'd +complain, saying that the choice of instance depended on the instantiation +of 'a'; but of course it isn't *going* to be instantiated. + +We do this only for pattern-bound skolems. For example we reject + g :: forall a => [a] -> Int + g x = op x +on the grounds that the correct instance depends on the instantiation of 'a'