Skip to content

Commit 390a9a6

Browse files
authored
fix: mixing variable binder updates and declarations (leanprover#5142)
Fixes leanprover#2143
1 parent 6d4ec15 commit 390a9a6

File tree

2 files changed

+22
-8
lines changed

2 files changed

+22
-8
lines changed

src/Lean/Elab/BuiltinCommand.lean

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,8 @@ private def replaceBinderAnnotation (binder : TSyntax ``Parser.Term.bracketedBin
176176
let mut binderIds := binderIds
177177
let mut binderIdsIniSize := binderIds.size
178178
let mut modifiedVarDecls := false
179-
for varDecl in varDecls do
179+
-- Go through declarations in reverse to respect shadowing
180+
for varDecl in varDecls.reverse do
180181
let (ids, ty?, explicit') ← match varDecl with
181182
| `(bracketedBinderF|($ids* $[: $ty?]? $(annot?)?)) =>
182183
if annot?.isSome then
@@ -208,15 +209,15 @@ private def replaceBinderAnnotation (binder : TSyntax ``Parser.Term.bracketedBin
208209
`(bracketedBinderF| ($id $[: $ty?]?))
209210
else
210211
`(bracketedBinderF| {$id $[: $ty?]?})
211-
for id in ids do
212+
for id in ids.reverse do
212213
if let some idx := binderIds.findIdx? fun binderId => binderId.raw.isIdent && binderId.raw.getId == id.raw.getId then
213214
binderIds := binderIds.eraseIdx idx
214215
modifiedVarDecls := true
215216
varDeclsNew := varDeclsNew.push (← mkBinder id explicit)
216217
else
217218
varDeclsNew := varDeclsNew.push (← mkBinder id explicit')
218219
if modifiedVarDecls then
219-
modifyScope fun scope => { scope with varDecls := varDeclsNew }
220+
modifyScope fun scope => { scope with varDecls := varDeclsNew.reverse }
220221
if binderIds.size != binderIdsIniSize then
221222
binderIds.mapM fun binderId =>
222223
if explicit then
@@ -228,15 +229,14 @@ private def replaceBinderAnnotation (binder : TSyntax ``Parser.Term.bracketedBin
228229

229230
@[builtin_command_elab «variable»] def elabVariable : CommandElab
230231
| `(variable $binders*) => do
232+
let binders ← binders.concatMapM replaceBinderAnnotation
231233
-- Try to elaborate `binders` for sanity checking
232234
runTermElabM fun _ => Term.withSynthesize <| Term.withAutoBoundImplicit <|
233235
Term.elabBinders binders fun _ => pure ()
236+
-- Remark: if we want to produce error messages when variables shadow existing ones, here is the place to do it.
234237
for binder in binders do
235-
let binders ← replaceBinderAnnotation binder
236-
-- Remark: if we want to produce error messages when variables shadow existing ones, here is the place to do it.
237-
for binder in binders do
238-
let varUIds ← (← getBracketedBinderIds binder) |>.mapM (withFreshMacroScope ∘ MonadQuotation.addMacroScope)
239-
modifyScope fun scope => { scope with varDecls := scope.varDecls.push binder, varUIds := scope.varUIds ++ varUIds }
238+
let varUIds ← (← getBracketedBinderIds binder) |>.mapM (withFreshMacroScope ∘ MonadQuotation.addMacroScope)
239+
modifyScope fun scope => { scope with varDecls := scope.varDecls.push binder, varUIds := scope.varUIds ++ varUIds }
240240
| _ => throwUnsupportedSyntax
241241

242242
open Meta

tests/lean/run/2143.lean

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/-!
2+
The elaboration pre-check of `variable`s should not fail on mixed binder updates (nor on shadowing)
3+
-/
4+
5+
variable (α : Type _) [OfNat α (nat_lit 0)]
6+
variable {α} (x : α) (h : x = 0)
7+
8+
variable (α : Type _) [OfNat α (nat_lit 0)]
9+
variable {α} (x : α)
10+
variable (h : x = 0)
11+
12+
variable (α : Type _) [OfNat α (nat_lit 0)]
13+
variable {α}
14+
variable (x : α) (h : x = 0)

0 commit comments

Comments
 (0)