Commit graph

26207 commits

Author SHA1 Message Date
Cameron Zwarich
89752e2242
fix: support compiling casesOn recursors of subsingleton predicates (#9977)
This PR adds support for compilation of `casesOn` recursors of
subsingleton predicates.

Fixes #9963.
2025-08-19 00:23:24 +00:00
Cameron Zwarich
b8fa6f17ee
fix: make lcAny-producing arrow types lower to tobj rather than obj (#9972)
This PR fixes an issue when running Mathlib's `FintypeCat` as code,
where an erased type former is passed to a polymorphic function. We were
lowering the arrow type to`object`, which conflicts with the runtime
representation of an erased value as a tagged scalar.
2025-08-18 22:18:26 +00:00
Sebastian Graf
1b0d83e7fc
fix: remove local Triple notation from SpecLemmas.lean to fix stage2 (#9967)
This PR removes local `Triple` notation from SpecLemmas.lean to work
around a bug that breaks the stage2 build.
2025-08-18 16:41:26 +00:00
Wojciech Rozowski
2d52d44710
feat: fixpoint_induct and partial_correctness lemmas for mutual blocks come in conjunction and projected variants (#9651)
This PR modifies the generation of induction and partial correctness
lemmas for `mutual` blocks defined via `partial_fixpoint`. Additionally,
the generation of lattice-theoretic induction principles of functions
via `mutual` blocks is modified for consistency with `partial_fixpoint`.

The lemmas now come in two variants:
1. A conjunction variant that combines conclusions for all elements of
the mutual block. This is generated only for the first function inside
of the mutual block.
2. Projected variants for each function separately

## Example 1
```lean4
axiom A : Type
axiom B : Type

axiom A.toB : A → B
axiom B.toA : B → A

mutual
noncomputable def f : A := g.toA
partial_fixpoint
noncomputable def g : B := f.toB
partial_fixpoint
end
```

Generated `fixpoint_induct` lemmas:
```lean4
f.fixpoint_induct (motive_1 : A → Prop) (motive_2 : B → Prop) (adm_1 : admissible motive_1)
  (adm_2 : admissible motive_2) (h_1 : ∀ (g : B), motive_2 g → motive_1 g.toA)
  (h_2 : ∀ (f : A), motive_1 f → motive_2 f.toB) : motive_1 f

g.fixpoint_induct (motive_1 : A → Prop) (motive_2 : B → Prop) (adm_1 : admissible motive_1)
  (adm_2 : admissible motive_2) (h_1 : ∀ (g : B), motive_2 g → motive_1 g.toA)
  (h_2 : ∀ (f : A), motive_1 f → motive_2 f.toB) : motive_2 g
```

Mutual (conjunction) variant:
```lean4
f.mutual_fixpoint_induct (motive_1 : A → Prop) (motive_2 : B → Prop) (adm_1 : admissible motive_1) (adm_2 : admissible motive_2)
  (h_1 : ∀ (g : B), motive_2 g → motive_1 g.toA) (h_2 : ∀ (f : A), motive_1 f → motive_2 f.toB) :
  motive_1 f ∧ motive_2 g
```

## Example 2 
```lean4
mutual
  def f (n : Nat) : Option Nat :=
    g (n + 1)
  partial_fixpoint

  def g (n : Nat) : Option Nat :=
    if n = 0 then .none else f (n + 1)
  partial_fixpoint
end
```
Generated `partial_correctness` lemmas (in a projected variant):
```lean4
f.partial_correctness (motive_1 motive_2 : Nat → Nat → Prop)
  (h_1 :
    ∀ (g : Nat → Option Nat),
      (∀ (n r : Nat), g n = some r → motive_2 n r) → ∀ (n r : Nat), g (n + 1) = some r → motive_1 n r)
  (h_2 :
    ∀ (f : Nat → Option Nat),
      (∀ (n r : Nat), f n = some r → motive_1 n r) →
        ∀ (n r : Nat), (if n = 0 then none else f (n + 1)) = some r → motive_2 n r)
  (n r✝ : Nat) : f n = some r✝ → motive_1 n r✝

g.partial_correctness (motive_1 motive_2 : Nat → Nat → Prop)
  (h_1 :
    ∀ (g : Nat → Option Nat),
      (∀ (n r : Nat), g n = some r → motive_2 n r) → ∀ (n r : Nat), g (n + 1) = some r → motive_1 n r)
  (h_2 :
    ∀ (f : Nat → Option Nat),
      (∀ (n r : Nat), f n = some r → motive_1 n r) →
        ∀ (n r : Nat), (if n = 0 then none else f (n + 1)) = some r → motive_2 n r)
  (n r✝ : Nat) : g n = some r✝ → motive_2 n r✝
```

Mutual (conjunction) variant:
```
f.mutual_partial_correctness (motive_1 motive_2 : Nat → Nat → Prop)
  (h_1 :
    ∀ (g : Nat → Option Nat),
      (∀ (n r : Nat), g n = some r → motive_2 n r) → ∀ (n r : Nat), g (n + 1) = some r → motive_1 n r)
  (h_2 :
    ∀ (f : Nat → Option Nat),
      (∀ (n r : Nat), f n = some r → motive_1 n r) →
        ∀ (n r : Nat), (if n = 0 then none else f (n + 1)) = some r → motive_2 n r) :
  (∀ (n r : Nat), f n = some r → motive_1 n r) ∧ ∀ (n r : Nat), g n = some r → motive_2 n r
```
2025-08-18 15:26:30 +00:00
Kyle Miller
af5322c7ef
feat: tactic info per intro hypothesis, rfl pattern (#9942)
This PR modifies `intro` to create tactic info localized to each
hypothesis, making it possible to see how `intro` works
variable-by-variable. Additionally:
- The tactic supports `intro rfl` to introduce an equality and
immediately substitute it, like `rintro rfl` (recall: the `rfl` pattern
is like doing `intro h; subst h`). The `rintro` tactic can also now
support `HEq` in `rfl` patterns if `eq_of_heq` applies.
- In `intro (h : t)`, elaboration of `t` is interleaved with unification
with the type of `h`, which prevents default instances from causing
unification to fail.
- Tactics that change types of hypotheses (including `intro (h : t)`,
`delta`, `dsimp`) now update the local instance cache.

In `intro x y z`, tactic info ranges are `intro x`, `y`, and `z`. The
reason for including `intro` with `x` is to make sure the info range is
"monotonic" while adding the first argument to `intro`.
2025-08-18 13:55:06 +00:00
Kyle Miller
3af9cc3f6f
doc: extend docstrings for let/have tactics (#9956)
This PR adds additional information to the `let` and `have` tactic
docstrings about opaqueness, when to use each, and associated tactics.
2025-08-18 13:48:08 +00:00
Rob23oba
688b930bad
feat: tree map lemmas for filter, map, filterMap (#9632)
This PR adds lemmas for the `TreeMap` operations `filter`, `map` and
`filterMap`. These lemmas existed already for hash maps and are simply
ported over from there.
2025-08-18 12:13:52 +00:00
Tom Levy
04f9baf4d3
fix: remove dependency on LawfulBEq from List.lookup lemmas (#9949)
This PR allows most of the `List.lookup` lemmas to be used when
`LawfulBEq α` is not available.

`LawfulBEq` is very strong. Most of the lemmas don't actually require it
-- some only require `ReflBEq`, and only `List.lookup_eq_some_iff`
actually requires `LawfulBEq`.
2025-08-18 10:16:30 +00:00
Johannes Tantow
19301f83eb
feat: verify toArray for hash maps (#9685)
This PR verifies `toArray` and related functions for hashmaps.
2025-08-18 09:39:44 +00:00
Markus Himmel
2e6c1a74e5
chore: move String.Pos operations out of Prelude (#9845)
This PR moves arithmetic of `String.Pos` out of the prelude.

Other `String` declarations are part of the prelude because they are
generated by macros, but this does not seem to be the case for these.
2025-08-18 09:23:02 +00:00
Henrik Böving
48a8dd4a56
fix: print mathlib toolchain URL properly (#9962)
This PR makes lake print the error message it intended for when fetching
the mathlib toolchain
fails.
2025-08-18 08:11:50 +00:00
Sebastian Ullrich
a805e7e12c
chore: avoid turning accesses to private decs from public signatures into auto implicits (#9961) 2025-08-18 08:01:12 +00:00
Jason Yuen
3c702f38ee
chore: add a missing backtick (#9959)
This PR adds a backtick and fixes the docs for `section`.
2025-08-18 07:48:05 +00:00
Kyle Miller
fd926cc44e
feat: clean up type annotations when elaborating declaration bodies (#9674)
This PR cleans up `optParam`/`autoParam`/etc. annotations before
elaborating definition bodies, theorem bodies, `fun` bodies, and `let`
function bodies. Both `variable`s and binders in declaration headers are
supported.

There are no changes to `inductive`/`structure`/`axiom`/etc. processing,
just `def`/`theorem`/`example`/`instance`.
2025-08-18 04:43:20 +00:00
Leonardo de Moura
f5bab3c8ba
feat: grind cutsat equations in solved form (#9958)
This PR ensures that equations in the `grind cutsat` module are
maintained in solved form. That is, given an equation `a*x + p = 0` used
to eliminate `x`, the linear polynomial `p` must not contain other
eliminated variables. Before this PR, equations were maintained in
triangular form. We are going to use the solved form to linearize
nonlinear terms.
2025-08-18 01:34:37 +00:00
Leonardo de Moura
973885d087
chore: remove NullCert leftovers (#9955) 2025-08-18 00:07:23 +00:00
Leonardo de Moura
a4496a4a6b
chore: remove grind +ringNull option (#9954)
This PR removes the option `grind +ringNull`. It provided an alternative
proof term construction for the `grind ring` module, but it was less
effective than the default proof construction mode and had effectively
become dead code.
This PR also optimizes semiring normalization proof terms using the
infrastructure added in #9946.
**Remark:** After updating stage0, we can remove several background
theorems from the `Init/Grind` folder.
2025-08-17 23:04:59 +00:00
Sebastian Ullrich
81a4b0ca99
chore: fix failing mk*Sorry in bootstrapping contexts (#9950) 2025-08-17 16:14:53 +00:00
Leonardo de Moura
6f7dba167a
feat: trim grind linarith proof context (#9947)
This PR optimizes the proof terms produced by `grind linarith`. It is
similar to #9945, but for the `linarith` module in `grind`.
It removes unused entries from the context objects when generating the
final proof, significantly reducing the amount of junk in the resulting
terms.
2025-08-17 05:32:40 +00:00
Leonardo de Moura
0cc0de9e51
feat: trim grind ring proof context (#9946)
This PR optimizes the proof terms produced by `grind ring`. It is
similar to #9945, but for the ring module in `grind`.
It removes unused entries from the context objects when generating the
final proof, significantly reducing the amount of junk in the resulting
terms. Example:
```lean
/--
trace: [grind.debug.proof] fun h h_1 h_2 h_3 =>
      Classical.byContradiction fun h_4 =>
        let ctx := RArray.branch 1 (RArray.leaf x) (RArray.leaf x⁻¹);
        let e_1 := (Expr.var 0).mul (Expr.var 1);
        let e_2 := Expr.num 0;
        let e_3 := Expr.num 1;
        let e_4 := (Expr.var 0).pow 2;
        let m_1 := Mon.mult (Power.mk 1 1) Mon.unit;
        let m_2 := Mon.mult (Power.mk 0 1) Mon.unit;
        let p_1 := Poly.num (-1);
        let p_2 := Poly.add (-1) (Mon.mult (Power.mk 0 1) Mon.unit) (Poly.num 0);
        let p_3 := Poly.add 1 (Mon.mult (Power.mk 0 2) Mon.unit) (Poly.num 0);
        let p_4 := Poly.add 1 (Mon.mult (Power.mk 0 1) (Mon.mult (Power.mk 1 1) Mon.unit)) (Poly.num (-1));
        let p_5 := Poly.add 1 (Mon.mult (Power.mk 0 1) Mon.unit) (Poly.num 0);
        one_eq_zero_unsat ctx p_1 (eagerReduce (Eq.refl true))
          (Stepwise.simp ctx 1 p_4 (-1) m_1 p_5 p_1 (eagerReduce (Eq.refl true))
            (Stepwise.core ctx e_1 e_3 p_4 (eagerReduce (Eq.refl true)) (diseq0_to_eq x h_4))
            (Stepwise.mul ctx p_2 (-1) p_5 (eagerReduce (Eq.refl true))
              (Stepwise.superpose ctx 1 m_2 p_4 (-1) m_1 p_3 p_2 (eagerReduce (Eq.refl true))
                (Stepwise.core ctx e_1 e_3 p_4 (eagerReduce (Eq.refl true)) (diseq0_to_eq x h_4))
                (Stepwise.core ctx e_4 e_2 p_3 (eagerReduce (Eq.refl true)) h))))
-/
#guard_msgs in -- Context should contains only `x` and its inverse.
set_option trace.grind.debug.proof true in
set_option pp.structureInstances false in
open Lean Grind CommRing in
example [Field α] (x y z w : α) :
   x^2 = 0 → y^2 = 0 → z^3 = 0 → w^2 = 0 → x = 0 := by
  grind
```
2025-08-17 04:44:47 +00:00
Leonardo de Moura
010468699f
feat: trim grind cutsat proof context (#9945)
This PR optimizes the proof terms produced by `grind cutsat`. It removes
unused entries from the context objects when generating the final proof,
significantly reducing the amount of junk in the resulting terms.
Example:
```lean
/--
trace: [grind.debug.proof] fun h h_1 h_2 h_3 h_4 h_5 h_6 h_7 h_8 =>
      let ctx := RArray.leaf (f 2);
      let p_1 := Poly.add 1 0 (Poly.num 0);
      let p_2 := Poly.add (-1) 0 (Poly.num 1);
      let p_3 := Poly.num 1;
      le_unsat ctx p_3 (eagerReduce (Eq.refl true)) (le_combine ctx p_2 p_1 p_3 (eagerReduce (Eq.refl true)) h_8 h_1)
-/
#guard_msgs in -- Context should contain only `f 2`
open Lean Int Linear in
set_option trace.grind.debug.proof true in
example (f : Nat → Int) :
    f 1 <= 0 → f 2 <= 0 → f 3 <= 0 → f 4 <= 0 → f 5 <= 0 → 
    f 6 <= 0 → f 7 <= 0 → f 8 <= 0 → -1 * f 2 + 1 <= 0 → False := by
  grind
```
2025-08-17 02:53:19 +00:00
Sebastian Ullrich
4a6004b8fa
perf: use Lean.realizeValue in getFunInfo (#9810) 2025-08-16 15:02:29 +00:00
Sebastian Graf
c6df4a4a89
fix: delegate to exact in mvcgen using invariants to avoid MVar mishaps (#9939)
This PR expands `mvcgen using invariants | $n => $t` to `mvcgen; case
inv<$n> => exact $t` to avoid MVar instantiation mishaps observable in
the test case for #9581.

Closes #9581.
2025-08-16 09:40:42 +00:00
Sebastian Graf
ee4cbbeb14
fix: remove duplicate mpure_intro tactic definition (#9938)
This PR removes a duplicate `mpure_intro` tactic definition.
2025-08-16 09:19:07 +00:00
Cameron Zwarich
0e968f010a
chore: fix indentation (#9936) 2025-08-16 05:30:36 +00:00
Sebastian Graf
bdc9124228
feat: implement Std.Do.Triple.mp (#9931)
This PR implements `Std.Do.Triple.mp`, enabling users to compose two
specifications for the same program.
2025-08-15 17:44:15 +00:00
Leonardo de Moura
aad98fe749
fix: revert Nat.sub embedding into Int (#9930)
This PR reverts the way `grind cutsat` embeds `Nat.sub` into `Int`. It
fixes a regression reported by David Renshaw on Zulip.


https://leanprover.zulipchat.com/#narrow/channel/113488-general/topic/v4.2E23.2E0/near/534646557
2025-08-15 16:06:31 +00:00
Sebastian Ullrich
506d16a603
chore: complete riscv_ast benchmark (#9928) 2025-08-15 14:39:25 +00:00
Sebastian Graf
9e1d97c261
feat: extended using invariants and with syntax for mvcgen (#9927)
This PR implements extended `induction`-inspired syntax for `mvcgen`,
allowing optional `using invariants` and `with` sections.

```lean
  mvcgen
  using invariants
  | 1 => Invariant.withEarlyReturn
      (onReturn := fun ret seen => ⌜ret = false ∧ ¬l.Nodup⌝)
      (onContinue := fun traversalState seen =>
        ⌜(∀ x, x ∈ seen ↔ x ∈ traversalState.prefix) ∧ traversalState.prefix.Nodup⌝)
  with mleave -- mleave is a no-op here, but we are just testing the grammar
  | vc1 => grind
  | vc2 => grind
  | vc3 => grind
  | vc4 => grind
  | vc5 => grind
```
2025-08-15 12:25:01 +00:00
Sebastian Ullrich
415a58f9fb
chore: warn on [expose] on private definition (#9917) 2025-08-15 11:31:33 +00:00
Sebastian Graf
85ba133df0
fix: better ProofMode/Delab (#9926)
This PR guards the `Std.Tactic.Do.MGoalEntails` delaborator by a check
ensuring that there are at least 3 arguments present, preventing
potential panics.
2025-08-15 08:36:34 +00:00
Kim Morrison
3ee8d35031
chore: begin dev cycle for v4.24.0 (#9925) 2025-08-15 08:02:04 +00:00
Sebastian Graf
45fbe4a73d
fix: documentated examples for PostCond, move around tests (#9924)
This PR fixes examples in the documentation for `PostCond`.
2025-08-15 07:59:33 +00:00
Sofia Rodrigues
287b173844
fix: background function and forIn (#9560)
This PR fixes the `forIn` function, that previously caused the resulting
Promise to be dropped without a value when an exception was thrown
inside of it. It also corrects the parameter order of the `background`
function.
2025-08-15 02:39:57 +00:00
Cameron Zwarich
05c1ba291d
fix: erase dependencies on let-bound fvars in internalizeCode (#9922)
This PR changes `internalizeCode` to replace all substitutions with
non-param-bound fvars in `Expr`s (which are all types) with `lcAny`,
preserving the invariant that there are no such dependencies. The
violation of this invariant across files caused test failures in a
pending PR, but it is difficult to write a direct test for it. In the
future, we should probably change the LCNF checker to detect this.

This change also speeds up some compilation-heavy benchmarks much more
than I would've expected, which is a pleasant surprise. This indicates
we might get more speedups from reducing the amount of type information
we preserve in LCNF.
2025-08-15 01:52:47 +00:00
Sebastian Ullrich
15a065d14d
fix: panic in delabPRange (#9920)
This PR fixes a panic in the delaborator for `Std.PRange`. It also
modifies the delaborators for both `Std.Range` and `Std.PRange` to not
use `let_expr`, which cleans up annotations and metadata, since
delaborators must follow the structures of expressions. It adds support
for `pp.notation` and `pp.explicit` options. It also adds tests for
these delaborators.

---------

Co-authored-by: Kim Morrison <kim@tqft.net>
Co-authored-by: Kyle Miller <kmill31415@gmail.com>
2025-08-15 01:50:23 +00:00
Kim Morrison
35a753dc98
fix: panic in ProofMode/Delab (#9923)
This PR adds a guard for a delaborator that is causing panics in
doc-gen4. This is a band-aid solution for now, and @sgraf812 will take a
look when they're back from leave.
2025-08-15 01:01:12 +00:00
Leonardo de Moura
06d05d1f46
feat: missing grind annotations (#9921)
This PR marks `List.drop_length` and `List.take_length` with `[grind
=]`.
2025-08-14 22:47:42 +00:00
Leonardo de Moura
fe7e0859d5
fix: div/norm normalization assumptions in grind (#9919)
This PR ensures `grind cutsat` does not rely on div/mod terms to have
been normalized. The `grind` preprocessor has normalizers for them, but
sometimes they cannot be applied because of type dependencies.

Closes #9907
2025-08-14 22:28:25 +00:00
Sebastian Ullrich
ddfeca1b1b
fix: do not allow access to private primitives in public scope (#9890)
This PR addresses a missing check in the module system where private
names that remain in the public environment map for technical reasons
(e.g. inductive constructors generated by the kernel and relied on by
the code generator) accidentally were accessible in the public scope.
2025-08-14 15:34:54 +00:00
Sebastian Ullrich
0ab29c7420
fix: do not show progress bar for checking/compiling helper decls (#9786)
This PR ensures we only show progress bars for computations directly
relevant to users

---------

Co-authored-by: Marc Huisinga <mhuisi@protonmail.com>
2025-08-14 14:46:38 +00:00
Sebastian Ullrich
1ba1424ac3
perf: local metaExt (#9822) 2025-08-14 14:26:12 +00:00
Kim Morrison
c8dae31ba5
feat: review of grind annotations for Option (#9863)
This PR reviews `grind` annotations for `Option`, preferring to use
`@[grind =]` instead of `@[grind]` (and fixing a few problems revealed
by this), and making sure `@[grind =]` theorems are "fully applied".
2025-08-14 11:08:05 +00:00
Sebastian Ullrich
6e1451dbd8
fix: duplicate private instance name avoidance under the module system (#9914) 2025-08-14 10:03:41 +00:00
Joachim Breitner
6b3aed29b9
feat: unused simp argument linter to explain false positives around (#9912)
This PR lets the unused simp argument linter explain that the given hint
of removing `←` arguments may be too strong, and that replacing them
with `-` arguments can be needed. Fixes #9909.
2025-08-14 09:54:21 +00:00
Sebastian Graf
34fe6b460c
chore: fix docs of mspec (#9913)
Just docs.
2025-08-14 09:49:11 +00:00
Joachim Breitner
62f9de5edf
fix: fun_induction to instantiateMVars (#9877)
This PR makes `fun_induction foo` instantiate the MVars in the goal
before searching for suitable applications of foo. Fixes #9844.
2025-08-14 09:42:26 +00:00
Sebastian Graf
0c39a50337
feat: Rename Std.List.Zipper to List.Cursor (#9911)
This PR renames `Std.List.Zipper` to `List.Cursor`, with slight changes
to the implementation (no `reverse`) and use in loop specification
lemmas.
2025-08-14 09:17:54 +00:00
Marc Huisinga
93e35dc3da
feat: add lakefile.toml json schema (#9871)
This PR adds a JSON schema for `lakefile.toml`. Importantly, this schema
is *not* intended for validating `lakefile.toml`, but is instead
optimized for auto-completion and hovers using the [Even Better
TOML](https://marketplace.visualstudio.com/items?itemName=tamasfe.even-better-toml)
VS Code extension.

Once merged, I will attempt to contribute a link to this schema to the
[JSON Schema store](https://github.com/SchemaStore/schemastore). When
that is done, we can integrate the Lean 4 VS Code extension with Even
Better TOML, providing us with language server support in
`lakefile.toml`.

The schema contributed by this PR has the following known deficiencies:
- Superfluous properties do not produce an error.
- The structure of complicated structures (e.g. path or version
patterns) is deliberately not accurately reflected in the schema. Even
Better TOML doesn't seem to handle these structures well in
auto-completion.
- Due to the lack of an accurate declarative spec of the lakefile.toml
format and several deviations from the format to provide better
auto-completions, this schema will have to be kept in sync manually with
the code in Lake, at least for now.
2025-08-14 07:24:40 +00:00
Leonardo de Moura
05e8c856fa
fix: reset decision stack in grind linarith (#9904)
This PR ensures the decision stack is reset after an assignment is found
in `grind linarith`.

Closes #9897
2025-08-14 02:53:01 +00:00