Commit graph

9953 commits

Author SHA1 Message Date
Joachim Breitner
3b40682b22
perf: handle per-constructor noConfusion in toLCNF (#11566)
This PR lets the compiler treat per-constructor `noConfusion` like the
general one, and moves some more logic closer to no confusion
generation.
2025-12-10 09:03:55 +00:00
Joachim Breitner
19e1fe55f3
perf: do not consult isNoConfusion in whnf (#11571)
This PR lets `whnf` not consult `isNoConfusion`, to speed up this hot
path a bit.
2025-12-09 23:36:46 +00:00
Joachim Breitner
5bf5c73f74
chore: prune imports in Try.Collect (#11570)
This PR removed unused imports from Try.Collect
2025-12-09 22:15:34 +00:00
Robert J. Simmons
5326530383
feat: suggestions for ambiguous dotted identifiers (#11555)
This PR scans the environment for viable replacements for a dotted
identifier (like `.zero`) and suggests concrete alternatives as
replacements.

## Example

```
#example .zero
```

Error message:
```
Invalid dotted identifier notation: The expected type of `.cons` could not be determined
```

Additional hint added by this PR:
```
Hint: Using one of these would be unambiguous:
  [apply] `BitVec.cons`
  [apply] `List.cons`
  [apply] `List.Lex.cons`
  [apply] `List.Pairwise.cons`
  [apply] `List.Perm.cons`
  [apply] `List.Sublist.cons`
  [apply] `List.Lex.below.cons`
  [apply] `List.Pairwise.below.cons`
  [apply] `List.Perm.below.cons`
  [apply] `List.Sublist.below.cons`
  [apply] `Lean.Grind.AC.Seq.cons`
```

## Additional changes

This PR also brings several related error message descriptions and code
actions more in line with each other, changing several "Suggested
replacement: " code actions to the more common "Change to " wording, and
sorts suggestions obtained from searching the context by the default
sort for Names (which prefers names with fewer segments).
2025-12-09 17:27:22 +00:00
Sebastian Ullrich
d247dcffc4
chore: delete obsolete C++ file (#11561) 2025-12-09 15:47:54 +00:00
Henrik Böving
ecce5e69bf
feat: tagged_return attribute (#11530)
This PR introduces the new `tagged_return` attribute. It allows users to
mark `extern` declarations to be guaranteed to always return `tagged`
return values. Unlike with `object` or `tobject` the compiler does not
emit reference counting operations for them. In the future information
from this attribute will be used for a more powerful analysis to remove
reference counts when possible.
2025-12-08 10:55:46 +00:00
Markus Himmel
459e9f702f
feat: ToJson and FromJson for String.Slice (#11548)
This PR adds `Lean.ToJson` and `Lean.FromJson` instances for
`String.Slice`.
2025-12-08 10:19:42 +00:00
Kim Morrison
62f2f92293
fix: make register_try?_tactic auxiliary definitions internal (#11547)
This PR ensures the auxiliary definitions created by
`register_try?_tactic` are internal implementation details that should
not be visible to user-facing linters.

🤖 Generated with Claude Code
2025-12-08 05:49:01 +00:00
Tom Levy
2ca3bc2859
chore: fix spelling (#11531)
Hi, these are just some spelling corrections.

There is one I wasn't completely sure about in
src/Init/Data/List/Lemmas.lean:

> See also
> ...
> Also
> \* \`Init.Data.List.Monadic\` for **addiation** _(additional?)_ lemmas
about \`List.mapM\` and \`List.forM\`
2025-12-06 13:54:27 +00:00
Robert J. Simmons
72ddc479bf
fix: modify @[suggest_for] to work with the Prelude (#11529)
This PR fixes a syntax-pattern-matching issue from #11367 that prevented
the addition of suggestions in Init prior to Lean.Parser being
introduced, which was a significant shortcoming. It preserves the
ability to have multiple suggestions for one annotation later in the
process.

Additionally, tweaks a (not-yet-user-visible) error message and modifies
the attribute declaration to store a wrongIdentifier ->
correctIdentifier mapping instead of a correctIdentifier ->
wrongIdentifier mapping.
2025-12-05 22:06:11 +00:00
Henrik Böving
c5e04176b8
perf: eliminate cases with all branches unreachable (#11525)
This PR makes the LCNF simplifier eliminate cases where all alts are
`.unreach` to just an `.unreach`.
  an `.unreach`

We considered dropping a cases in a situation like this but decided
against it because it might hinder reuse.
```
def test x : Bool :=
  cases x : Bool
  | Except.error a.1 =>
    ⊥
  | Except.ok a.2 =>
    let _x.3 := true;
    return _x.3
```
2025-12-05 20:30:20 +00:00
Joachim Breitner
4b77e226ab
perf: when matching on values, avoid generating hyps when not needed (#11508)
This PR avoids generating hyps when not needed (i.e. if there is a
catch-all so no completeness checking needed) during matching on values.
    
This tweak was made possible by #11220.
2025-12-05 16:29:20 +00:00
Sebastian Ullrich
e0650a0336
feat: shake: make Mathlib-ready (#11496)
This PR implements new flags and annotations for `shake` for use in
Mathlib:

> Options:
>   --keep-implied
> Preserves existing imports that are implied by other imports and thus
not technically needed
>     anymore
> 
>   --keep-prefix
> If an import `X` would be replaced in favor of a more specific import
`X.Y...` it implies,
> preserves the original import instead. More generally, prefers
inserting `import X` even if it
> was not part of the original imports as long as it was in the original
transitive import closure
>     of the current module.
> 
>   --keep-public
> Preserves all `public` imports to avoid breaking changes for external
downstream modules
> 
>   --add-public
> Adds new imports as `public` if they have been in the original public
closure of that module.
> In other words, public imports will not be removed from a module
unless they are unused even
> in the private scope, and those that are removed will be re-added as
`public` in downstream
> modules even if only needed in the private scope there. Unlike
`--keep-public`, this may
> introduce breaking changes but will still limit the number of inserted
imports.
> 
> Annotations:
> The following annotations can be added to Lean files in order to
configure the behavior of
> `shake`. Only the substring `shake: ` directly followed by a directive
is checked for, so multiple
> directives can be mixed in one line such as `-- shake:
keep-downstream, shake: keep-all`, and they
> can be surrounded by arbitrary comments such as `-- shake: keep
(metaprogram output dependency)`.
> 
>   * `module -- shake: keep-downstream`:
> Preserves this module in all (current) downstream modules, adding new
imports of it if needed.
> 
>   * `module -- shake: keep-all`:
> Preserves all existing imports in this module as is. New imports now
needed because of upstream
>     changes may still be added.
> 
>   * `import X -- shake: keep`:
> Preserves this specific import in the current module. The most common
use case is to preserve a
> public import that will be needed in downstream modules to make sense
of the output of a
> metaprogram defined in this module. For example, if a tactic is
defined that may synthesize a
> reference to a theorem when run, there is no way for `shake` to detect
this by itself and the
> module of that theorem should be publicly imported and annotated with
`keep` in the tactic's
>     module.
>     ```
>     public import X  -- shake: keep (metaprogram output dependency)
> 
>     ...
> 
>     elab \"my_tactic\" : tactic => do
> ... mkConst ``f -- `f`, defined in `X`, may appear in the output of
this tactic
>     ```
2025-12-05 09:37:58 +00:00
Leonardo de Moura
b3753ba6db
feat: grind propagators for Nat operators (#11522)
This PR implements `grind` propagators for `Nat` operators that have a
simproc associated with them, but do not have any theory solver support.
Examples:

```lean
example (a b : Nat) : a = 3 → b = 6 → a &&& b = 2 := by grind
example (a b : Nat) : a = 3 → b = 6 → a ||| b = 7 := by grind
example (a b : Nat) : a = 3 → b = 6 → a ^^^ b = 5 := by grind
example (a b : Nat) : a = 3 → b = 6 → a <<< b = 192 := by grind
example (a b : Nat) : a = 1135 → b = 6 → a >>> b = 17 := by grind
```

Closes #11498
2025-12-05 05:41:34 +00:00
Leonardo de Moura
71991296e0
feat: add not_value constraint to grind_pattern (#11520)
This PR implements the constraint `not_value x` in the `grind_pattern`
command. It is the negation of the constraint `is_value`.
2025-12-05 04:19:34 +00:00
Robert J. Simmons
ab606ba754
feat: hint when an autobound variable's type fails to be a function (#11518)
This PR provides an additional hint when the type of an autobound
implicit is required to have function type or equality type — this
fails, and the existing error message does not address the fact that the
source of the error is an unknown identifier that was automatically
bound.

## Example

```
import Lean
example : MetaM String := pure ""
```

Current error message:
```
Function expected at
  MetaM
but this term has type
  ?m

Note: Expected a function because this term is being applied to the argument
  String
```

Additional error message provided by this PR:
```
Hint: The identifier `MetaM` is unknown, and Lean's `autoImplicit` option 
causes an unknown identifier to be treated as an implicitly bound variable 
with an unknown type. However, the unknown type cannot be a function, and a 
function is what Lean expects here. This is often the result of a typo or a 
missing `import` or `open` statement.
```
2025-12-05 03:07:16 +00:00
Henrik Böving
6ca57a74ed
feat: constant folding for Nat.mul (#11517)
This PR implements constant folding for Nat.mul
2025-12-04 23:38:56 +00:00
Kim Morrison
0ba40b798b
feat: exact? uses star-indexed lemmas as fallback (#11494)
This PR re-enables star-indexed lemmas as a fallback for `exact?` and
`apply?`.

Star-indexed lemmas (those with overly-general discrimination tree keys
like `[*]`)
were previously dropped entirely for performance reasons. This caused
useful lemmas
like `Empty.elim`, `And.left`, `not_not.mp`, `Sum.elim`, and
`Function.mtr` to be
unfindable by library search.

The implementation adds a two-pass search strategy:
1. First, search using concrete discrimination keys (the current
behavior)
2. If no results are found, fall back to trying star-indexed lemmas

The star-indexed lemmas are extracted during tree initialization and
cached in an
environment extension, avoiding repeated computation.

Users can disable the fallback with `-star`:
```lean
example {α : Sort u} (h : Empty) : α := by apply? -star  -- error: no lemmas found
example {α : Sort u} (h : Empty) : α := by apply?        -- finds Empty.elim
```

🤖 Prepared with Claude Code

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-04 22:50:52 +00:00
Joachim Breitner
f0738c2cd1
perf: in CaseValues, subst only once (#11510)
This PR avoids running substCore twice in caseValues.
2025-12-04 15:43:46 +00:00
Joachim Breitner
af6d2077a0
refactor: use match compilation to generate splitter (#11220)
This PR changes how match splitters are generated: Rather than rewriting
the match statement, the match compilation pipeline is used again.


The benefits are:

* Re-doing the match compilation means we can do more intelligent book
keeping, e.g. prove overlap assumptions only once and re-use the proof,
or prune the context of the MVar to speed up `contradiction`. This may
have allowed a different solution than #11200.
 
* It would unblock #11105, as the existing splitter implementation would
have trouble dealing with the matchers produced that way.
 
* It provides the necessary machinery also for source-exposed “none of
the above” bindings, a feature that we probably want at some point (and
we mostly need to find good syntax for, see #3136, although maybe I
should open a dedicated RFC).

* It allows us to skip costly things during matcher creation that would
only be useful for the splitter, and thus allows performance
improvements like #11508.
 
 * We can drop the existing implementation.
 
It’s not entirely free:

* We have to run `simpH` twice, once for the match equations and once
for the splitter.
2025-12-04 15:03:13 +00:00
Robert J. Simmons
dd57725244
feat: @[suggest_for] attribute to inform replacements (#11367)
This PR introduces a new annotation that allows definitions to describe
plausible-but-wrong name variants for the purpose of improving error
messages.

This PR just adds the notation and extra functionality; a stage0 update
will allow standard Lean functions to have suggestion annotations.
(Hence the changelog-no tag: this should go in the changelog when some
preliminary annotations are actually added.)

## Example

```lean4
inductive MyBool where | tt | ff

attribute [suggest_for MyBool.true] MyBool.tt
attribute [suggest_for MyBool.false] MyBool.ff

@[suggest_for MyBool.not]
def MyBool.swap : MyBool → MyBool
  | tt => ff
  | ff => tt

/--
error: Unknown constant `MyBool.true`

Hint: Perhaps you meant `MyBool.tt` in place of `MyBool.true`:
  M̵y̵B̵o̵o̵l̵.̵t̵r̵u̵e̵M̲y̲B̲o̲o̲l̲.̲t̲t̲
-/
#guard_msgs in
example := MyBool.true

/--
error: Invalid field `not`: The environment does not contain `MyBool.not`, so it is not possible to project the field `not` from an expression
  MyBool.tt
of type `MyBool`

Hint: Perhaps you meant one of these in place of `MyBool.not`:
  [apply] `MyBool.swap`: MyBool.tt.swap
-/
#guard_msgs in
example := MyBool.tt.not
```
2025-12-04 13:20:37 +00:00
Markus Himmel
e548fa414c
fix: Char -> Bool as default instance for string search (#11503)
This PR marks `Char -> Bool` patterns as default instances for string
search. This means that things like `" ".find (·.isWhitespace)` can now
be elaborated without error.

Previously, it was necessary to write `" ".find Char.isWhitespace`.

Thank you to David Christiansen for the idea of using a default
instance.
2025-12-04 09:25:16 +00:00
Robert J. Simmons
dd28f00588
feat: hint alternatives when field-projecting from an unknown type (#11482)
This PR gives suggestions based on the currently-available constants
when projecting from an unknown type.

## Example: single suggestion in namespace

This was the originally motivating example, as the string refactor led
to a number of anonymous-lambda-expressions with `Char` functions that
were no longer recognized as such.

```lean4
example := (·.isWhitespace)
```
Before:
```
Invalid field notation: Type of
  x✝
is not known; cannot resolve field `isWhitespace`
```
The message is unchanged, but this PR adds a hint:
```
Hint: Consider replacing the field projection `.isWhitespace` with a call to the function `Char.isWhitespace`.
```

## Example: single suggestion in namespace

```lean4
example := fun n => n.succ
```
Before:
```
Invalid field notation: Type of
  n
is not known; cannot resolve field `succ`
```
The message is unchanged, but this PR adds a hint:
```
Hint: Consider replacing the field projection with a call to one of the following:
  • `Fin.succ`
  • `Nat.succ`
  • `Std.PRange.succ`
```
2025-12-03 20:48:34 +00:00
Joachim Breitner
54fbe931ab
refactor: make MatchEqs a leaf module (#11493)
This PR makes `Match.MatchEqs` a leaf module, to be less restricted in
which features we can use there.
2025-12-03 09:15:36 +00:00
Joachim Breitner
fb261921b9
refactor: use withImplicitBinderInfos and mkArrowN in more places (#11492)
This PR uses the the helper functions withImplicitBinderInfos and
mkArrowN in more places.
2025-12-03 08:42:16 +00:00
Leonardo de Moura
0173444d24
feat: heterogeneous contructor injectivity in grind (#11491)
This PR implements heterogeneous contructor injectivity in `grind`.

Example:
```lean
opaque double : Nat → Nat

inductive Parity : Nat -> Type
  | even (n) : Parity (double n)
  | odd  (n) : Parity (Nat.succ (double n))

opaque q : Nat → Nat → Prop
axiom qax : q a b → double a = double b
attribute [grind →] qax

example
  (motive : (x : Nat) → Parity x → Sort u_1)
  (h_2 : (j : Nat) → motive (double j) (Parity.even j))
  (j n : Nat)
  (heq_1 : q j n) -- Implies that `double j = double n`
  (heq_2 : Parity.even n ≍ Parity.even j):
  h_2 n ≍ h_2 j := by
grind
```

Closes #11449
2025-12-03 04:01:19 +00:00
Leonardo de Moura
1377da0c76
feat: heterogeneous constructor injectivity theorems (#11487)
This PR adds a heterogeneous version of the constructor injectivity
theorems. These theorems are useful for indexed families, and will be
used in `grind`.
2025-12-03 01:42:46 +00:00
Leonardo de Moura
8bc3eb1265
fix: grind pattern validation (#11484)
This PR fixes a bug in the `grind` pattern validation. The bug affected
type classes that were propositions.

Closes #11477
2025-12-02 19:57:58 +00:00
David Thrane Christiansen
3fe368e8e7
feat: allow Verso docstrings to suppose the existence of instances (#11476)
This PR adds a `` {givenInstance}`C` `` documentation role that adds an
instance of `C` to the document's local assumptions.
2025-12-02 19:16:35 +00:00
Leonardo de Moura
f8866dcc59
fix: grind? dropping options (#11481)
This PR fixes a bug in `grind?`. The suggestion using the `grind`
interactive mode was dropping the configuration options provided by the
user. In the following account, the third suggestion was dropping the
`-reducible` option.

```lean
/--
info: Try these:
  [apply] grind -reducible only [Equiv.congr_fun, #5103]
  [apply] grind -reducible only [Equiv.congr_fun]
  [apply] grind -reducible => cases #5103 <;> instantiate only [Equiv.congr_fun]
-/
example :
    (Equiv.sigmaCongrRight e).trans (Equiv.sigmaEquivProd α₁ β₂)
    = (Equiv.sigmaEquivProd α₁ β₁).trans (prodCongrRight e) := by
  grind? -reducible [Equiv.congr_fun]
```
2025-12-02 19:00:29 +00:00
Leonardo de Moura
9263a6cc9c
feat: add Grind.Config.reducible (#11480)
This PR adds the `grind` option `reducible` (default: `true`). When
enabled, definitional equality tests expand only declarations marked as
`@[reducible]`.
Use `grind -reducible` to allow expansion of non-reducible declarations
during definitional equality tests.
This option affects only definitional equality; the canonicalizer and
theorem pattern internalization always unfold reducible declarations
regardless of this setting.
2025-12-02 18:10:55 +00:00
Robert J. Simmons
edcef51434
feat: improve error messages for invalid field access (#11456)
This PR refines several error error messages, mostly involving invalid
use of field notation, generalized field notation, and numeric
projection. Provides a new error explanation for field notation.

## Error message changes

In general:
- Uses a slightly different convention for expression-type pairs, where
the expression is always given `indentExpr` and the type is given
`inlineExpr` treatment. This is something of a workaround for the fact
that the `Format` type is awkward for embedding possibly-linebreaking
expressions in not-linebreaking text, which may be a separate issue
worth addressing.
- Tries to give slightly more "why" reasoning — the environment does not
contain `String.parse`, and _therefore you can't project `.parse` from a
`String`_.

Some specific examples:

### No such projection function
```lean4
#check "".parse
```
before:
```
error: Invalid field `parse`: The environment does not contain `String.parse`
  ""
has type
  String
```
after:
```
error: Invalid field `parse`: The environment does not contain `String.parse`, so it is not possible to project the field `parse` from an expression
  ""
of type `String`
```

### Type does not have the correct form
```lean4
example (x : α) := (foo x).foo
```
before:
```
error: Invalid field notation: Type is not of the form `C ...` where C is a constant
  foo x
has type
  α
```
after:
```
error: Invalid field notation: Field projection operates on types of the form `C ...` where C is a constant. The expression
  foo x
has type `α` which does not have the necessary form.
```

## Refactoring
Includes some refactoring changes as well:
- factors out multiple uses of number (1, 2, 3, 212, 222) to ordinal
("first", "second", "third", "212th", "222nd") conversion into
Lean.Elab.ErrorUtils
- significant refactoring of `resolveLValAux` in `Lean.Elab.App` — in
place of five helper functions, a special-case function case analysis,
and a case analysis on the projection type and structure, there's now a
single case analysis on the projection type and structure. This allows
several error messages to be more explicit (there were a number of cases
where index projection was being described as field projection in an
error messages) and gave the opportunity to slightly improve positining
for several errors: field *notation* errors should appear on `foo.bar`,
but field *projection* errors should appear only on the `bar` part of
`foo.bar`.
2025-12-02 17:46:12 +00:00
Mac Malone
79838834c1
refactor: port shell option processing to Lean (v2) (#11434)
This PR moves the processing of options passed to the CLI from
`shell.cpp` to `Shell.lean`.

As with previous ports, this attempts to mirror as much of the original
behavior as possible, Benefits to be gained from the ported code can
come in later PRs. There should be no significant behavioral changes
from this port. Nonetheless, error reporting has changed some, hopefully
for the better. For instance, errors for improper argument
configurations has been made more consistent (e.g., Lean will now error
if numeric arguments fall outside the expected range for an option).

(Redo of #11345 to fix Windows issue.)
2025-12-02 17:41:51 +00:00
Joachim Breitner
edf804c70f
feat: heterogeneous noConfusion (#11474)
This PR generalizes the `noConfusion` constructions to heterogeneous
equalities (assuming propositional equalities between the indices). This
lays ground work for better support for applying injection to
heterogeneous equalities in grind.

The `Meta.mkNoConfusion` app builder shields most of the code from these
changes.

Since the per-constructor noConfusion principles are now more
expressive, `Meta.mkNoConfusion` no longer uses the general one.

In `Init.Prelude` some proofs are more pedestrian because `injection`
now needs a bit more machinery.

This is a breaking change for whoever uses the `noConfusion` principle
manually and explicitly for a type with indices.

Fixes #11450.
2025-12-02 15:19:47 +00:00
Henrik Böving
3dd99fc29c
perf: eta contract instead of lambda lifting if possible (#11451)
This PR adapts the lambda lifter in LCNF to eta contract instead of
lambda lift if possible. This prevents the creation of a few hundred
unnecessary lambdas across the code base.
2025-12-02 08:39:24 +00:00
Kim Morrison
2eca5ca6e4
fix: getEqnsFor? should not panic on matchers (#11463)
This PR fixes a panic in `getEqnsFor?` when called on matchers generated
from match expressions in theorem types.

When a theorem's type contains a match expression (e.g., `theorem bar :
(match ... with ...) = 0`), the compiler generates a matcher like
`bar.match_1`. Calling `getEqnsFor?` on this matcher would panic with:

```
PANIC: duplicate normalized declaration name bar.match_1.eq_1 vs. _private...bar.match_1.eq_1
```

This also affected the `try?` tactic, which internally uses
`getEqnsFor?`.

We make `shouldGenerateEqnThms` return `false` for matchers, since their
equations are already generated separately by
`Lean.Meta.Match.MatchEqs`. This prevents the equation generation
machinery from attempting to create duplicate equation theorems.

Closes #11461
Closes #10390


🤖 Prepared with Claude Code

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-02 07:53:50 +00:00
Leonardo de Moura
1fc4768b68
fix: incorrect reducibility setting in grind interactive mode (#11471)
This PR fixes an incorrect reducibility setting when using `grind`
interactive mode.

Signed-off-by: Leonardo de Moura <leomoura@amazon.com>
2025-12-02 07:04:04 +00:00
Alok Singh
1e1ed16a05
doc: correct typos in documentation and comments (#11465)
This PR fixes various typos across the codebase in documentation and
comments.

- `infered` → `inferred` (ParserCompiler.lean)
- `declartation` → `declaration` (Cleanup.lean)
- `certian` → `certain` (CasesInfo.lean)
- `wil` → `will` (Cache.lean)
- `the the` → `the` (multiple files - PrefixTree.lean, Sum/Basic.lean,
List/Nat/Perm.lean, Time.lean, Bounded.lean, Lake files)
- `to to` → `to` (MutualInductive.lean, simp_bubblesort_256.lean)
- Grammar improvements in Bounded.lean and Time.lean

All changes are to comments and documentation only - no functional
changes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-02 06:38:05 +00:00
Kim Morrison
226a90f1eb
feat: exact? +grind and exact? +try? discharger options (#11469)
This PR adds `+grind` and `+try?` options to `exact?` and `apply?`
tactics.

## `+grind` option

When `+grind` is enabled, `grind` is used as a fallback discharger for
subgoals that `solve_by_elim` cannot close. The proof is wrapped in
`Grind.Marker` so suggestions display `(by grind)` instead of the
complex grind proof term.

Example:
```lean
axiom foo (x : Nat) : x < 37 → 5 < x → x.log2 < 6

/--
info: Try this:
  [apply] exact foo x (by grind) (by grind)
-/
#guard_msgs in
example (x : Nat) (h₁ : x < 30) (h₂ : 8 < x) : x.log2 < 6 := by
  exact? +grind
```

## `+try?` option

When `+try?` is enabled, `try?` is used as a fallback discharger for
subgoals. This is useful when subgoals require induction or other
strategies that `try?` can find but `solve_by_elim` and `grind` cannot.

Example:
```lean
inductive MyList (α : Type _) where
  | nil : MyList α
  | cons : α → MyList α → MyList α

axiom MyListProp : MyList α → Prop
@[grind .] axiom mylist_nil : MyListProp (MyList.nil : MyList α)
@[grind .] axiom mylist_cons : ∀ (x : α) (xs : MyList α), MyListProp xs → MyListProp (MyList.cons x xs)

axiom qux (xs : MyList α) (p : MyListProp xs) : MyListProp2 xs

/--
info: Try this:
  [apply] exact qux xs (by try?)
-/
example (xs : MyList α) : MyListProp2 xs := by
  exact? +try?
```

🤖 Prepared with Claude Code

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-02 06:31:56 +00:00
Kim Morrison
519ccf5d9d
feat: add solve_by_elim +suggestions (#11468)
This PR adds `+suggestions` support to `solve_by_elim`, following the
pattern established by `grind +suggestions` and `simp_all +suggestions`.

Gracefully handles invalid/nonexistent suggestions by filtering them out

🤖 Prepared with Claude Code

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-02 02:11:32 +00:00
Kim Morrison
1c1c534a03
feat: add solve_by_elim to try? tactic pipeline (#11462)
This PR adds `solve_by_elim` as a fallback in the `try?` tactic's simple
tactics. When `rfl` and `assumption` both fail but `solve_by_elim`
succeeds (e.g., for goals requiring hypothesis chaining or
backtracking), `try?` will now suggest `solve_by_elim`.

The structure is `first | (attempt_all | rfl | assumption) |
solve_by_elim`, so `solve_by_elim` only runs when the faster tactics
fail.

This is a prerequisite for removing the "first pass" `solve_by_elim`
from `apply?`. Currently `apply?` calls `solve_by_elim` twice: once
before library search, and once after each lemma application. The first
pass can be removed once `try?` includes `solve_by_elim`.

🤖 Prepared with Claude Code

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-02 02:09:59 +00:00
Kim Morrison
8b103f33cf
feat: remove solve_by_elim first pass from exact?/apply? (#11466)
This PR removes the "first pass" behavior where `exact?` and `apply?`
would try `solve_by_elim` on the original goal before doing library
search. This simplifies the `librarySearch` API and focuses these
tactics on their primary purpose: finding library lemmas.

Users who want to find proofs using local hypotheses should use `try?`
instead, which now includes `solve_by_elim` in its pipeline (see
https://github.com/leanprover/lean4/pull/11462).

Changes:
- Removed first pass from `librarySearch`
- Simplified `tactic` parameter from `Bool → List MVarId → MetaM (List
MVarId)` to `List MVarId → MetaM (List MVarId)`
- Updated test expectations

🤖 Prepared with Claude Code

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-02 02:05:27 +00:00
Kim Morrison
a0c8404ab8
fix: improve "no library suggestions engine registered" error message (#11464)
This PR improves the error message when no library suggestions engine is
registered to recommend importing `Lean.LibrarySuggestions.Default` for
the built-in engine.

**Before:**
```
No library suggestions engine registered. (Note that Lean does not provide a default library suggestions engine, these must be provided by a downstream library, and configured using `set_library_suggestions`.)
```

**After:**
```
No library suggestions engine registered. (Add `import Lean.LibrarySuggestions.Default` to use Lean's built-in engine, or use `set_library_suggestions` to configure a custom one.)
```

🤖 Prepared with Claude Code

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-02 00:55:46 +00:00
Sebastian Ullrich
96461a4b03
feat: recordIndirectModUse (#11437)
This PR adds recording functionality such that `shake` can more
precisely track whether an import should be preserved solely for its
`attribute` commands.
2025-12-01 20:02:38 +00:00
Henrik Böving
310abce62b
fix: boxing may have to correct let binder types (#11426)
This PR closes #11356.
2025-12-01 17:22:32 +00:00
Henrik Böving
5e165e358c
fix: better types when creating boxed decls (#11445)
This PR slightly improves the types involved in creating boxed
declarations. Previously the type of
the vdecl used for the return was always `tobj` when returning a boxed
scalar. This is not the most
precise annotation we can give.
2025-12-01 15:11:15 +00:00
Robert J. Simmons
429734c02f
feat: suggest deriving an instance when the instance might be derivable (#11346)
This PR modifies the error message for type synthesis failure for the
case where the type class in question is potentially derivable using a
`deriving` command. Also changes the error explanation for type class
instance synthesis failure with an illustration of this pattern.

## Example

```lean4
inductive MyColor where
  | chartreuse | sienna | thistle
def forceColor (oc : Option MyColor) :=
  oc.get!
```

Before this PR, this gives the potentially confusing impression that
Lean may have decided that `MyColor` is _not_ inhabited — people used to
Rust may be especially inclined towards this confusion.
```
failed to synthesize instance of type class
  Inhabited MyColor

Hint: Type class instance resolution failures can be inspected with the `set_option trace.Meta.synthInstance true` command.
```

After this PR, a targeted hint suggests precisely the command that will
fix the issue:
```
error: failed to synthesize instance of type class
  Inhabited MyColor

Hint: Adding the command `deriving instance Inhabited for MyColor` may allow Lean to derive the missing instance.
```
2025-12-01 14:28:15 +00:00
Joachim Breitner
f9dc77673b
feat: dedicated fix operator for well-founded recursion on Nat (#7965)
This PR lets recursive functions defined by well-founded recursion use a
different `fix` function when the termination measure is of type `Nat`.
This fix-point operator use structural recursion on “fuel”, initialized
by the given measure, and is thus reasonable to reduce, e.g. in `by
decide` proofs.

Extra provisions are in place that the fixpoint operator only starts
reducing when the fuel is fully known, to prevent “accidential” defeqs
when the remaining fuel for the recursive calls match the initial fuel
for that recursive argument.

To opt-out, the idiom `termination_by (n,0)` can be used.

We still use `@[irreducible]` as the default for such recursive
definitions, to avoid unexpected `defeq` lemmas. Making these functions
`@[semireducible]` by default showed performance regressions in lean.
When the measure is of type `Nat`, the system will accept an explicit
`@[semireducible]` without the usual warning.

Fixes #5234. Fixes: #11181.
2025-12-01 12:51:55 +00:00
Markus Himmel
1ae680c5e2
chore: minor String API improvements (#11439)
This PR performs minor maintenance on the String API

- Rename `String.Pos.toCopy` to `String.Pos.copy` to adhere to the
naming convention
- Rename `String.Pos.extract` to `String.extract` to get sane dot
notation again
- Add `String.Slice.Pos.extract`
2025-12-01 11:44:14 +00:00
David Thrane Christiansen
677561522d
fix: add missing import (#11441)
This PR fixes an issue that prevented the manual from building due to
the missing explanation of an error.
2025-12-01 11:02:03 +00:00