fix: unused variables linter: search fvar aliases in tactics

This commit is contained in:
Sebastian Ullrich 2022-06-03 19:16:31 +02:00
parent f3a7654a63
commit 05c5dd4441
3 changed files with 19 additions and 7 deletions

View file

@ -111,7 +111,8 @@ def unusedVariables : Linter := fun stx => do
if ignoredPatternFns.any (· declStx stack) then
continue
if uses.isEmpty && !tacticFVarUses.contains id then
if uses.isEmpty && !tacticFVarUses.contains id &&
decl.aliases.all (match · with | .fvar id => !tacticFVarUses.contains id | _ => false) then
publishMessage s!"unused variable `{localDecl.userName}`" range
return ()

View file

@ -20,6 +20,8 @@ open Lsp Lean.Elab Std
structure Reference where
ident : RefIdent
/-- FVarIds that are logically identical to this reference -/
aliases : Array RefIdent := #[]
range : Lsp.Range
stx : Syntax
ci : ContextInfo
@ -177,10 +179,12 @@ partial def combineFvars (refs : Array Reference) : Array Reference := Id.run do
for ref in refs do
match ref with
| { ident := ident@(RefIdent.fvar id), isBinder, .. } =>
-- downgrade chained definitions to usages
-- (we shouldn't completely remove them in case they do not have usages)
let isBinder := isBinder && !idMap.contains id
refs' := refs'.push { ref with ident := applyIdMap idMap ident, isBinder }
if isBinder && idMap.contains id then
-- downgrade chained definitions to usages
-- (we shouldn't completely remove them in case they do not have usages)
refs' := refs'.push { ref with ident := applyIdMap idMap ident, isBinder := false, aliases := #[ident] }
else
refs' := refs'.push { ref with ident := applyIdMap idMap ident }
| _ =>
refs' := refs'.push ref
refs'
@ -197,8 +201,10 @@ where
def dedupReferences (refs : Array Reference) : Array Reference := Id.run do
let mut refsByIdAndRange : HashMap (RefIdent × Lsp.Range) Reference := HashMap.empty
for ref in refs do
if ref.isBinder || !(refsByIdAndRange.contains (ref.ident, ref.range)) then
refsByIdAndRange := refsByIdAndRange.insert (ref.ident, ref.range) ref
let key := (ref.ident, ref.range)
refsByIdAndRange := match refsByIdAndRange[key] with
| some ref' => refsByIdAndRange.insert key { ref' with isBinder := ref'.isBinder || ref.isBinder, aliases := ref'.aliases ++ ref.aliases }
| none => refsByIdAndRange.insert key ref
let dedupedRefs := refsByIdAndRange.fold (init := #[]) fun refs _ ref => refs.push ref
return dedupedRefs.qsort (·.range < ·.range)

View file

@ -196,3 +196,8 @@ def externDef (x : Nat) : Nat :=
constant externConst (x : Nat) : Nat :=
let y := 3
5
theorem not_eq_zero_of_lt (h : b < a) : a ≠ 0 := by -- *not* unused
cases a
exact absurd h (Nat.not_lt_zero _)
apply Nat.noConfusion