Commit graph

2427 commits

Author SHA1 Message Date
Leonardo de Moura
41c41e455a
feat: One.one support in linarith (#8694)
This PR implements special support for `One.one` in linarith when the
structure is a ordered ring. It also fixes bugs during initialization.
2025-06-09 20:17:48 +00:00
Leonardo de Moura
00f6b1e70a
fix: denotation functions for interfacing CommRing and linarith (#8693)
This PR fixes the denotation functions used to interface the ring and
linarith modules in grind.
2025-06-09 14:43:13 +00:00
Leonardo de Moura
dd1d3e6a3a
feat: model search procedure for grind linarith (#8690)
This PR implements the main framework of the model search procedure for
the linarith component in grind. It currently handles only inequalities.
It can already solve simple goals such as
```lean
example [IntModule α] [Preorder α] [IntModule.IsOrdered α] (a b c : α)
    : a < b → b < c → c < a → False := by
  grind

example [IntModule α] [LinearOrder α] [IntModule.IsOrdered α] (a b c : α)
    : a < b → b < c + d → a - d < c := by
  grind
```
2025-06-09 04:31:28 +00:00
Leonardo de Moura
e38b8a0a7a
feat: proof terms generation for CommRing and linarith interface (#8689)
This PR implements proof term generation for the `CommRing` and
`linarith` interface. It also fixes the `CommRing` helper theorems.
2025-06-08 23:38:03 +00:00
Leonardo de Moura
3e0168df58
feat: proof term construction infrastructure for linarith in grind (#8687)
This PR implements the infrastructure for constructing proof terms in
the linarith procedure in `grind`. It also adds the `ToExpr` instances
for the reified objects.
2025-06-08 19:58:48 +00:00
Leonardo de Moura
7e1d0cc125
feat: use CommRing to normalize linarith expressions (#8682)
This PR uses the `CommRing` module to normalize linarith inequalities.
2025-06-08 05:41:00 +00:00
Leonardo de Moura
c9c794ee8a
feat: reification and denotation for linarith module in grind (#8680)
This PR adds the `reify?` and `denoteExpr` for the new linarith module
in `grind`.
2025-06-08 02:53:28 +00:00
Leonardo de Moura
106708ee78
feat: grind linarith module infrastructure (#8677)
This PR adds the basic infrastructure for the linarith module in
`grind`.
2025-06-08 00:19:52 +00:00
Leonardo de Moura
4abc4430dc
refactor: ENodeKey => ExprPtr (#8674) 2025-06-07 19:30:02 +00:00
Joachim Breitner
24cb133eb2
feat: explicit defeq attribute (#8419)
This PR introduces an explicit `defeq` attribute to mark theorems that
can be used by `dsimp`. The benefit of an explicit attribute over the
prior logic of looking at the proof body is that we can reliably omit
theorem bodies across module boundaries. It also helps with intra-file
parallelism.

If a theorem is syntactically defined by `:= rfl`, then the attribute is
assumed and need not given explicitly. This is a purely syntactic check
and can be fooled, e.g. if in the current namespace, `rfl` is not
actually “the” `rfl` of `Eq`. In that case, some other syntax has be
used, such as `:= (rfl)`. This is also the way to go if a theorem can be
proved by `defeq`, but one does not actually want `dsimp` to use this
fact.

The `defeq` attribute will look at the *type* of the declaration, not
the body, to check if it really holds definitionally. Because of
different reduction settings, this can sometimes go wrong. Then one
should also write `:= (rfl)`, if one does not want this to be a defeq
theorem. (If one does then this is currently not possible, but it’s
probably a bad idea anyways).

The `set_option debug.tactic.simp.checkDefEqAttr true`, `dsimp` will
warn if could not apply a lemma due to a missing `defeq` attribute.

With `set_option backward.dsimp.useDefEqAttr.get false` one can revert
to the old behavior of inferring rfl-ness based on the theorem body.

Both options will go away eventually (too bad we can’t mark them as
deprecated right away, see #7969)

Meta programs that generate theorems (e.g. equational theorems) can use
`inferDefEqAttr` to set the attribute based on the theorem body of the
just created declaration.

This builds on #8501 to update Init to `@[expose]` a fair amount of
definitions that, if not exposed, would prevent some existing `:= rfl`
theorems from being `defeq` theorems. In the interest of starting
backwards compatible, I exposed these function. Hopefully many can be
un-exposed later again.

A mathlib adaption branch exists that includes both the meta programming
fixes and changes to the theorems (e.g. changing `:= by rfl` to `:=
rfl`).

With the module system there is now no special handling for `defeq`
theorem bodies, because we don’t look at the body anymore. The previous
hack is removed. The `defeq`-ness of the theorem needs to be checked in
the context of the theorem’s *type*; the error message contains a hint
if the defeq check fails because of the exported context.
2025-06-06 18:40:06 +00:00
Leonardo de Moura
3ce7dd318d
feat: sort equivalence classes in grind diagnostics (#8638)
This PR improves the diagnostic information produced by `grind`. It now
sorts the equivalence classes by generation and then `Expr. lt`.
2025-06-05 04:35:59 +00:00
Leonardo de Moura
e08b2a1f62
feat: track case-split source in grind (#8633)
This PR implements case-split tracking in `grind`. The information is
displayed when `grind` fails or diagnostic information is requested.
Examples:

- Failure

![image](https://github.com/user-attachments/assets/b10516c3-d205-4e08-80a4-daca195c1d8a)

- Success with `set_option diagnostics true`

![image](https://github.com/user-attachments/assets/15ee31e0-27d8-473f-a469-12b424ce6d24)
2025-06-04 16:59:36 +00:00
Sebastian Ullrich
8457342d33 feat: meta syntax 2025-06-04 18:26:05 +02:00
Joachim Breitner
b9243e19be
feat: make equational theorems of non-exposed defs private (#8519)
This PR makes the equational theorems of non-exposed defs private. If
the author of a module chose not to expose the body of their function,
then they likely don't want that implementation to leak through
equational theorems. Helps with #8419.

There is some amount of incidential complexity due to how `private`
works in lean, by mangling the name: lots of code paths that need now do
the right thing™ about private and non-private names, including the
whole reserved name machinery.

So this includes a number of refactorings:

* The logic for calculating an equational theorem name (or similar) is
now done by a single function, `mkEqLikeNameFor`, rather than all over
the place.

* Since the name of the equational theorem now depends on the current
context (in particular whether it’s a proper module, or a non-module
file), the forward map from declaration to equational theorem doesn’t
quite work anymore. This map is deleted; the list of equational theorems
are now always found by looking for declaration of the expected names
(`alreadyGenerated). If users define such theorems themselves (and make
it past the “do not allow reserved names to be declared”) they get to
keep both pieces.

* Because this map was deleted, mathlib’s `eqns` command can no longer
easily warn if equational lemmas have already been generated too early
(adaption branch exists). But in general I think lean could provide a
more principled way of supporting custom unfold lemmas, and ideally the
whole equational theorem machinery is just using that.

* The ReservedNamePredicate is used by `resolveExact`, so we need to
make sure that it returns the right name, including privateness. It is
not ok to just reserve both the private and non-private name but then
later in the ReservedNameAction produce just one of the two.
 
* We create `foo.def_eq` eagerly for well-founded recursion. This is
needed because we need feed in the proof of the rewriting done by
`wf_preprocess`. But if `foo.def_eq` is private in a module, then a
non-module importing it will still expect a non-private `foo.def_eq` to
exist. To patch that, we install a `copyPrivateUnfoldTheorem :
GetUnfoldEqnFn` that declares a theorem aliasing the private one. Seems
to work.
2025-06-04 11:52:08 +00:00
Leonardo de Moura
1629440cb8
feat: improve grind diagnostics for successful case (#8625)
This PR improves the diagnostic information produced by `grind` when it
succeeds. We now include the list of case-splits performed, and the
number of application per function symbol. Example:


![image](https://github.com/user-attachments/assets/109f3f80-85a1-4368-8958-fdf56707ea7d)
2025-06-04 09:34:48 +00:00
Kim Morrison
4500a7f02b
fix: remove global NatCast (Fin n) instance (#8620)
This PR removes the `NatCast (Fin n)` global instance (both the direct
instance, and the indirect one via `Lean.Grind.Semiring`), as that
instance causes causes `x < n` (for `x : Fin k`, `n : Nat`) to be
elaborated as `x < ↑n` rather than `↑x < n`, which is undesirable. Note
however that in Mathlib this happens anyway!
2025-06-04 06:58:39 +00:00
Leonardo de Moura
c12159b519
refactor: move read-only data to Grind.Context (#8624) 2025-06-04 02:50:43 +00:00
Leonardo de Moura
8165ecc1db
fix: bug in the equality resolution procedure in grind (#8621)
This PR fixes a bug in the equality-resolution procedure used by
`grind`.
The procedure now performs a topological sort so that every simplified
theorem declaration is emitted **before** any place where it is
referenced.
Previously, applying equality resolution to
```lean
h : ∀ x, p x a → ∀ y, p y b → x ≠ y
```
in the example
```lean
example
  (p : Nat → Nat → Prop)
  (a b c : Nat)
  (h  : ∀ x, p x a → ∀ y, p y b → x ≠ y)
  (h₁ : p c a)
  (h₂ : p c b) :
  False := by
  grind
```
caused `grind` to produce the incorrect term
```lean
p ?y a → ∀ y, p y b → False
```
The patch eliminates this error, and the following correct simplified
theorem is generated
```lean
∀ y, p y a → p y b → False
```
2025-06-04 00:34:47 +00:00
Leonardo de Moura
344b52f999
fix: term internalization issue in grind (#8619)
This PR fixes an internalization (aka preprocessing) issue in `grind`
when applying injectivity theorems.
2025-06-04 00:13:51 +00:00
Sebastian Ullrich
f718f26200 feat: create private aux decls in private contexts 2025-06-03 15:53:05 +02:00
Sebastian Ullrich
569e46033b
feat: do not export private declarations (#8337)
This PR adjusts the experimental module system to not export any private
declarations from modules.

Fixes #5002
2025-06-02 08:01:08 +00:00
Leonardo de Moura
193f59aefe
feat: grind +ring by default (#8576)
This PR sets `ring := true` by default in `grind`. It also fixes a bug
in the reification procedure, and improves the term internalization in
the ring and cutsat modules.
2025-06-01 17:46:49 +00:00
Leonardo de Moura
db353ab964
fix: ematch generalized patterns (#8570)
This PR fixes some issues in the E-matching generalized pattern support
after the update stage0.
2025-06-01 02:38:29 +00:00
Leonardo de Moura
157ca5a4f3
feat: ematch generalized patterns (#8569)
This PR adds support for generalized E-match patterns to arbitrary
theorems.
2025-05-31 19:08:33 -07:00
jrr6
43aec5b254
fix: improve error-message hint rendering and API (#8486)
This PR improves the rendering of hints in error messages by
consistently indenting diffs and splitting large diffs less granularly;
it also improves the ergonomics of `Lean.MessageData.hint`. Note that
the changes to the signature of `Lean.MessageData.hint` are breaking.

This PR depends on #8457.
2025-06-01 01:22:09 +00:00
Leonardo de Moura
2c8ee4f29c
fix: simplify interface between grind core and cutsat (#8564)
This PR simplifies the interface between the `grind` core and the cutsat
procedure. Before this PR, core would try to minimize the number of
numeric literals that have to be internalized in cutsat. This
optimization was buggy (see `grind_cutsat_zero.lean` test), and produced
counterintuitive counterexamples.
2025-05-31 16:28:31 +00:00
Leonardo de Moura
0988db9ab2
refactor: simplify inferface between core and offset module (#8562)
`processNewEqLit` optimization is not worth the extra complexity.
2025-05-31 15:16:29 +00:00
Leonardo de Moura
999fcd2d95
fix: hash function for congruence closure in grind (#8549)
This PR fixes the hash function used to implement congruence closure in
`grind`. The hash of an `Expr` must not depend on whether the expression
has been internalized or not.
2025-05-30 17:07:26 +00:00
Leonardo de Moura
d2e01bbd09
feat: overapplied ite and dite applications in grind (#8544)
This PR implements support for over-applied `ite` and `dite`
applications in the `grind` tactic. It adds support for propagation and
case-split.
2025-05-30 06:34:04 +00:00
Leonardo de Moura
069fb4351c
fix: inappropriate whnfD uses in grind (#8542)
This PR fixes two inappropriate uses of `whnfD` in `grind`. They were
potential performance foot guns, and were producing unexpected errors
since `whnfD` is not consistently used (and it should not be) in all
modules.
2025-05-30 04:35:29 +00:00
Leonardo de Moura
f54a65f72f
feat: nested proof propagation in grind (#8541)
This PR ensures that for any nested proof `h : p` in a goal, we
propagate that `p` is true in the `grind` tactic.
2025-05-30 03:25:14 +00:00
Leonardo de Moura
4316629119
fix: BEq support in grind (#8536)
This PR fixes the support for `LawfulBEq` and `BEq` in `grind`.
2025-05-29 23:47:40 +00:00
Leonardo de Moura
1fd7206f00
feat: match-expressions with congruence equation theorems (#8506)
This PR implements `match`-expressions in `grind` using `match`
congruence equations. The goal is to minimize the number of `cast`
operations that need to be inserted, and avoid `cast` over functions.
The new approach support `match`-expressions of the form `match h : ...
with ...`.
2025-05-29 02:23:26 +00:00
Kim Morrison
c6194e05b8
chore: remove prime from Fin.ofNat' (#8515)
This PR removes the prime from `Fin.ofNat'`: the old `Fin.ofNat` has
completed its 6 month deprecation cycle and is being removed.
2025-05-28 11:51:00 +00:00
Kyle Miller
921ce7682e
feat: use omission dots for hidden let values in Infoview (#8041)
This PR changes the behavior of `pp.showLetValues` to use a hoverable
`⋯` to hide let values. This is now false by default, and there is a new
option `pp.showLetValues.threshold` for allowing small expressions to be
shown anyway. For tactic metavariables, there is an additional option
`pp.showLetValues.tactic.threshold`, which by default is set to the
maximal value, since in tactic states local values are usually
significant.
2025-05-27 23:09:11 +00:00
Kyle Miller
a6dd6a4656
feat: clear_value tactic (#8449)
This PR upstreams and extends the Mathlib `clear_value` tactic. Given a
local definition `x : T := v`, the tactic `clear_value x` replaces it
with a hypothesis `x : T`, or throws an error if the goal does not
depend on the value `v`. The syntax `clear_value x with h` creates a
hypothesis `h : x = v` before clearing the value of `x`. Furthermore,
`clear_value *` clears all values that can be cleared, or throws an
error if none can be cleared.
2025-05-27 01:52:08 +00:00
Leonardo de Moura
11f7d6da39
feat: reuse simp cache in grind (#8483)
This PR ensures `grind` reuses the `simp` cache between different calls.
Recall that `grind` uses `simp` to normalize terms during
internalization.
2025-05-26 04:10:58 +00:00
Leonardo de Moura
03e905d994
feat: hash consing with alpha equivalence in grind (#8479)
This PR implements hash-consing for `grind` that takes alpha equivalence
into account.
2025-05-26 00:51:18 +00:00
Leonardo de Moura
2a1354b3cc
chore: add seal to workaround performance issue (#8469)
This PR adds `seal` commands at `grind_ite.lean` to workaround expensive
definitionally equality tests in the canonicalizer. The new module
system will automatically hide definitions such as `HashMap.insert` and
`TreeMap.insert` which are being unfolded by the canonicalizer in this
test.
This PR also adds a `profileItM` for tracking the time spent in the
`grind` canonicalizer.
2025-05-25 00:54:30 +00:00
Leonardo de Moura
a54872f5f6
fix: preprocessLight at ensureInternalized (#8466)
This PR fixes another instance of the `grind` issue "unexpected kernel
projection term during internalization".
2025-05-24 17:13:20 +00:00
Leonardo de Moura
21846ebdf8
feat: non-chronological backtracking for grind (WIP) (#8440)
This PR implements non-chronological backtracking for the `grind`
tactic. This feature ensures that `grind` does not need to process
irrelevant branches after performing a case-split that is not relevant.
It is not just about performance, but also the size of the final proof
term. The new test demonstrates this feature in practice.
```lean
-- In the following test, the first 8 case-splits are irrelevant,
-- and non-choronological backtracking is used to avoid searching
-- (2^8 - 1) irrelevant branches
/--
trace: 
[grind.split] p8 ∨ q8, generation: 0
[grind.split] p7 ∨ q7, generation: 0
[grind.split] p6 ∨ q6, generation: 0
[grind.split] p5 ∨ q5, generation: 0
[grind.split] p4 ∨ q4, generation: 0
[grind.split] p3 ∨ q3, generation: 0
[grind.split] p2 ∨ q2, generation: 0
[grind.split] p1 ∨ q1, generation: 0
[grind.split] ¬p ∨ ¬q, generation: 0
-/
#guard_msgs (trace) in
set_option trace.grind.split true in
theorem ex
    : p ∨ q →
      ¬ p ∨ q →
      p ∨ ¬ q →
      ¬ p ∨ ¬ q →
      p1 ∨ q1 →
      p2 ∨ q2 →
      p3 ∨ q3 →
      p4 ∨ q4 →
      p5 ∨ q5 →
      p6 ∨ q6 →
      p7 ∨ q7 →
      p8 ∨ q8 →
      False := by
  grind (splits := 10)
```
2025-05-23 19:33:54 +00:00
Sebastian Graf
8fc94c5c90
fix: Make split work with metavariables in the target (#8437)
This PR fixes `split` in the presence of metavariables in the target.

The fix consists of replacing an internal use of `apply` for
instantiating match splitters by a new, simpler variant `applyN`. This
new `applyN` is not prone to #8436, which is the ultimate cause for
`split` failing on targets containing metavariables.

---------

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>
2025-05-23 12:46:27 +00:00
Eric Wieser
ae1ab94992
fix: replace bad simp lemmas for Id (#7352)
This PR reworks the `simp` set around the `Id` monad, to not elide or
unfold `pure` and `Id.run`

In particular, it stops encoding the "defeq abuse" of `Id X = X` in the
statements of theorems, instead using `Id.run` and `pure` to pass back
and forth between these two spellings. Often when writing these with
`pure`, they generalize to other lawful monads; though such changes were
split off to other PRs.

This fixes the problem with the current simp set where `Id.run (pure x)`
is simplified to `Id.run x`, instead of the desirable `x`.
This is particularly bad because the` x` is sometimes inferred with type
`Id X` instead of `X`, which prevents other `simp` lemmas about `X` from
firing.

Making `Id` reducible instead is not an option, as then the `Monad`
instances would have nothing to key on.

---------

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
Co-authored-by: Kim Morrison <kim@tqft.net>
Co-authored-by: Paul Reichert <6992158+datokrat@users.noreply.github.com>
2025-05-22 22:45:35 +00:00
Joachim Breitner
5e40f4af52
feat: linear-size noConfusionType construction (#8037)
This PR introduces a `noConfusionType` construction that’s sub-quadratic
in size, and reduces faster.

The previous `noConfusion` construction with two nested `match`
statements is quadratic in size and reduction behavior. Using some
helper definitions, a linear size construction is possible.

With this, processing the RISC-V-AST definition from
https://github.com/opencompl/sail-riscv-lean takes 6s instead of 60s.

The previous construction is still used when processing the early
prelude, and can be enabled elsewhere using `set_option
backwards.linearNoConfusionType false`.
2025-05-22 14:54:05 +00:00
Marc Huisinga
c8d245a08f
fix: unknown identifier ranges (#8362)
This PR fixes a bug where the unknown identifier code actions wouldn't
work correctly for some unknown identifier error spans and adjusts
several unknown identifier spans to actually end on the identifier in
question.

The following additional adjustments are made:
- The fallback mechanism of the unknown identifier code actions is
removed, since it could produce severely incorrect suggestions for
unknown identifier errors on fields.
- A performance bug when using the code action to import all unknown
identifiers is fixed.
- A bug that occurs when the elaborator produces multiple overlapping
completion infos is fixed.
- A bug in the snapshot selection that could cause it to wait for
snapshots in snapshots with non-canonical syntax is fixed.
- Some invariants of the snapshot tree are documented.
- The snapshot tree formatting is adjusted to display the final info
tree again.
2025-05-22 10:05:31 +00:00
Leonardo de Moura
4eccb5b479
fix: grind diagnostics at maxHeartbeats (#8438)
This PR ensures that `grind` diagnostics are obtained even when
`maxHeartbeats` is reached.
This PR also removes some dead code.
2025-05-21 22:14:59 +00:00
Leonardo de Moura
c28b052576
feat: [grind?] attribute (#8426)
This PR adds the attribute `[grind?]`. It is like `[grind]` but displays
inferred E-matching patterns. It is a more convinient than writing.
Thanks @kim-em for suggesting this feature.
```lean
set_option trace.grind.ematch.pattern true
```
This PR also improves some tests, and adds helper function
`ENode.isRoot`.
2025-05-21 00:32:49 +00:00
Leonardo de Moura
8753239226
chore: remove Grind.Config.failures options (#8423)
Option is not very useful.
2025-05-20 15:40:51 +00:00
Leonardo de Moura
8535a2268b
fix: simplify isCasesAttrCandidate? in grind (#8415)
The behavior was counterintuitive.
2025-05-20 14:29:07 +00:00
Kim Morrison
3790f8c78e
chore: deduplicate Grind.RatModule and Grind.NoNatZeroDivisors (#8416)
Also adds instances from e.g. `Semiring` to `NatModule` and `Ring` to
`IntModule`.
2025-05-20 07:49:42 +00:00