lean4-htt/src/Lean/Compiler/LCNF/Simp/Used.lean
Cameron Zwarich c1f1287e24
fix: delete code with false assumption that LCNF local vars can occur in types (#9221)
This PR removes code that has the false assumption that LCNF local vars
can occur in types. There are other comments in `ElimDead.lean`
asserting that this is not possible, so this must have been a change
early in the development of the new compiler.
2025-07-06 15:04:13 +00:00

95 lines
2.8 KiB
Text

/-
Copyright (c) 2022 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
prelude
import Lean.Compiler.LCNF.Simp.SimpM
namespace Lean.Compiler.LCNF
namespace Simp
/--
Mark `fvarId` as an used free variable.
This is information is used to eliminate dead local declarations.
-/
def markUsedFVar (fvarId : FVarId) : SimpM Unit :=
modify fun s => { s with used := s.used.insert fvarId }
/--
Mark all free variables occurring in `arg` as used.
-/
def markUsedArg (arg : Arg) : SimpM Unit :=
match arg with
| .fvar fvarId => markUsedFVar fvarId
-- Locally declared variables do not occur in types.
| .type _ | .erased => return ()
/--
Mark all free variables occurring in `e` as used.
-/
def markUsedLetValue (e : LetValue) : SimpM Unit := do
match e with
| .lit .. | .erased => return ()
| .proj _ _ fvarId => markUsedFVar fvarId
| .const _ _ args => args.forM markUsedArg
| .fvar fvarId args => markUsedFVar fvarId; args.forM markUsedArg
/--
Mark all free variables occurring on the right-hand side of the given let declaration as used.
This is information is used to eliminate dead local declarations.
-/
def markUsedLetDecl (letDecl : LetDecl) : SimpM Unit :=
markUsedLetValue letDecl.value
mutual
/--
Mark all free variables occurring in `code` as used.
-/
partial def markUsedCode (code : Code) : SimpM Unit := do
match code with
| .let decl k => markUsedLetDecl decl; markUsedCode k
| .jp decl k | .fun decl k => markUsedFunDecl decl; markUsedCode k
| .return fvarId => markUsedFVar fvarId
| .unreach .. => return ()
| .jmp fvarId args => markUsedFVar fvarId; args.forM markUsedArg
| .cases c => markUsedFVar c.discr; c.alts.forM fun alt => markUsedCode alt.getCode
/--
Mark all free variables occurring in `funDecl` as used.
-/
partial def markUsedFunDecl (funDecl : FunDecl) : SimpM Unit :=
markUsedCode funDecl.value
end
/--
Return `true` if `fvarId` is in the `used` set.
-/
def isUsed (fvarId : FVarId) : SimpM Bool :=
return (← get).used.contains fvarId
/--
Attach the given `decls` to `code`. For example, assume `decls` is `#[.let _x.1 := 10, .let _x.2 := true]`,
then the result is
```
let _x.1 := 10
let _x.2 := true
<code>
```
-/
def attachCodeDecls (decls : Array CodeDecl) (code : Code) : SimpM Code := do
go decls.size code
where
go (i : Nat) (code : Code) : SimpM Code := do
if i > 0 then
let decl := decls[i-1]!
if (← isUsed decl.fvarId) then
match decl with
| .let decl => markUsedLetDecl decl; go (i-1) (.let decl code)
| .fun decl => markUsedFunDecl decl; go (i-1) (.fun decl code)
| .jp decl => markUsedFunDecl decl; go (i-1) (.jp decl code)
else
eraseCodeDecl decl
go (i-1) code
else
return code