[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