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.analyzeTactics true in 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 section variable (bar) variable (bar' : (x : Nat) → Nat) variable {α β} [inst : ToString α] end @[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 section variable {α : Type} 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 end 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 /-! These are *not* linted against anymore as they are parameters used in the eventual body term. -/ 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 inductive A where | intro : Nat → A def A.out : A → Nat | .intro n => n /-! `h` is used indirectly via an alias introduced by `match` that is used only via the mvar ctx -/ theorem problematicAlias (n : A) (i : Nat) (h : i ≤ n.out) : i ≤ n.out := match n with | .intro _ => by assumption /-! The wildcard pattern introduces a copy of `x` that should not be linted as it is in an inaccessible annotation. -/ example : (x = y) → y = x | .refl _ => .refl _ /-! We do lint parameters by default (`analyzeTactics false`) even when they have lexical uses -/ theorem lexicalTacticUse (p : α → Prop) (ha : p a) (hb : p b) : p b := by simp [ha, hb] /-! ... however, `analyzeTactics true` consistently takes lexical uses for all variables into account -/ set_option linter.unusedVariables.analyzeTactics true in theorem lexicalTacticUse' (p : α → Prop) (ha : p a) (hb : p b) : p b := by simp [ha, hb]