X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2Ftypes%2FInstEnv.lhs;h=b8e10d5ed37f53823026c1b5be3fa28bc5be281f;hb=b88025eabcd83f65d1d81f09272f5172f06a60e7;hp=d4a7b771b7de4b9c7d46c968929e30a4236b319b;hpb=0065d5ab628975892cea1ec7303f968c3338cbe1;p=ghc-hetmet.git diff --git a/compiler/types/InstEnv.lhs b/compiler/types/InstEnv.lhs index d4a7b77..b8e10d5 100644 --- a/compiler/types/InstEnv.lhs +++ b/compiler/types/InstEnv.lhs @@ -1,4 +1,5 @@ % +% (c) The University of Glasgow 2006 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % \section[InstEnv]{Utilities for typechecking instance declarations} @@ -20,25 +21,24 @@ module InstEnv ( #include "HsVersions.h" -import Class ( Class ) -import Var ( Id, TyVar, isTcTyVar ) +import Class +import Var import VarSet -import Name ( Name, NamedThing(..), getSrcLoc, nameIsLocalOrFrom, nameModule ) -import OccName ( OccName ) -import NameSet ( unionNameSets, unitNameSet, nameSetToList ) -import Type ( TvSubst ) -import TcType ( Type, PredType, tcEqType, - tcSplitDFunTy, tyVarsOfTypes, isExistentialTyVar, - pprThetaArrow, pprClassPred, - tyClsNamesOfType, tcSplitTyConApp_maybe - ) -import TyCon ( tyConName ) -import Unify ( tcMatchTys, tcUnifyTys, BindFlag(..) ) +import Name +import OccName +import NameSet +import Type +import TcType +import TyCon +import TcGadt +import Unify import Outputable -import UniqFM ( UniqFM, lookupUFM, emptyUFM, addToUFM_C, eltsUFM ) -import Id ( idType, idName ) -import SrcLoc ( pprDefnLoc ) -import Maybe ( isJust, isNothing ) +import BasicTypes +import UniqFM +import Id +import SrcLoc + +import Data.Maybe ( isJust, isNothing ) \end{code} @@ -61,68 +61,74 @@ data Instance , is_tys :: [Type] -- Full arg types , is_dfun :: DFunId - , is_flag :: OverlapFlag + , is_flag :: OverlapFlag -- See detailed comments with + -- the decl of BasicTypes.OverlapFlag , is_orph :: Maybe OccName } +\end{code} --- The "rough-match" fields --- ~~~~~~~~~~~~~~~~~~~~~~~~~ --- The is_cls, is_args fields allow a "rough match" to be done --- without poking inside the DFunId. Poking the DFunId forces --- us to suck in all the type constructors etc it involves, --- which is a total waste of time if it has no chance of matching --- So the Name, [Maybe Name] fields allow us to say "definitely --- does not match", based only on the Name. --- --- In is_tcs, --- Nothing means that this type arg is a type variable --- --- (Just n) means that this type arg is a --- TyConApp with a type constructor of n. --- This is always a real tycon, never a synonym! --- (Two different synonyms might match, but two --- different real tycons can't.) --- NB: newtypes are not transparent, though! --- --- The "proper-match" fields --- ~~~~~~~~~~~~~~~~~~~~~~~~~ --- The is_tvs, is_tys fields are simply cahced values, pulled --- out (lazily) from the dfun id. They are cached here simply so --- that we don't need to decompose the DFunId each time we want --- to match it. The hope is that the fast-match fields mean --- that we often never poke th proper-match fields --- --- However, note that: --- * is_tvs must be a superset of the free vars of is_tys --- --- * The is_dfun must itself be quantified over exactly is_tvs --- (This is so that we can use the matching substitution to --- instantiate the dfun's context.) --- --- The "orphan" field --- ~~~~~~~~~~~~~~~~~~ --- An instance is an orphan if its head (after the =>) mentions --- nothing defined in this module. --- --- Just n The head mentions n, which is defined in this module --- This is used for versioning; the instance decl is --- considered part of the defn of n when computing versions --- --- Nothing The head mentions nothing defined in this modle --- --- If a module contains any orphans, then its interface file is read --- regardless, so that its instances are not missed. --- --- Functional dependencies worsen the situation a bit. Consider --- class C a b | a -> b --- In some other module we might have --- module M where --- data T = ... --- instance C Int T where ... --- This isn't considered an orphan, so we will only read M's interface --- if something from M is used (e.g. T). So there's a risk we'll --- miss the improvement from the instance. Workaround: import M. +The "rough-match" fields +~~~~~~~~~~~~~~~~~~~~~~~~~ +The is_cls, is_args fields allow a "rough match" to be done +without poking inside the DFunId. Poking the DFunId forces +us to suck in all the type constructors etc it involves, +which is a total waste of time if it has no chance of matching +So the Name, [Maybe Name] fields allow us to say "definitely +does not match", based only on the Name. + +In is_tcs, + Nothing means that this type arg is a type variable + + (Just n) means that this type arg is a + TyConApp with a type constructor of n. + This is always a real tycon, never a synonym! + (Two different synonyms might match, but two + different real tycons can't.) + NB: newtypes are not transparent, though! + +The "proper-match" fields +~~~~~~~~~~~~~~~~~~~~~~~~~ +The is_tvs, is_tys fields are simply cahced values, pulled +out (lazily) from the dfun id. They are cached here simply so +that we don't need to decompose the DFunId each time we want +to match it. The hope is that the fast-match fields mean +that we often never poke th proper-match fields + +However, note that: + * is_tvs must be a superset of the free vars of is_tys + + * The is_dfun must itself be quantified over exactly is_tvs + (This is so that we can use the matching substitution to + instantiate the dfun's context.) + + +Note [Orphans]: the "is_orph" field +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +An instance is an orphan if its head (after the =>) mentions +nothing defined in this module. + + Just n The head mentions n, which is defined in this module + This is used for versioning; the instance decl is + considered part of the defn of n when computing versions + + Nothing The head mentions nothing defined in this module + +If a module contains any orphans, then its interface file is read +regardless, so that its instances are not missed. + +Functional dependencies worsen the situation a bit. Consider + class C a b | a -> b +In some other module we might have + module M where + data T = ... + instance C Int T where ... +This isn't considered an orphan, so we will only read M's interface +if something from M is used (e.g. T). So there's a risk we'll +miss the improvement from the instance. Workaround: import M. + +Rules are orphans and versioned in much the same way. +\begin{code} instanceDFunId :: Instance -> DFunId instanceDFunId = is_dfun @@ -213,38 +219,6 @@ instanceCantMatch :: [Maybe Name] -> [Maybe Name] -> Bool -- False is non-committal instanceCantMatch (Just t : ts) (Just a : as) = t/=a || instanceCantMatch ts as instanceCantMatch ts as = False -- Safe - ---------------------------------------------------- -data OverlapFlag - = NoOverlap -- This instance must not overlap another - - | OverlapOk -- Silently ignore this instance if you find a - -- more specific one that matches the constraint - -- you are trying to resolve - -- - -- Example: constraint (Foo [Int]) - -- instances (Foo [Int]) - -- (Foo [a]) OverlapOk - -- Since the second instance has the OverlapOk flag, - -- the first instance will be chosen (otherwise - -- its ambiguous which to choose) - - | Incoherent -- Like OverlapOk, but also ignore this instance - -- if it doesn't match the constraint you are - -- trying to resolve, but could match if the type variables - -- in the constraint were instantiated - -- - -- Example: constraint (Foo [b]) - -- instances (Foo [Int]) Incoherent - -- (Foo [a]) - -- Without the Incoherent flag, we'd complain that - -- instantiating 'b' would change which instance - -- was chosen - -instance Outputable OverlapFlag where - ppr NoOverlap = empty - ppr OverlapOk = ptext SLIT("[overlap ok]") - ppr Incoherent = ptext SLIT("[incoherent]") \end{code} @@ -504,9 +478,9 @@ lookupInstEnv (pkg_ie, home_ie) cls tys = find ms us rest | otherwise - = ASSERT2( not (tyVarsOfTypes tys `intersectsVarSet` tpl_tvs), - (ppr cls <+> ppr tys <+> ppr all_tvs) $$ - (ppr dfun <+> ppr tpl_tvs <+> ppr tpl_tys) + = ASSERT2( tyVarsOfTypes tys `disjointVarSet` tpl_tvs, + (ppr cls <+> ppr tys <+> ppr all_tvs) $$ + (ppr dfun <+> ppr tpl_tvs <+> ppr tpl_tys) ) -- Unification will break badly if the variables overlap -- They shouldn't because we allocate separate uniques for them