Skip to content

Commit 3069656

Browse files
committed
feat: haveI/letI tactic linter (leanprover-community#41657)
This PR implements a variation on the linter that was written by Claude in leanprover-community#41562. It suggest to use `have`/`let` instead of `haveI`/`letI` whenever the goal is a proposition. See also https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/surprising.20have.2FhaveI.20kernel.20phenomenon/with/609718493
1 parent af3493f commit 3069656

21 files changed

Lines changed: 135 additions & 26 deletions

File tree

Archive/Imo/Imo2008Q3.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ namespace Imo2008Q3
3434

3535
theorem p_lemma (p : ℕ) (hpp : Nat.Prime p) (hp_mod_4_eq_1 : p ≡ 1 [MOD 4]) (hp_gt_20 : p > 20) :
3636
∃ n : ℕ, p ∣ n ^ 2 + 1 ∧ (p : ℝ) > 2 * n + sqrt (2 * n) := by
37-
haveI := Fact.mk hpp
37+
have := Fact.mk hpp
3838
have hp_mod_4_ne_3 : p % 43 := by linarith [show p % 4 = 1 from hp_mod_4_eq_1]
3939
obtain ⟨y, hy⟩ := ZMod.exists_sq_eq_neg_one_iff.mpr hp_mod_4_ne_3
4040
let m := ZMod.valMinAbs y

Archive/Imo/Imo2019Q2.lean

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ theorem A₁_ne_B : cfg.A₁ ≠ cfg.B := by
275275
rw [AffineSubspace.eq_iff_direction_eq_of_mem (left_mem_affineSpan_pair _ _ _)
276276
hwbtw.mem_affineSpan]
277277
exact cfg.PQ_parallel_AB.direction_eq
278-
haveI := someOrientation V
278+
have := someOrientation V
279279
have haQ : (2 : ℤ) • ∡ cfg.C cfg.B cfg.Q = (2 : ℤ) • ∡ cfg.C cfg.B cfg.A := by
280280
rw [Collinear.two_zsmul_oangle_eq_right _ cfg.A_ne_B cfg.Q_ne_B]
281281
rw [Set.pair_comm, Set.insert_comm]
@@ -389,7 +389,7 @@ end Oriented
389389

390390

391391
theorem not_collinear_QPA₂ : ¬Collinear ℝ ({cfg.Q, cfg.P, cfg.A₂} : Set Pt) := by
392-
haveI := someOrientation V
392+
have := someOrientation V
393393
rw [collinear_iff_of_two_zsmul_oangle_eq cfg.two_zsmul_oangle_QPA₂_eq_two_zsmul_oangle_BAA₂, ←
394394
affineIndependent_iff_not_collinear_set]
395395
have h : Cospherical ({cfg.B, cfg.A, cfg.A₂} : Set Pt) := by
@@ -515,13 +515,13 @@ end Oriented
515515

516516

517517
theorem not_collinear_CA₂A₁ : ¬Collinear ℝ ({cfg.C, cfg.A₂, cfg.A₁} : Set Pt) := by
518-
haveI := someOrientation V
518+
have := someOrientation V
519519
rw [collinear_iff_of_two_zsmul_oangle_eq cfg.two_zsmul_oangle_CA₂A₁_eq_two_zsmul_oangle_CBA,
520520
Set.pair_comm, Set.insert_comm, Set.pair_comm]
521521
exact cfg.not_collinear_ABC
522522

523523
theorem cospherical_A₁Q₁CA₂ : Cospherical ({cfg.A₁, cfg.Q₁, cfg.C, cfg.A₂} : Set Pt) := by
524-
haveI := someOrientation V
524+
have := someOrientation V
525525
rw [Set.insert_comm cfg.Q₁, Set.insert_comm cfg.A₁, Set.pair_comm, Set.insert_comm cfg.A₁,
526526
Set.pair_comm]
527527
exact cospherical_of_two_zsmul_oangle_eq_of_not_collinear

Archive/Wiedijk100Theorems/BallotProblem.lean

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -315,9 +315,9 @@ theorem ballot_problem' :
315315
rw [div_self]
316316
exact Nat.cast_add_one_ne_zero p
317317
· intro q p qp h₁ h₂
318-
haveI := isProbabilityMeasure_uniformOn
318+
have := isProbabilityMeasure_uniformOn
319319
(countedSequence_finite p (q + 1)) (countedSequence_nonempty _ _)
320-
haveI := isProbabilityMeasure_uniformOn
320+
have := isProbabilityMeasure_uniformOn
321321
(countedSequence_finite (p + 1) q) (countedSequence_nonempty _ _)
322322
have h₃ : 0 < p + 1 + (q + 1) := Nat.add_pos_left (Nat.succ_pos _) _
323323
rw [← uniformOn_add_compl_eq {l : List ℤ | l.headI = 1} _ (countedSequence_finite _ _),
@@ -344,7 +344,7 @@ theorem ballot_problem' :
344344
theorem ballot_problem :
345345
∀ q p, q < p → uniformOn (countedSequence p q) staysPositive = (p - q) / (p + q) := by
346346
intro q p qp
347-
haveI :=
347+
have :=
348348
isProbabilityMeasure_uniformOn (countedSequence_finite p q) (countedSequence_nonempty _ _)
349349
have :
350350
(uniformOn (countedSequence p q) staysPositive).toReal =

Archive/Wiedijk100Theorems/CubingACube.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ variable (h v)
378378
direction will intersect one of the neighbouring cubes on the same boundary as `mi`. -/
379379
theorem mi_not_onBoundary (j : Fin n) : ¬OnBoundary (mi_mem_bcubes : mi h v ∈ _) j := by
380380
let i := mi h v; have hi : i ∈ bcubes cs c := mi_mem_bcubes
381-
haveI := h.nontrivial_fin
381+
have := h.nontrivial_fin
382382
rcases exists_ne j with ⟨j', hj'⟩
383383
intro hj
384384
rcases smallest_onBoundary hj with ⟨x, ⟨hx, h2x⟩, h3x⟩

Archive/Wiedijk100Theorems/FriendshipGraphs.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ theorem false_of_three_le_degree (hd : G.IsRegularOfDegree d) (h : 3 ≤ d) : Fa
250250
have p_dvd_d_pred := (ZMod.natCast_eq_zero_iff _ _).mpr (d - 1).minFac_dvd
251251
have dpos : 1 ≤ d := by lia
252252
have d_cast : ↑(d - 1) = (d : ℤ) - 1 := by norm_cast
253-
haveI : Fact p.Prime := ⟨Nat.minFac_prime (by lia)⟩
253+
have : Fact p.Prime := ⟨Nat.minFac_prime (by lia)⟩
254254
have hp2 : 2 ≤ p := (Fact.out (p := p.Prime)).two_le
255255
have dmod : (d : ZMod p) = 1 := by
256256
rw [← Nat.succ_pred_eq_of_pos dpos, Nat.succ_eq_add_one, Nat.pred_eq_sub_one]

Counterexamples/CliffordAlgebraNotInjective.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ theorem sq_map_add_char_two {ι R : Type*} [CommRing R] [CharP R 2] (i : ι) (a
155155

156156
theorem sq_map_sub_char_two {ι R : Type*} [CommRing R] [CharP R 2] (i : ι) (a b : ι → R) :
157157
sq i (a - b) = sq i a - sq i b := by
158-
haveI : Nonempty ι := ⟨i⟩
158+
have : Nonempty ι := ⟨i⟩
159159
rw [CharTwo.sub_eq_add, CharTwo.sub_eq_add, sq_map_add_char_two]
160160

161161
/-- The quadratic form (metric) is just Euclidean -/

Counterexamples/Phillips.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ theorem exists_discrete_support_nonpos (f : BoundedAdditiveMeasure α) :
248248
-- convenient to formalize the inductive construction.
249249
let A : Set (Set α) := {t | t.Countable}
250250
let empty : A := ⟨∅, countable_empty⟩
251-
haveI : Nonempty A := ⟨empty⟩
251+
have : Nonempty A := ⟨empty⟩
252252
-- given a countable set `s`, one can find a set `t` in its complement with measure close to
253253
-- maximal.
254254
have : ∀ s : A, ∃ t : A, ∀ u : A, f (↑u \ ↑s) ≤ 2 * f (↑t \ ↑s) := by

Counterexamples/SorgenfreyLine.lean

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ theorem isOpen_Ici (a : ℝₗ) : IsOpen (Ici a) :=
6868

6969
theorem nhds_basis_Ico (a : ℝₗ) : (𝓝 a).HasBasis (a < ·) (Ico a ·) := by
7070
rw [TopologicalSpace.nhds_generateFrom]
71-
haveI : Nonempty { x // x ≤ a } := Set.nonempty_Iic_subtype
71+
have : Nonempty { x // x ≤ a } := Set.nonempty_Iic_subtype
7272
have : (⨅ x : { i // i ≤ a }, 𝓟 (Ici ↑x)) = 𝓟 (Ici a) := by
7373
refine (IsLeast.isGLB ?_).iInf_eq
7474
exact ⟨⟨⟨a, le_rfl⟩, rfl⟩, forall_mem_range.2 fun b => principal_mono.2 <| Ici_subset_Ici.2 b.2
@@ -313,7 +313,7 @@ theorem not_separatedNhds_rat_irrational_antidiag :
313313
/-- Topology on the Sorgenfrey line is not metrizable. -/
314314
theorem not_metrizableSpace : ¬MetrizableSpace ℝₗ := by
315315
intro
316-
letI := metrizableSpaceMetric ℝₗ
316+
let := metrizableSpaceMetric ℝₗ
317317
exact not_normalSpace_prod inferInstance
318318

319319
/-- Topology on the Sorgenfrey line is not second countable. -/

Counterexamples/ZeroDivisorsInAddMonoidAlgebras.lean

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,8 @@ example : ¬UniqueProds ℕ := by
244244

245245
/-- Some Types that do not have `UniqueSums`. -/
246246
example (n : ℕ) (n2 : 2 ≤ n) : ¬UniqueSums (ZMod n) := by
247-
haveI : Fintype (ZMod n) := @ZMod.fintype n ⟨(zero_lt_two.trans_le n2).ne'⟩
248-
haveI : Nontrivial (ZMod n) := CharP.nontrivial_of_char_ne_one (one_lt_two.trans_le n2).ne'
247+
have : Fintype (ZMod n) := @ZMod.fintype n ⟨(zero_lt_two.trans_le n2).ne'⟩
248+
have : Nontrivial (ZMod n) := CharP.nontrivial_of_char_ne_one (one_lt_two.trans_le n2).ne'
249249
rintro ⟨h⟩
250250
refine not_not.mpr (h Finset.univ_nonempty Finset.univ_nonempty) ?_
251251
suffices ∀ x y : ZMod n, ∃ x' y' : ZMod n, x' + y' = x + y ∧ (x' = x → ¬y' = y) by

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7421,6 +7421,7 @@ public import Mathlib.Tactic.Linter.FindDeprecations
74217421
public import Mathlib.Tactic.Linter.FlexibleLinter
74227422
public import Mathlib.Tactic.Linter.GlobalAttributeIn
74237423
public import Mathlib.Tactic.Linter.HashCommandLinter
7424+
public import Mathlib.Tactic.Linter.HaveILetI
74247425
public import Mathlib.Tactic.Linter.HaveLetLinter
74257426
public import Mathlib.Tactic.Linter.Header
74267427
public import Mathlib.Tactic.Linter.Lint

0 commit comments

Comments
 (0)