Commit graph

38589 commits

Author SHA1 Message Date
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
Lean stage0 autoupdater
9fc90488ce chore: update stage0 2025-11-19 08:40:32 +00:00
Markus Himmel
59949f89ee
chore: add function String.Pos.extract (#11251)
This PR is a preparatory bootstrapping PR for #11240.
2025-11-19 08:05:28 +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
Robert J. Simmons
d5ecca995f
chore: update some error explanations (#11225)
This PR updates some of the Error Explanations that had gotten out of
sync with actual error messages
2025-11-19 03:16:40 +00:00
Robert J. Simmons
f81e64936a
feat: improve error when an identifier is unbound because autoImplicit is off (#11119)
This PR introduces a clarifying note to "undefined identifier" error
messages when the undefined identifier is in a syntactic position where
autobinding might generally apply, but where and autobinding is
disabled. A corresponding note is made in the `lean.unknownIdentifier`
error explanation.

The core intended audience for this error message change is "newcomer
who would otherwise be baffled why the thing that works in this Mathlib
project gets 'unknown identifier' errors in this non-Mathlib project."

## Modified behavior

### Example 1
```lean4
set_option autoImplicit true in
set_option relaxedAutoImplicit false in
def thisBreaks (x : α₂) (y : size₂) := ()
```

Before:
```
Unknown identifier `size₂`
```

After:
```
Unknown identifier `size₂`

Note: It is not possible to treat `size₂` as an implicitly bound variable here because it has multiple characters while the `relaxedAutoImplicit` option is set to `false`.
```

### Example 2
```lean4
set_option autoImplicit false in
def thisAlsoBreaks (x : α₃) (y : size₃) := ()
```

Before:
```
Unknown identifier `α₃`
Unknown identifier `size₃`
```

After:
```
Unknown identifier `α₃`

Note: It is not possible to treat `α₃` as an implicitly bound variable here because the `autoImplicit` option is set to `false`.
Unknown identifier `size₃`

Note: It is not possible to treat `size₃` as an implicitly bound variable here because the `autoImplicit` option is set to `false`.
```

## How this works

The elaboration process knows whether it is considering syntax where we
be able to auto-bind implicits thanks to information in the
`Lean.Elab.Term.Context`.

Before this PR, this contains:
* `autoBoundImplicit`, a boolean that is true when we are considering
syntax that might be able to auto-bind implicit AND when the
`autoImplicit` flag is set to true
* `autoBoundImplicits`, an array of `Expr` variables that we've
autobound

After this PR, this contains:
* `autoBoundImplicitCtx`, an option which is `some` **whenever** we are
considering syntax that might be able to auto-bind implicit, and carries
the array of exprs as well as a copy of the `autoImplicit` flag's value.
(The latter lets us re-implement the `autoBoundImplicit` flag for
backward compatibility.)

Therefore, rather than having access to "elaboration is in an
autobinding context && flag is enabled", it's possible to recover both
of those individual values, and give different information to the user
in cases where we didn't attempt autobinding but would have if different
options had been set.

## Rationale

The revised error message avoids offering much guidance — it doesn't
actively suggest setting the option to a different value or suggest
adding an implicit binding. Care needs to be taken here to make sure
advice is not misleading; as the accepted RFC in #6462 points out, a
substantial portion of autobinding failures are just going to be
misspellings.

I considered and then rejected a code action here to that would add a
local `set_option autoImplicit true`. This seems undesirable or
counterproductive — if a project like Mathlib has proactively disabled
`autoImplicit`, its odd to be pushing local exceptions.

A hint prompting the user to add an implicit binding would be more
proper, but only in certain circumstances — we want to be conservative
in suggesting specific code actions! In a situation like this one, we'd
want to _avoid_ giving the suggestion of adding a `{HasArr}` binding,
which I think either requires tricky heuristics or means we'd want the
elaboration to play through the consequences of auto-binding and make
sure it doesn't cause any follow-on errors before suggesting adding an
implicit binding.

```
set_option autoImplicit true
set_option relaxedAutoImplicit false
instance has_arr : HasArr Preorder := { Arr := Function }
```

Additionally, it seems like it would make the most sense to offer to
auto-bind _all_ the relevant unknown identifiers at once. To avoid being
misleading, this too would seem to require playing through the
consequences of autobinding before being able to safely suggest the
change. This is enough additional complexity that I'm leaving it for
future work.

---------

Co-authored-by: David Thrane Christiansen <david@davidchristiansen.dk>
2025-11-19 03:11:34 +00:00
Mac Malone
5bb9839887
fix: symbol clashes between packages (#11082)
This PR prevents symbol clashes between (non-`@[export]`) definitions
from different Lean packages.

Previously, if two modules define a function with the same name and were
transitively imported (even privately) by some downstream module,
linking would fail due to a symbol clash. Similarly, if a user defined a
symbol with the same name as one in the `Lean` library, Lean would use
the core symbol even if one did not import `Lean`.

This is solved by changing Lean's name mangling algorithm to include an
optional package identifier. This identifier is provided by Lake via
`--setup` when building a module. This information is weaved through the
elaborator, interpreter, and compiler via a persistent environment
extension that associates modules with their package identifier.

With a package identifier, standard symbols have the form
`lp_<pkg-id>_<mangled-def>`. Without one, the old scheme is used (i.e.,
`l_<mangled-def>`). Module initializers are also prefixed with package
identifier (if any). For example, the initializer for a module `Foo` in
a package `test` is now `initialize_test_Foo` (instead of
`initialize_Foo`). Lake's default for native library names has also been
adjusted accordingly, so that libraries can still, by default, be used
as plugins. Thus, the default library name of the `lean_lib Foo` in
`package test` will now be `libtest_Foo`.

When using Lake to build the Lean core (i.e., `bootstrap = true`), no
package identifier will be used. Thus, definitions in user packages can
never have symbol clashes with core.

Closes #222.
2025-11-19 02:24:44 +00:00
Mac Malone
687698e79d
test: module clash across packages (#11246)
This PR adds a test that covers importing modules defined in multiple
packages.

Currently, will resolve the module to its first occurrence in the its
search order. However, this will soon change, so this test is designed
to analyze that behavior.
2025-11-19 02:23:34 +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
Markus Himmel
fa5d08b7de
refactor: use String.Slice in String.take and variants (#11180)
This PR redefines `String.take` and variants to operate on
`String.Slice`. While previously functions returning a substring of the
input sometimes returned `String` and sometimes returned
`Substring.Raw`, they now uniformly return `String.Slice`.

This is a BREAKING change, because many functions now have a different
return type. So for example, if `s` is a string and `f` is a function
accepting a string, `f (s.drop 1)` will no longer compile because
`s.drop 1` is a `String.Slice`. To fix this, insert a call to `copy` to
restore the old behavior: `f (s.drop 1).copy`.

Of course, in many cases, there will be more efficient options. For
example, don't write `f <| s.drop 1 |>.copy |>.dropEnd 1 |>.copy`, write
`f <| s.drop 1 |>.dropEnd 1 |>.copy` instead. Also, instead of `(s.drop
1).copy = "Hello"`, write `s.drop 1 == "Hello".toSlice` instead.
2025-11-18 16:13:48 +00:00
Markus Himmel
03eb2f73ac
chore: deprecate String.toSubstring (#11232)
This PR deprecates `String.toSubstring` in favor of
`String.toRawSubstring` (cf. #11154).
2025-11-18 13:50:50 +00:00
Wrenna Robson
36a6844625
feat: add Std.Trichotomous (#10945)
This PR adds `Std.Tricho r`, a typeclass for relations which identifies
them as trichotomous. This is preferred to `Std.Antisymm (¬ r · ·)` in
all cases (which it is equivalent to).
2025-11-18 13:20:53 +00:00
Lean stage0 autoupdater
4296f8deee chore: update stage0 2025-11-18 11:23:27 +00:00
Markus Himmel
e301f86c6c
chore: add String.Pos.next (#11238)
This PR is split from a future PR and adds the function
`String.Pos.next`, an alias (and soon to be correct name) of
`String.ValidPos.next`.

This is for boring bootstrapping reasons.
2025-11-18 10:41:22 +00:00
Jovan Gerbscheid
4c972ba0d6
fix: add missing s! in UInt64.fromJson? (#11237)
This PR fixes the error thrown by `UInt64.fromJson?` and
`USize.fromJson?` to use the missing `s!`.
2025-11-18 10:31:31 +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
Sebastian Graf
51ed5f247c
fix: register node kind for elabToSyntax functionality (#11235)
This PR registers a node kind for `Lean.Parser.Term.elabToSyntax` in
order to support the `Lean.Elab.Term.elabToSyntax` functionality without
registering a dedicated parser for user-accessible syntax.
2025-11-18 09:47:08 +00:00
Henrik Böving
1759b83929
test: regression test for #6332 (#11234)
Closes: #6332
2025-11-18 09:47:04 +00:00
Wojciech Różowski
e35d65174c
feat: add intersection on DHashMap (#11112)
This PR adds intersection operation on `DHashMap`/`HashMap`/`HashSet`
and provides several lemmas about its behaviour.

---------

Co-authored-by: Markus Himmel <markus@himmel-villmar.de>
2025-11-18 09:40:44 +00:00
Paul Reichert
1a4c3ca35d
refactor: small iterator improvements (#11175)
This PR removes duplicated instance parameters in the standard library
and flips lemmas of the form `toList_eq_toListIter` into a form that is
suitable for `simp`.
2025-11-18 09:28:55 +00:00
Lean stage0 autoupdater
1f807969b7 chore: update stage0 2025-11-18 09:08:13 +00:00
Wojciech Różowski
f46c17fa1d
feat: add lemmas for DHashMap/HashMap/HashSet about emptyWithCapacity/empty (#11223)
This PR adds missing lemmas relating `emptyWithCapacity`/`empty` and
`toList`/`keys`/`values` for `DHashMap`/`HashMap`/`HashSet`.
2025-11-18 08:17:16 +00:00
Kim Morrison
155db16572
chore: begin dev cycle for v4.27.0 (#11229)
Set LEAN_VERSION_MINOR to 27.
2025-11-18 08:12:49 +00:00
Markus Himmel
f6a9059709
chore: rename String.offsetOfPos to String.Pos.Raw.offsetOfPos (#11218)
This PR renames `String.offsetOfPos` to `String.Pos.Raw.offsetOfPos` to
align with the other `String.Pos.Raw` operations.
2025-11-18 07:24:06 +00:00
Sebastian Graf
59d2d00132
feat: turn a term elaborator into a syntax object with elabToSyntax (#11222)
This PR implements `elabToSyntax` for creating scoped syntax `s :
Syntax` for an arbitrary elaborator `el : Option Expr -> TermElabM Expr`
such that `elabTerm s = el`.

Roundtripping example implementing an elaborator imitating `let`:

```lean
elab "lett " decl:letDecl ";" e:term : term <= ty? => do
  let elabE (ty? : Option Expr) : TermElabM Expr := do elabTerm e ty?
  elabToSyntax elabE fun body => do
    elabTerm (← `(let $decl:letDecl; $body)) ty?

#guard lett x := 42; (x + 1) = 43
```
2025-11-18 07:10:31 +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
Mac Malone
81d716069c
fix: lake: improper uses of computeArtifact w/o text (#11216)
This PR ensures that the `text` argument of `computeArtifact` is always
provided in Lake code, fixing a hashing bug with
`buildArtifactUnlessUpToDate` in the process.

Closes #11209
2025-11-17 22:27:19 +00:00
Henrik Böving
033fa8c585
test: add additional regression test for #11131 from #10925 (#11224)
Closes #10925
2025-11-17 21:23:53 +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
Lean stage0 autoupdater
1c82929c34 chore: update stage0 2025-11-17 19:02:56 +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
Lean stage0 autoupdater
be6457284a chore: update stage0 2025-11-17 17:15:47 +00:00
Henrik Böving
07e6b99e2e
fix: deallocation for closures in non default configurations (#11217)
This PR fixes fallout of the closure allocator changes in #10982. As far
as we know
this bug only meaningfully manifests in non default build configurations
without mimalloc such as:
`cmake --preset release -DUSE_MIMALLOC=OFF`

The issue is that I forgot to update the deallocation functions for
closures. However, this only
seems to matter if we disable mimalloc which is why this slipped through
testing.
2025-11-17 16:27:20 +00:00
Paul Reichert
8eb0293098
feat: add MPL specs for slice for ... in (#11141)
This PR provides a polymorphic `ForIn` instance for slices and an MPL
`spec` lemma for the iteration over slices using `for ... in`. It also
provides a version specialized to `Subarray`.
2025-11-17 15:58:29 +00:00
Markus Himmel
8671f81aa5
fix: lakefile require syntax in package not found on Reservoir error (#11198)
This PR fixes an error message in Lake which suggested incorrect
lakefile syntax.

The error message (which was very helpful by the way) looked like this:
```
error: TwoFX/batteries: package not found on Reservoir.

  If the package is on GitHub, you can add a Git source. For example:

    require ...
      from git "https://github.com/TwoFX/batteries" @ git "main"

  or, if using TOML:

    [[require]]
    git = "https://github.com/TwoFX/batteries"
    rev = "main"
    ...
```

The suggested Lakefile syntax does not work. The correct syntax,
according to the reference manual and according to my tests, is
```
    require ...
      from git "https://github.com/TwoFX/batteries" @ "main"
```
without the second `git`.
2025-11-17 15:12:23 +00:00
David Thrane Christiansen
5ce1f67261
fix: module docstring header nesting in Verso format (#11215)
This PR fixes an issue where header nesting levels were properly tracked
between, but not within, moduledocs.
2025-11-17 13:57:00 +00:00
Henrik Böving
bef8574b93
fix: be more careful when recording cases in the compiler (#11210)
This PR fixes a bug in the LCNF simplifier unearthed while working on
#11078. In some situations caused by `unsafeCast`, the simplifier would
record incorrect information about `cases`, leading to further bugs down
the line.

Suppose we have `v : NonScalar` due to an `unsafeCast` and we run
`cases` on it, expecting `Prod.mk fst snd`. The current code attempts to
record both the arguments from the constructor application in the case
arm `fst`, `snd` and the parameters for the type by inspecting the discr
`v`. However, `NonScalar` does of course not have any parameters,
causing the simplifier to record wrong information. This patch makes the
`cases` infrastructure more cautious when extracting information from
the type of `v`.
2025-11-17 11:34:16 +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
Rob23oba
eba5a5a6ef
fix: consider over-applications in reduceArity compiler pass (#11185)
This PR fixes the `reduceArity` compiler pass to consider
over-applications to functions that have their arity reduced.
Previously, this pass assumed that the amount of arguments to
applications was always the same as the number of parameters in the
signature. This is usually true, since the compiler eagerly introduces
parameters as long as the return type is a function type, resulting in a
function with a return type that isn't a function type. However, for
dependent types that sometimes are function types and sometimes not,
this assumption is broken, resulting in the additional parameters to be
dropped.

Closes #11131
2025-11-17 07:51:37 +00:00
Kim Morrison
bba399eefe
chore: finish dealing with #grind_lint (#11207)
This ensures that no `grind` annotated theorem, simply by being
instantiated, causes a chain of >20 further instantiations, with a small
list of documented exceptions.
2025-11-17 06:58:28 +00:00
Kim Morrison
8b575dcbf2
chore: fixing grind annotations using #grind_lint (#11206)
Slightly more extensive version of #11205, for which I want separate CI.
2025-11-17 05:30:01 +00:00
Kim Morrison
d6f3ca24d3
chore: fixing grind annotations using #grind_lint (#11205) 2025-11-17 04:53:21 +00:00
Kim Morrison
8c7604f550
feat: try? runs tactics with separate heartbeats budgets (#11174)
This PR modifies the `try?` framework, so each subsidiary tactic runs
with a separate `maxHeartbeats` budget.

---------

Co-authored-by: Rob23oba <152706811+Rob23oba@users.noreply.github.com>
2025-11-17 01:30:43 +00:00
Kim Morrison
4b28713a44
feat: #grind_lint check produces a "Try this:" suggestion with #grind_list inspect commands (#11204)
This PR has `#grind_list check` produce a "Try this:" suggestion with
`#grind_list inspect` commands, as this is usually the next step in
dealing with problematic cases. We also fix the grind pattern for one
theorem, as part of testing the workflow. More to follow.
2025-11-17 00:52:57 +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
Sebastian Ullrich
0b93b3f182
chore: record uses of user-defined attributes as shake dependencies (#11202) 2025-11-16 20:34:23 +00:00
Sebastian Ullrich
ed34ee0cd5
chore: make declMetaExt persistent for shake (#11201) 2025-11-16 20:11:56 +00:00
Joachim Breitner
8ef742647e
test: benchmark for large partial match (#11199)
Creates an inductive data type with 100 constructors, and a function
that does
matches on half of its constructors, with a catch-all for the other
half, and generates the splitter.

Related to #11183.
2025-11-16 11:20:31 +00:00
Lean stage0 autoupdater
65a41c38a0 chore: update stage0 2025-11-16 10:13:26 +00:00