X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2FcoreSyn%2FCoreSubst.lhs;h=321ea8fc3603a37936a9a8ea9db6983815cc956a;hb=8100cd4395e46ae747be4298c181a4730d6206bc;hp=ac5617658b8918b449a3c1dd7c6b7a64778ea4eb;hpb=2a3c28723075eb36e3faa2bfb6c46d934e05f208;p=ghc-hetmet.git diff --git a/compiler/coreSyn/CoreSubst.lhs b/compiler/coreSyn/CoreSubst.lhs index ac56176..321ea8f 100644 --- a/compiler/coreSyn/CoreSubst.lhs +++ b/compiler/coreSyn/CoreSubst.lhs @@ -1,7 +1,9 @@ % +% (c) The University of Glasgow 2006 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % -\section[CoreUtils]{Utility functions on @Core@ syntax} + +Utility functions on @Core@ syntax \begin{code} module CoreSubst ( @@ -24,29 +26,23 @@ module CoreSubst ( #include "HsVersions.h" -import CoreSyn ( Expr(..), Bind(..), Note(..), CoreExpr, CoreBind, - CoreRule(..), hasUnfolding, noUnfolding - ) -import CoreFVs ( exprFreeVars ) -import CoreUtils ( exprIsTrivial ) +import CoreSyn +import CoreFVs +import CoreUtils -import qualified Type ( substTy, substTyVarBndr ) -import Type ( Type, tyVarsOfType, TvSubstEnv, TvSubst(..), mkTyVarTy ) +import qualified Type +import Type ( Type, TvSubst(..), TvSubstEnv ) import VarSet import VarEnv -import Var ( setVarUnique, isId ) -import Id ( idType, idInfo, setIdType, maybeModifyIdInfo, isLocalId ) -import IdInfo ( IdInfo, SpecInfo(..), specInfo, setSpecInfo, isEmptySpecInfo, - unfoldingInfo, setUnfoldingInfo, seqSpecInfo, - WorkerInfo(..), workerExists, workerInfo, setWorkerInfo - ) -import Unique ( Unique ) -import UniqSupply ( UniqSupply, uniqFromSupply, uniqsFromSupply ) -import Var ( Var, Id, TyVar, isTyVar ) -import Maybes ( orElse, isNothing ) +import Id +import Var ( Var, TyVar, setVarUnique ) +import IdInfo +import Unique +import UniqSupply +import Maybes import Outputable import PprCore () -- Instances -import Util ( mapAccumL ) +import Util import FastTypes \end{code} @@ -75,8 +71,51 @@ data Subst -- - make it empty because all the free vars of the subst are fresh, -- and hence can't possibly clash.a -- - -- INVARIANT 2: The substitution is apply-once; see notes with + -- INVARIANT 2: The substitution is apply-once; see Note [Apply once] with -- Types.TvSubstEnv + -- + -- INVARIANT 3: See Note [Extending the Subst] + +{- +Note [Extending the Subst] +~~~~~~~~~~~~~~~~~~~~~~~~~~ +For a core Subst, which binds Ids as well, we make a different choice for Ids +than we do for TyVars. + +For TyVars, see Note [Extending the TvSubst] with Type.TvSubstEnv + +For Ids, we have a different invariant + The IdSubstEnv is extended *only* when the Unique on an Id changes + Otherwise, we just extend the InScopeSet + +In consequence: + +* In substIdBndr, we extend the IdSubstEnv only when the unique changes + +* If the TvSubstEnv and IdSubstEnv are both empty, substExpr does nothing + (Note that the above rule for substIdBndr maintains this property. If + the incoming envts are both empty, then substituting the type and + IdInfo can't change anything.) + +* In lookupIdSubst, we *must* look up the Id in the in-scope set, because + it may contain non-trivial changes. Example: + (/\a. \x:a. ...x...) Int + We extend the TvSubstEnv with [a |-> Int]; but x's unique does not change + so we only extend the in-scope set. Then we must look up in the in-scope + set when we find the occurrence of x. + +Why do we make a different choice for the IdSubstEnv than the TvSubstEnv? + +* For Ids, we change the IdInfo all the time (e.g. deleting the + unfolding), and adding it back later, so using the TyVar convention + would entail extending the substitution almost all the time + +* The simplifier wants to look up in the in-scope set anyway, in case it + can see a better unfolding from an enclosing case expression + +* For TyVars, only coercion variables can possibly change, and they are + easy to spot +-} type IdSubstEnv = IdEnv CoreExpr @@ -124,31 +163,14 @@ extendTvSubstList (Subst in_scope ids tvs) prs = Subst in_scope ids (extendVarEn lookupIdSubst :: Subst -> Id -> CoreExpr lookupIdSubst (Subst in_scope ids tvs) v | not (isLocalId v) = Var v - | otherwise = case lookupVarEnv ids v of - Just e -> e - Nothing -> Var v - -{- We used to have to look up in the in-scope set, - because GADTs were implicit in the intermediate language - But with FC, the type of an Id does not change in its scope - The worst that can happen if we don't look up in the in-scope set - is that we don't propagate IdInfo as vigorously as we might. - But that'll happen (when it's useful) in SimplEnv.substId - - If you put this back in, you should worry about the - Just e -> e - case above too! - - case lookupInScope in_scope v of { - -- Watch out! Must get the Id from the in-scope set, - -- because its type there may differ - Just v -> Var v ; - Nothing -> WARN( True, ptext SLIT("CoreSubst.lookupIdSubst") <+> ppr v ) - Var v --} + | Just e <- lookupVarEnv ids v = e + | Just v' <- lookupInScope in_scope v = Var v' + -- Vital! See Note [Extending the Subst] + | otherwise = WARN( True, ptext SLIT("CoreSubst.lookupIdSubst") <+> ppr v ) + Var v lookupTvSubst :: Subst -> TyVar -> Type -lookupTvSubst (Subst _ ids tvs) v = lookupVarEnv tvs v `orElse` mkTyVarTy v +lookupTvSubst (Subst _ ids tvs) v = lookupVarEnv tvs v `orElse` Type.mkTyVarTy v ------------------------------ isInScope :: Var -> Subst -> Bool @@ -279,7 +301,8 @@ substIdBndr rec_subst subst@(Subst in_scope env tvs) old_id | otherwise = setIdType id1 (substTy subst old_ty) old_ty = idType old_id - no_type_change = isEmptyVarEnv tvs || isEmptyVarSet (tyVarsOfType old_ty) + no_type_change = isEmptyVarEnv tvs || + isEmptyVarSet (Type.tyVarsOfType old_ty) -- new_id has the right IdInfo -- The lazy-set is because we're in a loop here, with @@ -292,7 +315,9 @@ substIdBndr rec_subst subst@(Subst in_scope env tvs) old_id new_env | no_change = delVarEnv env old_id | otherwise = extendVarEnv env old_id (Var new_id) - no_change = False -- id1 == old_id && isNothing mb_new_info && no_type_change + no_change = id1 == old_id + -- See Note [Extending the Subst] + -- *not* necessary to check mb_new_info and no_type_change \end{code} Now a variant that unconditionally allocates a new unique. @@ -361,7 +386,7 @@ substTy (Subst in_scope id_env tv_env) ty \begin{code} substIdType :: Subst -> Id -> Id substIdType subst@(Subst in_scope id_env tv_env) id - | isEmptyVarEnv tv_env || isEmptyVarSet (tyVarsOfType old_ty) = id + | isEmptyVarEnv tv_env || isEmptyVarSet (Type.tyVarsOfType old_ty) = id | otherwise = setIdType id (substTy subst old_ty) -- The tyVarsOfType is cheaper than it looks -- because we cache the free tyvars of the type @@ -425,5 +450,5 @@ substVarSet subst fvs where subst_fv subst fv | isId fv = exprFreeVars (lookupIdSubst subst fv) - | otherwise = tyVarsOfType (lookupTvSubst subst fv) + | otherwise = Type.tyVarsOfType (lookupTvSubst subst fv) \end{code}