Commit graph

2971 commits

Author SHA1 Message Date
Sebastian Ullrich
4eba5ea96d
fix: shake: only record non-builtin simprocs (#11344) 2025-11-29 15:58:29 +00:00
Leonardo de Moura
075f1d66eb
feat: guard and check in grind_pattern (#11428)
This PR implements support for **guards** in `grind_pattern`. The new
feature provides additional control over theorem instantiation. For
example, consider the following monotonicity theorem:

```lean
opaque f : Nat → Nat
theorem fMono : x ≤ y → f x ≤ f y := ...
```

We can use `grind_pattern` to instruct `grind` to instantiate the
theorem for every pair `f x` and `f y` occurring in the goal:

```lean
grind_pattern fMono => f x, f y
```

Then we can automatically prove the following simple example using
`grind`:

```lean
/--
trace: [grind.ematch.instance] fMono: f a ≤ b → f (f a) ≤ f b
[grind.ematch.instance] fMono: f a ≤ c → f (f a) ≤ f c
[grind.ematch.instance] fMono: f a ≤ a → f (f a) ≤ f a
[grind.ematch.instance] fMono: f a ≤ f (f a) → f (f a) ≤ f (f (f a))
[grind.ematch.instance] fMono: f a ≤ f a → f (f a) ≤ f (f a)
[grind.ematch.instance] fMono: f (f a) ≤ b → f (f (f a)) ≤ f b
[grind.ematch.instance] fMono: f (f a) ≤ c → f (f (f a)) ≤ f c
[grind.ematch.instance] fMono: f (f a) ≤ a → f (f (f a)) ≤ f a
[grind.ematch.instance] fMono: f (f a) ≤ f (f a) → f (f (f a)) ≤ f (f (f a))
[grind.ematch.instance] fMono: f (f a) ≤ f a → f (f (f a)) ≤ f (f a)
[grind.ematch.instance] fMono: a ≤ b → f a ≤ f b
[grind.ematch.instance] fMono: a ≤ c → f a ≤ f c
[grind.ematch.instance] fMono: a ≤ a → f a ≤ f a
[grind.ematch.instance] fMono: a ≤ f (f a) → f a ≤ f (f (f a))
[grind.ematch.instance] fMono: a ≤ f a → f a ≤ f (f a)
[grind.ematch.instance] fMono: c ≤ b → f c ≤ f b
[grind.ematch.instance] fMono: c ≤ c → f c ≤ f c
[grind.ematch.instance] fMono: c ≤ a → f c ≤ f a
[grind.ematch.instance] fMono: c ≤ f (f a) → f c ≤ f (f (f a))
[grind.ematch.instance] fMono: c ≤ f a → f c ≤ f (f a)
[grind.ematch.instance] fMono: b ≤ b → f b ≤ f b
[grind.ematch.instance] fMono: b ≤ c → f b ≤ f c
[grind.ematch.instance] fMono: b ≤ a → f b ≤ f a
[grind.ematch.instance] fMono: b ≤ f (f a) → f b ≤ f (f (f a))
[grind.ematch.instance] fMono: b ≤ f a → f b ≤ f (f a)
-/
#guard_msgs in
example : f b = f c → a ≤ f a → f (f a) ≤ f (f (f a)) := by
  set_option trace.grind.ematch.instance true in
  grind
```

However, many unnecessary theorem instantiations are generated.

With the new `guard` feature, we can instruct `grind` to instantiate the
theorem **only if** `x ≤ y` is already known to be true in the current
`grind` state:

```lean
grind_pattern fMono => f x, f y where
  guard x ≤ y
  x =/= y
```

If we run the example again, only three instances are generated:

```lean
/--
trace: [grind.ematch.instance] fMono: a ≤ f a → f a ≤ f (f a)
[grind.ematch.instance] fMono: f a ≤ f (f a) → f (f a) ≤ f (f (f a))
[grind.ematch.instance] fMono: a ≤ f (f a) → f a ≤ f (f (f a))
-/
#guard_msgs in
example : f b = f c → a ≤ f a → f (f a) ≤ f (f (f a)) := by
  set_option trace.grind.ematch.instance true in
  grind
```

Note that `guard` does **not** check whether the expression is
*implied*. It only checks whether the expression is *already known* to
be true in the current `grind` state. If this fact is eventually
learned, the theorem will be instantiated.

If you want `grind` to check whether the expression is implied, you
should use:

```lean
grind_pattern fMono => f x, f y where
  check x ≤ y
  x =/= y
```

Remark: we can use multiple `guard`/`check`s in a `grind_pattern`
command.
2025-11-29 03:56:53 +00:00
Kim Morrison
958aa713fa
fix: rename ring variable indices in grind cancel_var proofs (#11410)
This PR fixes a kernel type mismatch error in grind's denominator
cleanup feature. When generating proofs involving inverse numerals (like
`2⁻¹`), the proof context is compacted to only include variables
actually used. This involves renaming variable indices - e.g., if
original indices were `{0: r, 1: 2⁻¹}` and only `2⁻¹` is used, it gets
renamed to index 0.

The bug was that polynomials were correctly renamed via `varRename`, but
the variable index `x` stored in `cancelDen` constraints was passed
directly to the proof without renaming, causing a mismatch between the
polynomial's variable references and the theorem's variable argument.

Added `ringVarDecls` to track ring variable indices that need renaming,
similar to how `ringPolyDecls` tracks polynomials. The `mkRingContext`
function now also renames these variable indices.

See zulip discussion at [#nightly-testing > Mathlib status updates @
💬](https://leanprover.zulipchat.com/#narrow/channel/428973-nightly-testing/topic/Mathlib.20status.20updates/near/560575295).

🤖 Prepared with Claude Code

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-28 04:43:46 +00:00
Kim Morrison
6a900dc9d6
fix: strip nested mdata in grind preprocessing (#11412)
This PR fixes an issue where `grind` would fail after multiple
`norm_cast`
calls with the error "unexpected metadata found during internalization".

The `norm_cast` tactic adds mdata nodes to expressions, and when called
multiple times it creates nested mdata. The `eraseIrrelevantMData`
preprocessing function was using `.continue e` when stripping mdata,
which causes `Core.transform` to reconstruct the mdata node around the
visited children. By changing to `.visit e`, the inner expression is
passed back to `pre` for another round of processing, allowing all
nested mdata layers to be stripped.

Closes #11411

🤖 Prepared with Claude Code

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-28 04:36:26 +00:00
Leonardo de Moura
9a5a9c2709
feat: add is_value and is_strict_value grind_pattern constraints (#11409)
This PR implements support for the `grind_pattern` constraints
`is_value` and `is_strict_value`.
2025-11-27 21:02:49 +00:00
Leonardo de Moura
16740a1540
feat: some grind_pattern constraints (#11405)
This PR implements the following `grind_pattern` constraints:
```lean
grind_pattern fax => f x  where
  depth x < 2

grind_pattern fax => f x where
  is_ground x

grind_pattern fax => f x where
  size x < 5

grind_pattern fax => f x where
  gen < 2

grind_pattern fax => f x where
  max_insts < 4

grind_pattern gax => g as where
  as =?= _ :: _
```
2025-11-27 18:05:47 +00:00
Leonardo de Moura
a4f9a793d9
feat: new constraints in grind_pattern (#11391)
This PR implements new kinds of constraints for the `grind_pattern`
command. These constraints allow users to control theorem instantiation
in `grind`.
It requires a manual `update-stage0` because the change affects the
`.olean` format, and the PR fails without it.
2025-11-26 21:13:14 -08:00
Joachim Breitner
9ce8a062ba
perf: macro_inline ctorIdx for single constructor inductives (#11379)
This PR sets `@[macro_inline]` on the (trivial) `.ctorIdx` for inductive
types with one constructor, to reduce the number of symbols generated by
the compiler.
2025-11-26 11:23:00 +00:00
Leonardo de Moura
5ac0931c8f
feat: cleanup denominators in grind linarith (#11375)
This PR adds support for cleaning up denominators in `grind linarith`
when the type is a `Field`.

Examples:
```lean
open Std Lean.Grind
section
variable {α : Type} [Field α] [LE α] [LT α] [LawfulOrderLT α] [IsLinearOrder α] [OrderedRing α]

example (a b : α) (h : a < b / 2) : 2 * a < b := by grind
example (a b : α) (_ : 0 ≤ a) (h : a ≤ b) : a / 7 ≤ b / 2 := by grind
example (a b : α) (_ : b < 0) (h : a < b) : (3/2) * a < (5/4) * b := by grind
example (a b : α) (h : a = b * (3⁻¹)^2) : 9 * a ≤ b := by grind
example (a b : α) (h : a / 2 ≠ b / 9) : 9 * a < 2 * b ∨ 9 * a > 2 * b := by grind
example (a b : α) (h : a < b / (2^2 - 3/2 + -1 + 1/2)) : 2 * a < b := by grind

end

example (a b : Rat) (h : a < b / 2) : a + a < b := by grind
example (a b : Rat) (h : a < b / 2) : a + a ≤ b := by grind
example (a b : Rat) (h : a ≠ b * (3⁻¹)^2) : 9 * a < b ∨ 9 * a > b := by grind
example (a b : Rat) (h : a / 2 ≠ b / 9) : 9 * a < 2 * b ∨ 9 * a > 2 * b := by grind
```
2025-11-26 05:21:55 +00:00
Leonardo de Moura
8ace95f99f
feat: Field norm num (#11350)
This PR implements a helper simproc for `grind`. It is part of the
infrastructure used to cleanup denominators in `grind linarith`.

---------

Co-authored-by: Kim Morrison <kim@tqft.net>
2025-11-25 19:47:31 +00:00
Kim Morrison
8a4fb762f3
feat: grind use/instantiate only can activate all scoped theorems in a namespace (#11335)
This PR enables the syntax `use [ns Foo]` and `instantiate only [ns
Foo]` inside a `grind` tactic block, and has the effect of activating
all grind patterns scoped to that namespace. We can use this to
implement specialized tactics using `grind`, but only controlled subsets
of theorems.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-25 02:41:08 +00:00
Markus Himmel
fa67f300f6
chore: rename String.ValidPos to String.Pos (#11240)
This PR renames `String.ValidPos` to `String.Pos`, `String.endValidPos`
to `String.endPos` and `String.startValidPos` to `String.startPos`.

Accordingly, the deprecations of `String.Pos` to `String.Pos.Raw` and
`String.endPos` to `String.rawEndPos` are removed early, after an
abbreviated deprecation cycle of two releases.
2025-11-24 16:40:21 +00:00
Joachim Breitner
54a10f0790
feat: remove the group field of an option description (#11305)
This PR removes the `group` field from option descriptions. It is
unused, does not have a clear meaning and often matches the first
component of the option name.
2025-11-24 11:40:58 +00:00
Sebastian Ullrich
bfbad53540
fix: avoid storing reference to environment in realization result to prevent promise cycle (#11328)
This PR fixes freeing memory accidentally retained for each document
version in the language server on certain elaboration workloads. The
issue must have existed since 4.18.0.
2025-11-24 10:16:56 +00:00
Leonardo de Moura
f2e191d0af
refactor: grind linarith ring normalization (#11334)
This PR adds an explicit normalization layer for ring constraints in the
`grind linarith` module. For example, it will be used to clean up
denominators when the ring is a field.
2025-11-24 03:11:13 +00:00
Markus Himmel
e6a07ca6b1
refactor: deprecate String.posOf and variants in favor of unified String.find (#11276)
This PR cleans up the API around `String.find` and moves it uniformly to
the new position types `String.ValidPos` and `String.Slice.Pos`

Overview:

- To search for a character, character predicate, string or slice in a
string or slice `s`, use `s.find?` or `s.find`.
- To do the same, but starting at a position `p` of a string or slice,
use `p.find?` or `p.find`.
- To do the same but between two positions `p` and `q`, construct the
slice from `p` to `q` and then use `find?` or `find` on that.
- To search backwards, all of the above applies, except that the
function is called `revFind?`, there is no non-question-mark version
(use `getD` if there is a sane default return value in your specific
application), and that you can only search for characters and character
predicates, not strings or slices.
2025-11-23 18:39:53 +00:00
Leonardo de Moura
216f7e8753
feat: grind proof parameters whose type is not a forall (#11326)
This PR ensures that users can provide `grind` proof parameters whose
types are not `forall`-quantified. Examples:

```lean
opaque f : Nat → Nat
axiom le_f (a : Nat) : a ≤ f a

example (a : Nat) : a ≤ f a := by
  grind [le_f a]

example (a b : α) (h : ∀ x y : α, x = y) : a = b := by
  grind [h a b]
```
2025-11-23 18:36:04 +00:00
Leonardo de Moura
4135674021
feat: add funCC (function-valued congruence closure) to grind (#11323)
This PR introduces a new `grind` option, `funCC` (enabled by default),
which extends congruence closure to *function-valued* equalities. When
`funCC` is enabled, `grind` tracks equalities of **partially applied
functions**, allowing reasoning steps such as:
```lean
a : Nat → Nat 
f : (Nat → Nat) → (Nat → Nat)
h : f a = a
⊢ (f a) m = a m

g : Nat → Nat
f : Nat → Nat → Nat
h : f a = g
⊢ f a b = g b
```

Given an application `f a₁ a₂ … aₙ`, when `funCC := true` and function
equality is enabled for `f`, `grind` generates and tracks equalities for
all partial applications:

* `f a₁`
* `f a₁ a₂`
* …
* `f a₁ a₂ … aₙ`

This allows equalities such as `f a₁ = g` to propagate through further
applications.

**When is function equality enabled for a symbol?**

Function equality is enabled for `f` in the following cases:

1. `f` is **not a constant** (e.g., a lambda, a local function, or a
function parameter).
2. `f` is a **structure field projection**, provided the structure is
**not a `class`**.
3. `f` is a constant marked with  `@[grind funCC]`

Users can also enable function equality for specific constants in a
single call using:
```lean
grind [funCC f, funCC g]
```

**Examples:**

```lean
example (m : Nat) (a : Nat → Nat) (f : (Nat → Nat) → (Nat → Nat)) (h : f a = a) :
    f a m = a m := by
  grind

example (m : Nat) (a : Nat → Nat) (f : (Nat → Nat) → (Nat → Nat)) (h : f a = a) :
    f a m = a m := by
  fail_if_success grind -funCC -- fails if `funCC` is disabled
  grind
```

```lean
example (a b : Nat) (g : Nat → Nat) (f : Nat → Nat → Nat) (h : f a = g) :
    f a b = g b := by
  grind

example (a b : Nat) (g : Nat → Nat) (f : Nat → Nat → Nat) (h : f a = g) :
    f a b = g b := by
  fail_if_success grind -funCC
  grind
```

**Enabling per-symbol with parameters or attributes**

```lean
opaque f : Nat → Nat → Nat
opaque g : Nat → Nat

example (a b c : Nat) : f a = g → b = c → f a b = g c := by
  grind [funCC f, funCC g]

attribute [grind funCC] f g

example (a b c : Nat) : f a = g → b = c → f a b = g c := by
  grind
```

This feature substantially improves `grind`’s support for higher-order
and partially-applied function equalities, while preserving
compatibility with first-order SMT behavior when `funCC` is disabled.

Closes #11309
2025-11-23 05:06:41 +00:00
Leonardo de Moura
0818cf6483
feat: improves Fin n support in grind (#11319)
This PR improves the support for `Fin n` in `grind` when `n` is not a
numeral.

- `toInt (0 : Fin n) = 0` in `grind lia`.
- `Fin.mk`-applications are treated as interpreted terms in `grind lia`.
- `Fin.val` applications are suppressed from `grind lia`
counterexamples.
2025-11-22 06:51:25 +00:00
Leonardo de Moura
db4206f2a9
fix: instantiate metavariables in hypotheses in grind (#11315)
This PR fixes an issue affecting `grind -revert`. In this mode, assigned
metavariables in hypotheses were not being instantiated. This issue was
affecting two files in Mathlib.
2025-11-22 04:28:53 +00:00
Leonardo de Moura
a0772dc82d
fix: grind internalization (#11318)
This PR fixes a local declaration internalization in `grind` that was
exposed when using `grind -revert`. This bug was affecting a `grind`
proof in Mathlib.
2025-11-22 04:24:11 +00:00
Robert J. Simmons
3a309ba4eb
feat: improve error message in the case of type class synthesis failure (#11245)
This PR improves the error message encountered in the case of a type
class instance resolution failure, and adds an error explanation that
discusses the common new-user case of binary operation overloading and
points to the `trace.Meta.synthInstance` option for advanced debugging.

## Example

```lean4
def f (x : String) := x + x
```

Before:
```
failed to synthesize
  HAdd String String ?m.5

Hint: Additional diagnostic information may be available using the `set_option diagnostics true` command.
```

After:
```
failed to synthesize instance of type class
  HAdd String String ?m.5

Hint: Type class instance resolution failures can be inspected with the `set_option trace.Meta.synthInstance true` command.
Error code: lean.failedToSynthesizeTypeclassInstance
[View explanation](https://lean-lang.org/doc/reference/latest/find/?domain=Manual.errorExplanation&name=lean.failedToSynthesizeTypeclassInstance)
```

The error message is changed in three important ways:
* Explains *what* failed to synthesize, using the "type class"
terminology that's more likely to be recognized than the "instance"
terminology
* Points to the `trace.Meta.synthInstance` option which is otherwise
nearly undiscoverable but is quite powerful (see also
leanprover/reference-manual#663 which is adding commentary on this
option)
* Gives an error explanation link (which won't actually work until the
next release after this is merged) which prioritizes the common-case
explanation of using the wrong binary operation
2025-11-21 21:24:27 +00:00
Joachim Breitner
4288aa71e0
chore: do not set unused Option.Decl.group (#11307)
This PR removes all code that sets the `Option.Decl.group` field, which
is unused and has no clearly documented meaning.

The actual removal of the field would be #11305.
2025-11-21 16:44:38 +00:00
Joachim Breitner
cce4873c25
chore: rename wrongly named backwards. options to backward. (#11303)
This PR renames rename wrongly named `backwards.` options to
`backward.`
2025-11-21 10:57:56 +00:00
Leonardo de Moura
5306a3469d
fix: bug ite/dite propagator used in grind (#11295)
This PR fixes a bug in the propagation rules for `ite` and `dite` used
in `grind`. The bug prevented equalities from being propagated to the
satellite solvers. Here is an example affected by this issue.

```lean
example
    [LE α] [LT α] [Std.IsLinearOrder α] [Std.LawfulOrderLT α]
    [Lean.Grind.CommRing α] [DecidableLE α] [Lean.Grind.OrderedRing α]
    (a b c : α) :
  (if a - b ≤ -(a - b) then -(a - b) else a - b) ≤
  ((if a - c ≤ -(a - c) then -(a - c) else a - c) + if c - d ≤ -(c - d) then -(c - d) else c - d) +
    if b - d ≤ -(b - d) then -(b - d) else b - d := by
  grind
```
2025-11-20 23:54:28 +00:00
Sebastian Ullrich
e5e7a89fdc
fix: shake: only record used simp theorems as dependencies, plus simprocs (#11287) 2025-11-20 15:43:25 +00:00
Leonardo de Moura
00600806ad
fix: proof construction in grind ring (#11273)
This PR fixes a bug during proof construction in `grind`.
2025-11-20 04:52:18 +00:00
Leonardo de Moura
2ed025ade8
feat: mark sizeOf theorems as grind theorems (#11265)
This PR marks the automatically generated `sizeOf` theorems as `grind`
theorems.

closes #11259

Note: Requested update stage0, we need it to be able to solve example in
the issue above.
```lean
example (a: Nat) (b: Nat): sizeOf a < sizeOf (a, b) := by
  grind
```
2025-11-19 18:38:35 +00:00
Joachim Breitner
5cc0a10346
refactor: use Match.AltParamInfo also for splitters (#11261)
This PR continues the homogenization between matchers and splitters,
following up on #11256. In particular it removes the ambiguity whether
`numParams` includes the `discrEqns` or not.
2025-11-19 16:13:53 +00:00
Joachim Breitner
63bd0b5e77
refactor: introduce Match.altInfos (#11256)
This PR replaces `MatcherInfo.numAltParams` with a more detailed data
structure that allows us, in particular, to distinguish between an
alternative for a constructor with a `Unit` field and the alternative
for a nullary constructor, where an artificial `Unit` argument is
introduced.
2025-11-19 15:09:17 +00:00
Joachim Breitner
75570f327f
refactor: thunk field-less alternatives of casesOnSameCtor (#11254)
This RP adds a `Unit` argument to `casesOnSameCtor` to make it behave
moere similar to a matcher. Follow up in spirit to #11239.
2025-11-19 09:53:09 +00:00
Joachim Breitner
f7031c7aa9
perf: in match splitters, thunk alts if needed (#11239)
This PR adds a `Unit` assumption to alternatives of the splitter that
would otherwise not have arguments. This fixes #11211.

In practice these argument-less alternatives did not cause wrong
behavior, as the motive when used with `split` is always a function
type. But it is better to be safe here (maybe someone uses splitters in
other ways), it may increase the effectiveness of #10184 and simplifies
#11220.

The perf impact is insignificant in the grand scheme of things on
stdlib, but the change is effective:
```
~/lean4 $ build/release/stage1/bin/lean tests/lean/run/matchSplitStats.lean 
969 splitters found
455 splitters are const defs
~/lean4 $ build/release/stage2/bin/lean tests/lean/run/matchSplitStats.lean 
969 splitters found
829 splitters are const defs
```
2025-11-19 09:08:34 +00:00
Leonardo de Moura
61186629d6
feat: grind -revert (#11248)
This PR implements the option `revert`, which is set to `false` by
default. To recover the old `grind` behavior, you should use `grind
+revert`. Previously, `grind` used the `RevSimpIntro` idiom, i.e., it
would revert all hypotheses and then re-introduce them while simplifying
and applying eager `cases`. This idiom created several problems:

* Users reported that `grind` would include unnecessary parameters. See
[here](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Grind.20aggressively.20includes.20local.20hypotheses.2E/near/554887715).
* Unnecessary section variables were also being introduced. See the new
test contributed by Sebastian Graf.
* Finally, it prevented us from supporting arbitrary parameters as we do
in `simp`. In `simp`, I implemented a mechanism that simulates local
universe-polymorphic theorems, but this approach could not be used in
`grind` because there is no mechanism for reverting (and re-introducing)
local universe-polymorphic theorems. Adding such a mechanism would
require substantial work: I would need to modify the local context
object. I considered maintaining a substitution from the original
variables to the new ones, but this is also tricky, because the mapping
would have to be stored in the `grind` goal objects, and it is not just
a simple mapping. After reverting everything, I would need to keep a
sequence of original variables that must be added to the mapping as we
re-introduce them, but eager case splits complicate this quite a bit.
The whole approach felt overly messy.

The new behavior `grind -revert` addresses all these issues. None of the
`grind` proofs in our test suite broke after we fixed the bugs exposed
by the new feature. That said, the traces and counterexamples produced
by `grind` are different. The new proof terms are also different.
2025-11-19 05:28:31 +00:00
Leonardo de Moura
8a0ee9aac7
fix: assigned universe metavars in grind (#11247)
This PR fixes an issue in the `grind` preprocessor. `simp` may introduce
assigned (universe) metavariables (e.g., when performing
zeta-reduction).
2025-11-19 00:19:17 +00:00
Leonardo de Moura
6dd8ad13e5
fix: grind minor issues (#11244)
This PR fixes minor issues in `grind`. In preparation for adding `grind
-revert`.
2025-11-18 22:11:20 +00:00
Joachim Breitner
f6e580ccf8
refactor: extract functionality from Match.MatchEqs (#11236)
This PR extracts two modules from `Match.MatchEqs`, in preparation of
#11220
and to use the module system to draw clear boundaries between concerns
here.
2025-11-18 10:02:10 +00:00
Leonardo de Moura
5a4226f2bd
refactor: remove old grindSearchM framework (#11226)
This PR finally removes the old `grind` framework `SearchM`. It has been
replaced with the new `Action` framework.
2025-11-18 00:33:38 +00:00
Joachim Breitner
09001ecad6
fix: let realizeConst run withDeclNameForAuxNaming (#11221)
This PR lets `realizeConst` use `withDeclNameForAuxNaming` so that
auxilary definitions created there get non-clashing names.
2025-11-17 21:17:16 +00:00
Joachim Breitner
b67e8a15d0
perf: avoid quadratic calculation of notAlts in match splitter (#11196)
This PR avoids match splitter calculation from testing all quadratically
many pairs of alternatives for overlaps, by keeping track of possible
overlaps during matcher calculation, storing that information in the
`MatcherInfo`, and using that during matcher calculation.
2025-11-17 18:10:13 +00:00
Joachim Breitner
27e5e21bfe
perf: use Nat-based bitmask in sparse cases construction (#11200)
This PR changes how sparse case expressions represent the
none-of-the-above information. Instead of of many `x.ctorIdx ≠ i`
hypotheses, it introduces a single `Nat.hasNotBit mask x.ctorIdx`
hypothesis which compresses that information into a bitmask. This avoids
a quadratic overhead during splitter generation, where all n assumptions
would be refined through `.subst` and `.cases` constructions for all n
assumption of the splitter alternative.

The definition of `Nat.hasNotBit` uses `Nat.rightShift` which is fiddly
to get to reduce well, especially on open terms and with `Meta.whnf`.
Some experimentation was needed to find proof terms that work, these are
all put together in the `Lean.Meta.HasNotBit` module.

Fixes #11183

---------

Co-authored-by: Rob23oba <152706811+Rob23oba@users.noreply.github.com>
2025-11-17 10:05:18 +00:00
Leonardo de Moura
4c189bc8f2
fix: grind actions (#11203)
This PR fixes a few minor issues in the new `Action` framework used in
`grind`. The goal is to eventually delete the old `SearchM`
infrastructure. The main `solve` function used by `grind` is now based
on the `Action` framework. The PR also deletes dead code in `SearchM`.
2025-11-17 00:37:19 +00:00
Markus Himmel
bf60550ce5
chore: rename Substring to Substring.Raw (#11154)
This PR renames `Substring`  to `Substring.Raw`.

This is to signify its status as a second-class citizen (not deprecated,
but no real plans for verification, like `String.Pos.Raw`) and to free
up the name `Substring` for a possible future type `String.Substring :
String -> Type` so that `s.Substring` is the type of substrings of `s`.

The functions `String.toSubstring` and `String.toSubstring'` will remain
for now for bootstrapping reasons.
2025-11-16 09:30:04 +00:00
Leonardo de Moura
ef1dc21f1c
feat: use new grind? infrastructure to implement try? (#11197)
This PR implements `try?` using the new `finish?` infrastructure. It
also removes the old tracing infrastructure, which is now obsolete.
Example:

```lean
/--
info: Try these:
  [apply] grind
  [apply] grind only [findIdx, insert, = mem_indices_of_mem, = getElem?_neg, = getElem?_pos, = HashMap.mem_insert,
    = HashMap.getElem_insert, #1bba]
  [apply] grind only [findIdx, insert, = mem_indices_of_mem, = getElem?_neg, = getElem?_pos, = HashMap.mem_insert,
    = HashMap.getElem_insert]
  [apply] grind =>
    instantiate only [findIdx, insert, = mem_indices_of_mem]
    instantiate only [= getElem?_neg, = getElem?_pos]
    cases #1bba
    · instantiate only [findIdx]
    · instantiate only
      instantiate only [= HashMap.mem_insert, = HashMap.getElem_insert]
-/
#guard_msgs in
example (m : IndexMap α β) (a : α) (b : β) :
    (m.insert a b).findIdx a = if h : a ∈ m then m.findIdx a else m.size := by
  try?
```
2025-11-16 05:26:17 +00:00
Leonardo de Moura
2f3939f1ea
fix: incorrect grind param warning (#11194)
This PR the redundant `grind` parameter warning message. It now checks
the `grind` theorem instantiation constraints too.
2025-11-15 20:17:55 +00:00
Joachim Breitner
e39894e62d
feat: realizeConst to set CoreM's maxHeartbeat (#11191)
This PR makes sure that inside a `realizeConst` the `maxHeartbeat`
option is effective.
2025-11-15 17:36:09 +00:00
Joachim Breitner
a6f4e9156e
fix: avoid unknown free variables in match error message (#11190)
This PR avoids running into an “unknown free variable” when printing the
“Failed to compile pattern matching” error. Fixes #11186.
2025-11-15 16:31:24 +00:00
Leonardo de Moura
6f2c04b6a2
feat: grind_pattern constraints (#11189)
This PR implements `grind_pattern` constraints. They are useful for
controlling theorem instantiation in `grind`. As an example, consider
the following two theorems:
```lean
theorem extract_empty {start stop : Nat} :
    (#[] : Array α).extract start stop = #[] := …

theorem extract_extract {as : Array α} {i j k l : Nat} :
    (as.extract i j).extract k l = as.extract (i + k) (min (i + l) j) := …
```

If both are used for theorem instantiation, an unbounded number of
instances is generated as soon as we add the term `#[].extract i j` to
the `grind` context.

We can now prevent this by adding a `grind_pattern` constraint to
`extract_extract`:

```lean
grind_pattern extract_extract => (as.extract i j).extract k l where
  as =/= #[]
```

With this constraint, only one instance is generated, as expected:

```lean
/-- trace: [grind.ematch.instance] extract_empty: #[].extract i j = #[] -/
#guard_msgs (drop error, trace) in
set_option trace.grind.ematch.instance true in
example (as : Array Nat) (h : #[].extract i j = as) : False := by
  grind only [= extract_empty, usr extract_extract]
```
2025-11-15 05:05:04 +00:00
Leonardo de Moura
d963d33985
feat: add grind_pattern constraints (#11187)
This PR adds syntax for specifying `grind_pattern` constraints and
extends the `EMatchTheorem` object.

--- 
Note: We need a manual stage0 update because it affects the .olean
files.
2025-11-14 18:27:17 -08:00
Sebastian Graf
09cf07b71c
feat: new do elaborator, part 1: doElem_elab attribute (#11150)
This PR adds a new, inactive and unused `doElem_elab` attribute that
will allow users to register custom elaborators for `doElem`s in the
form of the new type `DoElab`. The old `do` elaborator is active by
default but can be switched off by disabling the new option
`backward.do.legacy`.
2025-11-12 14:25:28 +00:00
Leonardo de Moura
f2b3f90724
refactor: symmetric equality congruence in grind (#11147)
This PR refactors the implementation of the symmetric equality
congruence rule used in `grind`.
2025-11-12 01:10:37 +00:00