[Git][ghc/ghc][master] Take care when simplifying unfoldings
Marge Bot (@marge-bot)
gitlab at gitlab.haskell.org
Fri Dec 8 20:54:47 UTC 2023
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
d8baa1bd by Simon Peyton Jones at 2023-12-08T15:40:37+00:00
Take care when simplifying unfoldings
This MR fixes a very subtle bug exposed by #24242.
See Note [Environment for simplLetUnfolding].
I also updated a bunch of Notes on shadowing
- - - - -
8 changed files:
- compiler/GHC/Core.hs
- compiler/GHC/Core/Opt/CSE.hs
- compiler/GHC/Core/Opt/FloatIn.hs
- compiler/GHC/Core/Opt/Pipeline.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Core/Opt/SpecConstr.hs
- compiler/GHC/Stg/CSE.hs
Changes:
=====================================
compiler/GHC/Core.hs
=====================================
@@ -154,7 +154,7 @@ These data types are the heart of the compiler
-- f_1 x_2 = let f_3 x_4 = x_4 + 1
-- in f_3 (x_2 - 2)
-- @
--- But see Note [Shadowing] below.
+-- But see Note [Shadowing in Core] below.
--
-- 3. The resulting syntax tree undergoes type checking (which also deals with instantiating
-- type class arguments) to yield a 'GHC.Hs.Expr.HsExpr' type that has 'GHC.Types.Id.Id' as it's names.
@@ -312,26 +312,6 @@ data Bind b = NonRec b (Expr b)
deriving Data
{-
-Note [Shadowing]
-~~~~~~~~~~~~~~~~
-While various passes attempt to rename on-the-fly in a manner that
-avoids "shadowing" (thereby simplifying downstream optimizations),
-neither the simplifier nor any other pass GUARANTEES that shadowing is
-avoided. Thus, all passes SHOULD work fine even in the presence of
-arbitrary shadowing in their inputs.
-
-In particular, scrutinee variables `x` in expressions of the form
-`Case e x t` are often renamed to variables with a prefix
-"wild_". These "wild" variables may appear in the body of the
-case-expression, and further, may be shadowed within the body.
-
-So the Unique in a Var is not really unique at all. Still, it's very
-useful to give a constant-time equality/ordering for Vars, and to give
-a key that can be used to make sets of Vars (VarSet), or mappings from
-Vars to other things (VarEnv). Moreover, if you do want to eliminate
-shadowing, you can give a new Unique to an Id without changing its
-printable name, which makes debugging easier.
-
Note [Literal alternatives]
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Literal alternatives (LitAlt lit) are always for *un-lifted* literals.
@@ -363,6 +343,39 @@ For example
Here 'c' is a CoVar, which is lambda-bound, but it /occurs/ in
a Coercion, (sym c).
+Note [Shadowing in Core]
+~~~~~~~~~~~~~~~~~~~~~~~~
+You might wonder if there is an invariant that a Core expression has no
+"shadowing". For example, is this illegal?
+ \x. \x. blah -- x is shadowed
+Answer; no! Core does /not/ have a no-shadowing invariant.
+
+Neither the simplifier nor any other pass GUARANTEES that shadowing is
+avoided. Thus, all passes SHOULD work fine even in the presence of
+arbitrary shadowing in their inputs.
+
+So the Unique in a Var is not really unique at all. Still, it's very
+useful to give a constant-time equality/ordering for Vars, and to give
+a key that can be used to make sets of Vars (VarSet), or mappings from
+Vars to other things (VarEnv). Moreover, if you do want to eliminate
+shadowing, you can give a new Unique to an Id without changing its
+printable name, which makes debugging easier.
+
+It would in many ways be easier to have a no-shadowing invariant. And the
+Simplifier does its best to clone variables that are shadowed. But it is
+extremely difficult to GUARANTEE it:
+
+* We use `GHC.Types.Id.mkTemplateLocal` to make up local binders, with uniques
+ that are locally-unique (enough for the purpose) but not globally unique.
+ It is convenient not to have to plumb a unique supply to these functions.
+
+* It is very difficult for the Simplifier to gurantee a no-shadowing result.
+ See Note [Shadowing in the Simplifier] in GHC.Core.Opt.Simplify.Iteration.
+
+* See Note [Shadowing in CSE] in GHC.Core.Opt.CSE
+
+* See Note [Shadowing in SpecConstr] in GHC.Core.Opt.SpecContr
+
Note [Core letrec invariant]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The Core letrec invariant:
=====================================
compiler/GHC/Core/Opt/CSE.hs
=====================================
@@ -53,8 +53,8 @@ So we carry an extra var->var substitution which we apply *before* looking up in
reverse mapping.
-Note [Shadowing]
-~~~~~~~~~~~~~~~~
+Note [Shadowing in CSE]
+~~~~~~~~~~~~~~~~~~~~~~~
We have to be careful about shadowing.
For example, consider
f = \x -> let y = x+x in
@@ -900,7 +900,7 @@ extendCSSubst :: CSEnv -> Id -> CoreExpr -> CSEnv
extendCSSubst cse x rhs = cse { cs_subst = extendSubst (cs_subst cse) x rhs }
-- | Add clones to the substitution to deal with shadowing. See
--- Note [Shadowing] for more details. You should call this whenever
+-- Note [Shadowing in CSE] for more details. You should call this whenever
-- you go under a binder.
addBinder :: CSEnv -> Var -> (CSEnv, Var)
addBinder cse v = (cse { cs_subst = sub' }, v')
=====================================
compiler/GHC/Core/Opt/FloatIn.hs
=====================================
@@ -306,7 +306,7 @@ It is obviously bogus for FloatIn to transform to
(y:ys) -> ...(let x = y+1 in x)...
[] -> blah
because the y is captured. This doesn't happen much, because shadowing is
-rare, but it did happen in #22662.
+rare (see Note [Shadowing in Core]), but it did happen in #22662.
One solution would be to clone as we go. But a simpler one is this:
=====================================
compiler/GHC/Core/Opt/Pipeline.hs
=====================================
@@ -309,7 +309,7 @@ getCoreToDo dflags hpt_rule_base extra_vars
[ CoreLiberateCase, simplify "post-liberate-case" ],
-- Run the simplifier after LiberateCase to vastly
-- reduce the possibility of shadowing
- -- Reason: see Note [Shadowing] in GHC.Core.Opt.SpecConstr
+ -- Reason: see Note [Shadowing in SpecConstr] in GHC.Core.Opt.SpecConstr
runWhen spec_constr $ CoreDoPasses
[ CoreDoSpecConstr, simplify "post-spec-constr"],
=====================================
compiler/GHC/Core/Opt/Simplify/Iteration.hs
=====================================
@@ -118,14 +118,6 @@ The general shape of the simplifier is this:
The returned floats and env both have an in-scope set, and they are
guaranteed to be the same.
-
-Note [Shadowing]
-~~~~~~~~~~~~~~~~
-The simplifier used to guarantee that the output had no shadowing, but
-it does not do so any more. (Actually, it never did!) The reason is
-documented with simplifyArgs.
-
-
Eta expansion
~~~~~~~~~~~~~~
For eta expansion, we want to catch things like
@@ -261,7 +253,7 @@ simplRecBind env0 bind_cxt pairs0
= do { (env1, triples) <- mapAccumLM add_rules env0 pairs0
; let new_bndrs = map sndOf3 triples
; (rec_floats, env2) <- enterRecGroupRHSs env1 new_bndrs $ \env ->
- go env triples
+ go env triples
; return (mkRecFloats rec_floats, env2) }
where
add_rules :: SimplEnv -> (InBndr,InExpr) -> SimplM (SimplEnv, (InBndr, OutBndr, InExpr))
@@ -302,10 +294,12 @@ simplRecOrTopPair env bind_cxt old_bndr new_bndr rhs
| otherwise
= case bind_cxt of
BC_Join is_rec cont -> simplTrace "SimplBind:join" (ppr old_bndr) $
- simplJoinBind env is_rec cont old_bndr new_bndr rhs env
+ simplJoinBind is_rec cont
+ (old_bndr,env) (new_bndr,env) (rhs,env)
BC_Let top_lvl is_rec -> simplTrace "SimplBind:normal" (ppr old_bndr) $
- simplLazyBind env top_lvl is_rec old_bndr new_bndr rhs env
+ simplLazyBind top_lvl is_rec
+ (old_bndr,env) (new_bndr,env) (rhs,env)
simplTrace :: String -> SDoc -> SimplM a -> SimplM a
simplTrace herald doc thing_inside = do
@@ -315,19 +309,16 @@ simplTrace herald doc thing_inside = do
else thing_inside
--------------------------
-simplLazyBind :: SimplEnv
- -> TopLevelFlag -> RecFlag
- -> InId -> OutId -- Binder, both pre-and post simpl
- -- Not a JoinId
+simplLazyBind :: TopLevelFlag -> RecFlag
+ -> (InId, SimplEnv) -- InBinder, and static env for its unfolding (if any)
+ -> (OutId, SimplEnv) -- OutBinder, and SimplEnv after simplifying that binder
-- The OutId has IdInfo (notably RULES),
-- except arity, unfolding
- -- Ids only, no TyVars
- -> InExpr -> SimplEnv -- The RHS and its environment
+ -> (InExpr, SimplEnv) -- The RHS and its static environment
-> SimplM (SimplFloats, SimplEnv)
--- Precondition: the OutId is already in the InScopeSet of the incoming 'env'
--- Precondition: not a JoinId
+-- Precondition: Ids only, no TyVars; not a JoinId
-- Precondition: rhs obeys the let-can-float invariant
-simplLazyBind env top_lvl is_rec bndr bndr1 rhs rhs_se
+simplLazyBind top_lvl is_rec (bndr,unf_se) (bndr1,env) (rhs,rhs_se)
= assert (isId bndr )
assertPpr (not (isJoinId bndr)) (ppr bndr) $
-- pprTrace "simplLazyBind" ((ppr bndr <+> ppr bndr1) $$ ppr rhs $$ ppr (seIdSubst rhs_se)) $
@@ -378,24 +369,23 @@ simplLazyBind env top_lvl is_rec bndr bndr1 rhs rhs_se
; let poly_floats = foldl' extendFloats (emptyFloats env) poly_binds
; return (poly_floats, body3) }
- ; let env' = env `setInScopeFromF` rhs_floats
- ; rhs' <- rebuildLam env' tvs' body3 rhs_cont
- ; (bind_float, env2) <- completeBind env' (BC_Let top_lvl is_rec) bndr bndr1 rhs'
+ ; let env1 = env `setInScopeFromF` rhs_floats
+ ; rhs' <- rebuildLam env1 tvs' body3 rhs_cont
+ ; (bind_float, env2) <- completeBind (BC_Let top_lvl is_rec) (bndr,unf_se) (bndr1,rhs',env1)
; return (rhs_floats `addFloats` bind_float, env2) }
--------------------------
-simplJoinBind :: SimplEnv
- -> RecFlag
+simplJoinBind :: RecFlag
-> SimplCont
- -> InId -> OutId -- Binder, both pre-and post simpl
- -- The OutId has IdInfo, except arity,
- -- unfolding
- -> InExpr -> SimplEnv -- The right hand side and its env
+ -> (InId, SimplEnv) -- InBinder, with static env for its unfolding
+ -> (OutId, SimplEnv) -- OutBinder; SimplEnv has the binder in scope
+ -- The OutId has IdInfo, except arity, unfolding
+ -> (InExpr, SimplEnv) -- The right hand side and its env
-> SimplM (SimplFloats, SimplEnv)
-simplJoinBind env is_rec cont old_bndr new_bndr rhs rhs_se
+simplJoinBind is_rec cont (old_bndr, unf_se) (new_bndr, env) (rhs, rhs_se)
= do { let rhs_env = rhs_se `setInScopeFromE` env
; rhs' <- simplJoinRhs rhs_env old_bndr rhs cont
- ; completeBind env (BC_Join is_rec cont) old_bndr new_bndr rhs' }
+ ; completeBind (BC_Join is_rec cont) (old_bndr, unf_se) (new_bndr, rhs', env) }
--------------------------
simplAuxBind :: SimplEnv
@@ -406,7 +396,7 @@ simplAuxBind :: SimplEnv
-- auxiliary bindings, notably in knownCon.
--
-- The binder comes from a case expression (case binder or alternative)
--- and so does not have rules, inline pragmas etc.
+-- and so does not have rules, unfolding, inline pragmas etc.
--
-- Precondition: rhs satisfies the let-can-float invariant
@@ -435,8 +425,8 @@ simplAuxBind env bndr new_rhs
-- Simplify the binder and complete the binding
; (env1, new_bndr) <- simplBinder (env `setInScopeFromF` rhs_floats) bndr
- ; (bind_float, env2) <- completeBind env1 (BC_Let NotTopLevel NonRecursive)
- bndr new_bndr rhs1
+ ; (bind_float, env2) <- completeBind (BC_Let NotTopLevel NonRecursive)
+ (bndr,env) (new_bndr, rhs1, env1)
; return (rhs_floats `addFloats` bind_float, env2) }
@@ -842,7 +832,7 @@ makeTrivial env top_lvl dmd occ_fs expr
; (arity_type, expr2) <- tryEtaExpandRhs env (BC_Let top_lvl NonRecursive) var expr1
-- Technically we should extend the in-scope set in 'env' with
-- the 'floats' from prepareRHS; but they are all fresh, so there is
- -- no danger of introducing name shadowig in eta expansion
+ -- no danger of introducing name shadowing in eta expansion
; unf <- mkLetUnfolding uf_opts top_lvl VanillaSrc var expr2
@@ -916,11 +906,11 @@ It does *not* attempt to do let-to-case. Why? Because it is used for
Nor does it do the atomic-argument thing
-}
-completeBind :: SimplEnv
- -> BindContext
- -> InId -- Old binder
- -> OutId -- New binder; can be a JoinId
- -> OutExpr -- New RHS
+completeBind :: BindContext
+ -> (InId, SimplEnv) -- Old binder, and the static envt in which to simplify
+ -- its stable unfolding (if any)
+ -> (OutId, OutExpr, SimplEnv) -- New binder and rhs; can be a JoinId.
+ -- And the SimplEnv with that OutId in scope.
-> SimplM (SimplFloats, SimplEnv)
-- completeBind may choose to do its work
-- * by extending the substitution (e.g. let x = y in ...)
@@ -928,7 +918,7 @@ completeBind :: SimplEnv
--
-- Binder /can/ be a JoinId
-- Precondition: rhs obeys the let-can-float invariant
-completeBind env bind_cxt old_bndr new_bndr new_rhs
+completeBind bind_cxt (old_bndr, unf_se) (new_bndr, new_rhs, env)
| isCoVar old_bndr
= case new_rhs of
Coercion co -> return (emptyFloats env, extendCvSubst env old_bndr co)
@@ -944,9 +934,10 @@ completeBind env bind_cxt old_bndr new_bndr new_rhs
-- See Note [Eta-expanding at let bindings] in GHC.Core.Opt.Simplify.Utils
; (new_arity, eta_rhs) <- tryEtaExpandRhs env bind_cxt new_bndr new_rhs
- -- Simplify the unfolding
- ; new_unfolding <- simplLetUnfolding env bind_cxt old_bndr
- eta_rhs (idType new_bndr) new_arity old_unf
+ -- Simplify the unfolding; see Note [Environment for simplLetUnfolding]
+ ; new_unfolding <- simplLetUnfolding (unf_se `setInScopeFromE` env)
+ bind_cxt old_bndr
+ eta_rhs (idType new_bndr) new_arity old_unf
; let new_bndr_w_info = addLetBndrInfo new_bndr new_arity new_unfolding
-- See Note [In-scope set as a substitution]
@@ -1063,6 +1054,36 @@ postInlineUnconditionally will return True, but we may not have an
unfolding because it's too big. Hence the belt-and-braces `orElse`
in the defn of unf_rhs. The Nothing case probably never happens.
+Note [Environment for simplLetUnfolding]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+We need to be rather careful about the static environment in which
+we simplify a stable unfolding. Consider (#24242):
+
+ f x = let y_Xb = ... in
+ let step1_Xb {Stable unfolding = ....y_Xb...} = rhs in
+ ...
+
+Note that `y_Xb` and `step1_Xb` have the same unique (`Xb`). This can happen;
+see Note [Shadowing in Core] in GHC.Core, and Note [Shadowing in the Simplifier].
+This is perfectly fine. The `y_Xb` in the stable unfolding of the non-
+recursive binding for `step1` refers, of course, to `let y_Xb = ....`.
+When simplifying the binder `step1_Xb` we'll give it a new unique, and
+extend the static environment with [Xb :-> step1_Xc], say.
+
+But when simplifying step1's stable unfolding, we must use static environment
+/before/ simplifying the binder `step1_Xb`; that is, a static envt that maps
+[Xb :-> y_Xb], /not/ [Xb :-> step1_Xc].
+
+That is why we pass around a pair `(InId, SimplEnv)` for the binder, keeping
+track of the right environment for the unfolding of that InId. See the type
+of `simplLazyBind`, `simplJoinBind`, `completeBind`.
+
+This only matters when we have
+ - A non-recursive binding for f
+ - has a stable unfolding
+ - and that unfolding mentions a variable y
+ - that has the same unique as f.
+So triggering a bug here is really hard!
************************************************************************
* *
@@ -1524,7 +1545,7 @@ rebuild env expr cont
completeBindX :: SimplEnv
-> FromWhat
- -> InId -> OutExpr -- Bind this Id to this (simplified) expression
+ -> InId -> OutExpr -- Non-recursively bind this Id to this (simplified) expression
-- (the let-can-float invariant may not be satisfied)
-> InExpr -- In this body
-> SimplCont -- Consumed by this continuation
@@ -1554,14 +1575,14 @@ completeBindX env from_what bndr rhs body cont
-- in T9630) to pass 'env' rather than 'env1'. It's fine to pass 'env',
-- because this is simplNonRecX, so bndr is not in scope in the RHS.
- ; (bind_float, env2) <- completeBind (env2 `setInScopeFromF` rhs_floats)
- (BC_Let NotTopLevel NonRecursive)
- bndr bndr2 rhs1
+ ; let env3 = env2 `setInScopeFromF` rhs_floats
+ ; (bind_float, env4) <- completeBind (BC_Let NotTopLevel NonRecursive)
+ (bndr,env) (bndr2, rhs1, env3)
-- Must pass env1 to completeBind in case simplBinder had to clone,
-- and extended the substitution with [bndr :-> new_bndr]
-- Simplify the body
- ; (body_floats, body') <- simplNonRecBody env2 from_what body cont
+ ; (body_floats, body') <- simplNonRecBody env4 from_what body cont
; let all_floats = rhs_floats `addFloats` bind_float `addFloats` body_floats
; return ( all_floats, body' ) }
@@ -1785,10 +1806,11 @@ simplLamBndrs env bndrs = mapAccumLM simplLamBndr env bndrs
simplNonRecE :: HasDebugCallStack
=> SimplEnv
-> FromWhat
- -> InId -- The binder, always an Id
- -- Never a join point
- -> (InExpr, SimplEnv) -- Rhs of binding (or arg of lambda)
- -> InExpr -- Body of the let/lambda
+ -> InId -- The binder, always an Id
+ -- Never a join point
+ -- The static env for its unfolding (if any) is the first parameter
+ -> (InExpr, SimplEnv) -- Rhs of binding (or arg of lambda)
+ -> InExpr -- Body of the let/lambda
-> SimplCont
-> SimplM (SimplFloats, OutExpr)
@@ -1817,8 +1839,8 @@ simplNonRecE env from_what bndr (rhs, rhs_se) body cont
| otherwise -- Evaluate RHS lazily
= do { (env1, bndr1) <- simplNonRecBndr env bndr
; (env2, bndr2) <- addBndrRules env1 bndr bndr1 (BC_Let NotTopLevel NonRecursive)
- ; (floats1, env3) <- simplLazyBind env2 NotTopLevel NonRecursive
- bndr bndr2 rhs rhs_se
+ ; (floats1, env3) <- simplLazyBind NotTopLevel NonRecursive
+ (bndr,env) (bndr2,env2) (rhs,rhs_se)
; (floats2, expr') <- simplNonRecBody env3 from_what body cont
; return (floats1 `addFloats` floats2, expr') }
@@ -1944,7 +1966,7 @@ simplNonRecJoinPoint env bndr rhs body cont
res_ty = contResultType cont
; (env1, bndr1) <- simplNonRecJoinBndr env bndr mult res_ty
; (env2, bndr2) <- addBndrRules env1 bndr bndr1 (BC_Join NonRecursive cont)
- ; (floats1, env3) <- simplJoinBind env2 NonRecursive cont bndr bndr2 rhs env
+ ; (floats1, env3) <- simplJoinBind NonRecursive cont (bndr,env) (bndr2,env2) (rhs,env)
; (floats2, body') <- simplExprF env3 body cont
; return (floats1 `addFloats` floats2, body') }
@@ -2284,7 +2306,7 @@ rebuildCall env fun_info
(StrictArg { sc_fun = fun_info, sc_fun_ty = fun_ty
, sc_dup = Simplified
, sc_cont = cont })
- -- Note [Shadowing]
+ -- Note [Shadowing in the Simplifier]
-- Lazy arguments
| otherwise
@@ -2413,10 +2435,10 @@ Here e1, e2 are simplified before the rule is applied, but don't really
participate in the rule firing. So we mark them as Simplified to avoid
re-simplifying them.
-Note [Shadowing]
-~~~~~~~~~~~~~~~~
-This part of the simplifier may break the no-shadowing invariant
-Consider
+Note [Shadowing in the Simplifier]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This part of the simplifier may return an expression that has shadowing.
+(See Note [Shadowing in Core] in GHC.Core.hs.) Consider
f (...(\a -> e)...) (case y of (a,b) -> e')
where f is strict in its second arg
If we simplify the innermost one first we get (...(\a -> e)...)
@@ -2437,6 +2459,8 @@ to get the effect that finding (error "foo") in a strict arg position will
discard the entire application and replace it with (error "foo"). Getting
all this at once is TOO HARD!
+See also Note [Shadowing in prepareAlts] in GHC.Core.Opt.Simplify.Utils.
+
Note [No eta-expansion in runRW#]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When we see `runRW# (\s. blah)` we must not attempt to eta-expand that
=====================================
compiler/GHC/Core/Opt/Simplify/Utils.hs
=====================================
@@ -190,10 +190,11 @@ data SimplCont
| StrictBind -- (StrictBind x b K)[e] = let x = e in K[b]
-- or, equivalently, = K[ (\x.b) e ]
{ sc_dup :: DupFlag -- See Note [DupFlag invariants]
- , sc_bndr :: InId
, sc_from :: FromWhat
+ , sc_bndr :: InId
, sc_body :: InExpr
- , sc_env :: StaticEnv -- See Note [StaticEnv invariant]
+ , sc_env :: StaticEnv -- Static env for both sc_bndr (stable unfolding thereof)
+ -- and sc_body. Also see Note [StaticEnv invariant]
, sc_cont :: SimplCont }
| StrictArg -- (StrictArg (f e1 ..en) K)[e] = K[ f e1 .. en e ]
@@ -2290,7 +2291,7 @@ Note [Shadowing in prepareAlts]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Note that we pass case_bndr::InId to prepareAlts; an /InId/, not an
/OutId/. This is vital, because `refineDefaultAlt` uses `tys` to build
-a new /InAlt/. If you pass an OutId, we'll end up appling the
+a new /InAlt/. If you pass an OutId, we'll end up applying the
substitution twice: disaster (#23012).
However this does mean that filling in the default alt might be
=====================================
compiler/GHC/Core/Opt/SpecConstr.hs
=====================================
@@ -254,7 +254,7 @@ So the grand plan is:
* Find the free variables of the abstracted pattern
* Pass these variables, less any that are in scope at
- the fn defn. But see Note [Shadowing] below.
+ the fn defn. But see Note [Shadowing in SpecConstr] below.
NOTICE that we only abstract over variables that are not in scope,
@@ -262,8 +262,8 @@ so we're in no danger of shadowing variables used in "higher up"
in f_spec's RHS.
-Note [Shadowing]
-~~~~~~~~~~~~~~~~
+Note [Shadowing in SpecConstr]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In this pass we gather up usage information that may mention variables
that are bound between the usage site and the definition site; or (more
seriously) may be bound to something different at the definition site.
@@ -2503,7 +2503,7 @@ callToPat env bndr_occs call@(Call fn args con_env)
-- Quantify over variables that are not in scope
-- at the call site
-- See Note [Free type variables of the qvar types]
- -- See Note [Shadowing] at the top
+ -- See Note [Shadowing in SpecConstr] at the top
(qktvs, qids) = partition isTyVar qvars
qvars' = scopedSort qktvs ++ map sanitise qids
=====================================
compiler/GHC/Stg/CSE.hs
=====================================
@@ -170,8 +170,8 @@ data CseEnv = CseEnv
-- ^ This substitution is applied to the code as we traverse it.
-- Entries have one of two reasons:
--
- -- * The input might have shadowing (see Note [Shadowing]), so we have
- -- to rename some binders as we traverse the tree.
+ -- * The input might have shadowing (see Note [Shadowing in Core]),
+ -- so we have to rename some binders as we traverse the tree.
-- * If we remove `let x = Con z` because `let y = Con z` is in scope,
-- we note this here as x ↦ y.
, ce_bndrMap :: IdEnv OutId
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/d8baa1bdeea1753afc939a20119d3ce555301167
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/d8baa1bdeea1753afc939a20119d3ce555301167
You're receiving this email because of your account on gitlab.haskell.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20231208/b8116a62/attachment-0001.html>
More information about the ghc-commits
mailing list