Skip to content

chore: replace haveI/letI with have/let in tactic proofs of propositions#41615

Open
kbuzzard wants to merge 3 commits into
leanprover-community:masterfrom
kbuzzard:haveILetI-linter-fixes
Open

chore: replace haveI/letI with have/let in tactic proofs of propositions#41615
kbuzzard wants to merge 3 commits into
leanprover-community:masterfrom
kbuzzard:haveILetI-linter-fixes

Conversation

@kbuzzard

Copy link
Copy Markdown
Member

My understanding is that we should be using have/let rather than haveI/letI in tactic proofs. I noticed that AI was getting this wrong and I suspect that it's because we're getting this wrong in mathlib a lot (possibly because haveI meant something different in Lean 3), and AI is training on mathlib.

Does this matter? In my experience the reaction of the community will be one of two things:

  1. No. In which case let's leave things as they are.
  2. Yes. In which case the correct approach is to (a) fix the error and (b) lint against it, to stop it happening in future.

I got Claude to write a linter to check for this, and it's #41562 . It's completely vibe-coded and I cannot vouch for any of it.

The result, when running it on mathlib, is the diff in this PR. In particular, we're getting it wrong a lot.


Open in Gitpod

I was intrigued to find out how often we're making this mistake in mathlib, and it probably took me about 10 minutes of my own time to get AI to write the linter and run it on mathlib. I will not mark this PR as AI-generated because it was generated by a linter. The linter itself was AI generated. It is not clear to me whether we should be merging this PR without merging the linter, and the linter will need careful human review, but I figured I would give the community the option to merge this PR anyway.

The `haveI`/`letI` tactics differ from `have`/`let` only in that they inline
their value into the proof term rather than binding it. In a tactic proof of a
proposition this difference is invisible by proof irrelevance, so `have`/`let`
should be used instead.

This applies the fixes flagged by the `linter.style.haveILetI` linter across
Mathlib, Archive and Counterexamples: 2649 sites in 964 files, each an
elaborator-certified use of the `haveI`/`letI` *tactic* whose main goal is a
proposition. Term-mode `haveI`/`letI` and uses whose goal is data are left
untouched.

One site (`CategoryTheory/Galois/Basic.lean`) additionally needed an explicit
universe annotation `FintypeCat.{w}`, because the `have` tactic checks the
declared type's universe eagerly whereas `haveI`, elaborated in term mode,
defers it until the value pins it down.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kbuzzard

Copy link
Copy Markdown
Member Author

!bench

@leanprover-radar

leanprover-radar commented Jul 11, 2026

Copy link
Copy Markdown

Benchmark results for 766ff5c against 32ea179 are in. No significant results found. @kbuzzard

Warning

These warnings may indicate that the benchmark results are not directly comparable, for example due to changes in the runner configuration or hardware.

  • Bench repo commit hashes for run main differ between commits.
  • 🟥 build//instructions: +204.0G (+0.13%)

Medium changes (1🟥)

  • 🟥 build/module/Mathlib.FieldTheory.PurelyInseparable.PerfectClosure//instructions: +4.5G (+13.95%)

Small changes (1🟥)

1 hidden

@github-actions github-actions Bot added the merge-conflict The PR has a merge conflict with master, and needs manual merging. (this label is managed by a bot) label Jul 11, 2026

theorem p_lemma (p : ℕ) (hpp : Nat.Prime p) (hp_mod_4_eq_1 : p ≡ 1 [MOD 4]) (hp_gt_20 : p > 20) :
∃ n : ℕ, p ∣ n ^ 2 + 1 ∧ (p : ℝ) > 2 * n + sqrt (2 * n) := by
haveI := Fact.mk hpp

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But for things like this, isnt inlining preferable?

@kbuzzard kbuzzard Jul 11, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps, but that is not the job of this PR. The job of this PR is to follow the convention of no haveI in tactic proofs. The issue you are raising is already present in mathlib master.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok good then. The convention of not using haveI in tactic proofs isnt in the style guide. I think maybe it would good to mention it explicitly there also (maybe that will also help AI to not use it as much).

…fixes

# Conflicts:
#	Mathlib/RingTheory/LaurentSeries.lean
#	Mathlib/RingTheory/UniqueFactorizationDomain/ClassGroup.lean
#	Mathlib/RingTheory/UniqueFactorizationDomain/GCDMonoid.lean
#	Mathlib/RingTheory/UniqueFactorizationDomain/Multiplicative.lean
#	Mathlib/RingTheory/UniqueFactorizationDomain/Multiplicity.lean
@github-actions github-actions Bot removed the merge-conflict The PR has a merge conflict with master, and needs manual merging. (this label is managed by a bot) label Jul 11, 2026
@github-actions

github-actions Bot commented Jul 11, 2026

Copy link
Copy Markdown

PR summary 115c0636d8

Import changes for modified files

No significant changes to the import graph

Import changes for all files
Files Import difference

Declarations diff (regex)

No declarations were harmed in the making of this PR! 🐙

You can run this locally as follows
## from your `mathlib4` directory:
git clone https://github.com/leanprover-community/mathlib-ci.git ../mathlib-ci

## summary with just the declaration names:
../mathlib-ci/scripts/pr_summary/declarations_diff.sh <optional_commit>

## more verbose report:
../mathlib-ci/scripts/pr_summary/declarations_diff.sh long <optional_commit>

The doc-module for scripts/pr_summary/declarations_diff.sh in the mathlib-ci repository contains some details about this script.

Declarations diff (Lean)

Lean-aware diff — post-build, computed from the Lean environment (commit 115c063).

  • +0 new declarations
  • −0 removed declarations

No declaration differences.


No changes to strong technical debt.

No changes to weak technical debt.

Current commit 115c0636d8
Reference commit 4efb186f10

This script lives in the mathlib-ci repository. To run it locally, from your mathlib4 directory:

git clone https://github.com/leanprover-community/mathlib-ci.git ../mathlib-ci
../mathlib-ci/scripts/reporting/technical-debt-metrics.sh pr_summary
  • The relative value is the weighted sum of the differences with weight given by the inverse of the current value of the statistic.
  • The absolute value is the relative value divided by the total sum of the inverses of the current values (i.e. the weighted average of the differences).

@kbuzzard

Copy link
Copy Markdown
Member Author

!radar

@leanprover-radar

leanprover-radar commented Jul 11, 2026

Copy link
Copy Markdown

Benchmark results for 115c063 against 4efb186 are in. No significant results found. @kbuzzard

  • 🟥 build//instructions: +7.1G (+0.00%)

Medium changes (1🟥)

  • 🟥 build/module/Mathlib.FieldTheory.PurelyInseparable.PerfectClosure//instructions: +4.4G (+13.62%)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants