Commit aae915d6 authored by simonpj@microsoft.com's avatar simonpj@microsoft.com

Fix a nasty bug in RULE matching: Trac #4814

See Note [Matching lets], which explains it all in detail.
It took me a day to think of a nice way to fix the bug,
but I think the result is quite respectable. Subtle, though.
parent d2f11ea8
......@@ -36,7 +36,8 @@ module VarEnv (
-- ** Operations on RnEnv2s
mkRnEnv2, rnBndr2, rnBndrs2, rnOccL, rnOccR, inRnEnvL, inRnEnvR,
rnBndrL, rnBndrR, nukeRnEnvL, nukeRnEnvR, extendRnInScopeList,
rnBndrL, rnBndrR, nukeRnEnvL, nukeRnEnvR,
addRnInScopeSet,
rnEtaL, rnEtaR,
rnInScope, rnInScopeSet, lookupRnInScope,
......@@ -204,9 +205,10 @@ mkRnEnv2 vars = RV2 { envL = emptyVarEnv
, envR = emptyVarEnv
, in_scope = vars }
extendRnInScopeList :: RnEnv2 -> [Var] -> RnEnv2
extendRnInScopeList env vs
= env { in_scope = extendInScopeSetList (in_scope env) vs }
addRnInScopeSet :: RnEnv2 -> VarEnv Var -> RnEnv2
addRnInScopeSet env vs
| isEmptyVarEnv vs = env
| otherwise = env { in_scope = extendInScopeSetSet (in_scope env) vs }
rnInScope :: Var -> RnEnv2 -> Bool
rnInScope x env = x `elemInScopeSet` in_scope env
......
......@@ -20,8 +20,9 @@ module CoreSubst (
emptySubst, mkEmptySubst, mkSubst, mkOpenSubst, substInScope, isEmptySubst,
extendIdSubst, extendIdSubstList, extendTvSubst, extendTvSubstList,
extendSubst, extendSubstList, zapSubstEnv,
extendInScope, extendInScopeList, extendInScopeIds,
isInScope,
addInScopeSet, extendInScope, extendInScopeList, extendInScopeIds,
isInScope, setInScope,
delBndr, delBndrs,
-- ** Substituting and cloning binders
substBndr, substBndrs, substRecBndrs,
......@@ -232,6 +233,17 @@ lookupIdSubst doc (Subst in_scope ids _) v
lookupTvSubst :: Subst -> TyVar -> Type
lookupTvSubst (Subst _ _ tvs) v = lookupVarEnv tvs v `orElse` Type.mkTyVarTy v
delBndr :: Subst -> Var -> Subst
delBndr (Subst in_scope tvs ids) v
| isId v = Subst in_scope tvs (delVarEnv ids v)
| otherwise = Subst in_scope (delVarEnv tvs v) ids
delBndrs :: Subst -> [Var] -> Subst
delBndrs (Subst in_scope tvs ids) vs
= Subst in_scope (delVarEnvList tvs vs_tv) (delVarEnvList ids vs_id)
where
(vs_id, vs_tv) = partition isId vs
-- | Simultaneously substitute for a bunch of variables
-- No left-right shadowing
-- ie the substitution for (\x \y. e) a1 a2
......@@ -245,7 +257,14 @@ mkOpenSubst in_scope pairs = Subst in_scope
isInScope :: Var -> Subst -> Bool
isInScope v (Subst in_scope _ _) = v `elemInScopeSet` in_scope
-- | Add the 'Var' to the in-scope set: as a side effect, removes any existing substitutions for it
-- | Add the 'Var' to the in-scope set, but do not remove
-- any existing substitutions for it
addInScopeSet :: Subst -> VarSet -> Subst
addInScopeSet (Subst in_scope ids tvs) vs
= Subst (in_scope `extendInScopeSetSet` vs) ids tvs
-- | Add the 'Var' to the in-scope set: as a side effect,
-- and remove any existing substitutions for it
extendInScope :: Subst -> Var -> Subst
extendInScope (Subst in_scope ids tvs) v
= Subst (in_scope `extendInScopeSet` v)
......@@ -263,6 +282,9 @@ extendInScopeIds :: Subst -> [Id] -> Subst
extendInScopeIds (Subst in_scope ids tvs) vs
= Subst (in_scope `extendInScopeSetList` vs)
(ids `delVarEnvList` vs) tvs
setInScope :: Subst -> InScopeSet -> Subst
setInScope (Subst _ ids tvs) in_scope = Subst in_scope ids tvs
\end{code}
Pretty printing, for debugging only
......
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment