Commit graph

10021 commits

Author SHA1 Message Date
David Thrane Christiansen
c3f61ba3a2
chore: fix typo in test (#7460)
This PR fixes a minor typo in a test.
2025-03-12 16:43:35 +00:00
David Thrane Christiansen
eb58f46ce7
feat: language reference links and examples in docstrings (#7240)
This PR adds a canonical syntax for linking to sections in the language
reference along with formatting of examples in docstrings according to
the docstring style guide.


Docstrings are now pre-processed as follows:

* Output included as part of examples is shown with leading line comment
indicators in hovers

* URLs of the form `lean-manual://section/section-id` are rewritten to
links that point at the corresponding section in the Lean reference
manual. The reference manual's base URL is configured when Lean is built
and can be overridden with the `LEAN_MANUAL_ROOT` environment variable.
This way, releases can point documentation links to the correct
snapshot, and users can use their own, e.g. for offline reading.

Manual URLs in docstrings are validated when the docstring is added. The
presence of a URL starting with `lean-manual://` that is not a
syntactically valid section link causes the docstring to be rejected.
This allows for future extensibility to the set of allowed links. There
is no validation that the linked-to section actually exists. To provide
the best possible error messages in case of validation failures,
`Lean.addDocString` now takes a `TSyntax ``docComment` instead of a
string; clients should adapt by removing the step that extracts the
string, or by calling the lower-level `addDocStringCore` in cases where
the docstring in question is obtained from the environment and has thus
already had its links validated.

A stage0 update is required to make the documentation site configurable
at build time and for releases. A local commit on top of a stage0 update
that will be sent in a followup PR includes the configurable reference
manual root and updates to the release checklist.

---------

Co-authored-by: Marc Huisinga <mhuisi@protonmail.com>
2025-03-12 09:17:27 +00:00
Kim Morrison
c1d145e9d7
feat: revision of Nat/Int lemmas (#7435)
This PR reviews the `Nat` and `Int` API, making the interfaces more
consistent.
2025-03-12 05:52:09 +00:00
Henrik Böving
2952cf81e6
feat: bv_decide rewrites for concatenation and extraction (#7441)
This PR adds the BV_CONCAT_CONST, BV_CONCAT_EXTRACT and ELIM_ZERO_EXTEND
rule from Bitwuzla to bv_decide.
2025-03-11 22:24:05 +00:00
Sebastian Ullrich
7c5b423659
chore: unconditionally re-enable realizeConst (#7334)
To be merged when Mathlib adaption passes
2025-03-11 16:39:17 +00:00
Henrik Böving
1731f2f850
feat: add more constant related rewrites to bv_decide (#7438)
This PR adds the EQUAL_CONST_BV_ADD and BV_AND_CONST rules to
bv_decide's preprocessor.
2025-03-11 13:37:12 +00:00
Henrik Böving
bb47469d1a
feat: add simprocs for turning shifts by constants into extracts to bv_decide (#7436)
This PR adds simprocs that turn left and right shifts by constants into
extracts to bv_decide.
2025-03-11 10:09:16 +00:00
Parth Shastri
7c0b72e2c5
fix: make the Subsingleton instance for Squash work for an arbitrary Sort (#7406)
This PR makes the instance for `Subsingleton (Squash α)` work for `α :
Sort u`.

Closes #7405

The fix removes some unused `section`/`variable` commands. They were
mistakenly kept when `EqvGen` was removed in 1d338c4.
2025-03-11 08:41:30 +00:00
Henrik Böving
0af15f9b1d
feat: bv_decide add BV_EXTRACT_FULL preprocessing rule (#7429)
This PR adds the BV_EXTRACT_FULL preprocessing rule from Bitwuzla to
bv_decide.
2025-03-10 22:08:59 +00:00
jrr6
acfc11ae42
fix: correctly collect let-rec fvars through delayed-assigned mvar (#7304)
This PR fixes an issue where nested `let rec` declarations within
`match` expressions or tactic blocks failed to compile if they were
nested within, and recursively called, a `let rec` that referenced a
variable bound by a containing declaration.

Closes #6927

---------

Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>
2025-03-10 18:13:48 +00:00
Joachim Breitner
829522ba55
test: expand f91 test (#7421) 2025-03-10 17:15:54 +00:00
Henrik Böving
e0fa6a1792
feat: bv_decide support enum inductive matches with default branches (#7417)
This PR adds support for enum inductive matches with default branches to
bv_decide.
2025-03-10 14:05:04 +00:00
Joachim Breitner
754bab442a
feat: omega to abstract its own proofs (#5998)
This PR lets `omega` always abstract its own proofs into an auxiliary
definition. The size of the olean of Vector.Extract goes down from 20MB
to 5MB with this, overall stdlib olean size and build instruction count
go down 5%.

Needs #7362.
2025-03-10 12:39:30 +00:00
Markus Himmel
7bfa8f6296
feat: finite type conversions (Nat/Int/Fin/BitVec -> IntX -> *) (#7368)
This PR adds lemmas for iterated conversions between finite types,
starting with something of type `Nat`/`Int`/`Fin`/`BitVec` and going
through `IntX`.
2025-03-10 05:53:41 +00:00
Leonardo de Moura
84c7e5db1f
test: cutsat (#7411) 2025-03-10 03:30:36 +00:00
Joachim Breitner
c797525d2a
fix: WellFounded preprocessing: use dsimp (#7409)
This PR allows the use of `dsimp` during preprocessing of well-founded
definitions. This fixes regressions when using `if-then-else` without
giving a name to the condition, but where the condition is needed for
the termination proof, in cases where that subexpression is reachable
only by dsimp, but not by simp (e.g. inside a dependent let)

Also fixes some preprocessing lemmas to not be bad simp lemmas (with
lambdas on the LHS, due to dot notation and unfortunate argument order)

This fixes #7408.
2025-03-09 22:19:16 +00:00
Henrik Böving
0714a7150b
feat: add more multiplication lemmas to bv_normalize (#7407)
This PR adds rules for `-1#w * a = -a` and `a * -1#w = -a` to
bv_normalize as seen in Bitwuzla's BV_MUL_SPECIAL_CONST.

This allows us to solve 
```lean
example {a : BitVec 32} : a + -1 * a = 0 := by bv_normalize
```
which would previously time out.
2025-03-09 18:14:30 +00:00
Leonardo de Moura
da2d877019
fix: cutsat conflict resolution bug (#7403) 2025-03-09 03:58:30 +00:00
Leonardo de Moura
09161f6fdd
chore: remove workaround (#7402) 2025-03-09 01:46:17 +00:00
Leonardo de Moura
8dc3c53240
feat: tight inequalities using divisibility constraints in cutsat (#7401)
This PR improves the cutsat model search procedure by tightening
inequalities using divisibility constraints.
2025-03-09 00:23:32 +00:00
Cameron Zwarich
8d0093b43f
fix: properly handle scoping of join point candidates in cce (#7398)
This PR fixes a scoping error in the cce (Common Case Elimination) pass
of the old code generator. This pass would create a join point for
common minor premises even if some of those premises were in the bodies
of locally defined functions, which results in an improperly scoped
reference to a join point. The fix is to save/restore candidates when
visiting a lambda.
2025-03-08 18:10:41 +00:00
Leonardo de Moura
d07897fc36
fix: Poly.mul p 0 (#7397)
This PR ensures that `Poly.mul p 0` always returns `Poly.num 0`.
2025-03-08 16:57:13 +00:00
Leonardo de Moura
bfe8e5a958
fix: bug in cutsat model construction (#7396)
This PR fixes a bug in the cutsat model construction. It was searching
for a solution in the wrong direction.
2025-03-08 15:58:20 +00:00
Leonardo de Moura
0d3ae7fde5
feat: infrastructure for supporting Nat in cutsat (#7394)
This PR adds infrastructure necessary for supporting `Nat` in the cutsat
procedure. It also makes the `grind` more robust.
2025-03-08 08:36:58 +00:00
Leonardo de Moura
565c6f3eb2
fix: if-then-else split + normalization issue in grind (#7392)
This PR fixes an issue in the `grind` tactic when case splitting on
if-then-else expressions.

It adds a new marker gadget that prevents `grind` for re-normalizing the
condition `c` of an if-then-else
expression. Without this marker, the negated condition `¬c` might be
rewritten into
an alternative form `c'`, which `grind` may not recognize as equivalent
to `¬c`.
As a result, `grind` could fail to propagate that `if c then a else b`
simplifies to `b`
in the `¬c` branch.
2025-03-07 23:05:59 +00:00
Henrik Böving
77ae842496
feat: bv_decide remove casts (#7390)
This PR makes bv_decide's preprocessing handle casts, as we are in the
constant BitVec fragment we should be able to always remove them using
BitVec.cast_eq.
2025-03-07 22:40:53 +00:00
Marc Huisinga
dc5eb40ca3
feat: 'unsolved goals' & 'goals accomplished' diagnostics (#7366)
This PR adds server-side support for dedicated 'unsolved goals' and
'goals accomplished' diagnostics that will have special support in the
Lean 4 VS Code extension. The special 'unsolved goals' diagnostic is
adapted from the 'unsolved goals' error diagnostic, while the 'goals
accomplished' diagnostic is issued when a `theorem` or `Prop`-typed
`example` has no errors or `sorry`s. The Lean 4 VS Code extension
companion PR is at leanprover/vscode-lean4#585.

Specifically, this PR extends the diagnostics served by the language
server with the following fields:
- `leanTags`: Custom tags that denote the kind of diagnostic that is
being served. As opposed to the `code`, `leanTags` should never be
displayed in the UI. Examples introduced by this PR are a tag to
distinguish 'unsolved goals' errors from other diagnostics, as well as a
tag to distinguish the new 'goals accomplished' diagnostic from other
diagnostics.
- `isSilent`: Whether a diagnostic should not be displayed as a regular
diagnostic in the editor. In VS Code, this means that the diagnostic is
displayed in the InfoView under 'Messages', but that it will not be
displayed under 'All Messages' and that it will also not be displayed
with a squiggly line.

The `isSilent` field is also implemented for `Message` so that silent
diagnostics can be logged in the elaborator. All code paths except for
the language server that display diagnostics to users are adjusted to
filter `Message`s with `isSilent := true`.
2025-03-07 13:50:56 +00:00
Henrik Böving
20571a938b
feat: bv_decide support for simple pattern matching on enum inductives (#7329)
This PR adds support to bv_decide for simple pattern matching on enum
inductives. By simple we mean non dependent match statements with all
arms written out.

This PR enables use cases such as:
```lean
namespace PingPong

inductive Direction where
  | goingDown
  | goingUp

structure State where
  val : BitVec 16
  low : BitVec 16
  high : BitVec 16
  direction : Direction

def State.step (s : State) : State :=
  match s.direction with
  | .goingDown =>
    if s.val = s.low then
      { s with direction := .goingUp }
    else
      { s with val := s.val - 1 }
  | .goingUp =>
    if s.val = s.high then
      { s with direction := .goingDown }
    else
      { s with val := s.val + 1 }

def State.steps (s : State) (n : Nat) : State :=
  match n with
  | 0 => s
  | n + 1 => (State.steps s n).step

def Inv (s : State) : Prop := s.low ≤ s.val ∧ s.val ≤ s.high ∧ s.low < s.high

example (s : State) (h : Inv s) (n : Nat) : Inv (State.steps s n) := by
  induction n with
  | zero => simp only [State.steps, Inv] at *; bv_decide
  | succ n ih =>
    simp only [State.steps, State.step, Inv] at *
    bv_decide
```

There is an important thing to consider in this implementation. As the
enums pass can now deal with control flow there is a tension between the
structures and enums pass at play:
1. Enums should run before structures as it could convert matches on
enums into `cond`
chains. This in turn can be used by the structures pass to float
projections into control
   flow which might be necessary.
2. Structures should run before enums as it could reveal new facts about
enums that we might
need to handle. For example a structure might contain a field that
contains a fact about
   some enum. This fact needs to be processed properly by the enums pass

To resolve this tension we do the following:
1. Run the structures pass (if enabled)
2. Run the enums pass (if enabled)
3. Within the enums pass we rerun the part of the structures pass (if
enabled) that could profit from the
enums pass as described above. This comes down to adding a few more
lemmas to a simp
invocation that is going to happen in the enums pass anyway and should
thus be cheap.
2025-03-07 09:23:48 +00:00
Leonardo de Moura
e9f2e1861e
feat: cutsat missing case: disequality+inequality+divisibility conflict (#7373)
This PR implements the last missing case for the cutsat procedure and
fixes a bug. During model construction, we may encounter a bounded
interval containing integer solutions that satisfy the divisibility
constraint but fail to satisfy known disequalities.
2025-03-07 01:36:29 +00:00
Leonardo de Moura
905b2eedcd
test: cutsat (#7372)
Additional tests for cutsat
2025-03-07 00:31:49 +00:00
JovanGerb
11aff52fb1
fix: abstractNestedProofs should see into the head of an application (#7353)
This PR changes `abstractNestedProofs` so that it also visits the
subterms in the head of an application.

This oversight caused some definitions in mathlib to have unabstracted
proofs, such as
[CategoryTheory.StructuredArrow.commaMapEquivalenceInverse](https://leanprover-community.github.io/mathlib4_docs/Mathlib/CategoryTheory/Comma/StructuredArrow/CommaMap.html#CategoryTheory.StructuredArrow.commaMapEquivalenceInverse)

Mathlib
[bench](https://github.com/leanprover-community/mathlib4/pull/22613#issuecomment-2704288815):
build instructions -0,166 %
lint instructions -0.72 %

This speedup comes from files containing `CategoryTheory.Functor`, which
contains beta unreduced expressions, where abstracting proofs used to
not happen.

Zulip:
https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/dsimp.20simplifies.20proofs.2C.20which.20is.20slow/near/503630173
2025-03-06 20:08:38 +00:00
Leonardo de Moura
b958109d06
feat: let-decls for polynomials in cutsat proof terms (#7369)
This PR uses `let`-declarations for each polynomial occurring in a proof
term generated by the cutsat procedure.
2025-03-06 18:34:26 +00:00
Joachim Breitner
20d191bc8e
fix: allow simp dischargers to add aux decls to the environment (#7362)
This PR allows simp dischargers to add aux decls to the environment.
This enables tactics like `native_decide` to be used here, and unblocks
improvements to omega in #5998.

Fixes #7318
2025-03-06 16:00:59 +00:00
Leonardo de Moura
061ebe1dca
feat: mod and div in cutsat (#7357)
This PR adds support for `/` and `%` to the cutsat procedure.
2025-03-06 04:15:28 +00:00
Leonardo de Moura
7a8c8a4fb3
fix: markNestedProofs (#7355)
This PR fixes a bug in the `markNestedProofs` preprocessor used in the
`grind` tactic.
2025-03-06 00:51:13 +00:00
Leonardo de Moura
3ff10c6cdd
test: cutsat cooper resolution (#7354) 2025-03-06 00:40:38 +00:00
Leonardo de Moura
9ae2ac39c9
feat: avoid cooper case analysis for univariate polynomials (#7351)
This PR ensures cutsat does not have to perform case analysis in the
univariate polynomial case. That it, it can close a goal whenever there
is no solution for a divisibility constraint in an interval. Example of
theorem that is now proved in a single step by cutsat:
```lean
example (x : Int) : 100 ≤ x → x ≤ 10000 → 20000 ∣ 3*x → False := by
  grind
```
2025-03-05 20:37:29 +00:00
Wojciech Rozowski
2c8fb9d3fc
fix: strip optional parameters when elaborating the termination hints (#7335)
This PR modifies `elabTerminationByHints` in a way that the type of the
recursive function used for elaboration of the termination measure is
striped of from optional parameters. It prevents introducing
dependencies between the default values for arguments, that can cause
the termination checker to fail.

Closes https://github.com/leanprover/lean4/issues/6351.
2025-03-05 18:15:49 +00:00
Sebastian Ullrich
72c4630aab
feat: use realizeConst for all equation and unfold theorems (#7348)
This PR ensures all equation and unfold theorem generators in core are
compatible with parallelism.
2025-03-05 14:56:50 +00:00
Leonardo de Moura
f312170f21
feat: cooper resolution in cutsat (#7339)
This PR implements cooper conflict resolution in the cutsat procedure.
It also fixes several bugs in the proof term construction. We still need
to add more tests, but we can already solve the following example that
`omega` fails to solve:
```lean
example (x y : Int) :
    27 ≤ 11*x + 13*y →
    11*x + 13*y ≤ 45 →
    -10 ≤ 7*x - 9*y →
    7*x - 9*y ≤ 4 → False := by
  grind
```
2025-03-05 03:37:45 +00:00
Joachim Breitner
f45c19b428
feat: identify more fixed parameters (#7166)
This PR extends the notion of “fixed parameter” of a recursive function
also to parameters that come after varying function. The main benefit is
that we get nicer induction principles.


Before the definition

```lean
def app (as : List α) (bs : List α) : List α :=
  match as with
  | [] => bs
  | a::as => a :: app as bs
```

produced

```lean
app.induct.{u_1} {α : Type u_1} (motive : List α → List α → Prop) (case1 : ∀ (bs : List α), motive [] bs)
  (case2 : ∀ (bs : List α) (a : α) (as : List α), motive as bs → motive (a :: as) bs) (as bs : List α) : motive as bs
```
and now you get
```lean
app.induct.{u_1} {α : Type u_1} (motive : List α → Prop) (case1 : motive [])
  (case2 : ∀ (a : α) (as : List α), motive as → motive (a :: as)) (as : List α) : motive as
```
because `bs` is fixed throughout the recursion (and can completely be
dropped from the principle).

This is a breaking change when such an induction principle is used
explicitly. Using `fun_induction` makes proof tactics robust against
this change.

The rules for when a parameter is fixed are now:

1. A parameter is fixed if it is reducibly defq to the the corresponding
argument in each recursive call, so we have to look at each such call.
2. With mutual recursion, it is not clear a-priori which arguments of
another function correspond to the parameter. This requires an analysis
with some graph algorithms to determine.
3. A parameter can only be fixed if all parameters occurring in its type
are fixed as well.
This dependency graph on parameters can be different for the different
functions in a recursive group, even leading to cycles.
4. For structural recursion, we kinda want to know the fixed parameters
before investigating which argument to actually recurs on. But once we
have that we may find that we fixed an index of the recursive
parameter’s type, and these cannot be fixed. So we have to un-fix them
5. … and all other fixed parameters that have dependencies on them.

Lean tries to identify the largest set of parameters that satisfies
these criteria.

Note that in a definition like
```lean
def app : List α → List α → List α
  | [], bs => bs
  | a::as, bs => a :: app as bs
```
the `bs` is not considered fixes, as it goes through the matcher
machinery.


Fixes #7027
Fixes #2113
2025-03-04 22:26:20 +00:00
Joachim Breitner
e2ee629022
fix: allow aux decls to be generated by decreasing_by tactics (#7333)
This PR allows aux decls (like generated by `match`) to be generated by
decreasing_by tactics.

Fixes #7332.
2025-03-04 18:42:36 +00:00
Joachim Breitner
23b5baa5ec
feat: WF/Fix.lean: only refine fix’s ih for atomic discriminant onlys (#7324)
This PR changes the internal construction of well-founded recursion, to
not change the type of `fix`’s induction hypothesis in non-defeq ways.

Fixes #7322 and hopefully unblocks #7166.
2025-03-04 13:49:01 +00:00
Kim Morrison
88edd13642
feat: alignment of Int.ediv/fdiv/tdiv lemmas (#7319)
This PR continues alignment of lemmas about `Int.ediv/fdiv/tdiv`,
including adding notes about "missing" lemmas that do not apply in one
case. Also lemmas about `emod/fmod/tmod`. There's still more to do.
2025-03-04 10:41:01 +00:00
Henrik Böving
017a1f2b94
fix: bv_decide structures pass instantiate mvars (#7309)
This PR fixes a bug where bv_decide's new structure support would
sometimes not case split on all available structure fvars as their type
was an mvar.
2025-03-03 21:27:53 +00:00
Sebastian Ullrich
8e47d29bf9
feat: debug_assert! (#7256)
This PR introduces the `assert!` variant `debug_assert!` that is
activated when compiled with `buildType` `debug`.

---------

Co-authored-by: Mac Malone <tydeu@hatpress.net>
2025-03-03 16:34:44 +00:00
jrr6
e337129108
fix: move auxDeclToFullName to LocalContext to fix name (un)resolution (#7075)
This PR ensures that names suggested by tactics like `simp?` are not
shadowed by auxiliary declarations in the local context and that names
of `let rec` and `where` declarations are correctly resolved in tactic
blocks.

This PR contains the following potentially breaking changes:
* Moves the `auxDeclToFullName` map from `TermElab.Context` to
`LocalContext`.
* Refactors `Lean.Elab.Term.resolveLocalName : Name → TermElabM …` to
`Lean.resolveLocalName [MonadResolveName m] [MonadEnv m] [MonadLCtx m] :
Name → m …`.
* Refactors the `TermElabM` action `Lean.Elab.Term.withAuxDecl` to a
monad-polymorphic action `Lean.Meta.withAuxDecl`.
* Adds an optional `filter` argument to `Lean.unresolveNameGlobal`.

Closes #6706, closes #7073.
2025-03-03 16:10:54 +00:00
Markus Himmel
d2239a5770
feat: IntX simprocs (#7228)
This PR adds simprocs to reduce expressions involving `IntX`.
2025-03-03 13:37:57 +00:00
Henrik Böving
783671261d
feat: bv_decide add rewrites around ite + operations (#7298)
This PR adds rewrites to bv_decide's preprocessing that concern
combinations of if-then-else and operation such as multiplication or
negation.
2025-03-03 10:51:19 +00:00
Sebastian Ullrich
01d951c3fc
fix: cancel computations within command elaboration as soon as reuse is ruled out (#7241)
The other part of #7175
2025-03-03 10:37:10 +00:00