lean4-htt/tests/lean/linterUnusedVariables.lean
Mario Carneiro 49f66dc485
perf: rewrite UnusedVariables lint (#3186)
This is a rewrite of the `UnusedVariables` lint to inline and simplify
many of the dependent functions to try to improve the performance of
this lint, which quite often shows up in perf reports.

* The mvar assignment scanning is one of the most expensive parts of the
process, so we do two things to improve this:
  * Lazily perform the scan only if we need it
* Use an object-pointer hashmap to ensure that we don't have quadratic
behavior when there are many mvar assignments with slight differences.
* The dependency on `Lean.Server` is removed, meaning we don't need to
do the LSP conversion stuff anymore. The main logic of reference finding
is inlined.
* We take `fvarAliases` into account, and union together fvars which are
aliases of a base fvar. (It would be great if we had `UnionFind` here.)

More docs will be added once we confirm an actual perf improvement.

---------

Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
2024-03-21 12:28:57 +00:00

257 lines
5.3 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Lean
set_option linter.missingDocs false
set_option linter.all true
def explicitlyUsedVariable (x : Nat) : Nat :=
x
theorem implicitlyUsedVariable : P ∧ Q → Q := by
intro HPQ
have HQ : Q := by exact And.right HPQ
assumption
axiom axiomVariable (x : Prop) : True
def unusedVariables (x : Nat) : Nat :=
let y := 5
3
def usedAndUnusedVariables : Nat :=
let x : Nat :=
let x := 5
3
x
def letRecVariable : Nat :=
let rec x := 5
3
def whereVariable : Nat :=
3
where
x := 5 -- x is globally available via `whereVariable.x`
def unusedWhereArgument : Nat :=
f 2
where
f (x : Nat) := 3
def whereFunction : Nat :=
2
where
f (x : Nat) := 3
def unusedFunctionArgument : Nat :=
(fun x => 3) (x := 2)
def unusedTypedFunctionArgument : Nat :=
(fun (x : Nat) => 3) 2
def pattern (x y : Option Nat) : Nat :=
match x with
| some z =>
match y with
| some z => 1
| none => 0
| none => 0
def patternLet (x : Option Nat) : Nat :=
if let some y := x then
0
else
1
def patternMatches (x : Option Nat) : Nat :=
if x matches some y then
0
else
1
def implicitVariables {α : Type} [inst : ToString α] : Nat := 4
def autoImplicitVariable [Inhabited α] := 5
def unusedArrow : (x : Nat) → Nat := fun x => x
def mutVariable (x : Nat) : Nat := Id.run <| do
let mut y := 5
if x == 5 then
y := 3
y
def mutVariableDo (list : List Nat) : Nat := Id.run <| do
let mut sum := 0
for elem in list do
sum := sum + elem
return sum
def mutVariableDo2 (list : List Nat) : Nat := Id.run <| do
let mut sum := 0
for _ in list do
sum := sum.add 1
return sum
def unusedVariablesPattern (_x : Nat) : Nat :=
let _y := 5
3
set_option linter.unusedVariables false in
def nolintUnusedVariables (x : Nat) : Nat :=
let y := 5
3
set_option linter.all false in
def nolintAll (x : Nat) : Nat :=
let y := 5
3
set_option linter.all false in
set_option linter.unusedVariables true in
def lintUnusedVariables (x : Nat) : Nat :=
let y := 5
3
set_option linter.unusedVariables.funArgs false in
def nolintFunArgs (w : Nat) : Nat :=
let a := 5
let f (x : Nat) := 3
let g := fun (y : Nat) => 3
f <| g <| h <| 2
where
h (z : Nat) := 3
set_option linter.unusedVariables.patternVars false in
def nolintPatternVars (x : Option (Option Nat)) : Nat :=
match x with
| some (some y) => (fun z => 1) 2
| _ => 0
set_option linter.unusedVariables.patternVars false in
theorem nolintPatternVarsInduction (n : Nat) : True := by
induction n with
| zero => exact True.intro
| succ m =>
have h : True := by simp
exact True.intro
inductive Foo (α : Type)
| foo (x : Nat) (y : Nat)
structure Bar (α : Type) where
bar (x : Nat) : Nat
bar' (x : Nat) : Nat := 3
class Baz (α : Type) where
baz (x : Nat) : Nat
baz' (x : Nat) : Nat :=
let y := 5
3
instance instBaz (α β : Type) : Baz α where
baz (x : Nat) := 5
structure State where
fieldA : Nat
fieldB : Nat
abbrev M := StateT State Id
def modifyState : M Unit := do
let s ← get
modify fun s => { s with fieldA := s.fieldA + 1 }
def modifyState' : M Unit := do
modify fun s => { s with fieldA := 1}
def modifyStateUnnecessaryWith : M Unit := do
modify fun s => { s with fieldA := 1, fieldB := 2 }
def universeParam.{u} (T : Type u) (t : T) : T := t
open Lean in
initialize tc : Unit ← registerTraceClass `Baz
register_option opt : Nat := {
defValue := 3
descr := "test option"
}
opaque foo (x : Nat) : Nat
opaque foo' (x : Nat) : Nat :=
let y := 5
3
variable (bar)
variable (bar' : (x : Nat) → Nat)
variable {α β} [inst : ToString α]
@[specialize]
def specializeDef (x : Nat) : Nat := 3
@[implemented_by specializeDef]
def implementedByDef (x : Nat) : Nat :=
let y := 3
5
@[extern "test"]
def externDef (x : Nat) : Nat :=
let y := 3
5
@[extern "test"]
opaque externConst (x : Nat) : Nat :=
let y := 3
5
macro "useArg " name:declId arg:ident : command => `(def $name ($arg : α) : α := $arg)
useArg usedMacroVariable a
macro (name := doNotUse) "doNotUseArg " name:declId arg:ident : command =>
`(def $name ($arg : α) : Nat := 3)
doNotUseArg unusedMacroVariable b
@[unused_variables_ignore_fn]
def ignoreDoNotUse : Lean.Linter.IgnoreFunction := fun _ stack _ => stack.matches [``doNotUse]
doNotUseArg unusedMacroVariable2 b
macro "ignoreArg " id:declId sig:declSig : command => `(opaque $id $sig)
ignoreArg ignoredMacroVariable (x : UInt32) : UInt32
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
-- should not be reported either
example (a : Nat) : Nat := _
example (a : Nat) : Nat := sorry
example (a : sorry) : Nat := 0
example (a : Nat) : Nat := by
theorem Fin.eqq_of_val_eq {n : Nat} : ∀ {x y : Fin n}, x.val = y.val → x = y
| ⟨_, _⟩, _, rfl => rfl
def Nat.discriminate (n : Nat) (H1 : n = 0 → α) (H2 : ∀ m, n = succ m → α) : α :=
match n with
| 0 => H1 rfl
| succ m => H2 m rfl
example [ord : Ord β] (f : α → β) (x y : α) : Ordering := compare (f x) (f y)
example {α β} [ord : Ord β] (f : α → β) (x y : α) : Ordering := compare (f x) (f y)
example {h : Decidable True} (t e : α) : ite True t e = t := if_pos trivial
@[unused_variables_ignore_fn]
def ignoreEverything : Lean.Linter.IgnoreFunction :=
fun _ _ _ => true
def ignored (x : Nat) := 0