Compare commits

..

576 Commits

Author SHA1 Message Date
Kim Morrison
ffe0692471 feat: generalize Process.output/run to allow an input 2025-07-25 19:29:53 +10:00
Sebastian Ullrich
671057eecf fix: unif_hint under the module system (#9530) 2025-07-25 09:05:31 +00:00
Kim Morrison
0ab69a32cb chore: parameterize NoNatZeroDivisors by NatModule instead of HMul (#9527)
This PR changes `Lean.Grind.NoNatZeroDivisors` so that it is
parametrised by a `NatModule` instance rather than just a `HMul`
instance. This is sufficiently general for our purposes, and is a
band-aid (~40% improvement) for the performance problems we've been
seeing coming from inference here. The problems observed in Mathlib may
not see much improvement, however.
2025-07-25 08:46:05 +00:00
Joachim Breitner
6995f280b4 fix: unfold abstracted proofs before processing recursion (#9191)
This PR lets the equation compiler unfold abstracted proofs again if
they would otherwise hide recursive calls.
    
This fixes #8939.

---------

Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
2025-07-25 08:00:57 +00:00
Kim Morrison
73422d52fd chore: remove simp from unindexable Array.filterMap_some_fun (#9521) 2025-07-25 06:22:42 +00:00
Mac Malone
4875c6447f fix: lake: import all transitivity & related bugs (#9525)
This PR fixes Lake's handling of a module system `import all`.
Previously, Lake treated `import all` the same a non-module `import`,
importing all private data in the transitive import tree. Lake now
distinguishes the two, with `import all M` just importing the private
data of `M`. The direct private imports of `M` are followed, but they
are not promoted.

This also fixes some other Lake bugs with module system imports that
were discovered in the process.
2025-07-25 05:56:38 +00:00
Cameron Zwarich
820c1e6f15 chore: remove tests that recompile builtin definitions (#9523)
In the early days of the new compiler, it was common to make tests that
manually compiled a definition with the new compiler. The arity
reduction pass in LCNF deliberately does not compute a fixed point to
find a minimal set of used parameters for performance reasons, but
running it a second time can lead to different decisions being made and
a decl arity mismatch. This has been an issue for multiple people during
development. Removing the tests fixes the problem.

Fixes #9186.
2025-07-25 04:37:33 +00:00
Leonardo de Moura
92b870da4a fix: kernel deep recursion with normalizer (#9522)
This PR uses `withAbstractAtoms` to prevent the kernel from accidentally
reducing the atoms in the arith normlizer while typechecking. This PR
also sets `implicitDefEqProofs := false` in the `grind` normalizer
2025-07-25 04:37:17 +00:00
Kim Morrison
3eaa44dd4d fix: definition of Lean.Grind.Field (#9520)
This PR corrects the changes to `Lean.Grind.Field` made in #9500. 

(The lack of examples of fields in the core repository is a problem! I
guess it is likely that for interval arithmetic we will at least need
`Rat` soon.)
2025-07-25 00:35:43 +00:00
Rob23oba
e148871087 chore: fix spelling errors (#9175)
(Almost) only typos in constant names and doc-strings were considered;
grammar was not considered. Also, along others,
`mkDefinitionValInferrringUnsafe` has been fixed :-)
2025-07-24 23:35:32 +00:00
Henrik Böving
75b5c8b0aa perf: phashmap benchmark (#9517)
This PR adds a benchmark for the persistent hashmap, in particular also
covering the non
linear insert case which is often hit in practical uses. Furthermore the
same test case is also
added to the treemap benchmark.
2025-07-24 14:57:07 +00:00
Sebastian Ullrich
4177f123bc fix: expose LCNF of private inline decl referenced by implemented_by (#9514) 2025-07-24 13:05:21 +00:00
Sebastian Ullrich
db292b4c82 chore: minimize benchmark imports so we don't spend a majority in importing (#9513) 2025-07-24 12:14:12 +00:00
Henrik Böving
9669c6d5f1 perf: add benchmark for congruence reasoning in simp (#9511)
This PR adds a benchmark for putting pressure on simp's congruence
abilities.
2025-07-24 10:47:37 +00:00
Sebastian Graf
2748633637 fix: Make mframe, mspec and mvcgen hygienic (#9512)
This PR makes `mframe`, `mspec` and `mvcgen` respect hygiene.
Inaccessible stateful hypotheses can now be named with a new tactic
`mrename_i` that works analogously to `rename_i`.
2025-07-24 10:30:16 +00:00
Joachim Breitner
2075103cd9 fix: show kernel diagnostics even for examples (#9509)
This PR surfaces kernel diagnostics even in `example`.

The problem was that the kernel checking happens asynchronously. We
cannot use `reportDiag` in `addDecl`, which spawns that task, due to the
module hierarchy. For non `example`-declaration, `reportDiag` is called
somewhere else later, but for `example`, the `withoutModifyingEnv` in
`elabMutualDef` hid the kernel diagnostics. (But only the kernel
diagnostics; they are in the `Environment`, while the others are in the
`State`).

I also observed that the `reportDiag` in `elabAsync` (but not in
`elabSync`) duplicated the reporting, so without `elab.Async true` you
get the message twice. To fix this, `reportDiag` now resets the
diagnostics. This should avoid reporting counts twice in general (at
least within a linear use of the state).

---------

Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
2025-07-24 09:21:47 +00:00
Sebastian Graf
b7dfda4f45 chore: Extract collectFreshMVars from withCollectingNewGoalsFrom (#9502) 2025-07-24 07:44:06 +00:00
Sebastian Graf
45514a955e feat: Add missing simp lemmas to mleave (#9506)
This PR adds a few missing simp lemmas to `mleave`.
2025-07-24 07:12:32 +00:00
Sebastian Graf
4fdf74500d fix: Remove duplicate syntax definitions for mvcgen* (#9505)
This PR removes vestigial syntax definitions in
`Lean.Elab.Tactic.Do.VCGen` that when imported undefine the `mvcgen`
tactic. Now it should be possible to import Mathlib and still use
`mvcgen`.
2025-07-24 06:57:00 +00:00
Sebastian Graf
d8f9463af3 feat: Add *.by_wp adequacy theorems for ReaderM and ExceptM (#9504)
This PR adds a few more `*.by_wp` "adequacy theorems" that allows to
prove facts about programs in `ReaderM` and `ExceptM` using the `Std.Do`
framework.
2025-07-24 06:53:59 +00:00
Sebastian Graf
ab18c82371 chore: Remove unused definitions relating to PredTrans (#9503) 2025-07-24 06:50:57 +00:00
Kim Morrison
68adcdb475 chore: maintain failing grind tests about Nat as a semiring (#9501)
These tests (still failing until we embed a NatModule in its IntModule
envelope) had further broken because of name changes.
2025-07-24 06:44:39 +00:00
Kim Morrison
3cde12567f feat: add HPow Int field to Field (#9500)
This PR adds a `HPow \a Int \a` field to `Lean.Grind.Field`, and
sufficient axioms to connect it to the operations, so that in future we
can reason about exponents in `grind`. To avoid collisions, we also move
the `HPow \a Nat \a` field in `Semiring` from the extends clause to a
field. Finally, we add some failing tests about normalizing exponents.
2025-07-24 06:00:11 +00:00
Kim Morrison
8d5da6491a chore: remove provable fields from Grind.Nat/IntModule (#9499) 2025-07-24 05:23:35 +00:00
Kim Morrison
eea7e50519 chore: script/release_steps.py only merges nightly-testing on rc1 (#9498) 2025-07-24 04:31:11 +00:00
Lean stage0 autoupdater
c4c3497776 chore: update stage0 2025-07-24 01:57:24 +00:00
Kyle Miller
d45cc674ea feat: make cdot expansion take hygiene into account (#9443)
This PR makes cdot function expansion take hygiene information into
account, fixing "parenthesis capturing" errors that can make erroneous
cdots trigger cdot expansion in conjunction with macros. For example,
given
```lean
macro "baz% " t:term : term => `(1 + ($t))
```
it used to be that `baz% ·` would expand to `1 + fun x => x`, but now
the parentheses in `($t)` do not capture the cdot. We also fix an
oversight where cdot function expansion ignored the fact that type
ascriptions and tuples were supposed to delimit expansion, and also now
the quotation prechecker ignores the identifier in `hygieneInfo`. (#9491
added the hygiene information to the parenthesis and cdot syntaxes.)

This fixes a bug discovered by [Google
DeepMind](https://storage.googleapis.com/deepmind-media/DeepMind.com/Blog/imo-2024-solutions/P1/index.html),
which made use of `useλy . x=>y.rec λS p=>?_`. The `use` tactic from
Mathlib wrapped the provided term in a type ascription, and so this was
equivalent to `use fun x => λy x x=>y.rec λS p=>?_`. (Note that cdot
function expansion is not able to take into account *where* the cdots
are located, and it is syntactically valid to insert an identifier into
the binder list like this. If we ever want to address this in the
future, we could have cdots expand into a special term that wraps an
identifier that evaluates to a local, but which would cause errors in
other contexts.)

Design note: we put the `hygieneInfo` on the open parenthesis rather
than at the end, since that way the hygiene information is available
even when there are parsing errors. This is important since we rely on
being able to elaborate partial syntax to get elab info (e.g. in `(a.`
to get completion info). Note that syntax matchers check that the
`hygieneInfo` is actually present, so such partial syntax would not be
matched.
2025-07-24 00:43:32 +00:00
Cameron Zwarich
8a0d036e82 perf: use an FVarIdHashSet for ReduceArity.State.used (#9497) 2025-07-24 00:25:26 +00:00
Lean stage0 autoupdater
9d93b10919 chore: update stage0 2025-07-23 21:41:23 +00:00
Kyle Miller
2412d52536 feat: add hygiene info to paren/tuple/typeAscription syntaxes (#9491)
This PR adds hygiene info to paren/tuple/typeAscription syntaxes, which
will be used to implement hygienic cdot function expansion in #9443.
2025-07-23 20:57:06 +00:00
Kyle Miller
e686d040ea fix: add missing spaces for pretty printing (#9475)
This PR fixes the way some syntaxes are pretty printed due to missing
whitespace advice.

Removes a vestigal `have'` tactic macro introduced in
0032578d5b back when `let` syntax looked
like `let Type := v`.

While we're here, extends the `let`/`have` docstrings to mention `(eq :=
h)` syntax.

Whitespace issues were reported by Damiano Testa [on
Zulip](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Some.20pretty.20printing.20quirks/near/529964215).
2025-07-23 19:35:04 +00:00
Leonardo de Moura
2dce18655d fix: incorrect proof term in grind linarith (#9487)
This PR fixes an incorrect proof term constructed by `grind linarith`,
as reported in #9485.

closes #9485
2025-07-23 17:34:44 +00:00
Kyle Miller
6cf22b32aa feat: custom structure constructors can update binder kinds of parameters (#9480)
This PR adds a feature where `structure` constructors can override the
inferred binder kinds of the type's parameters. In the following, the
`(p)` binder on `toLp` causes `p` to be an explicit parameter to
`WithLp.toLp`:
```lean
structure WithLp (p : Nat) (V : Type) where toLp (p) ::
  ofLp : V
```
This reflects the syntax of the feature added in #7742 for overriding
binder kinds of structure projections. Similarly, only those parameters
in the header of the `structure` may be updated; it is an error to try
to update binder kinds of parameters included via `variable`.

Closes #9072.

Fixes a possible bug from stale caches when creating the type of the
constructor.
2025-07-23 16:33:34 +00:00
Rob23oba
d24219697e feat: unexpand Vector.mk #[...] _ to #v[...] (#8391)
This PR adds an unexpander for `Vector.mk` that unexpands `Vector.mk
#[...] _` to `#v[...]`.
```lean
-- previously:
#check #v[1, 2, 3] -- { toArray := #[1, 2, 3], size_toArray := ⋯ } : Vector Nat 3
-- now:
#check #v[1, 2, 3] -- #v[1, 2, 3] : Vector Nat 3
```

---------

Co-authored-by: Kyle Miller <kmill31415@gmail.com>
2025-07-23 16:27:51 +00:00
Lean stage0 autoupdater
d353a25a36 chore: update stage0 2025-07-23 16:53:11 +00:00
Sebastian Ullrich
9dc4dbebe1 perf: do not try to mmap .ir to the same address as .olean (#9488) 2025-07-23 16:12:44 +00:00
Sebastian Ullrich
04be1c6b5c chore: CI: cached Lake as secondary job (#9486) 2025-07-23 13:26:35 +00:00
Sebastian Ullrich
e46a3108d9 perf: do not export specializations (#9465)
Trading an insignificant amount of IR bloat for better recompilation
avoidance
2025-07-23 13:12:15 +00:00
Sebastian Ullrich
4cbfa485fa chore: fix test on macOS (#9483) 2025-07-23 12:10:13 +00:00
Sebastian Ullrich
9328271dd0 perf: do not export LCNF decls of closed terms (#9484)
This was only necessary when `isDeclMeta` and `isDeclPublic` were
intertwined
2025-07-23 09:50:29 +00:00
Lean stage0 autoupdater
f137d43931 chore: update stage0 2025-07-23 09:39:13 +00:00
Sebastian Ullrich
0ba5413266 refactor: remove unused Environment.extraConstNames (#9470)
Obsoleted in #9356
2025-07-23 08:58:32 +00:00
Sebastian Ullrich
fefc033515 chore: disable artifacts cache for building stage2+ (#9482) 2025-07-23 08:44:08 +00:00
Lean stage0 autoupdater
d888039468 chore: update stage0 2025-07-23 08:54:57 +00:00
Sebastian Ullrich
ddc4cf0a97 refactor: private field use in Meta.Context (#9468)
This PR resolves an issue where the `Meta.Context.configKey` field is
private but we still want to use the constructor of the structure for
setting other fields, which would be prevented by the module system
checks:
```lean
structure Context where
  private config    : Config               := {}
  private configKey : UInt64               := config.toKey
...

def ContextInfo.runMetaM (info : ContextInfo) (lctx : LocalContext) (x : MetaM α) : IO α := do
  -- cannot call private constructor of `Meta.Context`!
  (·.1) <$> info.runCoreM (x.run { lctx := lctx } { mctx := info.mctx })
```
Instead, the private field is extracted into an (existing) structure
that applies its default value:
```lean
/-- Configuration with key produced by `Config.toKey`. -/
structure ConfigWithKey where
  private mk ::
  config : Config := {}
  key    : UInt64 := config.toKey
  
structure Context where
  keyedConfig : ConfigWithKey := default
```
Thus `Context`'s constructor remains public without exposing a way to
set `key` directly.
2025-07-23 08:16:44 +00:00
Leonardo de Moura
aa5b392e35 fix: canonicalization of non-standard OfNat.ofNat terms (#9481)
This PR fixes a kernel type mismatch that occurs when using `grind` on
goals containing non-standard `OfNat.ofNat` terms. For example, in issue
#9477, the `0` in the theorem `range_lower` has the form:
```lean
(@OfNat.ofNat
  (Std.PRange.Bound (Std.PRange.RangeShape.lower (Std.PRange.RangeShape.mk Std.PRange.BoundShape.closed Std.PRange.BoundShape.open)) Nat)
  (nat_lit 0)
  (instOfNatNat (nat_lit 0)))
```
instead of the more standard form:
```lean
(@OfNat.ofNat
  Nat
  (nat_lit 0)
  (instOfNatNat (nat_lit 0)))
```

Closes #9477
2025-07-23 04:10:21 +00:00
Lean stage0 autoupdater
6346fdb253 chore: update stage0 2025-07-23 02:31:29 +00:00
Leonardo de Moura
7d2a7dba81 fix: improve evalInt? (#9479)
This PR improves the `evalInt?` function, which is used to evaluate
configuration parameters from the `ToInt` type class. This PR also adds
a new `evalNat?` function for handling the `IsCharP` type class, and
introduces a configuration option:
```
grind (exp := <num>)
```
This option controls the maximum exponent size considered during
expression evaluation. Previously, `evalInt?` used `whnf`, which could
run out of stack space when reducing terms such as `2^1024`.

closes #9427
2025-07-23 01:51:04 +00:00
Aaron Liu
98f05c47d0 fix: add binrel% macros for notation in Init.Core (#9084)
This PR adds `binrel%` macros for `!=` and `≠` notation defined in
`Init.Core`. This allows the elaborator to insert coercions on both
sides of the relation, instead of committing to the type on the left
hand side.

I first discovered this bug while working on Brouwer's fixed point
theorem. See the discussion on Zulip at [#lean4 > Elaboration of
&#96;≠&#96; @
💬](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Elaboration.20of.20.60.E2.89.A0.60/near/526236907).
2025-07-23 01:34:55 +00:00
Mac Malone
67bbc947af feat: lake: meta import support (#9478)
This PR adds proper Lake support for `meta import`. Module IR is now
tracked in traces and in the pre-resolved modules Lake passes to `lean
--setup`.
2025-07-23 01:17:20 +00:00
Leonardo de Moura
64219ac91e fix: assertNatCast in grind (#9476)
This PR fixes the bridge between `Nat` and `Int` in `grind cutsat`.

Closes #9467
2025-07-22 21:59:38 +00:00
Leonardo de Moura
dedd9275ec fix: mkCongrSimpCore? (#9472)
This PR fixes another issue at the `congr_simp` theorems that was
affecting Mathlib. Many thanks to Johan Commelin for creating the mwe.

closes #9466
2025-07-22 18:09:24 +00:00
Sebastian Ullrich
4dbe84dc98 chore: ensure Lake and Lean agree when .ir is needed (#9471) 2025-07-22 17:34:41 +00:00
Giles Shaw
0cc4c91800 fix: change the proof of Nat.zero_mod to rfl (#9391)
This PR replaces the proof of the simplification lemma `Nat.zero_mod`
with
`rfl` since it is, by design, a definitional equality. This solves an
issue
whereby the lemma could not be used by the simplifier when in 'dsimp'
mode.

Closes #9389

---------

Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>
2025-07-22 13:21:48 +00:00
Sebastian Graf
548d564c18 feat: Introduce mleave tactic that leaves the SPred proof mode (#9363) (#9454)
This PR introduces tactic `mleave` that leaves the `SPred` proof mode by
eta expanding through its abstractions and applying some mild
simplifications. This is useful to apply automation such as `grind`
afterwards.

Relates to #9363.
2025-07-22 11:50:16 +00:00
Sebastian Graf
2d30e3913c fix: Handle let/have in mintro (#9365) (#9451)
This PR adds support in the `mintro` tactic for introducing `let`/`have`
binders in stateful targets, akin to `intro`. This is useful when
specifications introduce such let bindings.

Closes #9365.
2025-07-22 11:35:46 +00:00
Joachim Breitner
ec13bb963f fix: PProdN.reduceProjs to also look for projection functions (#9464)
This PR makes `PProdN.reduceProjs` also look for projection functions.
Previously, all redexes were created by the functions in `PProdN`, which
used primitive projections. But with `mkAdmProj` the projection
functions creep in via the types of the `admissible_pprod_fst` theorem.
So let's just reduce both of them.

Fixes #9462.
2025-07-22 09:22:50 +00:00
Lean stage0 autoupdater
9006597f59 chore: update stage0 2025-07-22 09:47:42 +00:00
Sebastian Ullrich
e28569f2a1 perf: minimize exported codegen data (#9356)
To be documented
2025-07-22 09:05:49 +00:00
Kenny Lau
751947482f fix: use let rec for Fin.reverseInduction (#9142)
This PR changes `Fin.reverseInduction` from using well-founded recursion
to using `let rec`, which makes it have better definitional equality.
Co-authored by @digama0. See the test below:

```lean
namespace Fin

/-- The new one. -/
@[elab_as_elim] def reverseInduction' {motive : Fin (n + 1) → Sort _} (last : motive (Fin.last n))
    (cast : ∀ i : Fin n, motive i.succ → motive (castSucc i)) (i : Fin (n + 1)) : motive i :=
  let rec go (j : Nat) (h) (h2 : i ≤ j) (x : motive ⟨j, h⟩) : motive i :=
    if hi : i.1 = j then (show i = ⟨j, h⟩ by simp [← hi]) ▸ x
    else match j with
      | 0 => by omega
      | j+1 => go j (by omega) (by omega) (cast ⟨j, by omega⟩ x)
  go _ _ (by omega) last

/-- Same code but using reverseInduction'. -/
@[elab_as_elim] def lastCases' {n : Nat} {motive : Fin (n + 1) → Sort _} (last : motive (Fin.last n))
    (cast : ∀ i : Fin n, motive (castSucc i)) (i : Fin (n + 1)) : motive i :=
  reverseInduction' last (fun i _ => cast i) i

end Fin

theorem foo : (Fin.lastCases (-4) (fun i ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int) = -4 := rfl
#eval (Fin.lastCases (-4) (fun i ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int)
theorem foo' : (Fin.lastCases' (-4) (fun i ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int) = -4 := rfl
#eval (Fin.lastCases' (-4) (fun i ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int)

theorem bar : (Fin.reverseInduction (n := 2) (motive := fun _ ↦ Int)
    (-4) (fun i _ ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int) = -4 := rfl
#eval (Fin.reverseInduction (n := 2) (motive := fun _ ↦ Int)
    (-4) (fun i _ ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int)
theorem bar' : (Fin.reverseInduction' (n := 2) (motive := fun _ ↦ Int)
    (-4) (fun i _ ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int) = -4 := rfl
#eval (Fin.reverseInduction' (n := 2) (motive := fun _ ↦ Int)
    (-4) (fun i _ ↦ (i : Int) * 2 + 1) (2 : Fin 3) : Int)
```
[Link to Lean 4
Web](https://live.lean-lang.org/#project=lean-nightly&codez=HYQwtgpgzgDiDGEAEAxAlsAUJg9AWjyQBUALZYCAdyQHsKA6JPHTAAQG0IAbEAIwH0QUftzRgAukgAmEAGZIAThABuEBVAgBJYFICu8AC5o6AciQBvMDSOqkALlQYkACmBIA1EgCMASiSAkwiQAZRoFAyR+AF8XHihwhysbZGd0YHpY8OAfH0wkPJd4IXikQAAiJDR7RzdgABokRLRbNHoofXgA+utG5MK4oLby7JcKh1SXN09fPwSupvsAXlykLghwpXaAcxoXACtKgDkQAz9nEhOSACZKisATIiQdk4APSobbQAvyHbqSQEvyac6k8oLJZ5NDyEgjcr0LxIeb3JAGMhuZxQEg0agVWEfL7fJC8ACeSCgYhgSHYgATCJDg8R+QAdpEhHsCkNwNPUjvASHDKGgEYy8gAfJAABhhAD5cQSaJANiBeUgBTt3ND5mKtnDnPjaFKQCcNZKINKTr1wljxZr9SAcY8cnlVfwIi5dVq/BlsPhCEFwMh4DQZLjdOFdETgBtFCo1BptHpDMZgCZGMw2JweAIhCIuGJJDJ5BkAMJCaBmcxuByHAzRSyzZCjJyuDzePyBEJhCLRZwZF6VlypdJFJBZa35ZxGyplCFjWr/boFIr9eDtNBDZxjmsTet/V7IEaLPJKVTqLQ6fRGUzLXvOWS6NwVO3KpDDhflbAQHRVbAIiChCBgJCyGjbBwpBgPZxHmGhQC4eAACwnBeV5IIAZYTDJU2jHEgABUSBXJMJxXNWbgAMx/ChfiwlBCyKLIXCYAAxCoIBcF2QG5vm4HOFBMGXoCiFLshwCoRhWH1i4uFVEghG8ccmDvp+36/jQZgAd2zFgWYbHQS4sFcUhDjEehmF1r4wmVGM4k6XxJFMJB5EKJRNF0QxgFpMpBYQep56cRU3EQrpAkGThxlOKZSDEW+ZAybiIAKJUjn0Lu4YHlGx5IsWsIXCcG7kZpdqISF+SuRxcHZdpwXmXpgmGc4IkmURpWkVZdiwjZVG0co9GMWkcX7pGR4xuM5FpS4GUNT+nFFblg7sRpHn2l5El+L52FGXhYk1ZJ0lKN+vCRQp7WxWGXWHtGJ61sNA3OENsJZQhJWSXlakFYCRU8WZ/H6YtlUBQRq0WWRw1NXZrUOd2nURodSWqSlmHpZ2w1XTl5mMvdU2Fddz03fNb1CR9y1BcRQA)

Notice how `rfl` fails for the 1st and 5th tests that use the original
`Fin.reverseInduction`, but the 3rd and 7th tests that use the new code
in this PR succeed.

Closes #9141.

---------

Co-authored-by: Markus Himmel <markus@lean-fro.org>
2025-07-22 08:34:14 +00:00
Rob23oba
b7ab7ea745 fix: behavior of String.next (#9449)
This PR fix the behavior of `String.next` on the scalar boundary (`2 ^
63 - 1` on 64-bit platforms).

Closes #9440
2025-07-22 06:48:33 +00:00
Cameron Zwarich
6f5532f069 perf: make function types object rather than tobject (#9461) 2025-07-22 01:16:45 +00:00
Cameron Zwarich
30ca6c82e0 refactor: use named params (#9460) 2025-07-22 00:11:25 +00:00
Cameron Zwarich
968a708a9f perf: update type information in cases arms for RC optimizations (#9457)
The `isRef` check being removed here used to be an optimization, because
this structure only tracked whether ref counting operations need to be
inserted at all. Now the structure also tracks whether the value needs
to be checked for being a scalar or not, which is something that can be
refined by a `cases` arm, since inductive types can have a mix of scalar
and non-scalar constructors.
2025-07-21 23:10:11 +00:00
Cameron Zwarich
bb23700f24 chore: add named params to MonadWithReader.withReader (#9459)
This matches `MonadWithReaderOf`.
2025-07-21 23:02:19 +00:00
Cameron Zwarich
9a34f6bc95 refactor: remove questionable defaults in Context structure (#9458) 2025-07-21 22:16:14 +00:00
Cameron Zwarich
f3e1795175 refactor: clean up monad setup (#9456) 2025-07-21 21:22:20 +00:00
jrr6
d57d1fcd36 fix: prevent deriving handlers from generating ambiguous identifiers (#9371)
This PR fixes an issue that caused some `deriving` handlers to fail when
the name of the type being declared matched that of a declaration in an
open namespace.

Closes #9366
2025-07-21 17:45:54 +00:00
Lean stage0 autoupdater
e134cfea8f chore: update stage0 2025-07-21 16:24:20 +00:00
Marc Huisinga
8b8561a699 feat: improved go to definition (#9040)
This PR improves the 'Go to Definition' UX, specifically:
- Using 'Go to Definition' on a type class projection will now extract
the specific instances that were involved and provide them as locations
to jump to. For example, using 'Go to Definition' on the `toString` of
`toString 0` will yield results for `ToString.toString` and `ToString
Nat`.
- Using 'Go to Definition' on a macro that produces syntax with type
class projections will now also extract the specific instances that were
involved and provide them as locations to jump to. For example, using
'Go to Definition' on the `+` of `1 + 1` will yield results for
`HAdd.hAdd`, `HAdd α α α` and `Add Nat`.
- Using 'Go to Declaration' will now provide all the results of 'Go to
Definition' in addition to the elaborator and the parser that were
involved. For example, using 'Go to Declaration' on the `+` of `1 + 1`
will yield results for `HAdd.hAdd`, `HAdd α α α`, `Add Nat`,
``macro_rules | `($x + $y) => ...`` and `infixl:65 " + " => HAdd.hAdd`.
- Using 'Go to Type Definition' on a value with a type that contains
multiple constants will now provide 'Go to Definition' results for each
constant. For example, using 'Go to Type Definition' on `x` for `x :
Array Nat` will yield results for `Array` and `Nat`.

### Details
'Go to Definition' for type class projections was first implemented by
#1767, but there were still a couple of shortcomings with the
implementation. E.g. in order to jump to the instance in `toString 0`,
one had to add another space within the application and then use 'Go to
Definition' on that, or macros would block instances from being
displayed. Then, when the .ilean format was added, most 'Go to
Definition' requests were already handled using the .ileans in the
watchdog process, and so the file worker never received them to handle
them with the semantic information that it has available.

This PR resolves most of the issues with the previous implementation and
refactors the 'Go to Definition' control flow so that 'Go to Definition'
requests are always handled by the file worker, with the watchdog merely
using its .ilean position information to update the positions in the
response to a more up-to-date state. This is necessary because the file
worker obtains its position information from the .oleans, which need to
be rebuilt in order to be up-to-date, while the watchdog always receives
.ilean update notifications from each active file worker with the
current position information in the editor.

Finally, all of the 'Go to Definition' code is refactored to be easier
to maintain.

### Breaking changes
`InfoTree.hoverableInfoAt?` has been generalized to
`InfoTree.hoverableInfoAtM?` and now takes a general `filter` argument
instead of several boolean flags, as was the case before.
2025-07-21 15:47:44 +00:00
Lean stage0 autoupdater
51ae98ae30 chore: update stage0 2025-07-21 14:40:51 +00:00
Henrik Böving
09de5cd70e refactor: remove Lean.RBMap usages (#9260)
This PR removes uses of `Lean.RBMap` in Lean itself.

Furthermore some massaging of the import graph is done in order to avoid
having `Std.Data.TreeMap.AdditionalOperations` (which is quite
expensive) be the critical path for a large chunk of Lean. In particular
we can build `Lean.Meta.Simp` and `Lean.Meta.Grind` without it thanks to
these changes.

We did previously not conduct this change as `Std.TreeMap` was not
outperforming `Lean.RBMap` yet, however this has changed with the new
code generator.
2025-07-21 14:04:45 +00:00
Joachim Breitner
23e88b4e1d chore: test for issue #9018 (#9452) 2025-07-21 13:55:36 +00:00
Joachim Breitner
fcd60e73f8 fix: use withIncRecDepth in SizeOf deriving (#9448)
This PR addresses the lean crash (stack overflow) with nested induction
and the generation of the `SizeOf` spec lemmas, reported at #9018.

It does not address the underlying issue that in these cases, the
generated SizeOf code does not match the the SizeOf function found by
instance search, and thus the generation fails.

This seem hard to fix: `mkSizeOfMinors` would have to recognize that
given, say, `List (Id Tree)`, the derived instance (assuming there was
one for `Tree`) is not the same as for `List Tree`.

The problem seems just about as hard as getting derived SizeOf right in
the presence of nested induction and non-canonical SizeOf instances.
2025-07-21 12:43:19 +00:00
Rob23oba
b7f433c5b9 fix: behavior of String.prev (#9441)
This PR fixes the behavior of `String.prev`, aligning the runtime
implementation with the reference implementation. In particular, the
following statements hold now:
- `(s.prev p).byteIdx` is at least `p.byteIdx - 4` and at most
`p.byteIdx - 1`
- `s.prev 0 = 0`
- `s.prev` is monotone

Closes #9439
2025-07-21 10:50:14 +00:00
Sebastian Graf
f3ac38ff2c fix: Close pure, trivial goals in mvcgen (#9362) (#9447)
This PR ensures that `mvcgen` not only tries to close stateful subgoals
by assumption, but also pure Lean goals.

Closes #9362.
2025-07-21 10:12:34 +00:00
Lean stage0 autoupdater
c5a5c5572f chore: update stage0 2025-07-21 05:32:04 +00:00
Cameron Zwarich
2f7c0366f5 perf: treat partial application and eta expansion equally for specialization (#9438) 2025-07-20 14:57:21 +00:00
Cameron Zwarich
1a9757d1f6 refactor: make withReader calls more readable (#9442) 2025-07-20 13:39:35 +00:00
Mac Malone
3aaa3beeee feat: lake: job count in build success message (#9436)
This PR adds the number of jobs run to the final message Lake produces
on a successfully run of `lake build`.


**Examples**
```
Build completed successfully (1 job).
Build completed successfully (6 jobs).
```
2025-07-19 04:59:39 +00:00
Mac Malone
deef4e8e23 feat: lake: libPrefixOnWindows (#9435)
This PR adds the `libPrefixOnWindows` package and library configuration
option. When enabled, Lake will prefix static and shared libraries with
`lib` on Windows (i.e., the same way it does on Unix).
2025-07-19 04:46:42 +00:00
Mac Malone
c660f63748 refactor: lake: restore libs & exes from cache (#9434)
This PR changes the Lake local cache infrastructure to restore
executables and shared and static libraries from the cache. This means
they keep their expected names, which some use cases still rely on.
2025-07-19 03:28:42 +00:00
jrr6
b7e220039f feat: add hints for tuple projections (#9387)
This PR adds a hint to the "invalid projection" message suggesting the
correct nested projection for expressions of the form `t.n` where `t` is
a tuple and `n > 2`.

This feature was originally proposed by @nomeata in #8986.
2025-07-18 23:55:13 +00:00
jrr6
34bd6e8bfd feat: improve split error messages (#9424)
This PR improves the error messages produced by the `split` tactic,
including suggesting syntax fixes and related tactics with which it
might be confused.

Note that, to avoid clashing with the new error message styling
conventions used in these messages, this PR also updates the formatting
of the message produced by `throwTacticEx`.

Closes #6224
2025-07-18 22:36:10 +00:00
Cameron Zwarich
5cd5885da4 fix: make IRType.erased a tobject when boxing it (#9431)
This PR changes `IRType.boxed` to map `erased` to `tobject` rather than
`object`, since `erased` has a representation of a boxed scalar 0 when
we are forced to represent it at runtime. This case does not occur at
all in the Lean codebase.
2025-07-18 20:10:52 +00:00
jrr6
5f4e6a86d5 feat: update and explain "unknown constant" and "failed to infer type" errors (#9423)
This PR updates the formatting of, and adds explanations for, "unknown
identifier" errors as well as "failed to infer type" errors for binders
and definitions.

It attempts to ameliorate some of the confusion encountered in #1592 by
modifying the wording of the "header is elaborated before body is
processed" note and adding further discussion and examples of this
behavior in the corresponding error explanation.
2025-07-18 19:20:31 +00:00
Cameron Zwarich
1043569648 perf: use more precise IR types for overapplication (#9428) 2025-07-18 16:34:19 +00:00
Paul Reichert
383256defa chore: reintroduce Subarray.foldl on top of Slice.foldl (#9234)
An earlier PR (#9017) replaced certain subarray functions such as
`Subarray.foldl` with generic slice functions `Slice.foldl`. For
backward compatibility reasons, This PR reintroduces `Subarray.foldl`
etc. as aliases for the `Slice` versions.
2025-07-18 15:23:50 +00:00
Cameron Zwarich
cdab726e3d refactor: clean up creation of IR over-application (#9426) 2025-07-18 06:11:06 +00:00
Mac Malone
7b9ead4a1a chore: lake: module system tests & fixes (#9422)
This PR adds Lake tests for builds involving the Lean module system and
fixes some bugs encountered in the process. In particular, it fixes the
parsing of private imports and how Lake handles the `import all` of a
private import.
2025-07-18 02:34:13 +00:00
jrr6
6e191720b3 fix: open error explanations in new window in web editor (#9421)
This PR fixes a bug that caused error explanations to "steal" the
Infoview's container in the Lean web editor.
2025-07-17 23:20:35 +00:00
Sebastian Ullrich
9fc31abb1f chore: benchmark using USE_LAKE (#9361) 2025-07-17 18:44:29 +00:00
Markus Himmel
3878d6da85 chore: Grove: bump version (#9419) 2025-07-17 15:02:17 +00:00
Henrik Böving
097952c48f perf: simp subexpr benchmark (#9404)
This PR adds a simp benchmark to our suite, specifically targeting
caching of subexpression
rewriting results.
2025-07-17 11:53:48 +00:00
Sebastian Ullrich
e5730e9b7e refactor: module-ize remainder of Std (#9195) 2025-07-17 11:43:57 +00:00
Sebastian Ullrich
49546687d9 chore: update stage0 2025-07-17 11:54:06 +02:00
Sebastian Ullrich
2c08280854 fix: meta def should never be exposed (#9415) 2025-07-17 11:52:32 +02:00
Mac Malone
ebe68faf7f fix: lake: test script bugs w/ Mathlib & non-Linux (#9397)
This PR fixes some issues with the Lake tests on Windows and macOS. It
also avoids downloading Mathlib in the `init` test, which was currently
doing this after changes to the `math-lax` template in #8866.

To skip the Mathlib download in `init`, an undocumented `--offline`
option was added`. This option is currently meant for internal use only.
2025-07-17 07:08:00 +00:00
Leonardo de Moura
65abbd90bf perf: isArrowProposition (#9414)
This PR increases the number of cases where `isArrowProposition` returns
a result other than `.undef`. This function is used to implement the
`isProof` predicate, which is invoked on every subterm visited by
`simp`.
2025-07-17 04:12:15 +00:00
jrr6
119854e248 feat: add hints for missing structure instance fields (#9317)
This PR adds to the "fields missing" error message for structure
instance notation a code-action hint that inserts all missing fields.
2025-07-17 03:22:34 +00:00
jrr6
442ef6e64c feat: add case name hints (#9316)
This PR adds clickable code-action hints to the "invalid case name"
error message.
2025-07-17 03:22:30 +00:00
jrr6
fb462fdf9e feat: add named argument hints (#9315)
This PR adds improves the "invalid named argument" error message in
function applications and match patterns by providing clickable hints
with valid argument names. In so doing, it also fixes an issue where
this error message would erroneously flag valid match-pattern argument
names.
2025-07-17 03:22:25 +00:00
Cameron Zwarich
d667522524 refactor: remove special cases for subsingleton casesOn (#9412) 2025-07-16 23:41:41 +00:00
Cameron Zwarich
c1b5d54737 feat: compiler support for casesOn of subsingletons (#9411)
This PR adds support for compilation of `casesOn` for subsingletons. We
rely on the elaborator's type checking to restrict this to inductives in
`Prop` that can actually eliminate into `Type n`. This does not yet
cover other recursors of these types (or of inductives not in `Prop` for
that matter).
2025-07-16 23:07:32 +00:00
Sebastian Ullrich
f94d7b333a fix: do not export private instances (#9407)
Fixes #9383
2025-07-16 18:59:48 +00:00
Leonardo de Moura
d7ef2880c8 perf: avoid "dependent implications" as local E-matching theorems in grind (#9408)
This PR implements a simple optimization: dependent implications are no
longer treated as E-matching theorems in `grind`. In
`grind_bitvec2.lean`, this change saves around 3 seconds, as many
dependent implications are generated. Example:
```lean
 ∀ (h : i + 1 ≤ w), x.abs.getLsbD i = x.abs[i]
 ```
2025-07-16 17:13:52 +00:00
Sebastian Ullrich
f3944a3d49 chore: fix test 2025-07-16 17:51:42 +02:00
Sebastian Ullrich
263a77fa89 chore: update stage0 2025-07-16 16:04:47 +02:00
Sebastian Ullrich
2584b6abf9 fix: assorted module system fixes (#9406)
Encountered when porting `Std` and `Lean`
2025-07-16 13:31:08 +00:00
Markus Himmel
ca9b804163 chore: ci: specify which Linux toolchain Grove should download (#9405)
Since the old version of the workflow will run on PRs, we'll have to
"test" this on master.
2025-07-16 13:15:13 +00:00
Henrik Böving
e9ccdeecd0 perf: add a benchmark for simp on local hypotheses (#9403)
This PR adds a benchmark to our suite, specifically targeting the fact
that local hypotheses
are currently not indexed in simp and can thus cause significant
slowdowns compared to having them
as external declarations.
2025-07-16 12:16:29 +00:00
Sebastian Ullrich
2ed4f39ffe chore: adapt core to preceding syntax change 2025-07-16 13:32:11 +02:00
Sebastian Ullrich
1959e6088b chore: update stage0 2025-07-16 13:32:11 +02:00
Sebastian Ullrich
ffbb21a032 fix: order of @[expose] public section
This PR makes the order of `@[expose] public` at `section` consistent with that at `def`
2025-07-16 13:32:11 +02:00
Sebastian Ullrich
e088549330 refactor: module-ize Std.Time (#9100) 2025-07-16 09:57:53 +00:00
Mac Malone
587979341a refactor: lake: optimize module build code for new compiler (#9400)
This PR splits up `Module.recBuildLean` into smaller functions and
optimizes the implementation of `Module.cacheOutputArtifacts` for the
new compiler. Now, all functions within `Lake.Build.Module` take Lean
<1s to compile.
2025-07-16 07:27:34 +00:00
Mac Malone
180bfeaba4 feat: lake: pre-resolve module imports (#9053)
This PR updates Lake to resolve the `.olean` files for transitive
imports for Lean through the `modules` field of `lean --setup`. This
enables means the Lean can now directly use the `.olean` files from the
Lake cache without needed to locate them at a specific hierarchical
path.

Resolving transitive imports still has a performance penalty, but it is
now much less.
2025-07-16 04:21:31 +00:00
Lean stage0 autoupdater
e6cce355e3 chore: update stage0 2025-07-16 04:26:10 +00:00
Cameron Zwarich
e9b75e34b7 perf: decide whether to use _ref variants of inc/dec using IR types (#9399) 2025-07-16 03:52:58 +00:00
Leonardo de Moura
e286f20179 perf: avoid inferType at simpArith (#9398)
This PR avoids the expensive `inferType` call in `simpArith`. It also
cleans up some of the code and removes anti-patterns.
2025-07-16 03:42:26 +00:00
Lean stage0 autoupdater
d4afa3caaa chore: update stage0 2025-07-16 02:48:16 +00:00
Cameron Zwarich
e069c9eb0e perf: use IR type info to decide whether to insert RC ops (#9396)
This is mostly a refactoring that replaces other analyses with type
information, but due to the introduction of `tagged` it also has the
side effect of eliminating ref counting ops entirely for types that
always have a tagged scalar representation, e.g. `Unit`.
2025-07-16 02:02:32 +00:00
Leonardo de Moura
dc2f256448 fix: bug at mkCongrSimpCore? (#9395)
This PR fixes a bug at `mkCongrSimpCore?`. It fixes the issue reported
by @joehendrix at #9388.
The fix is just commit: afc4ba617f. The
rest of the PR is just cleaning up the file.

closes #9388
2025-07-16 00:54:31 +00:00
Cameron Zwarich
62ded77e81 chore: add a new tagged IRType for inline tagged scalars (#9394) 2025-07-16 00:42:56 +00:00
Cameron Zwarich
466e8a6c5e fix: adjust unsafe trick for upcoming optimization (#9393)
This PR fixes an unsafe trick where a sentinel for a hash table of Exprs
(keyed by pointer) is created by constructing a value whose runtime
representation can never be a valid Expr. The value chosen for this
purpose was Unit.unit, which violates the inference that Expr has no
scalar constructors. Instead, we change this to a freshly allocated Unit
× Unit value.
2025-07-16 00:10:01 +00:00
Cameron Zwarich
b131e8b97f chore: adopt tobject IRType (#9392) 2025-07-15 23:56:49 +00:00
Cameron Zwarich
d7ef2a8d1c refactor: add a CtorFieldInfo.object field for the object type (#9390) 2025-07-15 23:18:23 +00:00
jrr6
3b58a7d36b fix: improve error message when projecting from zero-field type (#9386)
This PR improves a confusing error message that occurred when attempting
to project from a zero-field structure.

Closes #9312
2025-07-15 21:32:59 +00:00
jrr6
e9a318df16 fix: reorder "application type mismatch" message (#9287)
This PR rewords the "application type mismatch" error message so that
the argument and its type precede the application expression.
2025-07-15 19:20:18 +00:00
Leonardo de Moura
166d1c0dab perf: avoid isDefEq test at simpEq simproc used in grind (#9385)
This PR replaces the `isDefEq` test in the `simpEq` simproc used in
`grind`. It is too expensive.
2025-07-15 18:38:11 +00:00
Joachim Breitner
0926d27100 chore: fix benchmark added in #9380 (#9384) 2025-07-15 18:24:34 +00:00
Henrik Böving
aa6f22d102 chore: reduce import closure of MPL (#9382)
This PR reduces the import closure of the monadic verification framework
from `Lean.Meta` to only
the submodules actually required.
2025-07-15 16:36:03 +00:00
Joachim Breitner
6adeab2160 chore: add simple simp benchmark (#9380)
A micro-benchmark for plain, mostly first-order rewriting of simp:

This uses axiom to make it independent of specific optimization (e.g.
for `Nat`).

It generates a “list” of 128 `b`s followed by 128 `a` and uses
bubble-sort to to sort it and compares it against the expected output.
2025-07-15 15:04:49 +00:00
Malhar A. Patel
6cbdd6b815 doc: correct the Option.getD docString example (#9190)
This PR corrects the second example in the `Option.getD` docString

Closes #9189
2025-07-15 12:39:58 +00:00
Henrik Böving
a8c0348300 chore: re-simp Std.LawfulEqCmp.compare_eq_iff_eq (#9377)
This PR readds `simp` annotations accidentally lost in previous PRs
2025-07-15 12:10:50 +00:00
Filippo A. E. Nuccio
08d8bed022 doc: fix a typo in Pairwise doc (#9375)
doc: fix a typo in Pairwise doc

This PR fixes a sentence in the Pairwise doc in List/Basic
2025-07-15 11:39:02 +00:00
Henrik Böving
6e9bc1359d fix: don't delay lake logging when cloning a dependency (#9332)
This PR changes the dependency cloning mechanism in lake so the log
message that lake is cloning a
dependency occurs before it is finished doing so (and instead before it
starts). This has been a
huge source of confusion for users that don't understand why lake seems
to be just stuck for no
reason when setting up a new project, the output now is:
```
λ lake +lean4 new math math
info: downloading mathlib `lean-toolchain` file
info: math: no previous manifest, creating one from scratch
info: leanprover-community/mathlib: cloning https://github.com/leanprover-community/mathlib4
<hang>
info: leanprover-community/mathlib: checking out revision 'cd11c28c6a0d514a41dd7be9a862a9c8815f8599'
```
2025-07-15 09:38:35 +00:00
Cameron Zwarich
aac501a645 refactor: split up mkExpr helper in lowerLet (#9374) 2025-07-15 05:26:21 +00:00
Cameron Zwarich
cf94e1b162 refactor: get the type of a literal from lowerLitValue (#9373)
This will let us have value-dependent types in the future for tracking
tagged/boxed values.
2025-07-15 04:46:47 +00:00
Leonardo de Moura
96e7ab078d fix: performance issue when elaborating match-expressions with many literals (#9372)
This PR fixes a performance issue that occurs when generating equation
lemmas for functions that use match-expressions containing several
literals. This issue was exposed by #9322 and arises from a combination
of factors:

1. Literal values are compiled into a chain of dependent if-then-else
expressions.
2. Dependent if-then-else expressions are significantly more expensive
to simplify than regular ones.
3. The `split` tactic selects a target, splits it, and then invokes
`simp` on the resulting subgoals. Moreover, `simp` traverses the entire
goal bottom-up and does not stop after reaching the target.

This PR addresses the issue by introducing a custom simproc that avoids
recursively simplifying nested if-then-else expressions. It does **not**
alter the user-facing behavior of the `split` tactic because such a
change would be highly disruptive. Instead, the PR adds a new flag,
`backward.split` to control the behavior of the user-facing `split`
tactic. It is currently set to `true`, i.e., the old behavior is still
the default one. In a future PR, we should set this flag to `false` by
default and begin repairing all affected proofs.

closes #9322
2025-07-15 03:52:23 +00:00
Cameron Zwarich
9d33f2ad33 chore: make IR.Arg pattern matching more exhaustive (#9370) 2025-07-14 22:46:40 +00:00
Leonardo de Moura
a4b5eecb8e perf: skip unnecessary preprocessing steps in grind when possible (#9369)
This PR optimizes the `grind` preprocessor by skipping unnecessary steps
when possible.
2025-07-14 22:05:02 +00:00
Cameron Zwarich
f224452971 chore: simplify box/unbox casting logic (#9368) 2025-07-14 21:51:09 +00:00
Sebastian Ullrich
caf815b009 feat: improve infer binder type failure message and range (#8263)
This PR improves the message and range of infer binder type failures.

---------

Co-authored-by: Joseph Rotella <7482866+jrr6@users.noreply.github.com>
2025-07-14 20:19:11 +00:00
Cameron Zwarich
c0079fd9dd perf: allow boxed scalars passed to scalar params to be borrowed (#9360) 2025-07-14 19:58:01 +00:00
Leonardo de Moura
cfb13b1689 perf: add unfoldReducible' using inShareCommon (#9367)
This PR implements a minor optimization to the `grind` preprocessor.
2025-07-14 19:04:04 +00:00
jrr6
105843519c doc: expand elab_as_elim docstring and fix typo (#9359)
This PR adds additional information from a recent Zulip thread to the
docstring for the `elab_as_elim` attribute and fixes the associated
example code.

The Zulip thread can be found
[here](https://leanprover.zulipchat.com/#narrow/channel/113488-general/topic/what.20is.20.60elab_as_elim.60/with/505631084).
2025-07-14 17:53:42 +00:00
Sebastian Ullrich
97698bfc38 chore: CI: use faster Windows runners for releases (#9357) 2025-07-14 16:26:22 +00:00
Sebastian Ullrich
7f1869016a chore: CI: do not use large runners for secondary jobs (#9352)
macOS in particular is expensive to use large machines for more than
necessary
2025-07-14 15:00:58 +00:00
Markus Himmel
0931033c72 chore: Grove: add some data (#9354) 2025-07-14 10:22:59 +00:00
Markus Himmel
a7789d863c chore: Grove: update and enable on master (#9353) 2025-07-14 09:21:51 +00:00
Leonardo de Moura
bcc6fb54c2 perf: use inShareCommon to skip preprocessing steps (#9351)
This PR optimizes the `grind` preprocessing steps by skipping steps when
the term is already present in the hash-consing table.
2025-07-14 04:53:49 +00:00
Cameron Zwarich
b04ee0de57 chore: remove outdated comments (#9349) 2025-07-14 01:15:36 +00:00
Cameron Zwarich
7a83adf10d refactor: rename mmodifyBody functions to modifyBodyM (#9348) 2025-07-14 01:01:46 +00:00
Leonardo de Moura
d642880b7d chore: remove leftovers (#9347)
after update stage0
2025-07-14 00:40:32 +00:00
Lean stage0 autoupdater
74206c755f chore: update stage0 2025-07-14 00:11:34 +00:00
Leonardo de Moura
c7b4d843e2 refactor: support for Nat in grind cutsat (#9340)
This PR modifies the encoding from `Nat` to `Int` used in `grind
cutsat`. It is simpler, more extensible, and similar to the generic
`ToInt`. After update stage0, we will be able to delete the leftovers.
2025-07-13 23:40:03 +00:00
Cameron Zwarich
c90cc392f7 fix: populate the xType field of FnBody.case (#9344)
This PR correctly populates the `xType` field of the `IR.FnBody.case`
constructor. It turns out that there is no obvious consequence for this
being incorrect, because it is conservatively recomputed by the `Boxing`
pass.
2025-07-13 21:56:07 +00:00
Leonardo de Moura
f298360ff9 refactor: more "efficient" contraint propagation theorems (#9343)
The certificates perform a single pass over the polynomials.
2025-07-13 19:52:43 +00:00
Leni Aniva
275e483885 refactor: Expose DeclNameGenerator idx (#9020)
This PR exposes the internal of DeclNameGenerator to facilitate merger
of two branches of goal state or proof snapshots.
2025-07-13 10:24:04 +00:00
Cameron Zwarich
e87ce2bd5b refactor: rename "irrelevant" to "erased" in IR (#9339)
This matches the terminology used by LCNF.
2025-07-13 04:51:34 +00:00
Cameron Zwarich
3c6a923f1b refactor: use the usize index in the CtorFieldInfo struct (#9337) 2025-07-13 03:05:13 +00:00
Cameron Zwarich
b25ef7682d chore: fix spacing (#9338) 2025-07-13 03:03:50 +00:00
Cameron Zwarich
71b5bf3ef6 fix: include ._closed decls in trace.Compiler.result output (#9336)
This PR changes the implementation of `trace.Compiler.result` to use the
decls as they are provided rather than looking them up in the LCNF mono
environment extension, which was seemingly done to save the trouble of
re-normalizing fvar IDs before printing the decl. This means that the
`._closed` decls created by the `extractClosed` pass will now be
included in the output, which was definitely confusing before if you
didn't know what was happening.
2025-07-13 02:24:00 +00:00
jrr6
8dfc71c4fd chore: remove superfluous whitespace from error message (#9335)
This PR fixes a typo that caused the "cannot infer resulting universe
level of inductive datatype" error message to have leading whitespace.
2025-07-12 23:04:02 +00:00
Leonardo de Moura
243bbd74a5 chore: compilation time for EMatch.lean (#9334)
This PR improves the compilation time for `EMatch.lean`
2025-07-12 22:01:16 +00:00
Cameron Zwarich
aba49508f1 refactor: port IR Checker to CompilerM (and thus CoreM) (#9331) 2025-07-12 15:25:46 +00:00
Leonardo de Moura
ae2a9b4688 perf: propagateEqUp (#9326)
This PR optimizes `propagateEqUp` used in `grind`.
2025-07-12 03:09:59 +00:00
Leonardo de Moura
d36fc8df67 perf: propagateBoolDiseq (#9325)
This PR optimizes the Boolean disequality propagator used in `grind`.
2025-07-12 02:20:48 +00:00
Leonardo de Moura
6c20cd08f1 perf: isDiseq and mkDiseqProof? in grind (#9324)
This PR improves the functions for checking whether two terms are
disequal in `grind`
2025-07-12 01:26:48 +00:00
Cameron Zwarich
46b04c8405 chore: lower Nat.zero in toMono (#9320)
This currently relies on the encoding pun of Nat.zero as the first
tagged constructor of Nat. Since Nat.succ is lowered to addition, it
makes sense to also lower Nat.zero to a zero literal. This might also
expose more optimization opportunities in the future.
2025-07-11 23:25:05 +00:00
Cameron Zwarich
efc101d3b4 chore: move Nat.succ lowering from toIR to toMono (#9319)
It makes more sense to do it here, since `cases` on `Nat` is also
lowered in `toMono`.
2025-07-11 22:49:41 +00:00
Cameron Zwarich
e2e36087e1 refactor: split noncomputable error into its own helper (#9314) 2025-07-11 17:30:22 +00:00
Cameron Zwarich
d4e11f754a chore: clean up loop over ctor fields (#9313) 2025-07-11 16:46:48 +00:00
Cameron Zwarich
837ea41ede fix: correctly compile irrelevant args to relevant ctor params (#9310)
This PR fixes IR constructor argument lowering to correctly handle an
irrelevant argument being passed for a relevant parameter in all cases.
This happened because constructor argument lowering (incompletely)
reimplemented general LCNF-to-IR argument lowering, and the fix is to
just adopt the generic helper functions. This is probably due to an
incomplete refactoring when the new compiler was still on a branch.
2025-07-11 15:29:12 +00:00
simon-dima
5778a3c0f2 chore: fix "isRuntimeBultinType" typo (#9307) 2025-07-11 12:27:07 +00:00
Lean stage0 autoupdater
668a892cdb chore: update stage0 2025-07-11 08:18:55 +00:00
Leonardo de Moura
0fdb63f258 perf: use mkCongrSimpForConst? (#9305)
This PR uses the `mkCongrSimpForConst?` API in `simp` to reduce the
number of times the same congruence lemma is generated. Before this PR,
`grind` would spend `1.5`s creating congruence theorems during
normalization in the `grind_bitvec2.lean` benchmark. It now spends
`0.6`s. This PR should make an even bigger difference after we merge
#9300.
2025-07-11 02:29:20 +00:00
Sebastian Graf
338456e765 feat: help simp and grind reasoning about Std.Do invariants (#9301)
This PR adds a `simp` and a `grind` annotation on `Zipper`-related
theorems to improve reasoning about `Std.Do` invariants.
2025-07-10 15:44:29 +00:00
Tasiro
18a82c04fc fix: remove BEq from (Array|Vector).(any|all)_push (#9285)
This PR removes the unnecessary requirement of `BEq α` for
`Array.any_push`, `Array.any_push'`, `Array.all_push`, `Array.all_push'`
as well as `Vector.any_push` and `Vector.all_push`.
2025-07-10 06:02:14 +00:00
Leonardo de Moura
4520206f4a chore: minor perf improvement (#9296) 2025-07-10 05:41:54 +00:00
Cameron Zwarich
9ee8e0c896 chore: remove outdated comment (#9294) 2025-07-10 03:29:22 +00:00
Leonardo de Moura
62dc8d64fa perf: use custom reduceCtorEq simproc in grind (#9293)
This PR replaces the `reduceCtorEq` simproc used in `grind` by a much
more efficient one. The default one use in `simp` is just overhead
because the `grind` normalizer is already normalizing arithmetic.
In a separate PR, we will push performance improvements to the default
`reduceCtorEq`.
2025-07-10 03:18:44 +00:00
Cameron Zwarich
7845154a3d refactor: base the IR phase of the compiler on CoreM (#9291) 2025-07-10 01:39:27 +00:00
Cameron Zwarich
66de09bc9c refactor: use getEnv/modifyEnv more in IR (#9290) 2025-07-10 00:01:56 +00:00
Cameron Zwarich
3e37eef9ea refactor: remove unused addBoxedVersion variants (#9289) 2025-07-09 23:44:18 +00:00
Cameron Zwarich
d3a4bb29a7 chore: remove comment indicating that implicit conversion should be removed (#9284) 2025-07-09 17:31:34 +00:00
Cameron Zwarich
1db5e35b59 chore: remove ABI hack for the old compiler (#9283) 2025-07-09 17:25:38 +00:00
Cameron Zwarich
efe5e9a752 refactor: remove unnecessary export attributes (#9281) 2025-07-09 16:55:00 +00:00
Cameron Zwarich
a4f38cc782 refactor: remove code marked for deletion after old compiler (#9280) 2025-07-09 15:30:11 +00:00
Cameron Zwarich
b579c5c7d8 fix: make compiler.extract_closed option work again after migration (#9279)
This PR fixes the `compiler.extract_closed` option after migrating it to
Lean (and adds a test so it would be caught in the future).
2025-07-09 14:31:58 +00:00
Cameron Zwarich
575adbae18 chore: remove now-unused Lean.Compiler.AtMostOnce (#9278) 2025-07-09 14:31:15 +00:00
Cameron Zwarich
5e19c47710 chore: remove now-unused Lean.Compiler.ConstFolding (#9277) 2025-07-09 14:18:32 +00:00
Cameron Zwarich
a7675ad4b2 chore: remove unnecessary export attributes in IR code (#9276) 2025-07-09 14:18:07 +00:00
Cameron Zwarich
d2e604f74d feat: remove the old compiler (#9275)
This PR removes the old compiler written in C++.
2025-07-09 06:00:46 +00:00
Chase Johnson
4c93ab7602 fix: typos in ISO 8601 formatted datetime (#9235) (#9263)
This PR fixes `toISO8601String` to produce a string that conforms to the
ISO 8601 format specification. The previous implementation separated the
minutes and seconds fragments with a `.` instead of a `:` and included
timezone offsets without the hour and minute fragments separated by a
`:`.

Closes #9235
2025-07-09 05:52:25 +00:00
Cameron Zwarich
625de14b23 chore: remove options from 'run' tests that are now meaningless (#9274) 2025-07-09 05:26:58 +00:00
Cameron Zwarich
b13b916b7e chore: move compiler.ir trace class registration to Lean (#9273) 2025-07-09 05:15:38 +00:00
Cameron Zwarich
9f2b796639 chore: move compiler.extract_closed option from C++ to Lean (#9272) 2025-07-09 04:36:16 +00:00
Leonardo de Moura
4955dde748 perf: grind normalizer (#9271)
This PR improves the performance of the formula normalizer used in
`grind`.
2025-07-09 03:49:44 +00:00
Cameron Zwarich
3b18ae2209 chore: move llvm.cpp from library/compiler to library (#9270) 2025-07-09 02:13:08 +00:00
Cameron Zwarich
9620cb1b90 chore: have shell.cpp use library/util.h rather than library/compiler… (#9269) 2025-07-09 01:41:04 +00:00
Cameron Zwarich
d664b6b888 fix: move lean_add_extern implementation to Lean (#9268)
This PR moves the implementation of `lean_add_extern`/`addExtern` from
C++ into Lean. I believe is the last C++ helper function from the
library/compiler directory being relied upon by the new compiler. I put
it into its own file and duplicated some code because this function
needs to execute in CoreM, whereas the other IR functions live in their
own monad stack. After the C++ compiler is removed, we can move the IR
functions into CoreM.
2025-07-09 00:02:56 +00:00
Leonardo de Moura
192c0c8e67 perf: skip canonicalization of Decidable instances and add congruence-closure support (#9267)
This PR optimizes support for `Decidable` instances in `grind`. Because
`Decidable` is a subsingleton, the canonicalizer no longer wastes time
normalizing such instances, a significant performance bottleneck in
benchmarks like `grind_bitvec2.lean`. In addition, the
congruence-closure module now handles `Decidable` instances, and can
solve examples such as:
```lean
example (p q : Prop) (h₁ : Decidable p) (h₂ : Decidable (p ∧ q)) : (p ↔ q) → h₁ ≍ h₂ := by
  grind
```
2025-07-08 21:55:40 +00:00
Cameron Zwarich
cec0c82f1c fix: support .mdata in LCNF mono types (#9266)
This PR adds support for `.mdata` in LCNF mono types (and then drops it
at the IR type level instead). This better matches the behavior of
extern decls in the C++ code of the old compiler, which is still being
used to create extern decls at the moment and will soon be replaced.

This is covered by existing tests.
2025-07-08 21:35:30 +00:00
Cameron Zwarich
4ff4ed88bc chore: move the IR interpreter from library/compiler to library (#9265) 2025-07-08 20:45:55 +00:00
Cameron Zwarich
a05311d1ec chore: split IR types out into their own header file (#9264) 2025-07-08 19:49:27 +00:00
Cameron Zwarich
f675ee2062 chore: remove unnecessary include of ir_interpreter.h (#9262) 2025-07-08 18:09:20 +00:00
Cameron Zwarich
cb127b42ac chore: rename compileDeclsNew to compileDeclsImpl (#9261) 2025-07-08 17:55:11 +00:00
Cameron Zwarich
c7c5de38b3 chore: clean up getDeclNamesForCodeGen (#9259) 2025-07-08 17:00:46 +00:00
Cameron Zwarich
6ad12525ad chore: make compileDecls and friends take an Array rather than a List (#9257) 2025-07-08 16:18:44 +00:00
Cameron Zwarich
bb5df157bc chore: remove unused optional parameter from compileDecls (#9255) 2025-07-08 15:31:06 +00:00
Sebastian Graf
77442f5486 chore: revert DefEq changes until it has passed proper review (#9254) 2025-07-08 14:54:18 +00:00
Hagb (Junyu Guo 郭俊余)
97aca690d0 fix: walk through types of axioms in collectAxioms (#8842)
This PR fixes the bug that `collectAxioms` didn't collect axioms
referenced by other axioms. One of the results of this bug is that
axioms collected from a theorem proved by `native_decide` may not
include `Lean.trustCompiler`.

Closes #8840.
2025-07-08 14:42:11 +00:00
Cameron Zwarich
173629ebd5 chore: remove compiler.enableNew option (#9252) 2025-07-08 14:17:05 +00:00
Cameron Zwarich
beeeead99f chore: remove mentions of the compiler being new from trace messages (#9253) 2025-07-08 14:15:15 +00:00
Lean stage0 autoupdater
d38c36001d chore: update stage0 2025-07-08 14:35:54 +00:00
Sebastian Graf
7386cc3b12 chore: Turn Std.Do.Triple elaborator into a macro (#9251)
This PR demotes the builtin elaborators for `Std.Do.PostCond.total` and
`Std.Do.Triple` into macros, following the DefEq improvements of #9015.

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-07-08 13:57:22 +00:00
Henrik Böving
7958e01b1c perf: basic micro benchmarks for Std.Data.TreeMap (#9250)
This PR adds micro-benchmarks for `Std.Data.TreeMap` in the same style
as for the hashmap.
2025-07-08 13:55:13 +00:00
Lean stage0 autoupdater
47e8483b38 chore: update stage0 2025-07-08 13:35:02 +00:00
Sebastian Graf
0b2bdaebd6 fix: More stuck definitional equalities involving smart unfoldings (#8766) (#9015)
This PR makes `isDefEq` detect more stuck definitional equalities
involving smart unfoldings. Specifically, if `t =?= defn ?m` and `defn`
matches on its argument, then this equality is stuck on `?m`. Prior to
this change, we would not see this dependency and simply return `false`.

Fixes #8766.

Co-authored-by: Kyle Miller <kmill31415@gmail.com>
2025-07-08 12:56:50 +00:00
Kyle Miller
ac600853c0 fix: let the congr tactic handle "under-applied" applications (#9225)
This PR improves the `congr` tactic so that it can handle function
applications with fewer arguments than the arity of the head function.
This also fixes a bug where `congr` could not make progress with
`Set`-valued functions in Mathlib, since `Set` was being unfolded and
making such functions have an apparently higher arity.

This addresses issue #2128 for the `congr` tactic, but not `simp` and
others.
2025-07-08 11:48:08 +00:00
Luisa Cicolini
77a0c2bf9b feat: add BitVec.clzAuxRec_eq_clzAuxRec_of_getLsbD_false (#9249)
This PR adds theorem `BitVec.clzAuxRec_eq_clzAuxRec_of_getLsbD_false` as
a more general statement than `BitVec.clzAuxRec_eq_clzAuxRec_of_le`,
replacing the latter in the bitblaster too.
2025-07-08 10:40:40 +00:00
Henrik Böving
46c43c3ecb perf: first set of HashMap benchmarks (#9233)
This PR adds basic microbenchmarks for `Std.Data.HashMap`
2025-07-08 08:11:52 +00:00
Cameron Zwarich
6de68dd8ef chore: remove compiler.enableNew=true from a test and rename it (#9247) 2025-07-08 05:49:57 +00:00
Cameron Zwarich
97fd75c660 chore: remove redundancy in toMono trivial structure check (#9245) 2025-07-08 05:07:16 +00:00
Leonardo de Moura
cf6a182f69 chore: profile grind satellite solvers (#9246) 2025-07-08 05:05:39 +00:00
Leonardo de Moura
655c7ab548 perf: optimize instance generation in grind linarith (#9244)
This PR improves the instance generation in the `grind linarith` module.
2025-07-08 05:04:06 +00:00
Cameron Zwarich
70368ed1a5 chore: reduce rightward drift (#9243) 2025-07-08 03:41:37 +00:00
Cameron Zwarich
765f98770b chore: improve pattern matching (#9242) 2025-07-08 03:36:34 +00:00
Leonardo de Moura
05630fc149 perf: synthesize ToInt instances on demand (#9241)
This PR ensures that the type class instances used to implement the
`ToInt` adapter (in `grind cutsat`) are generated on demand.
2025-07-08 02:36:16 +00:00
Cameron Zwarich
2d173615ba chore: remove unreachable branches (#9240)
There is a global `tryIrDecl?` check above all of this code.
2025-07-08 00:16:12 +00:00
Cameron Zwarich
b2920d6410 chore: consolidate noncomputable diagnostics (#9239) 2025-07-07 23:39:49 +00:00
Leonardo de Moura
aee2da809a chore: test for issue #9216 (#9238)
This PR adds a new test with the analysis for issue #9216.
2025-07-07 23:25:25 +00:00
Leonardo de Moura
2bf9130b63 chore: tests for #9206 (#9237)
Add examples in issue #9206 and Zulip thread as tests for `grind`.
2025-07-07 23:01:38 +00:00
Sebastian Graf
67d9d9d936 chore: Update CODEOWNERS (#9232)
Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-07-07 13:11:41 +00:00
Sebastian Graf
0c5946ab3f feat: Make Std.Do universe polymorphic (#9194)
This PR makes the logic and tactics of `Std.Do` universe polymorphic, at
the cost of a few definitional properties arising from the switch from
`Prop` to `ULift Prop` in the base case `SPred []`.

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-07-07 13:11:41 +00:00
Paul Reichert
98e4b2882f refactor: migrate to new ranges (#8841)
This PR migrates usages of `Std.Range` to the new polymorphic ranges.

This PR unfortunately increases the transitive imports for
frequently-used parts of `Init` because the ranges now rely on iterators
in order to provide their functionality for types other than `Nat`.
However, iteration over ranges in compiled code is as efficient as
before in the examples I checked. This is because of a special
`IteratorLoop` implementation provided in the PR for this purpose.

There were two issues that were uncovered during migration:

* In `IndPredBelow.lean`, migrating the last remaining range causes
`compilerTest1.lean` to break. I have minimized the issue and came to
the conclusion it's a compiler bug. Therefore, I have not replaced said
old range usage yet (see #9186).
* In `BRecOn.lean`, we are publicly importing the ranges. Making this
import private should theoretically work, but there seems to be a
problem with the module system, causing the build to panic later in
`Init.Data.Grind.Poly` (see #9185).
* In `FuzzyMatching.lean`, inlining fails with the new ranges, which
would have led to significant slowdown. Therefore, I have not migrated
this file either.
2025-07-07 12:41:53 +00:00
Henrik Böving
6e98dfbc64 perf: bv_decide rewriting benchmark (#9231)
This PR adds a benchmark for the rewriting engine of bv_decide, based on
a problem extracted from
SMT-LIB. Note that this problem has significant elaboration time itself
due to its sheer size though
the overall execution time is split approximately 50:50 between
elaboration and rewriting.
2025-07-07 10:24:08 +00:00
Cameron Zwarich
e7e4119cf4 chore: move handling of Quot.{mk, lcInv} from toIR to toMono (#9230) 2025-07-07 05:11:23 +00:00
Cameron Zwarich
6cf8828ce7 chore: remove unused code in the axiom path of toIR (#9229)
This must have been the result of an earlier refactoring, since there
are no axioms with IR decls.
2025-07-07 03:45:39 +00:00
Leonardo de Moura
5d46391dde perf: generate grind ring instances on demand (#9228)
This PR improves the startup time for `grind ring` by generating the
required type classes on demand. This optimization is particularly
relevant for files that make hundreds of calls to `grind`, such as
`tests/lean/run/grind_bitvec2.lean`. For example, before this change,
`grind` spent 6.87 seconds synthesizing type classes, compared to 3.92
seconds after this PR.
2025-07-07 03:29:42 +00:00
Cameron Zwarich
c9debdaf2a chore: move lcUnreachable handling from toIR to toLCNF (#9227)
We can probably remove `lcUnreachable` once we delete the old compiler,
but for now it makes more sense to move it earlier, since LCNF already
has `Code.unreachable`.
2025-07-07 02:17:30 +00:00
Cameron Zwarich
9b7a14b156 fix: erase args for erased app params in toMono (#9224)
This PR changes the `toMono` pass to consider the type of an application
and erase all arguments corresponding to erased params. This enables a
lightweight form of relevance analysis by changing the mono type of a
decl. I would have liked to unify this with the behavior for
constructors, but my attempt to give constructors the same behavior in
#9222 (which was in preparation for this PR) had a minor performance
regression that is really incidental to the change. Still, I decided to
hold off on it for the time being. In the future, we can hopefully
extend this to constructors, extern decls, etc.
2025-07-06 23:27:48 +00:00
Cameron Zwarich
ff5d96096a chore: use Array instead of PArray in elimDeadBranches state (#9220)
This is alway used linearly.
2025-07-06 21:31:47 +00:00
Cameron Zwarich
53d4139cf1 chore: revert #9218 (#9223)
I thought I understood why the the minor !bench performance regression
was spurious, but now I'm not so sure.
2025-07-06 15:33:10 +00:00
Cameron Zwarich
c1f1287e24 fix: delete code with false assumption that LCNF local vars can occur in types (#9221)
This PR removes code that has the false assumption that LCNF local vars
can occur in types. There are other comments in `ElimDead.lean`
asserting that this is not possible, so this must have been a change
early in the development of the new compiler.
2025-07-06 15:04:13 +00:00
Cameron Zwarich
4322a0c7d3 fix: make LCNF elimDeadBranches more optimistic on unsafe decls (#9218)
This PR makes the LCNF `elimDeadBranches` pass handle unsafe decls a bit
more carefully. Now the result of an unsafe decl will only become ⊤ if
there is value flow from a recursive call.
2025-07-06 13:28:07 +00:00
Cameron Zwarich
d0e097cd1d chore: remove IRType.{isStruct,isUnion} (#9219)
These are used by the checker for `.ctor`, but I don't think that that
unboxed types will reuse `.ctor`, whose implementation details are
intimately connected to our runtime representation of objects.
2025-07-06 13:24:24 +00:00
Cameron Zwarich
bd7e6c3c61 chore: use ``-prefixed Names when possible (#9217) 2025-07-06 12:58:13 +00:00
Leonardo de Moura
1443982924 perf: restore cache at withoutModifyingMCtx (#9215)
instead of resetting it.
2025-07-06 04:18:37 +00:00
Leonardo de Moura
15586e28a8 feat: local and scoped grind_pattern (#9214)
This PR implements support for local and scoped `grind_pattern`
commands.
2025-07-05 20:36:56 -07:00
Cameron Zwarich
6f5fdf5c3e chore: adopt do notation in IR checker (#9213)
I plan to make some changes here in the future, so I figured it would be
good to make it a bit more idiomatic first.
2025-07-06 02:39:03 +00:00
Eric Wieser
bd06e07624 fix: make the name in dependsOnNoncomputable clickable (#9207)
This PR makes the offending declaration clickable in the error message
produced when something should be marked `noncomputable`.
2025-07-05 21:28:35 +00:00
Leonardo de Moura
2cf6c2ddc9 feat: track type class inference time in grind (#9211) 2025-07-05 20:24:32 +00:00
Cameron Zwarich
38d4dc7058 chore: add deriving Repr to IR.Arg (#9210)
This is helpful when debugging.
2025-07-05 19:57:41 +00:00
Cameron Zwarich
149fc2173c fix: correctly handle constructor params in elimDeadBranches (#9209)
This PR changes the `getLiteral` helper function of `elimDeadBranches`
to correctly handle inductives with constructors. This function is not
used as often as it could be, which makes this issue rare to hit outside
of targeted test cases.
2025-07-05 19:52:12 +00:00
Leonardo de Moura
12536d2015 chore: remove old grind normalizers (#9205) 2025-07-05 06:19:34 +00:00
Cameron Zwarich
36c036d952 chore: replace custom instances with deriving for IR types (#9204) 2025-07-05 05:43:07 +00:00
Lean stage0 autoupdater
bebffc0d20 chore: update stage0 2025-07-05 05:51:10 +00:00
Leonardo de Moura
dd7bc0e643 perf: simproc for grind normalizations and decls to unfold (#9202)
This PR extends the `Eq` simproc used in `grind`. It covers more cases
now. It also adds 3 reducible declarations to the list of declarations
to unfold.
2025-07-05 05:13:49 +00:00
Cameron Zwarich
264aac4a33 chore: convert local functions to use where instead (#9203) 2025-07-05 05:10:55 +00:00
Leonardo de Moura
d981a2a9a8 chore: remove old normalizers (#9201) 2025-07-05 02:43:00 +00:00
Lean stage0 autoupdater
2ca6c3bf4d chore: update stage0 2025-07-05 02:09:15 +00:00
Leonardo de Moura
722ab706c8 perf: normalize exists expressions using a simproc in grind (#9200)
This PR implements `exists` normalization using a simproc instead of
rewriting rules in grind. This is the first part of the PR, after update
stage0, we must remove the normalization theorems.
2025-07-05 01:37:36 +00:00
Lean stage0 autoupdater
9697c7264d chore: update stage0 2025-07-05 01:13:38 +00:00
Leonardo de Moura
01b0c3e0cc perf: unfold GT.gt and GE.ge in the grind normalizer (#9199) 2025-07-05 00:41:43 +00:00
Cameron Zwarich
37cffbda51 fix: consider Prop-rebundled higher-order params to be fixed (#9198)
This PR changes the compiler's specialization analysis to consider
higher-order params that are rebundled in a way that only changes their
`Prop` arguments to be fixed. This means that they get specialized with
a mere `@[specialize]`, rather than the compiler having to opt-in to
more aggressive parameter-specific specialization.
2025-07-05 00:02:24 +00:00
Leonardo de Moura
f5e47480f2 chore: #9196 part 2 (#9197)
#9196 part 2 after update stage0
2025-07-04 23:27:00 +00:00
Lean stage0 autoupdater
66ffd8d5c2 chore: update stage0 2025-07-04 21:12:35 +00:00
Leonardo de Moura
162e81af57 perf: normalize forall expressions using a simproc in grind (#9196)
This PR implements `forall` normalization using a simproc instead of
rewriting rules in `grind`. This is the first part of the PR, after
update stage0, we must remove the normalization theorems.
2025-07-04 20:41:02 +00:00
Leonardo de Moura
2bf4192ab7 fix: unexpected kernel projection issue in grind (#9193)
This PR fixes the unexpected kernel projection issue reported by issue
#9187

closes #9187
2025-07-04 17:17:40 +00:00
Lean stage0 autoupdater
106d50e46c chore: update stage0 2025-07-04 13:05:44 +00:00
Sebastian Graf
d89f336db2 fix: Scope PostCond.total to Std.Do by making it non-builtin (#9184)
This PR fixes stealing of `⇓` syntax by the new notation for total
postconditions by demoting it to non-builtin syntax and scoping it to
`Std.Do`.

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-07-04 12:33:45 +00:00
Leonardo de Moura
e9a55bfff7 chore: move test to run (#9183) 2025-07-04 00:33:39 +00:00
Leonardo de Moura
55d5ace68e feat: pattern inference using symbol priorities in grind (#9182)
This PR tries to improve the E-matching pattern inference for `grind`.
That said, we still need better tools for annotating and maintaining
`grind` annotations in libraries.

closes #9125
2025-07-03 16:47:38 -07:00
Sebastian Ullrich
357b5f9ed8 chore: CI: restore cache in update-stage0 (#9179)
Avoid rebuilding stage 0 all the time
2025-07-03 20:55:14 +00:00
Cameron Zwarich
b1e5ecc582 chore: add a #guard_msgs to tests/lean/run/instanceUsingFalse.lean (#9180)
This test originally failed by hitting unreachable code, which is caught
by the test harness, but it's probably good to also check the result.
2025-07-03 20:42:12 +00:00
Paul Reichert
cd445dce76 refactor: replace some Subarray functions with generic slice functions (#9017)
This PR removes the `Subarray`-specific `toArray`, `foldlM` and `foldl`
methods and instead provides these operations on `Std.Slice`, which are
implemented with the `ToIterator` instance of the slice. Calling
`subarray.toArray` etc. still works, since `Subarray` is an abbreviation
for `Slice _`.

Because the benchmarks are not so clear, to be safe, I will merge this
only after the release. In contrast to the ranges, the iteration over
slices is not quite as efficient as the old `Subarray`-specific
implementation, which would require either more optimizations in the
iterator library (special `IteratorLoop` and `IteratorCollect`
implementations) or better unboxing support by the compiler.
2025-07-03 19:33:19 +00:00
Cameron Zwarich
501993eb7f fix: don't pull instances depending on erased propositions (#9177)
This PR makes the `pullInstances` pass avoid pulling any instance
expressions containing erased propositions, because we don't correctly
represent the dependencies that remain after erasure.
2025-07-03 19:17:25 +00:00
Mac Malone
9ed51959ef refactor: ignore the setup-file header in the server for now (#9163)
This PR disables the use of the header produced by `lake setup-file` in
the server for now. It will be re-enabled once Lake takes into account
the header given by the server when processing workspace modules.
Without that, `setup-file` header can produce odd behavior when the file
on disk and in an editor disagree on whether the file participates in
the module system.
2025-07-03 17:58:07 +00:00
Eric Wieser
0106ca3bec fix: undefined symbol without LEAN_USE_GMP (#9106)
This PR fixes `undefined symbol: lean::mpz::divexact(lean::mpz const&,
lean::mpz const&)` when building without `LEAN_USE_GMP`

This fixes a regression in #8089
2025-07-03 16:50:21 +00:00
Sebastian Ullrich
ba7135d73c fix: exposed wellfounded recursion (#9173)
This PR fixes an incompatibility in the experimental module system when
trying to combine wellfounded recursion with public exposed definitions.
2025-07-03 16:48:15 +00:00
Joachim Breitner
47b795a302 chore: CI: run stage0 update on faster runner (#9178)
To avoid it losing races against the merge queue.
2025-07-03 16:14:46 +00:00
Lean stage0 autoupdater
0b6df7d6a4 chore: update stage0 2025-07-03 16:14:28 +00:00
Sebastian Graf
c6689584ea fix: split ifs in mvcgen rather than relying on a spec (#9176)
This PR makes `mvcgen` split ifs rather than applying specifications.
Doing so fixes a bug reported by Rish.

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-07-03 14:29:17 +00:00
grunweg
a7c982204e doc: use modern configuration syntax in the Simp.Config documentation (#9174)
The new config syntax is preferred for new code: change the
documentation to use it.

This was [discussed on
zulip](https://leanprover.zulipchat.com/#narrow/channel/113488-general/topic/Using.20config.20vs.20optConfig.20in.20language.20documentation/with/526948836).
2025-07-03 14:16:37 +00:00
François G. Dorais
77d79f705f fix: typos in Std.Classes.Ord.Basic (#9145)
This PR fixes two typos.
2025-07-03 12:04:25 +00:00
Leonardo de Moura
ff130a25a2 fix: bug at matchEqBwdPat (#9172)
This PR fixes a bug at `matchEqBwdPat`. The type may contain pattern
variables.
2025-07-03 07:05:01 +00:00
Kim Morrison
c06af84d9f fix: refactor grind's module/ring design to avoid a diamond (#9168)
This PR resolves a defeq diamond, which caused a problem in Mathlib:
```
import Mathlib

example (R : Type) [I : Ring R] :
  @AddCommGroup.toGrindIntModule R (@Ring.toAddCommGroup R I) =
    @Lean.Grind.Ring.instIntModule R (@Ring.toGrindRing R I) := rfl -- fails
```
2025-07-03 06:50:46 +00:00
Leonardo de Moura
5f818826d1 feat: add [grind symbol <prio>] attribute (#9169)
This PR adds the attribute `[grind symbol <prio>]`. This is just the
first part of the PR.
2025-07-03 06:06:55 +00:00
Cameron Zwarich
c8ab8f45aa chore: share duplicated code for enum scalar representation (#9170) 2025-07-03 05:33:35 +00:00
Mac Malone
6f85e32501 fix: lake: recreate static archives & use T, not --thin (#9165)
This PR fixes two issues with Lake's process of creating static
archives.

Lake now always recreates static archives by first deleting any existing
one and then recreating it. `ar rcs` does not remove delete files, so
running it when the archive already exists can leave behind "ghost"
symbols of removed object files.

Second, Lake now use `T` rather than `--thin` to create thin archives.
While `--thin` is the recommended spelling, older versions of LLVM `ar`
do not support it. Thus, either choice produces tradeoffs. `T` is chosen
to make Lake consistent with the Lean core's own (Make) build scripts.
2025-07-03 03:33:10 +00:00
Cameron Zwarich
174b1301d8 chore: remove VarInfo defaults in IR RC pass (#9167)
These defaults don't make the code easier to understand.
2025-07-03 03:15:07 +00:00
Cameron Zwarich
01d32aa408 chore: add test for #9156 after stage0 update (#9166)
Fixes #9156.
2025-07-03 02:06:21 +00:00
Lean stage0 autoupdater
c832577470 chore: update stage0 2025-07-03 01:40:52 +00:00
Cameron Zwarich
cc7c9b48a0 fix: don't inline computed fields _override implementations in base phase (#9159)
This PR enforces the non-inlining of _override impls in the base phase
of LCNF compilation. The current situation allows for constructor/cases
mismatches to be exposed to the simplifier, which triggers an assertion
failure. The reason this didn't show up sooner for Expr is that Expr has
a custom extern implementation of its computed field getter.

Fixes #9156.
2025-07-03 00:26:01 +00:00
Cameron Zwarich
2b788b1a62 chore: make tests/lean/run/2291.lean less sensitive (#9164)
This test was originally checked in for a panic in the pretty printer,
but at some point the output of every LCNF simp pass was added to
#guard_msgs output. Since this is printing LCNF built by the stage0
compiler, this causes a lot of unnecessary churn.
2025-07-02 23:27:06 +00:00
Mac Malone
2e8102424f refactor: lake: use r for ir key in content hashes (#9162)
This PR changes the key Lake uses for the `,ir` artifact in the content
hash data structure to `r`, maintaining the convention of single
character key names.
2025-07-02 22:59:13 +00:00
Rob23oba
a0bb5f4961 chore: fixes for #9158 after stage0 update (#9161) 2025-07-02 18:46:21 +00:00
Lean stage0 autoupdater
921d252253 chore: update stage0 2025-07-02 18:26:42 +00:00
Rob23oba
3ede96accc fix: use patternIgnore(...) in grind syntax (#9158)
This PR fixes the syntax of `grind` modifiers to use `patternIgnore` for
cases where both unicode and ascii variants are matched. This fixes an
issue where several variants of grind syntax weren't accepted (e.g.
`@[grind ← gen]`). Additionally, this reduces the chance that we get
another syntax matching bootstrap hell.
2025-07-02 17:14:21 +00:00
Rob23oba
7aca460c11 fix: add groups around simpLemma and grindLemma syntax (#9157)
This PR wraps `simpLemma` and `grindLemma` in `ppGroup` to make sure
that the modifiers aren't printed separately from the term / identifier.
Example:
```
simp only [very_long_lemma_oh_no_can_you_please_stop_we're_getting_to_the_limit, ←
  wait_this_is_rewritten_backwards_oh_uhh_where's_the_arrow_you_ask?_oh_wait_it's_up_there!]
==>
simp only [very_long_lemma_oh_no_can_you_please_stop_we're_getting_to_the_limit,
  ← wait_this_is_rewritten_backwards_and_wow_it's_very_clear_and_obvious]
```
2025-07-02 15:11:51 +00:00
Cameron Zwarich
8954354216 fix: tighten IR typing rules for applications of closures (#9154)
This PR tightens the IR typing rules around applications of closures.
When re-reading some code, I realized that the code in `mkPartialApp`
has a clear typo—`.object` and `type` should be swapped. However, it
doesn't matter, because later IR passes smooth out the mismatch here. It
makes more sense to be strict up-front and require applications of
closures to always return an `.object`.
2025-07-02 14:06:24 +00:00
Joachim Breitner
977ae92e43 fix: module system: remove WellFounded-specific hacks (#9143)
This PR removes a rather ugly hack in the module system, exposing the
bodies of theorems whose type mention `WellFounded`.

The original motivation was that reducing well-founded definitions (e.g.
in `by rfl`) requires reducing proofs, so they need to be available.

But reducing proofs is generally fraught with peril, and we have been
nudging our users away from using it for a while, e.g. in #5182. Since
the module system is opt-in and users will gradually migrate to it, it
may be reasonable to expect them to avoid reducing well-founded
recursion in the process

This way we don't need hacks like this (which, without evidence, I
believe would be incomplete anyways) and we get the nice guarantee that
within the module system, theorems bodies are always private.
2025-07-02 11:58:50 +00:00
Sebastian Ullrich
2f162005b8 refactor: module-ize Std.Data.DHashMap (#9098) 2025-07-02 10:00:17 +00:00
Paul Reichert
84cd2c49eb feat: remove unnecessary decidability requirements (#9096)
This PR removes some unnecessary `Decidable*` instance arguments by
using lemmas in the `Classical` namespace instead of the `Decidable`
namespace.

This might lead to some additional dependency on classical axioms, but
large parts of the standard library are relying on them either way.
2025-07-02 06:20:50 +00:00
Paul Reichert
561f347f5a feat: universe-polymorphic loop operations on pure iterators (#9135)
This PR allows the result type of `forIn`, `foldM` and `fold` on pure
iterators (`Iter`) to be in a different universe than the iterators.
2025-07-02 06:18:20 +00:00
Leonardo de Moura
a4a3a3b596 feat: improve linarith markVars (#9153)
This PR improves the linarith `markVars`, and ensures it does not
produce spurious issue messages.
2025-07-02 05:05:10 +00:00
David Thrane Christiansen
8c0cff83bd doc: update obsolete docstring for registerDerivingHandler (#9152)
This PR fixes an obsolete docstring for `registerDerivingHandler`
2025-07-02 04:03:00 +00:00
Leonardo de Moura
094dd588d6 chore: simproc and helper theorems for grind (#9151) 2025-07-02 03:57:12 +00:00
Rob23oba
e6954b7837 fix: revert state on compilation failure (new compiler) (#8691)
This PR ensures that the state is reverted when compilation using the
new compiler fails. This is especially important for noncomputable
sections where the compiler might generate half-compiled functions which
may then be erroneously used while compiling other functions.
2025-07-02 03:42:00 +00:00
Leonardo de Moura
4a539715c8 fix: missing case at CommRing.toPoly (#9150)
This PR adds a missing case in the `toPoly` function used in `grind`.
2025-07-02 02:53:48 +00:00
Leonardo de Moura
2b1b2ed45c feat: pow_add for any semirings in grind (#9149)
This PR generalizes the `a^(m+n)` grind normalizer to any semirings.
Example:
```
variable [Field R]

example (M : R) (h₀ : M ≠ 0) {n : Nat} (hn : n > 0) : M ^ n / M = M ^ (n - 1) := by
  cases n <;> grind
```
2025-07-02 01:43:35 +00:00
Leonardo de Moura
b67fb4fa66 feat: polynomial operations with deep recursion and heartbeat checks (#9146)
This PR adds "safe" polynomial operations to `grind ring`. The use the
usual combinators: `withIncRecDepth` and `checkSystem`.
2025-07-02 00:05:28 +00:00
Cameron Zwarich
2864efb222 feat: support enums modulo irrelevance (#9144)
This PR adds support for representing more inductive as enums,
summarized up as extending support to those that fail to be enums
because of parameters or irrelevant fields. While this is nice to have,
it is actually motivated by correctness of a future desired
optimization. The existing type representation is unsound if we
implement `object`/`tobject` distinction between values guaranteed to be
an object pointer and those that may also be a tagged scalar. In
particular, types like the ones added in this PR's tests would have all
of their constructors encoded via tagged values, but under the natural
extension of the existing rules of type representation they would be
considered `object` rather than `tobject`.
2025-07-01 22:35:50 +00:00
Cameron Zwarich
f91d6ce16f chore: cache IR types of named types (#9140)
This PR converts the `lowerEnumToScalarType?` cache to a cache of IR
types of named types. This is more sensible than just focusing on the
enum optimization, and due to uniform representation of polymorphism we
have to compile `Constant T1` and `Constant T2` to the same
representation.
2025-07-01 21:39:05 +00:00
dependabot[bot]
8e5dfb0fd1 chore: CI: bump softprops/action-gh-release from 2.2.2 to 2.3.2 (#9139)
Bumps
[softprops/action-gh-release](https://github.com/softprops/action-gh-release)
from 2.2.2 to 2.3.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/softprops/action-gh-release/releases">softprops/action-gh-release's
releases</a>.</em></p>
<blockquote>
<h2>v2.3.2</h2>
<ul>
<li>fix: revert fs <code>readableWebStream</code> change</li>
</ul>
<h2>v2.3.1</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<h3>Bug fixes 🐛</h3>
<ul>
<li>fix: fix file closing issue by <a
href="https://github.com/WailGree"><code>@​WailGree</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/629">softprops/action-gh-release#629</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/WailGree"><code>@​WailGree</code></a>
made their first contribution in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/629">softprops/action-gh-release#629</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/softprops/action-gh-release/compare/v2.3.0...v2.3.1">https://github.com/softprops/action-gh-release/compare/v2.3.0...v2.3.1</a></p>
<h2>v2.3.0</h2>
<!-- raw HTML omitted -->
<ul>
<li>Migrate from jest to vitest</li>
<li>Replace <code>mime</code> with <code>mime-types</code></li>
<li>Bump to use node 24</li>
<li>Dependency updates</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/softprops/action-gh-release/compare/v2.2.2...v2.3.0">https://github.com/softprops/action-gh-release/compare/v2.2.2...v2.3.0</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md">softprops/action-gh-release's
changelog</a>.</em></p>
<blockquote>
<h2>2.3.2</h2>
<ul>
<li>fix: revert fs <code>readableWebStream</code> change</li>
</ul>
<h2>2.3.1</h2>
<h3>Bug fixes 🐛</h3>
<ul>
<li>fix: fix file closing issue by <a
href="https://github.com/WailGree"><code>@​WailGree</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/629">softprops/action-gh-release#629</a></li>
</ul>
<h2>2.3.0</h2>
<ul>
<li>Migrate from jest to vitest</li>
<li>Replace <code>mime</code> with <code>mime-types</code></li>
<li>Bump to use node 24</li>
<li>Dependency updates</li>
</ul>
<h2>2.2.2</h2>
<h2>What's Changed</h2>
<h3>Bug fixes 🐛</h3>
<ul>
<li>fix: updating release draft status from true to false by <a
href="https://github.com/galargh"><code>@​galargh</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/316">softprops/action-gh-release#316</a></li>
</ul>
<h3>Other Changes 🔄</h3>
<ul>
<li>chore: simplify ref_type test by <a
href="https://github.com/steinybot"><code>@​steinybot</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/598">softprops/action-gh-release#598</a></li>
<li>fix(docs): clarify the default for tag_name by <a
href="https://github.com/muzimuzhi"><code>@​muzimuzhi</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/599">softprops/action-gh-release#599</a></li>
<li>test(release): add unit tests when searching for a release by <a
href="https://github.com/rwaskiewicz"><code>@​rwaskiewicz</code></a> in
<a
href="https://redirect.github.com/softprops/action-gh-release/pull/603">softprops/action-gh-release#603</a></li>
<li>dependency updates</li>
</ul>
<h2>2.2.1</h2>
<h2>What's Changed</h2>
<h3>Bug fixes 🐛</h3>
<ul>
<li>fix: big file uploads by <a
href="https://github.com/xen0n"><code>@​xen0n</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/562">softprops/action-gh-release#562</a></li>
</ul>
<h3>Other Changes 🔄</h3>
<ul>
<li>chore(deps): bump <code>@​types/node</code> from 22.10.1 to 22.10.2
by <a href="https://github.com/dependabot"><code>@​dependabot</code></a>
in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/559">softprops/action-gh-release#559</a></li>
<li>chore(deps): bump <code>@​types/node</code> from 22.10.2 to 22.10.5
by <a href="https://github.com/dependabot"><code>@​dependabot</code></a>
in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/569">softprops/action-gh-release#569</a></li>
<li>chore: update error and warning messages for not matching files in
files field by <a
href="https://github.com/ytimocin"><code>@​ytimocin</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/568">softprops/action-gh-release#568</a></li>
</ul>
<h2>2.2.0</h2>
<h2>What's Changed</h2>
<h3>Exciting New Features 🎉</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="72f2c25fcb"><code>72f2c25</code></a>
release 2.3.2</li>
<li><a
href="552dc5524b"><code>552dc55</code></a>
fix: revert <code>fs:readableWebStream</code> change (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/632">#632</a>)</li>
<li><a
href="f3cad8bcbf"><code>f3cad8b</code></a>
release 2.3.1</li>
<li><a
href="07a2257003"><code>07a2257</code></a>
fix: fix file closing issue (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/629">#629</a>)</li>
<li><a
href="d5382d3e6f"><code>d5382d3</code></a>
release 2.3.0</li>
<li><a
href="a0e2122208"><code>a0e2122</code></a>
feat: migrate from jest to vitest (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/626">#626</a>)</li>
<li><a
href="8836085300"><code>8836085</code></a>
chore: replace <code>mime</code> with <code>mime-types</code> (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/624">#624</a>)</li>
<li><a
href="86463358d8"><code>8646335</code></a>
chore: bump node to 20.19.2</li>
<li><a
href="46b284799f"><code>46b2847</code></a>
chore(deps): bump the npm group across 1 directory with 5 updates (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/623">#623</a>)</li>
<li><a
href="37fd9d0351"><code>37fd9d0</code></a>
chore(deps): bump undici from 5.28.5 to 5.29.0 (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/621">#621</a>)</li>
<li>Additional commits viewable in <a
href="da05d55257...72f2c25fcb">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=softprops/action-gh-release&package-manager=github_actions&previous-version=2.2.2&new-version=2.3.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 21:22:15 +00:00
dependabot[bot]
5c86fd271f chore: CI: bump dawidd6/action-download-artifact from 10 to 11 (#9137)
Bumps
[dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact)
from 10 to 11.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/dawidd6/action-download-artifact/releases">dawidd6/action-download-artifact's
releases</a>.</em></p>
<blockquote>
<h2>v11</h2>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/dawidd6/action-download-artifact/compare/v10...v11">https://github.com/dawidd6/action-download-artifact/compare/v10...v11</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="ac66b43f0e"><code>ac66b43</code></a>
node_modules: upgrade</li>
<li><a
href="9b54a0a70c"><code>9b54a0a</code></a>
Update README.md</li>
<li>See full diff in <a
href="https://github.com/dawidd6/action-download-artifact/compare/v10...v11">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dawidd6/action-download-artifact&package-manager=github_actions&previous-version=10&new-version=11)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 21:21:43 +00:00
dependabot[bot]
402cba6f09 chore: CI: bump dcarbone/install-jq-action from 3.1.1 to 3.2.0 (#9138)
Bumps
[dcarbone/install-jq-action](https://github.com/dcarbone/install-jq-action)
from 3.1.1 to 3.2.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/dcarbone/install-jq-action/releases">dcarbone/install-jq-action's
releases</a>.</em></p>
<blockquote>
<h2>v3.2.0</h2>
<h2>What's Changed</h2>
<ul>
<li>case sensitive is off by <a
href="https://github.com/Rupreht"><code>@​Rupreht</code></a> in <a
href="https://redirect.github.com/dcarbone/install-jq-action/pull/19">dcarbone/install-jq-action#19</a></li>
<li>Adding 1.8.0 stuff by <a
href="https://github.com/dcarbone"><code>@​dcarbone</code></a> in <a
href="https://redirect.github.com/dcarbone/install-jq-action/pull/20">dcarbone/install-jq-action#20</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/Rupreht"><code>@​Rupreht</code></a> made
their first contribution in <a
href="https://redirect.github.com/dcarbone/install-jq-action/pull/19">dcarbone/install-jq-action#19</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/dcarbone/install-jq-action/compare/v3.1.1...v3.2.0">https://github.com/dcarbone/install-jq-action/compare/v3.1.1...v3.2.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="b7ef57d46e"><code>b7ef57d</code></a>
Adding 1.8.0 stuff (<a
href="https://redirect.github.com/dcarbone/install-jq-action/issues/20">#20</a>)</li>
<li><a
href="2eac2baa38"><code>2eac2ba</code></a>
case sensitive is off (<a
href="https://redirect.github.com/dcarbone/install-jq-action/issues/19">#19</a>)</li>
<li>See full diff in <a
href="https://github.com/dcarbone/install-jq-action/compare/v3.1.1...v3.2.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dcarbone/install-jq-action&package-manager=github_actions&previous-version=3.1.1&new-version=3.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 21:21:20 +00:00
Cameron Zwarich
c0aad8a27c chore: remove unnecessary special case for Bool (#9136) 2025-07-01 20:42:58 +00:00
Cameron Zwarich
dbcf5b9d9d fix: call lowerEnumToScalarType? with ConstructorVal.induct (#9134)
This PR changes ToIR to call `lowerEnumToScalarType?` with
`ConstructorVal.induct` rather than the name of the constructor itself.
This was an oversight in some refactoring of code in the new compiler
before landing it. It should not affect runtime of compiled code (due to
the extra tagging/untagging being optimized by LLVM), but it does make
IR for the interpreter slightly more efficient.
2025-07-01 20:00:34 +00:00
jrr6
d31dfe92de fix: account for namespaces/open decls in inlineExpr (#9108)
This PR fixes an issue that may have caused inline expressions in
messages to be unnecessarily rendered on a separate line.
2025-07-01 19:28:22 +00:00
Kyle Miller
a018ed3f0f feat: add usedLetOnly to LocalContext binder functions (#9131)
This PR adds a `usedLetOnly` parameter to `LocalContext.mkLambda` and
`LocalContext.mkForall`, to parallel the `MetavarContext` versions.
2025-07-01 18:41:49 +00:00
Leonardo de Moura
535ce0b8fd feat: pow_add normalization in grind (#9133)
This PR adds support for `a^(m+n)` in the `grind` normalizer.
2025-07-01 17:52:16 +00:00
Leonardo de Moura
2bfcb1f25c fix: expand pattern offset gadget in constant patterns (#9130)
This PR fixes unexpected occurrences of the `Grind.offset` gadget in
ground patterns. See new test
2025-07-01 16:31:58 +00:00
Rob23oba
0e5ce1496b fix: pretty-printing of grind syntax (#9128)
This PR fixes spacing in the `grind` attribute and tactic syntax.
Previously `@[grind]` was incorrectly pretty-printed as `@[grind ]`, and
`grind [...] on_failure ...` was pretty-printed `grind [...]on_failure
...`. Fixes that `on_failure` was reserved as keyword.
2025-07-01 16:15:11 +00:00
Eric Wieser
688d9a30d2 fix: incorrectly parenthesized Bool.nots (#9129)
This PR fixes simp lemmas about boolean equalities to say `(!x) = y`
instead of `(!decide (x = y)) = true`

This might be an argument for changing the operator precedence of `!`,
or writing a linter to detect these mistakes.

Zulip thread: [#lean4 > Sum.bnot_isLeft and Sum.bnot_isRight @
💬](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Sum.2Ebnot_isLeft.20and.20Sum.2Ebnot_isRight/near/525938158)
2025-07-01 15:57:14 +00:00
Parth Shastri
2c13d145dc fix: match against app fn for reducing recursor in whnfCore (#9090)
This PR fixes a bug in `whnfCore` where it would fail to reduce
applications of recursors/auxiliary defs.

Closes #9089
2025-07-01 13:30:31 +00:00
Eric Wieser
232443371b perf: add missing std::moves (#9107)
Continues from #4700.

This will save a handful of refcounts here and there.
2025-07-01 12:39:12 +00:00
Paul Reichert
c231b742ca refactor: move well-founded relations used by the iterators to init (#9095)
This PR moves the construction of the `Option.SomeLtNone.lt` (and `le`)
relation, in which `some` is less than `none`, to
`Init.Data.Option.Basic` and moves well-foundedness proofs for
`Option.lt` and `Option.SomeLtNone.lt` into `Init.Data.Option.Lemmas`.
2025-07-01 12:02:48 +00:00
Paul Reichert
c9dea51f7a chore: create iterator benchmark (#9094)
This PR adds a benchmark file that exemplifies some iterator usages
2025-07-01 11:47:36 +00:00
Eric Wieser
72f421054d fix: do not truncate at null bytes in panic messages (#9103)
This PR prevents truncation of `panic!` messages containing null bytes.

The C api for `lean_panic` is left untouched.

Closes #9102
2025-07-01 11:34:16 +00:00
Joachim Breitner
8424ddbb3e feat: prettier expected type mismatch error message (#9099)
This PR improves the “expected type mismatch” error message by omitting
the type's types when they are defeq, and putting them into separate
lines when not.

I found it rather tediuos to parse the error message when the expected
type is long, because I had to find the `:` in the middle of a large
expression somewhere. Also, when both are of sort `Prop` or `Type` it
doesn't add much value to print the sort (and it’s only one hover away
anyways).
2025-07-01 07:50:53 +00:00
Kim Morrison
6ab8ed34d0 chore: grind test case for matching Nat arguments (#9123) 2025-07-01 07:21:36 +00:00
Kim Morrison
0af3659d14 feat: attribute [grind cases eager] PProd MProd (#9121)
This PR allows `grind` to case on the universe variants of `Prod`.
2025-07-01 04:02:47 +00:00
Kim Morrison
8c1e5c5c07 chore: allow grind to unfold Array ifInBounds operations (#9120) 2025-07-01 02:44:27 +00:00
Kim Morrison
293d1dfd57 chore: improvements to release automation (#9119) 2025-07-01 02:39:10 +00:00
Cameron Zwarich
604312a3df chore: update doc/dev/ffi.md after #9088 (#9112) 2025-07-01 01:00:59 +00:00
Kim Morrison
835bc675ca chore: begin development cycle for v4.23.0 (#9118) 2025-07-01 00:40:35 +00:00
Cameron Zwarich
463f2c5f25 chore: improve readability of a zipWith call (#9116) 2025-07-01 00:10:54 +00:00
Cameron Zwarich
52ab0141cd chore: share more code in toIRType (#9115) 2025-06-30 23:13:02 +00:00
Kim Morrison
cd60e3b8fd feat: further release automation (#9114)
This PR further improves release automation, automatically incorporating
material from `nightly-testing` and `bump/v4.X.0` branches in the bump
PRs to downstream repositories.
2025-06-30 22:28:00 +00:00
Leonardo de Moura
b9e440d280 doc: improve grind doc string (#9113)
This PR improves the `grind` doc string and tries to make it more
approachable to new user.
2025-06-30 21:47:40 +00:00
Lean stage0 autoupdater
5296fa1dd5 chore: update stage0 2025-06-30 21:08:11 +00:00
Sebastian Ullrich
3d74e1ba44 chore: track .ir output files in Lake (#9060)
Co-authored-by: Mac Malone <tydeu@hatpress.net>
2025-06-30 15:59:18 +00:00
Sebastian Ullrich
de2d6ba37e perf: do not import non-template IR for codegen (#8666)
This PR adjusts the experimental module system to not import the IR of
non-`meta` declarations. It does this by replacing such IR with opaque
foreign declarations on export and adjusting the new compiler
accordingly.

This PR should not be merged before the new compiler.

Based on #8664.
2025-06-30 15:52:56 +00:00
Mac Malone
9db41f9931 fix: lake: source file not in module input trace & some logs dropped (#9101)
This PR fixes a bug introduce by #9081 where the source file was dropped
from the module input trace and some entries were dropped from the
module job log.
2025-06-30 15:48:01 +00:00
Cameron Zwarich
30fee8fb67 chore: update stage0 2025-06-30 15:39:58 +02:00
Cameron Zwarich
4c7ab7fc79 chore: set prefer_native=true for bootstrap 2025-06-30 15:39:58 +02:00
Cameron Zwarich
6f854a97a4 chore: update stage0 2025-06-30 15:39:58 +02:00
Cameron Zwarich
2e627d3692 feat: move constructor layout to Lean and add a few optimizations
This PR moves the constructor layout code from C++ to Lean. When
writing the new compiler, we just reused the existing C++ code,
even though it was a bit inconvenient, because we wanted to
ensure that constructor layout always matched the existing
compiler.

This fixes #2589 by handling struct field types just like any
other type being lowered, and thus applying the trivial structure
optimization in the process. Originally, I wanted to port the
code to Lean without any functional changes, but I found that
it took less code to just implement it "correctly" and get this
fix as a consequence than to emulate the bugs of the existing
C++ implementation.
2025-06-30 15:39:58 +02:00
Sebastian Graf
81fd7edd19 fix: More consistent transparency when calling mspec from mvcgen (#9097)
This PR ensures that `mspec` uses the configured transparency setting
and makes `mvcgen` use default transparency when calling `mspec`.

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-06-30 09:57:57 +00:00
Sebastian Ullrich
dfbebe0683 refactor: module-ize Std.Classes (#9079) 2025-06-30 09:45:24 +00:00
David Thrane Christiansen
9bbd2e64aa doc: add missing docstring for ToFormat.toFormat (#9093)
This PR adds a missing docstring for `ToFormat.toFormat`.
2025-06-30 06:59:12 +00:00
Kim Morrison
ae89b7ed43 feat: further release automation (#9092)
This PR further updates release automation. The per-repository update
scripts `script/release_steps.py` now actually performs the tests,
rather than outputting a script for the release manager to run line by
line. It's been tested on `v4.21.0` (i.e. the easy case of a stable
release), and we'll debug its behaviour on `v4.22.0-rc1` tonight.
2025-06-30 05:44:10 +00:00
David Thrane Christiansen
ede8a7e494 fix: error explanation needs updating (#9091)
This PR updates an error explanation to match the actual error.
2025-06-30 05:10:04 +00:00
Kyle Miller
044bfdb098 feat: eliminate letFun support, deprecate let_fun syntax (#9086)
This PR deprecates `let_fun` syntax in favor of `have` and removes
`letFun` support from WHNF and `simp`.
2025-06-30 02:10:18 +00:00
Mac Malone
5049a4893e refactor: lake: fix local artifact cache bugs, opt-in, & related cleanup (#9068)
This PR fixes some bugs with the local Lake artifact cache and cleans up
the surrounding API. It also adds the ability to opt-in to the cache on
packages without `enableArtifactCache` set using the
`LAKE_ARTIFACT_CACHE` environment variable.

Bug-wise, this fixes an issue where cached executable did not have right
permissions to run on Unix systems and a bug where cached artifacts
would not be invalidated on changes. Lake also now writes a trace file
to local build directory if there is none when fetching an artifact from
the cache. This trace has a new `synthetic` field set to `true` to
distinguish it from traces produced by full builds.
2025-06-30 01:02:55 +00:00
Lean stage0 autoupdater
d6c5c8c880 chore: update stage0 2025-06-30 01:20:30 +00:00
Kyle Miller
32894e7349 feat: remove irreducible from letFun (#9087)
This PR removes the `irreducible` attribute from `letFun`, which is one
step toward removing special `letFun` support; part of #9086.

Removing the attribute seems to break some `module` tests in stage2.
2025-06-30 00:04:59 +00:00
Sebastian Ullrich
d53d4722cc chore: compile stage 0 against correct version string (#9085)
This ensure the correct version string is embedded into shipped .oleans,
though only the githash is relevant for the version check.
2025-06-29 20:52:46 +00:00
Kyle Miller
cb3174b1c6 feat: hovers when pp.oneline is true (#7954)
This PR improves `pp.oneline`, where it now preserves tags when
truncating formatted syntax to a single line. Note that the `[...]`
continuation does not yet have any functionality to enable seeing the
untruncated syntax. Closes #3681.
2025-06-29 20:06:24 +00:00
Kyle Miller
68c006a95b feat: transform nondependent lets into haves in declarations and equation lemmas (#8373)
This PR enables transforming nondependent `let`s into `have`s in a
number of contexts: the bodies of nonrecursive definitions, equation
lemmas, smart unfolding definitions, and types of theorems. A motivation
for this change is that when zeta reduction is disabled, `simp` can only
effectively rewrite `have` expressions (e.g. `split` uses `simp` with
zeta reduction disabled), and so we cache the nondependence calculations
by transforming `let`s to `have`s. The transformation can be disabled
using `set_option cleanup.letToHave false`.

Uses `Meta.letToHave`, introduced in #8954.
2025-06-29 19:45:45 +00:00
Kyle Miller
44c8b0df85 feat: warn.sorry option (#8662)
This PR adds a `warn.sorry` option (default true) that logs the
"declaration uses 'sorry'" warning when declarations contain `sorryAx`.
When false, the warning is not logged.

Closes #8611 (assuming that one would set `warn.sorry` as an extra flag
when building).

Other change: Uses `warn.sorry` when creating auxiliary declarations in
`structure` elaborator, to suppress irrelevant 'sorry' warnings.

We could include the sorries themselves in the message if they are
labeled, letting users "go to definition" to see where the sorries are
coming from.

In an earlier version, added additional information to the warning when
it is a synthetic sorry, since these can be caused by elaboration bugs
and they can also be caused by elaboration failures in previous
declarations. This idea needs some more work, so it's not included.
2025-06-29 19:31:17 +00:00
Cameron Zwarich
85c45c409e chore: move lowerType to ToIRType and rename it (#9083) 2025-06-29 19:16:00 +00:00
Mac Malone
e0354cd856 fix: lake: module builds not appearing in job monitor (#9081)
This PR fixes a bug with Lake where the job monitor would sit on a
top-level build (e.g., `mathlib/Mathlib:default`) instead of reporting
module build progress.

The issue was actually simpler than it initially appeared. The wrong
portion of the module build was being registered to job monitor. Moving
it to right place fixes it, no job priorities necessary.
2025-06-29 18:39:06 +00:00
Cameron Zwarich
5d8cd35471 chore: rename Lean.Compiler.IR.CtorLayout to ToIRType (#9082) 2025-06-29 18:36:55 +00:00
Cameron Zwarich
0b738e07b4 chore: move more functions to CtorLayout (#9080) 2025-06-29 17:31:41 +00:00
Sebastian Ullrich
f475d5a428 chore: module-ize Init.lean 2025-06-29 16:52:13 +02:00
Sebastian Ullrich
5aa1950c3f chore: update stage0 2025-06-29 16:15:49 +02:00
Sebastian Ullrich
8085d3c930 chore: allow use of the module system in all of core (#9078) 2025-06-29 13:49:27 +00:00
Kim Morrison
a35425b192 feat: support for ReflCmp in grind (#9073)
This PR copies #9069 to handle `ReflCmp` the same way; we need to call
this in propagateUp rather than propagateDown.
2025-06-29 11:36:39 +00:00
Leonardo de Moura
8b1d2fc2d5 feat: OfSemiring.toQ unexpander (#9076)
This PR adds an unexpander for `OfSemiring.toQ`. This an auxiliary
function used by the `ring` module in `grind`, but we want to reduce the
clutter in the diagnostic information produced by `grind`. Example:
```
example [CommSemiring α] [AddRightCancel α] [IsCharP α 0] (x y : α)
    : x^2*y = 1 → x*y^2 = y → x + y = 2 → False := by
  grind
```
produces
```
  [ring] Ring `Ring.OfSemiring.Q α` ▼
    [basis] Basis ▼
      [_] ↑x + ↑y + -2 = 0
      [_] ↑y + -1 = 0
```
2025-06-29 11:22:24 +00:00
Kim Morrison
98e868e3d2 feat: BEq instances for ByteArray/FloatArray (#9075)
This PR adds `BEq` instances for `ByteArray` and `FloatArray` (also a
`DecidableEq` instance for `ByteArray`).
2025-06-29 11:12:48 +00:00
Leonardo de Moura
b95b0069e7 feat: use comm ring module to normalize nonlinear polynomials in grind cutsat (#9074)
This PR uses the commutative ring module to normalize nonlinear
polynomials in `grind cutsat`. Examples:
```lean
example (a b : Nat) (h₁ : a + 1 ≠ a * b * a) (h₂ : a * a * b ≤ a + 1) : b * a^2 < a + 1 := by 
  grind

example (a b c : Int) (h₁ : a + 1 + c = b * a) (h₂ : c + 2*b*a = 0) : 6 * a * b - 2 * a ≤ 2 := by 
  grind
```
2025-06-29 11:09:29 +00:00
Leonardo de Moura
f2e06ead54 feat: support for LawfulEqCmp in grind (#9069)
This PR implements support for the type class `LawfulEqCmp`. Examples:
```lean
example (a b c : Vector (List Nat) n)
    : b = c → a.compareLex (List.compareLex compare) b = o → o = .eq → a = c := by
  grind

example [Ord α] [Std.LawfulEqCmp (compare : α → α → Ordering)] (a b c : Array (Vector (List α) n))
    : b = c → o = .eq → a.compareLex (Vector.compareLex (List.compareLex compare)) b = o → a = c := by
  grind
```
2025-06-28 22:41:22 +00:00
Leonardo de Moura
f6bb524406 doc: grind docstring (#9067)
This PR adds a docstring for the `grind` tactic.
2025-06-28 20:20:55 +00:00
Cameron Zwarich
ef77322133 chore: fix a typo in an error message (#9066) 2025-06-28 19:48:50 +00:00
Leonardo de Moura
4247dcfea6 feat: improve counterexamples using ToInt.toInt in grind cutsat (#9065)
This PR improves the counterexamples produced by the `cutsat` procedure
in `grind` when using the `ToInt` gadget.
2025-06-28 19:30:25 +00:00
Cameron Zwarich
05978caa59 chore: move type lowering functions to CoreM (#9064) 2025-06-28 18:10:42 +00:00
Sebastian Ullrich
09a5b34931 feat: make private the default in module (#9044)
This PR adjusts the experimental module system to make `private` the
default visibility modifier in `module`s, introducing `public` as a new
modifier instead. `public section` can be used to revert the default for
an entire section, though this is more intended to ease gradual adoption
of the new semantics such as in `Init` (and soon `Std`) where they
should be replaced by a future decl-by-decl re-review of visibilities.
2025-06-28 16:30:53 +00:00
Cameron Zwarich
5144a3bf74 chore: rename lowerEnumToScalarType to lowerEnumToScalarType? (#9063) 2025-06-28 15:52:11 +00:00
Leonardo de Moura
5ca6eadd50 feat: equations <num> = 0 in grind ring (#9062)
This PR implements support for equations `<num> = 0` in rings and fields
of unknown characteristic. Examples:
```lean
example [Field α] (a : α) : (2 * a)⁻¹ = a⁻¹ / 2 := by grind

example [Field α] (a : α) : (2 : α) ≠ 0 → 1 / a + 1 / (2 * a) = 3 / (2 * a) := by grind

example [CommRing α] (a b : α) (h₁ : a + 2 = a) (h₂ : 2*b + a = 0) : a = 0 := by
  grind

example [CommRing α] (a b : α) (h₁ : a + 6 = a) (h₂ : b + 9 = b) (h₂ : 3*b + a = 0) : a = 0 := by
  grind

example [CommRing α] (a b : α) (h₁ : a + 6 = a) (h₂ : b + 9 = b) (h₂ : 3*b + a = 0) : a = 0 := by
  grind

example [CommRing α] (a b : α) (h₁ : a + 2 = a) (h₂ : b = 0) : 4*a + b = 0 := by
  grind

example [CommRing α] (a b c : α) (h₁ : a + 6 = a) (h₂ : c = c + 9) (h : b + 3*c = 0) : 27*a + b = 0 := by
  grind

```
2025-06-28 14:28:42 +00:00
Sebastian Ullrich
22152b8bfb chore: update stage0 2025-06-28 15:58:14 +02:00
Sebastian Ullrich
d7e35c77ca chore: reserve public import syntax (#9061)
This PR adds the `public import` syntax to be used by the experimental
module system
2025-06-28 13:11:34 +00:00
Leonardo de Moura
e844f9c82c feat: helper theorems for grind ring (#9059)
This PR adds helper theorems for normalizing coefficients in rings of
unknown characteristic.
2025-06-28 10:57:44 +00:00
Sebastian Ullrich
4f2d107b52 chore: update stage0 2025-06-28 12:09:50 +02:00
Paul Reichert
e86e978f26 feat: ToStream instance for ranges (#9058)
This PR provides a `ToStream` instance for slices so that they can be
used in `for i in xs, j in ys do` notation.
2025-06-28 09:38:37 +00:00
Paul Reichert
d380919fa3 feat: lemmas about toList, toListRev and toArray for slices (#9049)
This PR proves that the default `toList`, `toListRev` and `toArray`
functions on slices can be described in terms of the slice iterator.
Relying on new lemmas for the `uLift` and `attachWith` iterator
combinators, a more concrete description of said functions is given for
`Subarray`.
2025-06-28 08:29:09 +00:00
Leonardo de Moura
98b66ec373 feat: variable reordering heuristic for grind cutsat (#9057)
This PR introduces a simple variable-reordering heuristic for `cutsat`.
It is needed by the `ToInt` adapter to support finite types such as
`UInt64`. The current encoding into `Int` produces large coefficients,
which can enlarge the search space when an unfavorable variable order is
used. Example:
```lean
example (a b c : UInt64) : a ≤ 2 → b ≤ 3 → c - a - b = 0 → c ≤ 5 := by
  grind
```
2025-06-28 08:12:43 +00:00
Kim Morrison
291938c748 chore: generalize Array/Vector.extract_push (#9055)
This PR renames `Array/Vector.extract_push` to `extract_push_of_le`, and
replaces the lemma with one without a side condition.
2025-06-28 07:07:57 +00:00
Kim Morrison
c52605dfe3 fix: some inconsistencies in Map grind annotations (#9054)
This PR corrects some inconsistencies in `TreeMap`/`HashMap` grind
annotations, for `isSome_get?_eq_contains` and `empty_eq_emptyc`.
2025-06-28 06:41:19 +00:00
Leonardo de Moura
19fd1f060f feat: ToInt equality in grind cutsat (#9051)
This PR implements support for equalities and disequalities in `grind
cutsat`. We still have to improve the encoding. Examples:
```lean
example (a b c : Fin 11) : a ≤ 2 → b ≤ 3 → c = a + b → c ≤ 5 := by
  grind

example (a : Fin 2) : a ≠ 0 → a ≠ 1 → False := by
  grind
```
2025-06-27 21:52:23 +00:00
jrr6
a0e425748a chore: enable error explanation widget (#9043)
This PR enables the error explanation widget in named error messages.
Note that the displayed links won't work until the new manual version is
released (unless overriding `LEAN_MANUAL_ROOT` with a suitably recent
manual build).
2025-06-27 19:25:29 +00:00
Paul Reichert
6e538c35dd refactor: migrate all usages of old slice notation (#9000)
This PR replaces all usages of `[:]` slice notation in `src` with the
new `[...]` notation in production code, tests and comments. The
underlying implementation of the `Subarray` functions stays the same.

Notation cheat sheet:

* `*...*` is the doubly-unbounded range.
* `*...a` or `*...<a` contains all elements that are less than `a`.
* `*...=a` contains all elements that are less than or equal to `a`.
* `a...*` contains all elements that are greater than or equal to `a`.
* `a...b` or `a...<b` contains all elements that are greater than or
equal to `a` and less than `b`.
* `a...=b` contains all elements that are greater than or equal to `a`
and less than or equal to `b`.
* `a<...*` contains all elements that are greater than `a`.
* `a<...b` or `a<...<b` contains all elements that are greater than `a`
and less than `b`.
* `a<...=b` contains all elements that are greater than `a` and less
than or equal to `b`.

Benchmarks have shown that importing the iterator-backed parts of the
polymorphic slice library in `Init` impacts build performance. This PR
avoids this problem by separating those parts of the library that do not
rely on iterators from those those that do. Whereever the new slice
notation is used, only the iterator-independent files are imported.
2025-06-27 18:52:07 +00:00
Leonardo de Moura
422eb68f6f feat: assert ToInt bounds in grind cutsat (#9050)
This PR ensures the `ToInt` bounds are asserted for every `toInt a`
application internalized in `grind cutsat`.
2025-06-27 18:42:35 +00:00
Leonardo de Moura
7f5b47e831 feat: ToInt strict inequalities in grind cutsat (#9048)
This PR implements support for strict inequalities in the `ToInt`
adapter used in `grind cutsat`. Example:
```lean
example (a b c : Fin 11) : c ≤ 9 → a ≤ b → b < c → a < c + 1 := by
  grind
```
2025-06-27 17:34:12 +00:00
Sofia Rodrigues
bf2e91b6d1 feat: add system information functions to the standard library (#8109)
This PR adds system information functions to the standard library
2025-06-27 16:31:34 +00:00
Sebastian Graf
e886373dc8 fix: Avoid a type error in mvcgen and turn fewer natural goals into synthetic opaque ones (#9045)
This PR fixes a type error in `mvcgen` and makes it turn fewer natural
goals into synthetic opaque ones, so that tactics such as `trivial` may
instantiate them more easily.

---------

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-06-27 16:27:06 +00:00
Sebastian Ullrich
7ed1a4b576 perf: inline lean_inc_ref_cold (#4978)
The body is a single instruction
2025-06-27 15:58:00 +00:00
jrr6
4759506bcf chore: use note and hint' for message addenda (#8980)
This PR improves the consistency of error message formatting by
rendering addenda of several existing error messages as labeled notes
and hints.
2025-06-27 15:16:01 +00:00
Sebastian Ullrich
f5c389468f chore: update stage0 2025-06-27 08:13:31 -07:00
Sebastian Ullrich
aadc74bee2 perf: do not import non-meta IR 2025-06-27 08:13:31 -07:00
Sebastian Ullrich
bd16c0f87d chore: update stage0 2025-06-27 16:55:38 +02:00
Sebastian Graf
862a3dc552 fix: Use fullApproxDefEq in mspec to fix a bug reported by Rish (#9041)
This PR makes `mspec` detect more viable assignments by `rfl` instead of
generating a VC.

---------

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
Co-authored-by: Rishikesh Vaishnav <rishhvaishnav@gmail.com>
2025-06-27 14:31:39 +00:00
Markus Himmel
c3319f21ee chore: Grove: start on associative containers (#9039) 2025-06-27 13:34:10 +00:00
David Thrane Christiansen
2bb27af0d4 chore: automatically create reference manual PR branches (#9033)
This PR adds a Mathlib-like testing and feedback system for the
reference manual. Lean PRs will receive comments that reflect the status
of the language reference with respect to the PR.
2025-06-27 13:23:41 +00:00
Sebastian Graf
c79b89fb39 fix: More fixes for Std.Do accumulated while merging tests (#9038)
This PR adds test cases for the VC generator and implements a few small
and tedious fixes to ensure they pass.

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-06-27 13:10:43 +00:00
Henrik Böving
7a1113ada3 feat: extend identifiers to french (#9035)
This PR extends the list of acceptable characters to all the french ones
as well as some others,
by adding characters from the Latin-1-Supplement add Latin-Extended-A
unicode block.
2025-06-27 12:50:09 +00:00
Sebastian Ullrich
7845af3105 chore: reserve public section syntax (#9032)
To be used in the experimental module system
2025-06-27 12:21:01 +00:00
Sebastian Ullrich
35c168cb13 feat: allow access to private names through import all (#8828)
This PR extends the experimental module system to support resolving
private names imported (transitively) through `import all`.
2025-06-27 12:13:46 +00:00
Sofia Rodrigues
fe1b407031 feat: add DNS resolution functions to the standard library (#8072)
This PR adds DNS functions to the standard library

---------

Co-authored-by: Henrik Böving <hargonix@gmail.com>
Co-authored-by: Markus Himmel <markus@himmel-villmar.de>
2025-06-27 11:11:47 +00:00
Sofia Rodrigues
0f2cb91336 feat: add lean_setup_libuv for initializing required LIBUV components (#8636)
This PR adds a function called `lean_setup_libuv` that initializes
required LIBUV components. It needs to be outside of
`lean_initialize_runtime_module` because it requires `argv` and `argc`
to work correctly.

---------

Co-authored-by: Markus Himmel <markus@lean-fro.org>
Co-authored-by: Eric Wieser <wieser.eric@gmail.com>
2025-06-27 11:11:17 +00:00
Sebastian Graf
08737054fc fix: A couple of bootstrapping hiccups related to Std.Do (#9030)
This PR fixes a couple of bootstrapping-related hiccups in the newly
added `Std.Do` module. More precisely,

* The `spec` attribute syntax was registered under the wrong name and
its implementation needed to use a different priority parser
* Elaborators and delaborators for `MGoal`, `Triple`, `PostCond` and
`PostCond.total` were broken and are now properly builtin
* `Std.Do` should not transitively import `Std.Tactic.Do.Syntax`

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-06-27 09:53:17 +00:00
Henrik Böving
56d3de5358 fix: bv_decide internal error (#9031)
This PR fixes a minor usability issue in bv_decide.
2025-06-27 09:10:21 +00:00
Marc Huisinga
1edb7632b5 fix: highlight keywords when keyword is actual identifier (#9019)
This PR fixes a bug where semantic highlighting would only highlight
keywords that started with an alphanumeric character. Now, it uses
`Lean.isIdFirst`.
2025-06-27 08:23:10 +00:00
Paul Reichert
1a6eae16ec feat: introduce uLift iterator combinator, make Subarray.iter universe-polymorphic (#9027)
This PR provides an iterator combinator that lifts the emitted values
into a higher universe level via `ULift`. This combinator is then used
to make the subarray iterators universe-polymorphic. Previously, they
were only available for `Subarray α` if `α : Type`.
2025-06-27 07:34:08 +00:00
Kim Morrison
8d40cf5157 chore: missing Option lemma (#9028) 2025-06-27 07:28:59 +00:00
Leonardo de Moura
0aca10b228 feat: Toint inequalities in cutsat (#9026)
This PR implements support for (non strict) `ToInt` inequalities in
`grind cutsat`. `grind cutsat` can solve simple problems such as:
```lean
example (a b c : Fin 11) : a ≤ b → b ≤ c → a ≤ c := by
  grind

example (a b c : Fin 11) : c ≤ 9 → a ≤ b → b ≤ c → a ≤ c + 1 := by
  grind

example (a b c : UInt8) : a ≤ b → b ≤ c → a ≤ c := by
  grind

example (a b c d : UInt32) : a ≤ b → b ≤ c → c ≤ d → a ≤ d := by
  grind
```
Next step: strict inequalities, and equalities.
2025-06-27 06:29:31 +00:00
Mac Malone
541ff1e287 feat: lake: local artifact cache (#8922)
This PR introduces a local artifact cache for Lake. When enabled, Lake
will shared build artifacts (built files) across different instances of
the same package using an input- and content-addressed cache.

To enable support for the local cache, packages must set
`enableArtifactCache := true` in their package configuration. The reason
for this is twofold. This feature is new and experimental, so it should
be opt-in. Also, some packages may need to disable it as the cache
entails that artifacts are no longer necessarily available within the
build directory, which can break custom build scripts.

The cache location is determined by the system configuration. Lake's
first preference is to store it under the Lean toolchain in a
`lake/cache` directory. If Elan is not available, Lake will store it in
common system location (e.g., `$XDG_CACHE_HOME/lake`, or
`~/.cache/lake`). On an exotic system where neither of these exist, the
cache will be disabled. Users can override this location through the
`LAKE_CACHE_DIR` environment variable. If set to empty, caching will be
disabled.

The cache is both input and content-addressed. Mappings from input hash
to output content hash(es) are stored in a per-package JSON Lines file
(e.g., `<cache-dir>/inputs/<pkg-name>.jsonl`). Thus, mappings are shared
across different instances of a package, but not between packages. The
output content hashes are also now stored in trace files in a new
`outputs` field. The value of this field can be either a single hash or
an object of multiple content hashes for targets which produce multiple
artifacts (e.g., Lean module builds). Separately, artifacts are stored
in a single flat content-addressed cache (e.g.,
`<cache-dir>/artifacts/<hash>.art`. Artifacts are therefore shared
across all cache-enabled packages.

Module `*.olean` and and `*.ilean` artifacts are cached. However, each
package will still copy the files to their build directory, as Lean and
the server currently expect them to be at a specific path. This will be
changed for `*.olean` files when the performance issues with
pre-resolving modules in Lake for `lean --setup` are solved.
2025-06-27 04:06:50 +00:00
Leonardo de Moura
0371509e49 refactor: remove foreignTypes leftover from cutsat (#9024)
We will not use it with the new `ToInt` infrastructure.
2025-06-27 02:47:34 +00:00
Kyle Miller
7abc9106d7 feat: optimized simp routine for let telescopes (#8968)
This PR adds the following features to `simp`:
- A routine for simplifying `have` telescopes in a way that avoids
quadratic complexity arising from locally nameless expression
representations, like what #6220 did for `letFun` telescopes.
Furthermore, simp converts `letFun`s into `have`s (nondependent lets),
and we remove the #6220 routine since we are moving away from `letFun`
encodings of nondependent lets.
- A `+letToHave` configuration option (enabled by default) that converts
lets into haves when possible, when `-zeta` is set. Previously Lean
would need to do a full typecheck of the bodies of `let`s, but the
`letToHave` procedure can skip checking some subexpressions, and it
modifies the `let`s in an entire expression at once rather than one at a
time.
- A `+zetaHave` configuration option, to turn off zeta reduction of
`have`s specifically. The motivation is that dependent `let`s can only
be dsimped by let, so zeta reducing just the dependent lets is a
reasonable way to make progress. The `+zetaHave` option is also added to
the meta configuration.
- When `simp` is zeta reducing, it now uses an algorithm that avoids
complexity quadratic in the depth of the let telescope.
- Additionally, the zeta reduction routines in `simp`, `whnf`, and
`isDefEq` now all are consistent with how they apply the `zeta`,
`zetaHave`, and `zetaUnused` configurations.

The `letToFun` option is addressing a TODO in `getSimpLetCase` ("handle
a block of nested let decls in a single pass if this becomes a
performance problem").

Performance should be compared to before #8804, which temporarily
disabled the #6220 optimizations for `letFun` telescopes.

Good kernel performance depends on carefully handling the `have`
encoding. Due to the way the kernel instantiates bvars (it does *not*
beta reduce when instantiating), we cannot use congruence theorems of
the form `(have x := v; f x) = (have x ;= v'; f' x)`, since the bodies
of the `have`s will not be syntactically equal, which triggers zeta
reduction in the kernel in `is_def_eq`. Instead, we work with `f v = f'
v'`, where `f` and `f'` are lambda expressions. There is still zeta
reduction, but only when converting between these two forms at the
outset of the generated proof.
2025-06-27 02:13:20 +00:00
jrr6
05948f19e4 fix: improve precision of synthesis failure spans in interpolated strings (#9004)
This PR ensures that type-class synthesis failure errors in interpolated
strings are displayed at the interpolant at which they occurred.
2025-06-27 01:47:32 +00:00
Leonardo de Moura
6b520ede08 feat: generic toInt for cutsat (#9022)
This PR completes the generic `toInt` infrastructure for embedding terms
implementing the `ToInt` type classes into `Int`.
2025-06-27 00:28:51 +00:00
jrr6
2fe6d8a70b feat: add word-level hint suggestion diffs (#8574)
This PR adds an additional diff mode to the error-message hint
suggestion widget that displays diffs per word rather than per
character.
2025-06-26 23:56:19 +00:00
Luisa Cicolini
b1a306cf69 feat: add BitVec.toFin_(sdiv, smod, srem) and BitVec.toNat_srem (#8950)
This PR adds `BitVec.toFin_(sdiv, smod, srem)` and `BitVec.toNat_srem`.
The strategy for the `rhs` of the `toFin_*` lemmas is to consider what
the corresponding `toNat_*` theorems do and push the `toFin` closerto
the operands. For the `rhs` of `BitVec.toNat_srem` I used the same
strategy as `BitVec.toNat_smod`.
2025-06-26 20:01:01 +00:00
Kyle Miller
b56ad5a7d2 fix: apply newlines before and after comments when formatting syntax (#8626)
This PR closes #3791, making sure that the Syntax formatter inserts
whitespace before and after comments in the leading and trailing text of
Syntax to avoid having comments comment out any following syntax, and to
avoid comments' lexical syntax from being interpreted as being part of
another syntax. If the text contains newlines before or after any
comments, they are formatted as hard newlines rather than soft newlines.
For example, `--` comments will have a hard newline after them. Note:
metaprograms generating Syntax with comments should be sure to include
newlines at the ends of `--` comments.
2025-06-26 19:23:35 +00:00
jrr6
7ed716f904 feat: improve projection and field-notation errors (#8986)
This PR improves the error messages produced by invalid projections and
field notation. It also adds a hint to the "function expected" error
message noting the argument to which the term is being applied, which
can be helpful for debugging spurious "function expected" messages
actually caused by syntax errors.

---------

Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>
2025-06-26 18:36:47 +00:00
Lean stage0 autoupdater
928d37e4d4 chore: update stage0 2025-06-26 18:04:18 +00:00
Sebastian Graf
f87d05ad4e feat: Hoare logic for monadic programs and verification condition generation (#8995)
This PR introduces a Hoare logic for monadic programs in
`Std.Do.Triple`, and assorted tactics:

*  `mspec` for applying Hoare triple specifications
* `mvcgen` to turn a Hoare triple proof obligation `⦃P⦄ prog ⦃Q⦄` into
pure verification conditoins (i.e., without any traces of Hoare triples
or weakest preconditions reminiscent of `prog`). The resulting
verification conditions in the stateful logic of `Std.Do.SPred` can be
discharged manually with the tactics coming with its custom proof mode
or with automation such as `simp` and `grind`.

This is pre-release of a planned feature and not yet intended for
production use. We are grateful for feedback of early adopters, though.

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-06-26 15:49:56 +00:00
Paul Reichert
83e226204d feat: introduce slices (#8947)
This PR introduces polymorphic slices in their most basic form. They
come with a notation similar to the new range notation. `Subarray` is
now also a slice and can produce an iterator now. It is intended to
migrate more operations of `Subarray` to the `Slice` wrapper type to
make them available for slices of other types, too.

The PR also moves the `filterMap` combinators into `Init` because they
are used internally to implement iterators on array slices.
2025-06-26 15:29:03 +00:00
Rob23oba
9bf5fc2fd3 feat: extensional tree maps (#8721)
This PR adds the types `Std.ExtDTreeMap`, `Std.ExtTreeMap` and
`Std.ExtTreeSet` of extensional tree maps and sets. These are very
similar in construction to the existing extensional hash maps with one
exception: extensional tree maps and sets provide all functions from
regular tree maps and sets. This is possible because in contrast to hash
maps, tree maps are always ordered.
2025-06-26 13:13:45 +00:00
Markus Himmel
2f43f02cb6 chore: Grove: high-level sections (#9011) 2025-06-26 13:06:56 +00:00
Markus Himmel
65ea45b17b chore: ci: fixes to Grove workflow (#9014) 2025-06-26 12:15:51 +00:00
Sebastian Graf
0d7fe9a196 feat: Upstream MPL.SPred.* from mpl (#8928)
This PR adds a logic of stateful predicates SPred to Std.Do in order to
support reasoning about monadic programs. It comes with a dedicated
proof mode the tactics of which are accessible by importing
Std.Tactic.Do.

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-06-26 11:15:11 +00:00
Markus Himmel
790ae27f2b chore: ci: fixes to Grove workflow (#9013) 2025-06-26 11:13:19 +00:00
Markus Himmel
40d2c99463 chore: ci: fixes to Grove workflow (#9012) 2025-06-26 09:55:06 +00:00
Lean stage0 autoupdater
2c60f1a254 chore: update stage0 2025-06-26 09:48:45 +00:00
Markus Himmel
4f1d828541 chore: ci: build Linux toolchain for master commits (but not merge queue runs) (#9010) 2025-06-26 08:20:04 +00:00
Paul Reichert
70b4b2b36c feat: polymorphic ranges (#8784)
This PR introduces ranges that are polymorphic, in contrast to the
existing `Std.Range` which only supports natural numbers.

Breakdown of core changes:

* `Lean.Parser.Basic`: Modified the number parser (`Lean.Parser.Basic`)
so that it will only consider a *single* dot to be part of a decimal
number. `1..` will no longer be parsed as `1.` followed by `.`, but as
`1` followed by `..`.
* The test `ellipsisProjIssue` ensures that `#check Nat.add ...succ`
produces a syntax error. After introducing the new range notation (see
below), it returns a different (less nice) error message. I updated the
test to reflect the new error message. (The error message will become
nicer as soon as a delaborator for the ranges is implemented. This is
out of scope for this PR.)

Breakdown of standard library changes:

Modified modules: `Init.Data.Range.Polymorphic` (added),
`Init.Data.Iterators`, `Std.Data.Iterators`

* Introduced the type `Std.PRange` that is parameterized over the type
in which the range operates and the shapes of the lower and upper bound.
* Introduced a new notation for ranges. Examples for this notation are:
`1...*`, `1...=3`, `1...<3`, `1<...=2`, `*...=3`.
* Defined lots of typeclasses for different capabilities of ranges,
depending on their shape and underlying type.
* Introduced `Iter(M).size`.
* Introduced the `Iter(M).stepSize n` combinator, which iterates over an
iterator with the given step size `n`. It will drop `n - 1` values
between every value it emits.
* Replaced `LawfulPureIterator` with a new and better typeclass
`LawfulDeterministicIterator`.
* Simplified some lemma statements in the iterator library such as
`IterM.toList_eq_match`, which unnecessarily matched over a `Subtype`,
hindering rewrites due to type dependencies.

Reasons for the concrete choice of notation:

* `lean4-cli` uses `...`-based notation for the `Cmd` notation and it
clashes with `...a` range notation.
* test `2461` fails when using two-dot-based notation because of the
existing `{ a.. }` notation.
2025-06-26 08:18:11 +00:00
Paul Reichert
3695059504 feat: introduce MonadLiftT Id m (#8977)
This PR adds a generic `MonadLiftT Id m` instance. We do not implement a
`MonadLift Id m` instance because it would slow down instance resolution
and because it would create more non-canonical instances. This change
makes it possible to iterate over a pure iterator, such as `[1, 2,
3].iter`, in arbitrary monads.
2025-06-26 07:33:07 +00:00
Leonardo de Moura
b76bf44654 feat: infrastructure for cutsat generic ToInt (#9008)
This PR implements the basic infrastructure for the generic `ToInt`
support in `cutsat`.
2025-06-26 07:01:19 +00:00
Markus Himmel
d3dda9f6d4 chore: initial Grove setup (#8997) 2025-06-26 05:03:02 +00:00
Kim Morrison
561c18819c chore: typo (#9007) 2025-06-26 03:50:29 +00:00
David Thrane Christiansen
5ec3cc5df7 doc: review Repr and Format docstrings (#8998)
This PR makes the docstrings related to `Format` and `Repr` have
consistent formatting and style, and adds missing docstrings.
2025-06-26 03:20:23 +00:00
Kim Morrison
62e9d73f8b chore: revert BitVec/Lemmas grind proofs; too many bootstrapping difficulties (#9006) 2025-06-26 03:04:01 +00:00
Sofia Rodrigues
b15cfadde8 feat: monadic interface for asynchronous operations in Std (#8003)
This PR adds a new monadic interface for `Async` operations.

This is the design for the `Async` monad that I liked the most. The idea
was refined with the help of @tydeu. Before that, I had some
prerequisites in mind:

1. Good performance
2. Explicit `yield` points, so we could avoid using `bindTask` for every
lifted IO operation
3. A way to avoid creating an infinite chain of `Task`s during recursion

The 2 and 3 points are not covered in this PR, I wish I had a good
solution but right now only a few sketches of this.

### Explicit `yield` points

I thought this would be easy at first, but it actually turned out kinda
tricky. I ended up creating the `suspend` syntax, which is just a small
modification of the lift method (`<- ...`) syntax. It desugars to
`Suspend.suspend task fun _ => ...`. So something like:

```lean
do
  IO.println "a"
  IO.println "b"
  let result := suspend (client.recv? 1024)
  IO.println "c"
  IO.println "d"
```

Would become:

```lean
Bind.bind (IO.println "a") fun _ =>
Bind.bind (IO.println "b") fun _ =>
Suspend.suspend (client.recv? 1024) fun message =>
  Bind.bind (IO.println "c") fun _ =>
  IO.println "d"
```

This makes things a bit more efficient. When using `bind`, we would try
to avoid creating a `Task` chain, and the `suspend` would be the only
place we use `Task.bind`. But there's a problem if we use `bind` with
something that needs `suspend`, it’ll block the whole task. Blocking is
the only way to prevent task accumulation when using plain `bind` inside
a structure like that:

```
inductive AsyncResult (ε σ α : Type u) where
    | ok    : α → σ → AsyncResult ε σ α
    | error : ε → σ → AsyncResult ε σ α
    | ofTask  : Task (EStateM.Result ε σ α) → σ →AsyncResult ε σ α
```

Because we simply need to remove the `ofTask` and transform it into an
`ok`.

### Infinite chain of Tasks

If you create an infinite recursive function using `Task` (which is
super common in servers like HTTP ones), it can lead to a lot of memory
usage. Because those tasks get chained forever and won't be freed until
the function returns.

To get around that, I used CPS and instead of just calling `Task.bind`,
I’d spawn a new task and return an "empty" one like:

```lean
fun k => Task.bind (...) fun value => do k value; pure emptyTask
```

This works great with a CPS-style monad, but it generates a huge IR by
itself.

Just doing CPS alone was too much, though, because every lifted
operation created a new continuation and a `Task.bind`. So, I used it
with `suspend` and got a better performance, but the usage is not good
with `suspend`.

### The current monad

Right now, the monad I’m using is super simple. It doesn't solve the
earlier problems, but the API is clean, and the generated IR is small
enough. An example of how we should use it is:

```lean
-- A loop that repeatedly sends a message and waits for a reply.
partial def writeLoop (client : Socket.Client) (message : String) : Async (AsyncTask Unit) := async do
  IO.println s!"sending: {message}"
  await (← client.send (String.toUTF8 message))

  if let some mes ← await (← client.recv? 1024) then
    IO.println s!"received: {String.fromUTF8! mes}"
    -- use parallel to avoid building up an infinite task chain
    parallel (writeLoop client message)
  else
    IO.println "client disconnected from receiving"

-- Server’s main accept loop, keeps accepting and echoing for new clients.
partial def acceptLoop (server : Socket.Server) (promise : IO.Promise Unit) : Async (AsyncTask Unit) := async do
  let client ← await (← server.accept)
  await (← client.send (String.toUTF8 "tutturu "))

  -- allow multiple clients to connect at the same time
  parallel (writeLoop client "hi!!")

  -- and keep accepting more clients, parallel again to avoid building up an infinite task chain
  parallel (acceptLoop server promise)

-- A simple client that connects and sends a message.
def echoClient (addr : SocketAddress) (message : String) : Async (AsyncTask Unit) := async do
  let socket ← Client.mk
  await (← socket.connect addr)
  parallel (writeLoop socket message)

-- TCP setup: bind, listen, serve, and run a sample client.
partial def mainTCP : Async Unit := do
  let addr := SocketAddressV4.mk (.ofParts 127 0 0 1) 8080

  let server ← Server.mk
  server.bind addr
  server.listen 128

  -- promise exists since the server is (probably) never going to stop
  let promise ← IO.Promise.new
  let acceptAction ← acceptLoop server promise

  await (← echoClient addr "hi!")
  await acceptAction
  await promise

-- Entry point
def main : IO Unit := mainTCP.wait
```

---------

Co-authored-by: Henrik Böving <hargonix@gmail.com>
Co-authored-by: Mac Malone <tydeu@hatpress.net>
2025-06-26 02:51:26 +00:00
Kim Morrison
1e135f2187 fix: refactor ToInt.OfNat (#9005)
This PR changes the definition of `Lean.Grind.ToInt.OfNat`, introducing
a `wrap` on the right-hand-side.
2025-06-26 02:27:15 +00:00
Cameron Zwarich
d6fdbe2b23 fix: implement main type validity check in the new compiler (#9003)
This PR implements the validity check for the type of `main` in the new
compiler. There were no tests for this, so it slipped under the radar.
2025-06-25 23:59:27 +00:00
Cameron Zwarich
567280cb41 chore: remove outdated comment (#9002) 2025-06-25 22:16:36 +00:00
jrr6
8da2f7105c chore: reword redundant alternative error explanation (#9001)
This PR adjusts the `lean.redundantMatchAlt` error explanation to remove
the word "unprefixed," which the reference manual's style linter does
not recognize.
2025-06-25 22:15:22 +00:00
Luisa Cicolini
25b1b46572 feat: add BitVec.msb_(smod, srem) (#8974)
This PR adds `BitVec.msb_(smod, srem)`. 

co-authored with @tobiasgrosser and @bollu

---------

Co-authored-by: Tobias Grosser <github@grosser.es>
Co-authored-by: Siddharth <siddu.druid@gmail.com>
2025-06-25 13:49:33 +00:00
Kim Morrison
0ddd9341d6 feat: refactor of Lean.Grind.ToInt and remaining instances (#8996)
This PR provides the remaining instances for the `Lean.Grind.ToInt`
typeclasses.
2025-06-25 13:32:38 +00:00
Joachim Breitner
b2a8d890c1 refactor: linearNoConfusionType: use PULift, not PUnit → (#8973)
This PR refactors the juggling of universes in the linear
`noConfusionType` construction: Instead of using `PUnit.{…} → ` in the
to get the branches of `withCtorType` to the same universe level, we use
`PULift`.

This fixes https://github.com/leanprover/lean4/issues/8962, although
probably doesn’t solve all issues of that kind while level equality
checking is incomplete.
2025-06-25 09:05:03 +00:00
Joachim Breitner
9641a9ac6c feat: PULift (#8992)
This PR adds `PULift`, a more general form of `ULift` and `PLift` that
subsumes both.

Needed in #8973
2025-06-25 09:04:52 +00:00
Wojciech Rozowski
15d1d38bd9 fix: add isDefEq check in the recursive call case of solveMonoStep inside monotonicity tactic (#8978)
This PR updates the `solveMonoStep` function used in the `monotonicity`
tactic to check for definitional equality between the current goal and
the monotonicity proof obtained from a recursive call. This ensures
soundness by preventing incorrect applications when
`Lean.Order.PartialOrder` instances differ—an issue that can arise with
`mutual` blocks defined using the `partial_fixpoint` keyword, where
different `Lean.Order.CCPO` structures may be involved.

Closes https://github.com/leanprover/lean4/issues/8894.
2025-06-25 08:40:15 +00:00
Kim Morrison
94f48c3cec feat: add ToInt typeclasses for grind (#8991)
This PR adds some missing `ToInt.X` typeclass instances for `grind`.

There are still several more to add (in particular, for `ToInt.Pow`),
but I am going to perform an intermediate refactor first.
2025-06-25 05:38:15 +00:00
Kim Morrison
58c69909a1 feat: doc-strings for grind algebra classes (#8990)
This PR adds missing doc-strings for grind's internal algebra
typeclasses, for inclusion in the reference manual.
2025-06-25 04:46:44 +00:00
Kim Morrison
708c5f1d9a chore: cleanup of grind in BitVec/Lemmas (#8989) 2025-06-25 03:00:31 +00:00
Kim Morrison
af22926d53 chore: updates to (failing) grind algebra tests (#8987) 2025-06-25 02:44:59 +00:00
Mac Malone
311ae6168d feat: lake: avoid use of Lean root directories (#8981)
This PR removes Lake's usage of `lean -R` and `moduleNameOfFileName` to
pass module names to Lean. For workspace names, it now relies on
directly passing the module name through `lean --setup`. For
non-workspace modules passed to `lake lean` or `lake setup-file`, it
uses a fixed module name of `_unknown`.

This means that `lake lean` and `lake setup-file` can be successfully
and consistently used on modules that do not lie under the working
directory or the workspace root.
2025-06-25 01:04:13 +00:00
Leonardo de Moura
f1021e4537 fix: congruence proof for over-applied terms (#8983)
This PR fixes a bug in congruence proof generation in `grind` for
over-applied functions.
2025-06-24 22:04:23 +00:00
Mac Malone
ddbba944d4 fix: pass Lean CMake CI options to the Lake build (#8823)
This PR passes Lean options configured via CMake variables onto the Lake
build. For example, this will ensure CI' setting of `warningAsError` via
`LEAN_EXTRA_MAKE_OPTS` reaches Lake.
2025-06-24 11:39:29 +00:00
Kim Morrison
3e8d28ae6b feat: use grind in BitVec/Lemmas (#8967)
This PR both adds initial `@[grind]` annotations for `BitVec`, and uses
`grind` to remove many proofs from `BitVec/Lemmas`.

---------

Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
2025-06-24 10:54:43 +00:00
Joachim Breitner
9d363e3541 fix: linter.simpUnusedSimpArgs to check syntax kind (#8971)
This PR fixes `linter.simpUnusedSimpArgs` to check the syntax kind, to
not fire on `simp` calls behind macros. Fixes #8969
2025-06-24 08:31:57 +00:00
Henrik Böving
a223e92f85 chore: remove use of deprecated API (#8970) 2025-06-24 08:22:50 +00:00
Luisa Cicolini
46a7c9108f feat: add BitVec.(getElem, getLsbD, getMsbD)_(smod, sdiv, srem) (#8941)
This PR adds `BitVec.(getElem, getLsbD, getMsbD)_(smod, sdiv, srem)`
theorems to complete the API for `sdiv`, `srem`, `smod`. Even though the
rhs is not particularly succint (it's hard to find a meaning for what it
means to have "the n-th bit of the result of a signed division/modulo
operation"), these lemmas prevent the need to `unfold` of operations.

---------

Co-authored-by: Kim Morrison <477956+kim-em@users.noreply.github.com>
2025-06-24 07:09:00 +00:00
Kyle Miller
a427a8264a chore: cleanup after stage0 update (#8966)
This PR cleans up the bootstrapping code added in #8957.
2025-06-24 05:34:57 +00:00
Kim Morrison
cc493e688b feat: embed a NatModule in its IntModule completion (#8963)
This PR embeds a NatModule into its IntModule completion, which is
injective when we have AddLeftCancel, and monotone when the modules are
ordered. Also adds some (failing) grind test cases that can be verified
once `grind` uses this embedding.
2025-06-24 05:30:43 +00:00
Kim Morrison
5a9d7ae925 feat: revise grind annotations for bitwise operations (#8965)
This PR revises @[grind] annotations on Nat bitwise operations.
2025-06-24 05:16:21 +00:00
Kim Morrison
e0c2263073 chore: add @[expose] in Grind/Ring/Poly.lean (#8964)
This PR adds `@[expose]` attributes to proof terms constructed by
`grind` that need to be evaluated in the kernel.
2025-06-24 05:14:12 +00:00
Lean stage0 autoupdater
e51d2d8747 chore: update stage0 2025-06-24 05:02:20 +00:00
Kim Morrison
449bc31832 chore: adds (failing) grind algebra tests (#8961) 2025-06-24 03:51:39 +00:00
Kim Morrison
8fe068ef68 feat: move lean-pr-testing-NNNN branches to a fork (#8933)
This PR changes the CI setup to generate `lean-pr-testing-NNNN` branches
for Mathlib on the `leanprover-community/mathlib4-nightly-testing` fork,
rather than on the main repo.
2025-06-24 03:30:43 +00:00
Kim Morrison
6970d77ae4 feat: the grothendieck envelope of an ordered semiring is an ordered ring (#8959)
This PR add instances showing that the Grothendieck (i.e. additive)
envelope of a semiring is an ordered ring if the original semiring is
ordered (and satisfies ExistsAddOfLE), and in this case the embedding is
monotone.
2025-06-24 03:23:18 +00:00
Leonardo de Moura
07662aafe3 fix: better case-split for match-conditions in grind (#8958)
This PR improves the case splitting strategy used in `grind`, and
ensures `grind` also considers simple `match`-conditions for
case-splitting. Example:

```lean
example (x y : Nat)
    : 0 < match x, y with
          | 0, 0   => 1
          | _, _ => x + y := by -- x or y must be greater than 0
  grind
```
2025-06-24 02:56:50 +00:00
Kyle Miller
b28dc8c5fb feat: add configuration for let/have tactics (#8957)
This PR adds configuration options to the `let`/`have` tactic syntaxes.
For example, `let (eq := h) x := v` adds `h : x = v` to the local
context. The configuration options are the same as those for the
`let`/`have` term syntaxes.
2025-06-24 02:49:02 +00:00
Cameron Zwarich
81740da50a fix: avoid caching uses of never_extract constants in toLCNF (#8956)
This PR changes `toLCNF` to stop caching translations of expressions
upon seeing an expression marked `never_extract`. This is more
coarse-grained than it needs to be, but it is difficult to do any
better, as the new compiler's `Expr` cache is based on structural
identity (rather than the pointer identity of the old compiler).

The newly added `tests/compiler/never_extract.lean` is also converted
into a `run` tests, because during development I found the order of the
output to `stderr` to be a bit finicky. The reason for making it a
`compiler` test in the first place is that closed term decls work
slightly differently between native code and the interpreter, and it
would be good to test both, but we already have separate tests for
`never_extract` and closed term extraction.

Fixes #8944.
2025-06-24 02:04:56 +00:00
Kyle Miller
32f8a95437 fix: Lean.MVarId.deltaLocalDecl (#8955)
This PR fixes `Lean.MVarId.deltaLocalDecl`, which previously replaced
the local definition with the target.
2025-06-24 01:37:18 +00:00
Kyle Miller
71cf266cd7 feat: add Meta.letToHave and the let_to_have tactic (#8954)
This PR adds a procedure that efficiently transforms `let` expressions
into `have` expressions (`Meta.letToHave`). This is exposed as the
`let_to_have` tactic.

It uses the `withTrackingZetaDelta` technique: the expression is
typechecked, and any `let` variables that don't enter the zeta delta set
are nondependent. The procedure uses a number of heuristics to limit the
amount of typechecking performed. For example, it is ok to skip
subexpressions that do not contain fvars, mvars, or `let`s.
2025-06-24 01:33:53 +00:00
Leonardo de Moura
0941d53f6a feat: semiring normalizer in grind (#8953)
This PR implements support for normalization for commutative semirings
that do not implement `AddRightCancel`. Examples:
```lean
variable (R : Type u) [CommSemiring R]

example (a b c : R) : a * (b + c) = a * c + b * a := by grind
example (a b : R) : (a + b)^2 = a^2 + 2 * a * b + b^2 := by grind
example (a b : R) : (a + 2 * b)^2 = a^2 + 4 * a * b + 4 * b^2 := by grind
example (a b : R) : (a + 2 * b)^2 = 4 * b^2 + b * 4 * a + a^2 := by grind
```
2025-06-24 01:09:22 +00:00
Leonardo de Moura
ba07e46368 refactor: simplify semiring normalization helper theorems (#8946)
This PR simplifies the semiring normalization theorem that will be used
by `grind`.
2025-06-23 23:20:20 +00:00
Cameron Zwarich
24cbd4efbe fix: correctly handle never_extract attribute in LCNF CSE (#8952)
This PR fixes the handling of the `never_extract` attribute in the
compiler's CSE pass. There is an interesting debate to be had about
exactly how hard the compiler should try to avoid duplicating anything
that transitively uses `never_extract`, but this is the simplest form
and roughly matches the check in the old compiler (although due to
different handling of local function decls in the two compilers, the
consequences might be slightly different).

This gets half of the way to #8944.
2025-06-23 23:03:10 +00:00
Cameron Zwarich
b0269d2875 chore: share leading prefix between then/else branches (#8951) 2025-06-23 22:17:54 +00:00
Wojciech Rozowski
22cd34c341 chore: rename keywords for (co)inductive predicates and the names of the associated (co)induction principles 2025-06-23 20:40:08 +02:00
Wojciech Rozowski
b4b68415e0 chore: update stage0 2025-06-23 20:40:08 +02:00
Wojciech Rozowski
07c398e441 chore: rename keywords for (co)inductive predicates and the names of their associated (co)induction principles
chore: rename `fixpoint_induct` to `induct` and `coinduct` for (co)inductive predicates
2025-06-23 20:40:08 +02:00
Mac Malone
dd64678f07 feat: server support for new module setup (#8699)
This PR adds support to the server for the new module setup process by
changing how `lake setup-file` is used.

In the new server setup, `lake setup-file` is invoked with the file name
of the edited module passed as a CLI argument and with the parsed header
passed to standard input in JSON form. Standard input is used to avoid
potentially exceeding the CLI length limits on Windows. Lake will build
the module's imports along with any other dependencies and then return
the module's workspace configuration via JSON (now in the form of
`ModuleSetup`). The server then post-processes this configuration a bit
and returns it back to the Lean language processor.

The server's header is currently only fully respected by Lake for
external modules (files that are not part of any workspace library). For
workspace modules, the saved module header is currently used to build
imports (as has been done since #7909). A follow-up Lake PR will align
both cases to follow the server's header.

Lean search paths (e.g., `LEAN_PATH`, `LEAN_SRC_PATH`) are no longer
negotiated between the server and Lake. These environment variables are
already configured during sever setup by `lake serve` and do not change
on a per-file basis. Lake can also pre-resolve the `.olean` files of
imports via the `importArts` field of `ModuleSetup`, limiting the
potential utility of communicating `LEAN_PATH`.
2025-06-23 18:00:14 +00:00
Mac Malone
e0a793ae20 feat: ignore lean -R if module name is in setup (#8874)
This PR skips attempting to compute a module name from the file name and
root directory (i.e., `lean -R`) if a name is already provided via `lean
--setup`.

This is accomplished by porting the rest of the frontend code in the
`try` block to Lean.
2025-06-23 17:55:52 +00:00
jrr6
32795911d2 feat: add initial error explanations (#8934)
This PR adds explanations for a few errors concerning noncomputability,
redundant match alternatives, and invalid inductive declarations.

These adopt a lower-case error naming style, which is also applied to
existing error explanation tests.
2025-06-23 17:24:09 +00:00
Anne Baanen
ecf670e08c feat: make math Lake template follow Mathlib standards (#8866)
This PR upgrades the `math` template for `lake init` and `lake new` to
configures the new project to meet rigorous Mathlib maintenance
standards. In comparison with the previous version (now available as
`lake new ... math-lax`), this automatically provides:

* Strict linting options matching Mathlib.
* GitHub workflow for automatic upgrades to newer Lean and Mathlib
releases.
* Automatic release tagging for toolchain upgrades.
* API documentation generated by
[doc-gen4](https://github.com/leanprover/doc-gen4) and hosted on
`github.io`.
* README with some GitHub-specific instructions.

The previous edition of the template is still available, renamed to
`math-lax`.

---------

Co-authored-by: Mac Malone <tydeu@hatpress.net>
2025-06-23 13:28:47 +00:00
Leonardo de Moura
9a202a420b feat: semiring normalization theorems (#8943)
This PR adds helper theorems for normalizing semirings that do not
implement `AddRightCancel`.
2025-06-23 13:07:46 +00:00
Wojciech Rozowski
489d7b6d72 feat: add antitonicity lemmas for (co)inductive predicates (#8940)
This PR introduces antitonicity lemmas that support the elaboration of
mixed inductive-coinductive predicates defined using the
`least_fixpoint` / `greatest_fixpoint` constructs.

For instance, the following definition elaborates correctly because all
occurrences of the inductively defined predicate `tock `within the
coinductive definition of `tick` appear in negative positions. The dual
situation applies to the definition of `tock`:
```
  mutual
    def tick : Prop :=
      tock → tick
    greatest_fixpoint

    def tock : Prop :=
      tick → tock
    least_fixpoint
  end
```
2025-06-23 11:02:08 +00:00
Parth Shastri
8223a96bf5 fix: correct universe used in below/brecOn for non-reflexive inductive types (#8937)
This PR changes the output universe of the generated `below`
implementation for non-reflexive inductive types to match the
implementation for reflexive inductive types in #7639.

This fixes the `below`/`brecOn` implementations for certain nested
inductive types, as reported in
https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Universes/near/525030149.
2025-06-23 09:42:31 +00:00
Joachim Breitner
29298c9f30 feat: linter.loopingSimpArgs (#8865)
This PR allows `simp` to recognize and warn about simp lemmas that are
likely looping in the current simp set. It does so automatically
whenever simplification fails with the dreaded “max recursion depth”
error fails, but it can be made to do it always with `set_option
linter.loopingSimpArgs true`. This check is not on by default because it
is somewhat costly, and can warn about simp calls that still happen to
work.

This closes #5111. In the end, this implemented much simpler logic than
described there (and tried in the abandoned #8688; see that PR
description for more background information), but it didn’t work as well
as I thought. The current logic is:

“Simplify the RHS of the simp theorem, complain if that fails”.

It is a reasonable policy for a Lean project to say that all simp
invocation should be so that this linter does not complain. Often it is
just a matter of explicitly disabling some simp theorems from the
default simp set, to make it clear and robust that in this call, we do
not want them to trigger. But given that often such simp call happen to
work, it’s too pedantic to impose it on everyone.
2025-06-23 07:36:21 +00:00
Cameron Zwarich
596a3034e7 chore: fix indentation (#8936) 2025-06-23 05:07:33 +00:00
Lean stage0 autoupdater
91a4e17b6d chore: update stage0 2025-06-23 03:43:45 +00:00
Kyle Miller
7b0a9bdadf feat: let +generalize (#8935)
This PR adds the `+generalize` option to the `let` and `have` syntaxes.
For example, `have +generalize n := a + b; body` replaces all instances
of `a + b` in the expected type with `n` when elaborating `body`. This
can be likened to a term version of the `generalize` tactic. One can
combine this with `eq` in `have +generalize (eq := h) n := a + b; body`
as an analogue of `generalize h : n = a + b`.
2025-06-23 02:21:57 +00:00
Kim Morrison
8f4b2909de chore: cleanup of grind's order typeclasses (#8913)
This PR cleans up `grind`'s internal order typeclasses, removing
unnecessary duplication.
2025-06-22 23:36:48 +00:00
Kyle Miller
bb0132e4b3 chore: for #8914 after stage0 update, part 2 (#8931)
This PR finishes post-stage0-cleanup after #8914 and #8929. Also:
- adds configuration options for `haveI` and `letI` terms.
- adds `letConfig` parser alias
2025-06-22 22:40:00 +00:00
Kyle Miller
02c8c2f9e1 feat: use nondep flag in Expr.letE and LocalContext.ldecl (#8804)
This PR implements first-class support for nondependent let expressions
in the elaborator; recall that a let expression `let x : t := v; b` is
called *nondependent* if `fun x : t => b` typechecks, and the notation
for a nondependent let expression is `have x := v; b`. Previously we
encoded `have` using the `letFun` function, but now we make use of the
`nondep` flag in the `Expr.letE` constructor for the encoding. This has
been given full support throughout the metaprogramming interface and the
elaborator. Key changes to the metaprogramming interface:
- Local context `ldecl`s with `nondep := true` are generally treated as
`cdecl`s. This is because in the body of a `have` expression the
variable is opaque. Functions like `LocalDecl.isLet` by default return
`false` for nondependent `ldecl`s. In the rare case where it is needed,
they take an additional optional `allowNondep : Bool` flag (defaults to
`false`) if the variable is being processed in a context where the value
is relevant.
- Functions such as `mkLetFVars` by default generalize nondependent let
variables and create lambda expressions for them. The
`generalizeNondepLet` flag (default true) can be set to false if `have`
expressions should be produced instead. **Breaking change:** Uses of
`letLambdaTelescope`/`mkLetFVars` need to use `generalizeNondepLet :=
false`. See the next item.
- There are now some mapping functions to make telescoping operations
more convenient. See `mapLetTelescope` and `mapLambdaLetTelescope`.
There is also `mapLetDecl` as a counterpart to `withLetDecl` for
creating `let`/`have` expressions.
- Important note about the `generalizeNondepLet` flag: it should only be
used for variables in a local context that the metaprogram "owns". Since
nondependent let variables are treated as constants in most cases, the
`value` field might refer to variables that do not exist, if for example
those variables were cleared or reverted. Using `mapLetDecl` is always
fine.
- The simplifier will cache its let dependence calculations in the
nondep field of let expressions.
- The `intro` tactic still produces *dependent* local variables. Given
that the simplifier will transform lets into haves, it would be
surprising if that would prevent `intro` from creating a local variable
whose value cannot be used.

Note that nondependence of lets is not checked by the kernel. To
external checker authors: If the elaborator gets the nondep flag wrong,
we consider this to be an elaborator error. Feel free to typecheck `letE
n t v b true` as if it were `app (lam n t b default) v` and please
report issues.

This PR follows up from #8751, which made sure the nondep flag was
preserved in the C++ interface.
2025-06-22 21:54:57 +00:00
Lean stage0 autoupdater
2ebc001dd1 chore: update stage0 2025-06-22 20:38:51 +00:00
Kyle Miller
f4f664e1ed fix: update Parser.Term.letIdDeclNoBinders to use new letIdDecl format (#8929)
This PR is a followup to #8914, fixing an oversight where
`letIdDeclBinders` is was not updated with the new format. This relies
on some bootstrapping code to stay in place, but we do bootstrap cleanup
that is currently possible.
2025-06-22 19:28:46 +00:00
Mac Malone
ded8a0cb57 feat: IO.FS.Stream.readToEnd (#8886)
This PR adds `IO.FS.Stream.readToEnd` which parallels
`IO.FS.Handle.readToEnd` along with its upstream definitions (i.e.,
`readBinToEndInto` and `readBinToEnd`). It also removes an unnecessary
`partial` from `IO.FS.Handle.readBinToEnd`.

This function is useful for reading, for example, all of standard input.
2025-06-22 15:39:10 +00:00
Mac Malone
52bdc9bcbd feat: IO.FS.Stream.lines & IO.FS.Handle.lines (#8887)
This PR generalizes `IO.FS.lines` with `IO.FS.Handle.lines` and adds the
parallel `IO.FS.Stream.lines` for streams.

The stream version is useful for reading, for example, the lines of
standard input.
2025-06-22 14:57:17 +00:00
Joachim Breitner
6092561f93 refactor: SimpM.run (#8843)
This PR factors out the common code for running `SimpM` from `mainCore`
and `dsimpMainCore`, and make it available separately (e.g. for #8865).
2025-06-22 13:50:44 +00:00
Joachim Breitner
117f73fc84 feat: linter.unusedSimpArgs (#8901)
This PR adds a linter (`linter.unusedSimpArgs`) that complains when a
simp argument (`simp [foo]`) is unused. It should do the right thing if
the `simp` invocation is run multiple times, e.g. inside `all_goals`. It
does not trigger when the `simp` call is inside a macro. The linter
message contains a clickable hint to remove the simp argument.

I chose to display a separate warning for each unused argument. This
means that the user has to click multiple times to remove all of them
(and wait for re-elaboration in between). But this just means multiple
endorphine kicks, and the main benefit over a single warning that would
have to span the whole argument list is that already the squigglies tell
the users about unused arguments.

This closes #4483.

Making Init and Std clean wrt to this linter revealed close to 1000
unused simp args, a pleasant experience for anyone enjoying tidying
things: #8905
2025-06-22 09:10:21 +00:00
Sebastian Graf
1e78207d3a chore: Revert "feat: Upstream MPL.SPred.* from mpl" (#8927)
Reverts leanprover/lean4#8745 until I take a closer look on its breakage
in Mathlib on Monday
2025-06-22 09:02:54 +00:00
Lean stage0 autoupdater
16c918a652 chore: update stage0 2025-06-22 08:08:57 +00:00
Kyle Miller
239534cbb7 chore: for #8914 after stage0 update (#8925)
This PR does a first pass at cleaning things up for #8914 after a stage0
update.
2025-06-22 06:52:11 +00:00
Cameron Zwarich
85e061bed5 chore: remove unused impure LCNF Phase (#8924)
The `.impure` LCNF `Phase` is not currently used, but was intended for a
potential future where the current `IR` passes (which operate on a
highly impure representation) were rewritten to operate on LCNF instead.
For several reasons, I don't think this is very likely to happen, and
instead we are more likely to remove some of the unnecessary differences
between LCNF and IR while keeping them distinct.
2025-06-22 05:38:16 +00:00
Cameron Zwarich
d41b9f004a feat: support casesOn for Thunk and Task (#8923)
This PR implements `casesOn` for `Thunk` and `Task`. Since these are
builtin types, this needs to be special-cased in `toMono`.

Fixes #8659.
2025-06-22 05:24:33 +00:00
Lean stage0 autoupdater
c63618b7b8 chore: update stage0 2025-06-22 05:33:59 +00:00
Kyle Miller
219f8214d3 feat: make let and have term syntaxes be consistent (#8914)
This PR modifies `let` and `have` term syntaxes to be consistent with
each other. Adds configuration options; for example, `have` is
equivalent to `let +nondep`, for *nondependent* lets. Other options
include `+usedOnly` (for `let_tmp`), `+zeta` (for `letI`/`haveI`), and
`+postponeValue` (for `let_delayed)`. There is also `let (eq := h) x :=
v; b` for introducing `h : x = v` when elaborating `b`. The `eq` option
works for pattern matching as well, for example `let (eq := h) (x, y) :=
p; b`.

Future PRs will add these options to tactic syntax, once a stage0 update
has been done.
2025-06-22 04:22:47 +00:00
Leonardo de Moura
7531d16112 feat: (commutative) semiring support in grind (#8921)
This PR implements support for (commutative) semirings in `grind`. It
uses the Grothendieck completion to construct a (commutative) ring
`Lean.Grind.Ring.OfSemiring.Q α` from a (commutative) semiring `α`. This
construction is mostly useful for semirings that implement
`AddRightCancel α`. Otherwise, the function `toQ` is not injective.
Examples:
```lean
example (x y : Nat) : x^2*y = 1 → x*y^2 = y → y*x = 1 := by
  grind 

example [CommSemiring α] [AddRightCancel α] (x y : α) : x^2*y = 1 → x*y^2 = y → y*x = 1 := by
  grind

example (a b : Nat) : 3 * a * b = a * b * 3 := by grind

example (k z : Nat) : k * (z * 2 * (z * 2 + 1)) = z * (k * (2 * (z * 2 + 1))) := by grind

example [CommSemiring α] [AddRightCancel α] [IsCharP α 0] (x y : α) 
    : x^2*y = 1 → x*y^2 = y → x + y = 1 → False := by
  grind
```
2025-06-21 23:00:16 +00:00
Joachim Breitner
61518e4357 chore: remove more unused simp args (#8920)
This PR uses the linter from #8901 to clean up more simp arguments,
completing #8905.
2025-06-21 18:34:17 +00:00
Joachim Breitner
2441bf1f76 perf: check simp cache in simpLoop (#8880)
This PR makes `simp` consult its own cache more often, to avoid
replicating work.

Before, the simp cache was checked upon entry of `simpImpl` only, which
then calls `simpLoop`, which recursively iterates the `pre`-lemmas,
without checking the cache again.

Now, `simpLoop` itself checks the cache. This seems more principled,
given that `simpLoop` is actually putting entries into the cache for
each of its calls, so it’s more uniform if it checks the cache itself.

This avoids repeated rewrites. For example given
```
theorem ab : a = b := testSorry
theorem bc : b = c := testSorry
example (h : P c) : P b ∧ P a := by simp [ab, bc, h]
```
simp would rewrite `b ==> c` twice (once as part of `b ==> c` and then
again as part of `a ==> b ==> c`). And it’d be order dependent: With
```
example (h : P c) : P a ∧ P b := by simp [ab, bc, h]
```
the `a ==> b ==> c` chain would insert `b ==> c` into the cache, and
picked up by `simpImpl` when rewriting `P b`.

With this change, `b ==> c` is performed only once in both examples.

Instruction counts on stdlib and mathlib both show a mild improvement
across the board (0.5%), with individual modules improving by up to 4%
in stdlib and even more in mathlib.


(This does not check the cache before applying `post`, which explains
where there are still some repeated rewrites in the trace logs. But I’m
less sure about inserting a cache check here and so I am treading
carefully here. It’s also going to be at most one `post` application
that’s duplicated, because if `post` returns `.visit`, we go back to
`pre` and thus a cache check.)
2025-06-21 17:58:05 +00:00
Joachim Breitner
4d697874b7 refactor: simp arg elaboration (#8815)
This PR refactors the way simp arguments are elaborated: Instead of
changing the `SimpTheorems` structure as we go, this elaborates each
argument to a more declarative description of what it does, and then
apply those. This enables more interesting checks of simp arguments that
need to happen in the context of the eventually constructed simp context
(the checks in #8688), or after simp has run (unused argument linter
#8901).

The new data structure describing an elaborated simp argument isn’t the
most elegant, but follows from the code.

While I am at it, move handling of `[*]` into `elabSimpArgs`. Downstream
adaption branches exist (but may not be fully up to date because of the
permission changes).

While I am at it, I cleaned up `SimpTheorems.lean` file a bit (sorting
declarations, mild renaming) and added documentation.
2025-06-21 17:55:53 +00:00
Cameron Zwarich
85992757e7 fix: check guard_msgs.diff using .get rather than Options.getBool (#8918)
This PR fixes the `guard_msgs.diff` default behavior so that the default
specified in the option definition is actually used everywhere.
2025-06-21 16:03:31 +00:00
Cameron Zwarich
7d82dd99c9 chore: add test for #4278, which was fixed by the new compiler (#8916) 2025-06-21 15:05:46 +00:00
Kyle Miller
3878432ac7 fix: make sure local instance detection sees through reductions (#8903)
This PR make sure that the local instance cache calculation applies more
reductions. In #2199 there was an issue where metavariables could
prevent local variables from being considered as local instances. We use
a slightly different approach that ensures that, for example, `let`s at
the ends of telescopes do not cause similar problems. These reductions
were already being calculated, so this does not require any additional
work to be done.

Metaprogramming interface addition: the various forall telescope
functions that do reduction now have a `whnfType` flag (default false).
If it's true, then the callback `k` is given the WHNF of the type. This
is a free operation, since the telescope function already computes it.
2025-06-21 06:26:32 +00:00
Kim Morrison
5198a3fbb7 feat: refactor grind's typeclasses for ordered algebra (#8855)
This PR refactors `Lean.Grind.NatModule/IntModule/Ring.IsOrdered`.

We ensure the the diamond from `Ring` to `NatModule` via either
`Semiring` or `IntModule` is defeq, which was not previously the case.

---------

Co-authored-by: Leonardo de Moura <leomoura@amazon.com>
2025-06-21 04:49:13 +00:00
Leonardo de Moura
921453e3e6 feat: NoNatZeroDivisors for Semiring envelope (#8910)
This PR adds the `NoNatZeroDivisors` instance for `OfSemiring.Q α`
2025-06-21 03:56:37 +00:00
Leonardo de Moura
9ece4e463a refactor: NoNatZeroDivisors (#8909)
This PR refactors the `NoNatZeroDivisors` to make sure it will work with
the new `Semiring` support.
2025-06-21 03:01:05 +00:00
Sebastian Ullrich
c38c0898a3 chore: allow module in tests (#8881)
This PR adjusts the test scripts and adds a simple test-only lakefile so
that `experimental.module` is set both when editing and running tests.
2025-06-21 02:49:22 +00:00
Leonardo de Moura
12a8f1b5f8 chore: remove staging workarounds (#8908) 2025-06-21 02:38:09 +00:00
Lean stage0 autoupdater
7050dc6d38 chore: update stage0 2025-06-21 01:59:13 +00:00
Kim Morrison
376ae32c7c feat: fix pretty printing of grind attributes (#8892)
This PR corrects the pretty printing of `grind` modifiers. Previously
`@[grind →]` was being pretty printed as `@[grind→ ]` (Space on the
right of the symbol, rather than left.) This fixes the pretty printing
of attributes, and preserves the presence of spaces after the symbol in
the output of `grind?`.

---------

Co-authored-by: Leonardo de Moura <leomoura@amazon.com>
2025-06-21 00:50:25 +00:00
Cameron Zwarich
0c44aab811 chore: add a test for #4716, which is fixed by the new compiler (#8907) 2025-06-20 23:43:25 +00:00
Kim Morrison
a5eeed4f2c chore: a few missing grind typeclass docstrings (#8906) 2025-06-20 23:35:58 +00:00
Joachim Breitner
be80a23281 chore: remove unused simp args (#8905)
This PR uses the linter from
https://github.com/leanprover/lean4/pull/8901 to clean up simp
arguments.
2025-06-20 22:34:30 +00:00
Sebastian Ullrich
92ac564f3c fix: make mkHCongrWithArityForConst? compatible with parallelism (#8899)
This PR ensures the helper is compatible with using `grind` in
asynchronous proofs
2025-06-20 21:55:14 +00:00
Cameron Zwarich
0fcb6495d6 chore: add a test for #6957, fixed by the new compiler (#8904) 2025-06-20 21:44:09 +00:00
Lean stage0 autoupdater
e7c8baaef5 chore: update stage0 2025-06-20 18:52:57 +00:00
Cameron Zwarich
8d8c73416a chore: add a test for #2602, which was fixed by the new compiler (#8902) 2025-06-20 17:37:19 +00:00
Sebastian Graf
cf527e05bd feat: where ... finally section to assign leftover goals (#8723)
This PR implements a `finally` section following a (potentially empty)
`where` block. `where ... finally` opens a tactic sequence block in
which the goals are the unassigned metavariables from the definition
body and its auxiliary definitions that arise from use of `let rec` and
`where`.

This can be useful for discharging multiple proof obligations in the
definition body by a single invocation of a tactic such as `all_goals`:
```lean
example (i j : Nat) (xs : Array Nat) (hi : i < xs.size) (hj: j < xs.size) :=
  match i with
  | 0 => x
  | _ => xs[i]'?_ + xs[j]'?_
where x := 13
finally all_goals assumption
```

---------

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-06-20 15:51:28 +00:00
Sebastian Graf
61ee83f73b feat: Upstream MPL.SPred.* from mpl (#8745)
This PR adds a logic of stateful predicates `SPred` to `Std.Do` in order
to support reasoning about monadic programs. It comes with a dedicated
proof mode the tactics of which are accessible by importing
`Std.Tactic.Do`.

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-06-20 15:13:40 +00:00
Cameron Zwarich
26b7e49c05 chore: update stage0 2025-06-20 17:29:10 +02:00
Cameron Zwarich
466c9b56ba chore: add new tests for noncomputable 2025-06-20 17:29:10 +02:00
Cameron Zwarich
00474e17ff chore: add an extra test case to lean/run/noncomp.lean 2025-06-20 17:29:10 +02:00
Cameron Zwarich
891a2c6590 chore: reenable subset of new-compiler tests and delete others 2025-06-20 17:29:10 +02:00
Cameron Zwarich
d489c6196c chore: update expected test outputs
This makes it easier to distinguish tests that are actually
failing while we work on the new codegen.
2025-06-20 17:29:10 +02:00
Cameron Zwarich
6703af1ea0 chore: rename closed term suffix from _closedTerm to _closed
The longer name was chosen to avoid clashes with the old compiler.
2025-06-20 17:29:10 +02:00
Cameron Zwarich
7f8ccd8425 feat: enable the new compiler 2025-06-20 17:29:10 +02:00
Joachim Breitner
a8d5982fce chore: Init: clean up some simp calls (#8897)
This PR simplifies some `simp` calls.

These are the good parts of #8896.
2025-06-20 13:26:04 +00:00
Henrik Böving
50cfe354be chore: remove old LEAN_AUTO_THREAD_FINALIZATION workaround (#8885)
This PR removes an old workaround around non-implemented C++11 features
in the thread finalization.

This `ifdef` dates back to approximately 2015 as can be seen
[here](https://github.com/leanprover/lean3/blame/master/src/util/thread.cpp#L177),
the comments mention that it was originally implemented because not all
compilers at the time were able to support the C++11 `thread_local`
keyword. 10 years later this is hopefully the case and we can remove
this workaround.

There is an additional motivation for doing this,
`lean::initialize_thread` contains the following allocation:
```cpp
    g_thread_finalizers_mgr = new thread_finalizers_manager;
```
this is supposed to be freed at some point but:
```cpp
// TODO(gabriel): race condition with thread finalizers
void delete_thread_finalizer_manager() {
    // delete g_thread_finalizers_mgr;
    // g_thread_finalizers_mgr = nullptr;
}
```
so `g_thread_finalizers_mgr` leaks upon repeated invocation of
`lean::initialize_thread`.

Note that Windows has already been using this alternative implementation
for a while so the alternative implementation has (hopefully) not rotten
away in the meantime.
2025-06-20 08:52:17 +00:00
Kim Morrison
a750da5a7f chore: convert DHashMap to a structure (#8761)
This PR changes the definition of `DHashMap` to a structure. This makes
it more consistent with the other map types, which are generally defined
as structures. It also ensures that the type `DHashMap α β` is already
in weak head normal form, making it easier for `grind` to successfully
generate patterns for `DHashMap` lemmas.
2025-06-20 08:16:46 +00:00
Leonardo de Moura
588df4612a fix: missing isEqFalse (#8893)
This PR fixes a bug in the `dvd` propagation function in cutsat.
2025-06-20 08:16:08 +00:00
Miyahara Kō
dd78012ddd style: replace HEq x y with x ≍ y (#8872)
Although `HEq` was abbreviated as `≍` in #8503, many instances of the
form `HEq x y` still remain.
Therefore, I searched for occurrences of `HEq x y` using the regular
expression `(?<![A-Za-z/@]|``)HEq(?![A-Za-z.])` and replaced as many as
possible with the form `x ≍ y`.
2025-06-20 07:47:33 +00:00
Kim Morrison
db499e96aa feat: add doc-string to grind algebra typeclasses (#8890)
This PR adds doc-strings to the `Lean.Grind` algebra typeclasses, as
these will appear in the reference manual explaining how to extend
`grind` algebra solvers to new types. Also removes some redundant
fields.
2025-06-20 04:05:47 +00:00
jrr6
f416143fbc feat: improve error behavior of end command (#8387)
This PR improves the error messages produced by `end` and prevents
invalid `end` commands from closing scopes on failure.

---------

Co-authored-by: Rob23oba <152706811+Rob23oba@users.noreply.github.com>
Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>
2025-06-20 03:05:51 +00:00
Kim Morrison
743c60224a chore: minimize grind panic (#8889) 2025-06-20 01:07:14 +00:00
Kim Morrison
8af3b89203 chore: @[expose] defs that appear in grind proof terms (#8882)
This PR adds `@[expose]` annotations to terms that appear in `grind`
proof certificates, so `grind` can be used in the module system. It's
possible/likely that I haven't identified all of them yet.
2025-06-19 22:39:50 +00:00
Siddharth
da9a536ffd feat: BitVec.msb_sdiv (#8178)
This PR provides a compact formula for the MSB of the sdiv. Most of the
work in the PR involves handling the corner cases of division
overflowing (e.g. `intMin / -1 = intMin`)

---------

Co-authored-by: Luisa Cicolini <48860705+luisacicolini@users.noreply.github.com>
Co-authored-by: Tobias Grosser <github@grosser.es>
2025-06-19 09:08:04 +00:00
Kim Morrison
0077dd3d55 chore: remove redundant field from Lean.Grind.IntModule (#8879) 2025-06-19 06:03:14 +00:00
Kim Morrison
63cfe908c5 feat: add grind annotations for List/Array/Vector monadic functions (#8878)
This PR adds grind annotations for List/Array/Vector monadic functions.
2025-06-19 05:10:43 +00:00
Kim Morrison
c796609159 feat: grind annotations for List/Array/Vector.attach/pmap (#8877)
This PR adds grind annotations for
`List/Array/Vector.attach/attachWith/pmap`.
2025-06-19 05:00:35 +00:00
Kim Morrison
827c69e46e feat: generalize Lean.Grind.IsCharP to semirings (#8847)
This PR relaxes the assumptions for `Lean.Grind.IsCharP` from `Ring` to
`Semiring`, and provides an alternative constructor for rings.
2025-06-19 04:39:53 +00:00
Cameron Zwarich
19d9f6c450 chore: remove brittle new compiler tests that depend on internal decls (#8875) 2025-06-19 03:56:14 +00:00
Cameron Zwarich
bec538cc57 chore: delete disabled new-compiler tests that are no longer very useful (#8873) 2025-06-18 21:18:58 +00:00
Kyle Miller
e74d3a2f1c chore: address stage0 update TODOs (#8869)
This PR addresses a few TODOs left in comments for things to do after a
stage0 update.
2025-06-18 20:52:50 +00:00
Paul Reichert
1b5a9be785 feat: ForIn' and size for iterators (#8768)
This PR introduces a `ForIn'` instance and a `size` function for
iterators in a minimal fashion. The `ForIn'` instance is not marked as
an instance because it is unclear which `Membership` relation is
sufficiently useful. The `ForIn'` instance existing as a `def` and
inducing the `ForIn` instance, it becomes possible to provide more
specialized `ForIn'` instances, with nice `Membership` relations, for
various types of iterators. The `size` function has no lemmas yet.
2025-06-18 19:41:20 +00:00
Marc Huisinga
aea8e11d4b fix: restore code action incrementality (#8868)
This PR ensures that code actions do not have to wait for the full file
to elaborate. This regression was accidentally introduced in #7665.
2025-06-18 18:00:20 +00:00
Lean stage0 autoupdater
935aa38603 chore: update stage0 2025-06-18 18:08:31 +00:00
jrr6
e5c6fe1dac feat: add elaborators, completions, and hovers for named errors (#8730)
This PR adds support for throwing named errors with associated error
explanations. In particular, it adds elaborators for the syntax defined
in #8649, which use the error-explanation infrastructure added in #8651.
This includes completions, hovers, and jump-to-definition for error
names.

Note that another stage0 rebuild will be required to define explanations
using `register_error_explanation`.

---------

Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>
Co-authored-by: Marc Huisinga <mhuisi@protonmail.com>
2025-06-18 15:51:34 +00:00
Luisa Cicolini
62f3ee2887 feat: add leading zero counter BitVec.clz and bitblaster circuit/infrastructure (#8546)
This PR adds a new `BitVec.clz` operation and a corresponding `clz`
circuit to `bv_decide`, allowing to bitblast the count leading zeroes
operation. The AIG circuit is linear in the number of bits of the
original expression, making the bitblasting convenient wrt. rewriting.
`clz` is common in numerous compiler intrinsics (see
[here](https://clang.llvm.org/docs/LanguageExtensions.html#intrinsics-support-within-constant-expressions))
and architectures (see
[here](https://en.wikipedia.org/wiki/Find_first_set)).

Co-authored by @bollu.

---------

Co-authored-by: Tobias Grosser <github@grosser.es>
Co-authored-by: Siddharth <siddu.druid@gmail.com>
2025-06-18 15:50:04 +00:00
Sebastian Ullrich
e8c82610cd refactor: make syntax covering snapshot tasks more precise on the top level (#8744) 2025-06-18 13:23:21 +00:00
Paul Reichert
86eded35db refactor: partially move iterators to Init (#8767)
This PR moves parts of the iterator library from `Std` to `Init`. The
reason is that the polymorphic range API must be in `Init` and it
depends on the iterators.
2025-06-18 10:08:04 +00:00
Lean stage0 autoupdater
f0fdab86bb chore: update stage0 2025-06-18 10:07:05 +00:00
Kim Morrison
d58e253671 chore: add missing List.eraseIdx_insertIdx deprecation (#8863) 2025-06-18 08:48:00 +00:00
Kim Morrison
d0c1053903 chore: add test case for grind panic (#8861)
This PR adds a (failing) test case for a panic caused by grind.
2025-06-18 08:00:17 +00:00
Kim Morrison
48a0e742d8 chore: Lean.Grind.IntModule instances (#8859)
This PR shows the equivalence between `Lean.Grind.NatModule.IsOrdered`
and `Lean.Grind.IntModule.IsOrdered` over an `IntModule`.
2025-06-18 07:30:37 +00:00
Sebastian Ullrich
d131cf39c1 fix: set public aux decl prefix in init_grind_norm (#8856)
This PR ensures simp theorems generated by `init_grind_norm` are
accessible in other `module`s
2025-06-18 07:19:37 +00:00
Markus Himmel
c16204615d chore: add a failing grind test (#8858) 2025-06-18 07:14:56 +00:00
Mac Malone
e83b768140 feat: lake: reintroduce lean --setup basics (#8846)
This PR reintroduces the basics of `lean --setup` integration into Lake
without the module computation which is still undergoing performance
debugging in #8787.

Partially reverts #8736 and partially reimplements #8447.
2025-06-18 06:12:39 +00:00
3871 changed files with 78767 additions and 28831 deletions

5
.github/actionlint.yaml vendored Normal file
View File

@@ -0,0 +1,5 @@
self-hosted-runner:
labels:
- nscloud-ubuntu-22.04-amd64-4x16
- nscloud-ubuntu-22.04-amd64-8x16
- nscloud-macos-sonoma-arm64-6x14

38
.github/workflows/awaiting-manual.yml vendored Normal file
View File

@@ -0,0 +1,38 @@
name: Check awaiting-manual label
on:
merge_group:
pull_request:
types: [opened, synchronize, reopened, labeled, unlabeled]
jobs:
check-awaiting-manual:
runs-on: ubuntu-latest
steps:
- name: Check awaiting-manual label
id: check-awaiting-manual-label
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const { labels, number: prNumber } = context.payload.pull_request;
const hasAwaiting = labels.some(label => label.name == "awaiting-manual");
const hasBreaks = labels.some(label => label.name == "breaks-manual");
const hasBuilds = labels.some(label => label.name == "builds-manual");
if (hasAwaiting && hasBreaks) {
core.setFailed('PR has both "awaiting-manual" and "breaks-manual" labels.');
} else if (hasAwaiting && !hasBreaks && !hasBuilds) {
core.info('PR is marked "awaiting-manual" but neither "breaks-manual" nor "builds-manual" labels are present.');
core.setOutput('awaiting', 'true');
}
- name: Wait for manual compatibility
if: github.event_name == 'pull_request' && steps.check-awaiting-manual-label.outputs.awaiting == 'true'
run: |
echo "::notice title=Awaiting manual::PR is marked 'awaiting-manual' but neither 'breaks-manual' nor 'builds-manual' labels are present."
echo "This check will remain in progress until the PR is updated with appropriate manual compatibility labels."
# Keep the job running indefinitely to show "in progress" status
while true; do
sleep 3600 # Sleep for 1 hour at a time
done

View File

@@ -97,16 +97,17 @@ jobs:
sudo apt-get update
sudo apt-get install -y gcc-multilib g++-multilib ccache libuv1-dev:i386 pkgconf:i386
if: matrix.cmultilib
- name: Cache
- name: Restore Cache
id: restore-cache
uses: actions/cache/restore@v4
with:
# NOTE: must be in sync with `save` below
# NOTE: must be in sync with `save` below and with `restore-cache` in `update-stage0.yml`
path: |
.ccache
${{ matrix.name == 'Linux Lake' && false && 'build/stage1/**/*.trace
${{ matrix.name == 'Linux Lake (cached)' && 'build/stage1/**/*.trace
build/stage1/**/*.olean*
build/stage1/**/*.ilean
build/stage1/**/*.ir
build/stage1/**/*.c
build/stage1/**/*.c.o*' || '' }}
key: ${{ matrix.name }}-build-v3-${{ github.sha }}
@@ -118,9 +119,15 @@ jobs:
run: |
ccache --zero-stats
if: runner.os == 'Linux'
- name: Set up NPROC
- name: Set up env
run: |
echo "NPROC=$(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || echo 4)" >> $GITHUB_ENV
if ! diff src/stdlib_flags.h stage0/src/stdlib_flags.h; then
echo "src/stdlib_flags.h and stage0/src/stdlib_flags.h differ, will test and pack stage 2"
echo "TARGET_STAGE=stage2" >> $GITHUB_ENV
else
echo "TARGET_STAGE=stage1" >> $GITHUB_ENV
fi
- name: Build
run: |
ulimit -c unlimited # coredumps
@@ -141,6 +148,9 @@ jobs:
if [[ -n '${{ matrix.prepare-llvm }}' ]]; then
wget -q ${{ matrix.llvm-url }}
PREPARE="$(${{ matrix.prepare-llvm }})"
if [ "$TARGET_STAGE" == "stage2" ]; then
cp -r stage1 stage2
fi
eval "OPTIONS+=($PREPARE)"
fi
if [[ -n '${{ matrix.release }}' && -n '${{ inputs.nightly }}' ]]; then
@@ -155,10 +165,10 @@ jobs:
fi
# contortion to support empty OPTIONS with old macOS bash
cmake .. --preset ${{ matrix.CMAKE_PRESET || 'release' }} -B . ${{ matrix.CMAKE_OPTIONS }} ${OPTIONS[@]+"${OPTIONS[@]}"} -DLEAN_INSTALL_PREFIX=$PWD/..
time make -j$NPROC
time make $TARGET_STAGE -j$NPROC
- name: Install
run: |
make -C build install
make -C build/$TARGET_STAGE install
- name: Check Binaries
run: ${{ matrix.binary-check }} lean-*/bin/* || true
- name: Count binary symbols
@@ -195,12 +205,12 @@ jobs:
id: test
run: |
ulimit -c unlimited # coredumps
time ctest --preset ${{ matrix.CMAKE_PRESET || 'release' }} --test-dir build/stage1 -j$NPROC --output-junit test-results.xml ${{ matrix.CTEST_OPTIONS }}
time ctest --preset ${{ matrix.CMAKE_PRESET || 'release' }} --test-dir build/$TARGET_STAGE -j$NPROC --output-junit test-results.xml ${{ matrix.CTARGET_OPTIONS }}
if: (matrix.wasm || !matrix.cross) && (inputs.check-level >= 1 || matrix.test)
- name: Test Summary
uses: test-summary/action@v2
with:
paths: build/stage1/test-results.xml
paths: build/${{ env.TARGET_STAGE }}/test-results.xml
# prefix `if` above with `always` so it's run even if tests failed
if: always() && steps.test.conclusion != 'skipped'
- name: Check Test Binary
@@ -225,8 +235,9 @@ jobs:
if: matrix.test-speedcenter
- name: Check rebootstrap
run: |
# clean rebuild in case of Makefile changes
make -C build update-stage0 && rm -rf build/stage* && make -C build -j$NPROC
# clean rebuild in case of Makefile changes/Lake does not detect uncommited stage 0
# changes yet
make -C build update-stage0 && make -C build/stage1 clean-stdlib && make -C build -j$NPROC
if: matrix.check-rebootstrap
- name: CCache stats
if: always()
@@ -245,9 +256,10 @@ jobs:
# NOTE: must be in sync with `restore` above
path: |
.ccache
${{ matrix.name == 'Linux Lake' && false && 'build/stage1/**/*.trace
${{ matrix.name == 'Linux Lake (cached)' && 'build/stage1/**/*.trace
build/stage1/**/*.olean*
build/stage1/**/*.ilean
build/stage1/**/*.ir
build/stage1/**/*.c
build/stage1/**/*.c.o*' || '' }}
key: ${{ steps.restore-cache.outputs.cache-primary-key }}

View File

@@ -145,6 +145,7 @@ jobs:
// use large runners where available (original repo)
let large = ${{ github.repository == 'leanprover/lean4' }};
const isPr = "${{ github.event_name }}" == "pull_request";
const isPushToMaster = "${{ github.event_name }}" == "push" && "${{ github.ref_name }}" == "master";
let matrix = [
/* TODO: to be updated to new LLVM
{
@@ -164,14 +165,16 @@ jobs:
{
// portable release build: use channel with older glibc (2.26)
"name": "Linux release",
"os": large && level < 2 ? "nscloud-ubuntu-22.04-amd64-4x16" : "ubuntu-latest",
"os": "ubuntu-latest",
"release": true,
// Special handling for release jobs. We want:
// 1. To run it in PRs so developrs get PR toolchains (so secondary is sufficient)
// 1. To run it in PRs so developers get PR toolchains (so secondary is sufficient)
// 2. To skip it in merge queues as it takes longer than the
// Linux lake build and adds little value in the merge queue
// 3. To run it in release (obviously)
"check-level": isPr ? 0 : 2,
// 4. To run it for pushes to master so that pushes to master have a Linux toolchain
// available as an artifact for Grove to use.
"check-level": (isPr || isPushToMaster) ? 0 : 2,
"secondary": isPr,
"shell": "nix develop .#oldGlibc -c bash -euxo pipefail {0}",
"llvm-url": "https://github.com/leanprover/lean-llvm/releases/download/19.1.2/lean-llvm-x86_64-linux-gnu.tar.zst",
@@ -191,6 +194,13 @@ jobs:
"test-speedcenter": large && level >= 2,
"CMAKE_OPTIONS": "-DUSE_LAKE=ON",
},
{
"name": "Linux Lake (cached)",
"os": "ubuntu-latest",
"check-level": (isPr || isPushToMaster) ? 0 : 2,
"secondary": true,
"CMAKE_OPTIONS": "-DUSE_LAKE=ON",
},
{
"name": "Linux Reldebug",
"os": "ubuntu-latest",
@@ -222,8 +232,8 @@ jobs:
},
{
"name": "macOS aarch64",
// standard GH runner only comes with 7GB so use large runner if possible
"os": large ? "nscloud-macos-sonoma-arm64-6x14" : "macos-14",
// standard GH runner only comes with 7GB so use large runner if possible when running tests
"os": large && !isPr ? "nscloud-macos-sonoma-arm64-6x14" : "macos-14",
"CMAKE_OPTIONS": "-DLEAN_INSTALL_SUFFIX=-darwin_aarch64",
"release": true,
"shell": "bash -euxo pipefail {0}",
@@ -231,13 +241,13 @@ jobs:
"prepare-llvm": "../script/prepare-llvm-macos.sh lean-llvm*",
"binary-check": "otool -L",
"tar": "gtar", // https://github.com/actions/runner-images/issues/2619
// See above for release job levels
// See "Linux release" for release job levels; Grove is not a concern here
"check-level": isPr ? 0 : 2,
"secondary": isPr,
},
{
"name": "Windows",
"os": "windows-2022",
"os": large && level == 2 ? "namespace-profile-windows-amd64-4x16" : "windows-2022",
"release": true,
"check-level": 2,
"shell": "msys2 {0}",
@@ -360,7 +370,7 @@ jobs:
with:
path: artifacts
- name: Release
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8
with:
files: artifacts/*/*
fail_on_unmatched_files: true
@@ -404,7 +414,7 @@ jobs:
echo -e "\n*Full commit log*\n" >> diff.md
git log --oneline "$last_tag"..HEAD | sed 's/^/* /' >> diff.md
- name: Release Nightly
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8
with:
body_path: diff.md
prerelease: true
@@ -421,6 +431,6 @@ jobs:
GITHUB_TOKEN: ${{ secrets.RELEASE_INDEX_TOKEN }}
- name: Update toolchain on mathlib4's nightly-testing branch
run: |
gh workflow -R leanprover-community/mathlib4 run nightly_bump_toolchain.yml
gh workflow -R leanprover-community/mathlib4-nightly-testing run nightly_bump_toolchain.yml
env:
GITHUB_TOKEN: ${{ secrets.MATHLIB4_BOT }}

161
.github/workflows/grove.yml vendored Normal file
View File

@@ -0,0 +1,161 @@
name: Grove
on:
workflow_run: # https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run
workflows: [CI]
types: [completed]
permissions:
pull-requests: write
jobs:
grove-build:
runs-on: ubuntu-latest
if: github.event.workflow_run.conclusion == 'success' && github.repository == 'leanprover/lean4'
steps:
- name: Retrieve information about the original workflow
uses: potiuk/get-workflow-origin@v1_1 # https://github.com/marketplace/actions/get-workflow-origin
# This action is deprecated and archived, but it seems hard to find a
# better solution for getting the PR number
# see https://github.com/orgs/community/discussions/25220 for some discussion
id: workflow-info
with:
token: ${{ secrets.GITHUB_TOKEN }}
sourceRunId: ${{ github.event.workflow_run.id }}
- name: Check if should run
id: should-run
run: |
# Check if it's a push to master (no PR number and target branch is master)
if [ -z "${{ steps.workflow-info.outputs.pullRequestNumber }}" ]; then
if [ "${{ github.event.workflow_run.head_branch }}" = "master" ]; then
echo "Push to master detected. Running Grove."
echo "should-run=true" >> "$GITHUB_OUTPUT"
else
echo "Push to non-master branch, skipping"
echo "should-run=false" >> "$GITHUB_OUTPUT"
fi
else
# Check if it's a PR with grove label
PR_LABELS='${{ steps.workflow-info.outputs.pullRequestLabels }}'
if echo "$PR_LABELS" | grep -q '"grove"'; then
echo "PR with grove label detected. Running Grove."
echo "should-run=true" >> "$GITHUB_OUTPUT"
else
echo "PR without grove label, skipping"
echo "should-run=false" >> "$GITHUB_OUTPUT"
fi
fi
- name: Fetch upstream invalidated facts
if: ${{ steps.should-run.outputs.should-run == 'true' && steps.workflow-info.outputs.pullRequestNumber != '' }}
id: fetch-upstream
uses: TwoFx/grove-action/fetch-upstream@v0.4
with:
artifact-name: grove-invalidated-facts
base-ref: master
- name: Download toolchain for this commit
if: ${{ steps.should-run.outputs.should-run == 'true' }}
id: download-toolchain
uses: dawidd6/action-download-artifact@v11
with:
commit: ${{ steps.workflow-info.outputs.sourceHeadSha }}
workflow: ci.yml
path: artifacts
name: "build-Linux release"
name_is_regexp: true
- name: Unpack toolchain
if: ${{ steps.should-run.outputs.should-run == 'true' }}
id: unpack-toolchain
run: |
cd artifacts
# Find the tar.zst file
TAR_FILE=$(find . -name "lean-*.tar.zst" -type f | head -1)
if [ -z "$TAR_FILE" ]; then
echo "Error: No lean-*.tar.zst file found"
exit 1
fi
echo "Found archive: $TAR_FILE"
# Extract the archive
tar --zstd -xf "$TAR_FILE"
# Find the extracted directory name
LEAN_DIR=$(find . -maxdepth 1 -name "lean-*" -type d | head -1)
if [ -z "$LEAN_DIR" ]; then
echo "Error: No lean-* directory found after extraction"
exit 1
fi
echo "Extracted directory: $LEAN_DIR"
echo "lean-dir=$LEAN_DIR" >> "$GITHUB_OUTPUT"
- name: Build
if: ${{ steps.should-run.outputs.should-run == 'true' }}
id: build
uses: TwoFx/grove-action/build@v0.4
with:
project-path: doc/std/grove
script-name: grove-stdlib
invalidated-facts-artifact-name: grove-invalidated-facts
comment-artifact-name: grove-comment
toolchain-id: lean4
toolchain-path: artifacts/${{ steps.unpack-toolchain.outputs.lean-dir }}
project-ref: ${{ steps.workflow-info.outputs.sourceHeadSha }}
# deploy-alias computes a URL component for the PR preview. This
# is so we can have a stable name to use for feedback on draft
# material.
- id: deploy-alias
if: ${{ steps.should-run.outputs.should-run == 'true' }}
uses: actions/github-script@v7
name: Compute Alias
with:
result-encoding: string
script: |
if (process.env.PR) {
return `pr-${process.env.PR}`
} else {
return 'deploy-preview-main';
}
env:
PR: ${{ steps.workflow-info.outputs.pullRequestNumber }}
- name: Deploy to Netlify
if: ${{ steps.should-run.outputs.should-run == 'true' }}
id: deploy-draft
uses: nwtgck/actions-netlify@v3.0
with:
publish-dir: ${{ steps.build.outputs.out-path }}
production-deploy: false
github-token: ${{ secrets.GITHUB_TOKEN }}
alias: ${{ steps.deploy-alias.outputs.result }}
enable-commit-comment: false
enable-pull-request-comment: false
fails-without-credentials: true
enable-github-deployment: false
enable-commit-status: false
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: "1cacfa39-a11c-467c-99e7-2e01d7b4089e"
# actions-netlify cannot add deploy links to a PR because it assumes a
# pull_request context, not a workflow_run context, see
# https://github.com/nwtgck/actions-netlify/issues/545
# We work around by using a comment to post the latest link
- name: "Comment on PR with preview links"
uses: marocchino/sticky-pull-request-comment@v2
if: ${{ steps.should-run.outputs.should-run == 'true' && steps.workflow-info.outputs.pullRequestNumber != '' }}
with:
number: ${{ env.PR_NUMBER }}
header: preview-comment
recreate: true
message: |
[Grove](${{ steps.deploy-draft.outputs.deploy-url }}) for revision ${{ steps.workflow-info.outputs.sourceHeadSha }}.
${{ steps.build.outputs.comment-text }}
env:
PR_NUMBER: ${{ steps.workflow-info.outputs.pullRequestNumber }}
PR_HEADSHA: ${{ steps.workflow-info.outputs.sourceHeadSha }}

View File

@@ -34,7 +34,7 @@ jobs:
- name: Download artifact from the previous workflow.
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
id: download-artifact
uses: dawidd6/action-download-artifact@v10 # https://github.com/marketplace/actions/download-workflow-artifact
uses: dawidd6/action-download-artifact@v11 # https://github.com/marketplace/actions/download-workflow-artifact
with:
run_id: ${{ github.event.workflow_run.id }}
path: artifacts
@@ -71,7 +71,7 @@ jobs:
GH_TOKEN: ${{ secrets.PR_RELEASES_TOKEN }}
- name: Release (short format)
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8
with:
name: Release for PR ${{ steps.workflow-info.outputs.pullRequestNumber }}
# There are coredumps files here as well, but all in deeper subdirectories.
@@ -86,7 +86,7 @@ jobs:
- name: Release (SHA-suffixed format)
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8
with:
name: Release for PR ${{ steps.workflow-info.outputs.pullRequestNumber }} (${{ steps.workflow-info.outputs.sourceHeadSha }})
# There are coredumps files here as well, but all in deeper subdirectories.
@@ -151,10 +151,10 @@ jobs:
- name: 'Setup jq'
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
uses: dcarbone/install-jq-action@v3.1.1
uses: dcarbone/install-jq-action@v3.2.0
# Check that the most recently nightly coincides with 'git merge-base HEAD master'
- name: Check merge-base and nightly-testing-YYYY-MM-DD
- name: Check merge-base and nightly-testing-YYYY-MM-DD for Mathlib/Batteries
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
id: ready
run: |
@@ -167,7 +167,7 @@ jobs:
echo "The merge base of this PR coincides with the nightly release"
BATTERIES_REMOTE_TAGS="$(git ls-remote https://github.com/leanprover-community/batteries.git nightly-testing-"$MOST_RECENT_NIGHTLY")"
MATHLIB_REMOTE_TAGS="$(git ls-remote https://github.com/leanprover-community/mathlib4.git nightly-testing-"$MOST_RECENT_NIGHTLY")"
MATHLIB_REMOTE_TAGS="$(git ls-remote https://github.com/leanprover-community/mathlib4-nightly-testing.git nightly-testing-"$MOST_RECENT_NIGHTLY")"
if [[ -n "$BATTERIES_REMOTE_TAGS" ]]; then
echo "... and Batteries has a 'nightly-testing-$MOST_RECENT_NIGHTLY' tag."
@@ -183,7 +183,6 @@ jobs:
echo "... but Batteries does not yet have a 'nightly-testing-$MOST_RECENT_NIGHTLY' tag."
MESSAGE="- ❗ Batteries CI can not be attempted yet, as the \`nightly-testing-$MOST_RECENT_NIGHTLY\` tag does not exist there yet. We will retry when you push more commits. If you rebase your branch onto \`nightly-with-mathlib\`, Batteries CI should run now."
fi
else
echo "The most recently nightly tag on this branch has SHA: $NIGHTLY_SHA"
echo "but 'git merge-base origin/master HEAD' reported: $MERGE_BASE_SHA"
@@ -265,6 +264,108 @@ jobs:
echo "mathlib_ready=true" >> "$GITHUB_OUTPUT"
fi
- name: Check merge-base and nightly-testing-YYYY-MM-DD for reference manual
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
id: reference-manual-ready
run: |
echo "Most recent nightly release in your branch: $MOST_RECENT_NIGHTLY"
NIGHTLY_SHA=$(git -C lean4.git rev-parse "nightly-$MOST_RECENT_NIGHTLY^{commit}")
echo "SHA of most recent nightly release: $NIGHTLY_SHA"
MERGE_BASE_SHA=$(git -C lean4.git merge-base origin/master "${{ steps.workflow-info.outputs.sourceHeadSha }}")
echo "SHA of merge-base: $MERGE_BASE_SHA"
if [ "$NIGHTLY_SHA" = "$MERGE_BASE_SHA" ]; then
echo "The merge base of this PR coincides with the nightly release"
MANUAL_REMOTE_TAGS="$(git ls-remote https://github.com/leanprover/reference-manual.git nightly-testing-"$MOST_RECENT_NIGHTLY")"
if [[ -n "$MANUAL_REMOTE_TAGS" ]]; then
echo "... and the reference manual has a 'nightly-testing-$MOST_RECENT_NIGHTLY' tag."
MESSAGE=""
else
echo "... but the reference manual does not yet have a 'nightly-testing-$MOST_RECENT_NIGHTLY' tag."
MESSAGE="- ❗ Reference manual CI can not be attempted yet, as the \`nightly-testing-$MOST_RECENT_NIGHTLY\` tag does not exist there yet. We will retry when you push more commits. If you rebase your branch onto \`nightly-with-manual\`, reference manual CI should run now."
fi
else
echo "The most recently nightly tag on this branch has SHA: $NIGHTLY_SHA"
echo "but 'git merge-base origin/master HEAD' reported: $MERGE_BASE_SHA"
git -C lean4.git log -10 origin/master
git -C lean4.git fetch origin nightly-with-manual
NIGHTLY_WITH_MANUAL_SHA="$(git -C lean4.git rev-parse "origin/nightly-with-manual")"
MESSAGE="- ❗ Reference manual CI will not be attempted unless your PR branches off the \`nightly-with-manual\` branch. Try \`git rebase $MERGE_BASE_SHA --onto $NIGHTLY_WITH_MANUAL_SHA\`."
fi
if [[ -n "$MESSAGE" ]]; then
# Check if force-manual-ci label is present
LABELS="$(curl --retry 3 --location --silent \
-H "Authorization: token ${{ secrets.MANUAL_COMMENT_BOT }}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/leanprover/lean4/issues/${{ steps.workflow-info.outputs.pullRequestNumber }}/labels" \
| jq -r '.[].name')"
if echo "$LABELS" | grep -q "^force-manual-ci$"; then
echo "force-manual-ci label detected, forcing CI despite issues"
MESSAGE="Forcing reference manual CI because the \`force-manual-ci\` label is present, despite problem: $MESSAGE"
FORCE_CI=true
else
MESSAGE="$MESSAGE You can force reference manual CI using the \`force-manual-ci\` label."
fi
echo "Checking existing messages"
# The code for updating comments is duplicated in the reference manual's
# scripts/lean-pr-testing-comments.sh
# so keep in sync
# Use GitHub API to check if a comment already exists
existing_comment="$(curl --retry 3 --location --silent \
-H "Authorization: token ${{ secrets.MANUAL_COMMENT_BOT }}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/leanprover/lean4/issues/${{ steps.workflow-info.outputs.pullRequestNumber }}/comments" \
| jq 'first(.[] | select(.body | test("^- . Manual") or startswith("Reference manual CI status")) | select(.user.login == "leanprover-bot"))')"
existing_comment_id="$(echo "$existing_comment" | jq -r .id)"
existing_comment_body="$(echo "$existing_comment" | jq -r .body)"
if [[ "$existing_comment_body" != *"$MESSAGE"* ]]; then
MESSAGE="$MESSAGE ($(date "+%Y-%m-%d %H:%M:%S"))"
echo "Posting message to the comments: $MESSAGE"
# Append new result to the existing comment or post a new comment
# It's essential we use the MANUAL_COMMENT_BOT token here, so that reference manual CI can subsequently edit the comment.
if [ -z "$existing_comment_id" ]; then
INTRO="Reference manual CI status:"
# Post new comment with a bullet point
echo "Posting as new comment at leanprover/lean4/issues/${{ steps.workflow-info.outputs.pullRequestNumber }}/comments"
curl -L -s \
-X POST \
-H "Authorization: token ${{ secrets.MANUAL_COMMENT_BOT }}" \
-H "Accept: application/vnd.github.v3+json" \
-d "$(jq --null-input --arg intro "$INTRO" --arg val "$MESSAGE" '{"body":($intro + "\n" + $val)}')" \
"https://api.github.com/repos/leanprover/lean4/issues/${{ steps.workflow-info.outputs.pullRequestNumber }}/comments"
else
# Append new result to the existing comment
echo "Appending to existing comment at leanprover/lean4/issues/${{ steps.workflow-info.outputs.pullRequestNumber }}/comments"
curl -L -s \
-X PATCH \
-H "Authorization: token ${{ secrets.MANUAL_COMMENT_BOT }}" \
-H "Accept: application/vnd.github.v3+json" \
-d "$(jq --null-input --arg existing "$existing_comment_body" --arg message "$MESSAGE" '{"body":($existing + "\n" + $message)}')" \
"https://api.github.com/repos/leanprover/lean4/issues/comments/$existing_comment_id"
fi
else
echo "The message already exists in the comment body."
fi
if [[ "$FORCE_CI" == "true" ]]; then
echo "manual_ready=true" >> "$GITHUB_OUTPUT"
else
echo "manual_ready=false" >> "$GITHUB_OUTPUT"
fi
else
echo "manual_ready=true" >> "$GITHUB_OUTPUT"
fi
- name: Report mathlib base
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' && steps.ready.outputs.mathlib_ready == 'true' }}
uses: actions/github-script@v7
@@ -355,7 +456,7 @@ jobs:
if: steps.workflow-info.outputs.pullRequestNumber != '' && steps.ready.outputs.mathlib_ready == 'true'
uses: actions/checkout@v4
with:
repository: leanprover-community/mathlib4
repository: leanprover-community/mathlib4-nightly-testing
token: ${{ secrets.MATHLIB4_BOT }}
ref: nightly-testing
fetch-depth: 0 # This ensures we check out all tags and branches.
@@ -411,3 +512,63 @@ jobs:
if: steps.workflow-info.outputs.pullRequestNumber != '' && steps.ready.outputs.mathlib_ready == 'true'
run: |
git push origin lean-pr-testing-${{ steps.workflow-info.outputs.pullRequestNumber }}
# We next automatically create a reference manual branch using this toolchain.
# Reference manual CI will be responsible for reporting back success or failure
# to the PR comments asynchronously (and thus transitively SubVerso/Verso).
- name: Cleanup workspace
if: steps.workflow-info.outputs.pullRequestNumber != '' && steps.reference-manual-ready.outputs.manual_ready == 'true'
run: |
sudo rm -rf ./*
# Checkout the reference manual repository with all branches
- name: Checkout mathlib4 repository
if: steps.workflow-info.outputs.pullRequestNumber != '' && steps.reference-manual-ready.outputs.manual_ready == 'true'
uses: actions/checkout@v4
with:
repository: leanprover/reference-manual
token: ${{ secrets.MANUAL_PR_BOT }}
ref: nightly-testing
fetch-depth: 0 # This ensures we check out all tags and branches.
- name: Check if tag in reference manual exists
if: steps.workflow-info.outputs.pullRequestNumber != '' && steps.reference-manual-ready.outputs.manual_ready == 'true'
id: check_manual_tag
run: |
git config user.name "leanprover-bot"
git config user.email "leanprover-bot@lean-fro.org"
if git ls-remote --heads --tags --exit-code origin "nightly-testing-${MOST_RECENT_NIGHTLY}" >/dev/null; then
BASE="nightly-testing-${MOST_RECENT_NIGHTLY}"
else
echo "Couldn't find a 'nightly-testing-${MOST_RECENT_NIGHTLY}' branch in the reference manual. Falling back to 'nightly-testing'."
BASE=nightly-testing
fi
echo "Using base tag: $BASE"
EXISTS="$(git ls-remote --heads origin lean-pr-testing-${{ steps.workflow-info.outputs.pullRequestNumber }} | wc -l)"
echo "Branch exists: $EXISTS"
if [ "$EXISTS" = "0" ]; then
echo "Branch does not exist, creating it."
git switch -c lean-pr-testing-${{ steps.workflow-info.outputs.pullRequestNumber }} "$BASE"
echo "leanprover/lean4-pr-releases:pr-release-${{ steps.workflow-info.outputs.pullRequestNumber }}-${{ env.SHORT_SHA }}" > lean-toolchain
git add lean-toolchain
git add lakefile.lean lake-manifest.json
git commit -m "Update lean-toolchain for testing https://github.com/leanprover/lean4/pull/${{ steps.workflow-info.outputs.pullRequestNumber }}"
else
echo "Branch already exists, updating lean-toolchain."
git switch lean-pr-testing-${{ steps.workflow-info.outputs.pullRequestNumber }}
# The reference manual's `nightly-testing` branch or `nightly-testing-YYYY-MM-DD` tag may have moved since this branch was created, so merge their changes.
# (This should no longer be possible once `nightly-testing-YYYY-MM-DD` is a tag, but it is still safe to merge.)
git merge "$BASE" --strategy-option ours --no-commit --allow-unrelated-histories
echo "leanprover/lean4-pr-releases:pr-release-${{ steps.workflow-info.outputs.pullRequestNumber }}-${{ env.SHORT_SHA }}" > lean-toolchain
git add lean-toolchain
git add lake-manifest.json
git commit -m "Update lean-toolchain for https://github.com/leanprover/lean4/pull/${{ steps.workflow-info.outputs.pullRequestNumber }}"
fi
- name: Push changes
if: steps.workflow-info.outputs.pullRequestNumber != '' && steps.reference-manual-ready.outputs.manual_ready == 'true'
run: |
git push origin lean-pr-testing-${{ steps.workflow-info.outputs.pullRequestNumber }}

View File

@@ -18,7 +18,7 @@ concurrency:
jobs:
update-stage0:
runs-on: ubuntu-latest
runs-on: nscloud-ubuntu-22.04-amd64-8x16
steps:
# This action should push to an otherwise protected branch, so it
# uses a deploy key with write permissions, as suggested at
@@ -52,6 +52,18 @@ jobs:
run: |
echo "NPROC=$(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || echo 4)" >> $GITHUB_ENV
shell: 'nix develop -c bash -euxo pipefail {0}'
- name: Restore Cache
if: env.should_update_stage0 == 'yes'
uses: actions/cache/restore@v4
with:
# NOTE: must be in sync with `restore-cache` in `build-template.yml`
# TODO: actually switch to USE_LAKE once it caches more; for now it just caches more often than any other build type so let's use its cache
path: |
.ccache
key: Linux Lake-build-v3-${{ github.sha }}
# fall back to (latest) previous cache
restore-keys: |
Linux Lake-build-v3
- if: env.should_update_stage0 == 'yes'
run: cmake --preset release
shell: 'nix develop -c bash -euxo pipefail {0}'

2
.gitignore vendored
View File

@@ -6,7 +6,6 @@
lake-manifest.json
/build
/src/lakefile.toml
/tests/lakefile.toml
/lakefile.toml
GPATH
GRTAGS
@@ -32,3 +31,4 @@ fwOut.txt
wdErr.txt
wdIn.txt
wdOut.txt
downstream_releases/

View File

@@ -16,7 +16,7 @@ foreach(var ${vars})
list(APPEND STAGE1_ARGS "-D${CMAKE_MATCH_1}=${${var}}")
elseif("${currentHelpString}" MATCHES "No help, variable specified on the command line." OR "${currentHelpString}" STREQUAL "")
list(APPEND CL_ARGS "-D${var}=${${var}}")
if("${var}" MATCHES "USE_GMP|CHECK_OLEAN_VERSION")
if("${var}" MATCHES "USE_GMP|CHECK_OLEAN_VERSION|LEAN_VERSION_.*|LEAN_SPECIAL_VERSION_DESC")
# must forward options that generate incompatible .olean format
list(APPEND STAGE0_ARGS "-D${var}=${${var}}")
elseif("${var}" MATCHES "LLVM*|PKG_CONFIG|USE_LAKE|USE_MIMALLOC")

View File

@@ -45,3 +45,6 @@
/src/Std/Tactic/BVDecide/ @hargoniX
/src/Lean/Elab/Tactic/BVDecide/ @hargoniX
/src/Std/Sat/ @hargoniX
/src/Std/Do @sgraf812
/src/Std/Tactic/Do @sgraf812
/src/Lean/Elab/Tactic/Do @sgraf812

View File

@@ -68,7 +68,7 @@ The memory order of the fields is derived from the types and order of the fields
* Fields of type `USize`
* Other scalar fields, in decreasing order by size
Within each group the fields are ordered in declaration order. **Warning**: Trivial wrapper types still count toward a field being treated as non-scalar for this purpose.
Within each group the fields are ordered in declaration order. Trivial wrapper types count as their underlying wrapped type for this purpose.
* To access fields of the first kind, use `lean_ctor_get(val, i)` to get the `i`th non-scalar field.
* To access `USize` fields, use `lean_ctor_get_usize(val, n+i)` to get the `i`th usize field and `n` is the total number of fields of the first kind.
@@ -80,32 +80,32 @@ structure S where
ptr_1 : Array Nat
usize_1 : USize
sc64_1 : UInt64
ptr_2 : { x : UInt64 // x > 0 } -- wrappers don't count as scalars
sc64_2 : Float -- `Float` is 64 bit
sc64_2 : { x : UInt64 // x > 0 } -- wrappers of scalars count as scalars
sc64_3 : Float -- `Float` is 64 bit
sc8_1 : Bool
sc16_1 : UInt16
sc8_2 : UInt8
sc64_3 : UInt64
sc64_4 : UInt64
usize_2 : USize
ptr_3 : Char -- trivial wrapper around `UInt32`
sc32_1 : UInt32
sc32_1 : Char -- trivial wrapper around `UInt32`
sc32_2 : UInt32
sc16_2 : UInt16
```
would get re-sorted into the following memory order:
* `S.ptr_1` - `lean_ctor_get(val, 0)`
* `S.ptr_2` - `lean_ctor_get(val, 1)`
* `S.ptr_3` - `lean_ctor_get(val, 2)`
* `S.usize_1` - `lean_ctor_get_usize(val, 3)`
* `S.usize_2` - `lean_ctor_get_usize(val, 4)`
* `S.sc64_1` - `lean_ctor_get_uint64(val, sizeof(void*)*5)`
* `S.sc64_2` - `lean_ctor_get_float(val, sizeof(void*)*5 + 8)`
* `S.sc64_3` - `lean_ctor_get_uint64(val, sizeof(void*)*5 + 16)`
* `S.sc32_1` - `lean_ctor_get_uint32(val, sizeof(void*)*5 + 24)`
* `S.sc16_1` - `lean_ctor_get_uint16(val, sizeof(void*)*5 + 28)`
* `S.sc16_2` - `lean_ctor_get_uint16(val, sizeof(void*)*5 + 30)`
* `S.sc8_1` - `lean_ctor_get_uint8(val, sizeof(void*)*5 + 32)`
* `S.sc8_2` - `lean_ctor_get_uint8(val, sizeof(void*)*5 + 33)`
* `S.usize_1` - `lean_ctor_get_usize(val, 1)`
* `S.usize_2` - `lean_ctor_get_usize(val, 2)`
* `S.sc64_1` - `lean_ctor_get_uint64(val, sizeof(void*)*3)`
* `S.sc64_2` - `lean_ctor_get_uint64(val, sizeof(void*)*3 + 8)`
* `S.sc64_3` - `lean_ctor_get_float(val, sizeof(void*)*3 + 16)`
* `S.sc64_4` - `lean_ctor_get_uint64(val, sizeof(void*)*3 + 24)`
* `S.sc32_1` - `lean_ctor_get_uint32(val, sizeof(void*)*3 + 32)`
* `S.sc32_2` - `lean_ctor_get_uint32(val, sizeof(void*)*3 + 36)`
* `S.sc16_1` - `lean_ctor_get_uint16(val, sizeof(void*)*3 + 40)`
* `S.sc16_2` - `lean_ctor_get_uint16(val, sizeof(void*)*3 + 42)`
* `S.sc8_1` - `lean_ctor_get_uint8(val, sizeof(void*)*3 + 44)`
* `S.sc8_2` - `lean_ctor_get_uint8(val, sizeof(void*)*3 + 45)`
### Borrowing
@@ -131,14 +131,21 @@ Thus `[init]` functions are run iff their module is imported, regardless of whet
The initializer for module `A.B` is called `initialize_A_B` and will automatically initialize any imported modules.
Module initializers are idempotent (when run with the same `builtin` flag), but not thread-safe.
**Important for process-related functionality**: If your application needs to use process-related functions from libuv, such as `Std.Internal.IO.Process.getProcessTitle` and `Std.Internal.IO.Process.setProcessTitle`, you must call `lean_setup_args(argc, argv)` (which returns a potentially modified `argv` that must be used in place of the original) **before** calling `lean_initialize()` or `lean_initialize_runtime_module()`. This sets up process handling capabilities correctly, which is essential for certain system-level operations that Lean's runtime may depend on.
Together with initialization of the Lean runtime, you should execute code like the following exactly once before accessing any Lean declarations:
```c
void lean_initialize_runtime_module();
void lean_initialize();
char ** lean_setup_args(int argc, char ** argv);
lean_object * initialize_A_B(uint8_t builtin, lean_object *);
lean_object * initialize_C(uint8_t builtin, lean_object *);
...
argv = lean_setup_args(argc, argv); // if using process-related functionality
lean_initialize_runtime_module();
//lean_initialize(); // necessary (and replaces `lean_initialize_runtime_module`) if you (indirectly) access the `Lean` package

View File

@@ -85,5 +85,13 @@ such that changing files in `Init` doesn't force a full rebuild of `Lean`.
You can test a Lean PR against Mathlib and Batteries by rebasing your PR
on to `nightly-with-mathlib` branch. (It is fine to force push after rebasing.)
CI will generate a branch of Mathlib and Batteries called `lean-pr-testing-NNNN`
that uses the toolchain for your PR, and will report back to the Lean PR with results from Mathlib CI.
on the `leanprover-community/mathlib4-nightly-testing` fork of Mathlib.
This branch uses the toolchain for your PR, and will report back to the Lean PR with results from Mathlib CI.
See https://leanprover-community.github.io/contribute/tags_and_branches.html for more details.
### Testing against the Lean Language Reference
You can test a Lean PR against the reference manual by rebasing your PR
on to `nightly-with-manual` branch. (It is fine to force push after rebasing.)
CI will generate a branch of the reference manual called `lean-pr-testing-NNNN`
in `leanprover/reference-manual`. This branch uses the toolchain for your PR,
and will report back to the Lean PR with results from Mathlib CI.

4
doc/std/grove/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
/.lake
!lake-manifest.json
metadata.json
invalidated.json

View File

@@ -0,0 +1,22 @@
import Grove.Framework
import GroveStdlib.Generated.«associative-query-operations»
import GroveStdlib.Generated.«associative-creation-operations»
import GroveStdlib.Generated.«associative-modification-operations»
import GroveStdlib.Generated.«associative-create-then-query»
import GroveStdlib.Generated.«associative-all-operations-covered»
/-
This file is autogenerated by grove. You can manually edit it, for example to resolve merge
conflicts, but be careful.
-/
open Grove.Framework Widget
namespace GroveStdlib.Generated
def restoreState : RestoreStateM Unit := do
«associative-query-operations».restoreState
«associative-creation-operations».restoreState
«associative-modification-operations».restoreState
«associative-create-then-query».restoreState
«associative-all-operations-covered».restoreState

View File

@@ -0,0 +1,34 @@
import Grove.Framework
/-
This file is autogenerated by grove. You can manually edit it, for example to resolve merge
conflicts, but be careful.
-/
open Grove.Framework Widget
namespace GroveStdlib.Generated.«associative-all-operations-covered»
def «all-covered» : Assertion.Fact where
widgetId := "associative-all-operations-covered"
factId := "all-covered"
assertionId := "all-covered"
state := {
assertionId := "all-covered"
description := "All operations should be covered"
passed := false
message := "There were 19697 operations that were not covered."
}
metadata := {
status := .bad
comment := "Still missing some!"
}
def table : Assertion.Data where
widgetId := "associative-all-operations-covered"
facts := #[
«all-covered»,
]
def restoreState : RestoreStateM Unit := do
addAssertion table

View File

@@ -0,0 +1,357 @@
import Grove.Framework
/-
This file is autogenerated by grove. You can manually edit it, for example to resolve merge
conflicts, but be careful.
-/
open Grove.Framework Widget
namespace GroveStdlib.Generated.«associative-create-then-query»
def «2cb3c441-9663-4ce7-9527-0f40fc29925a:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap» : Table.Fact .subexpression .subexpression .declaration where
widgetId := "associative-create-then-query"
factId := "2cb3c441-9663-4ce7-9527-0f40fc29925a:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap"
rowAssociationId := "2cb3c441-9663-4ce7-9527-0f40fc29925a"
columnAssociationId := "01f88623-fa5f-4380-9772-b30f2fec5c94"
selectedLayers := #["Std.DHashMap", "Std.DHashMap.Raw", "Std.ExtDHashMap", "Std.DTreeMap", "Std.DTreeMap.Raw", "Std.ExtDTreeMap", ]
layerStates := #[
{
layerIdentifier := "Std.DHashMap"
rowState :=
some "Std.DHashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.emptyWithCapacity,
renderedStatement := "Std.DHashMap.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.DHashMap α β",
isDeprecated := false })
columnState :=
some "Std.DHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.isEmpty,
renderedStatement := "Std.DHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.DHashMap α β) : Bool",
isDeprecated := false })
selectedCellStates := #[
]
},
{
layerIdentifier := "Std.DHashMap.Raw"
rowState :=
some "Std.DHashMap.Raw.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.Raw.emptyWithCapacity,
renderedStatement := "Std.DHashMap.Raw.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} (capacity : Nat := 8) :\n Std.DHashMap.Raw α β",
isDeprecated := false })
columnState :=
some "Std.DHashMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.Raw.isEmpty,
renderedStatement := "Std.DHashMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} (m : Std.DHashMap.Raw α β) : Bool",
isDeprecated := false })
selectedCellStates := #[
]
},
{
layerIdentifier := "Std.ExtDHashMap"
rowState :=
some "Std.ExtDHashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDHashMap.emptyWithCapacity,
renderedStatement := "Std.ExtDHashMap.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.ExtDHashMap α β",
isDeprecated := false })
columnState :=
some "Std.ExtDHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDHashMap.isEmpty,
renderedStatement := "Std.ExtDHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [EquivBEq α] [LawfulHashable α] (m : Std.ExtDHashMap α β) : Bool",
isDeprecated := false })
selectedCellStates := #[
]
},
{
layerIdentifier := "Std.DTreeMap"
rowState :=
some "Std.DTreeMap.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.empty,
renderedStatement := "Std.DTreeMap.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} :\n Std.DTreeMap α β cmp",
isDeprecated := false })
columnState :=
some "Std.DTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.isEmpty,
renderedStatement := "Std.DTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap α β cmp) : Bool",
isDeprecated := false })
selectedCellStates := #[
]
},
{
layerIdentifier := "Std.DTreeMap.Raw"
rowState :=
some "Std.DTreeMap.Raw.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.Raw.empty,
renderedStatement := "Std.DTreeMap.Raw.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} :\n Std.DTreeMap.Raw α β cmp",
isDeprecated := false })
columnState :=
some "Std.DTreeMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.Raw.isEmpty,
renderedStatement := "Std.DTreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) : Bool",
isDeprecated := false })
selectedCellStates := #[
]
},
{
layerIdentifier := "Std.ExtDTreeMap"
rowState :=
some "Std.ExtDTreeMap.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDTreeMap.empty,
renderedStatement := "Std.ExtDTreeMap.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} :\n Std.ExtDTreeMap α β cmp",
isDeprecated := false })
columnState :=
some "Std.ExtDTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDTreeMap.isEmpty,
renderedStatement := "Std.ExtDTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.ExtDTreeMap α β cmp) : Bool",
isDeprecated := false })
selectedCellStates := #[
]
},
]
metadata := {
status := .done
comment := "Not necessary for `ExtDHashMap` because of simp lemma turning into varno"
}
def «5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap» : Table.Fact .subexpression .subexpression .declaration where
widgetId := "associative-create-then-query"
factId := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap"
rowAssociationId := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
columnAssociationId := "01f88623-fa5f-4380-9772-b30f2fec5c94"
selectedLayers := #["Std.DHashMap", "Std.DHashMap.Raw", "Std.ExtDHashMap", "Std.DTreeMap", "Std.DTreeMap.Raw", "Std.ExtDTreeMap", ]
layerStates := #[
{
layerIdentifier := "Std.DHashMap"
rowState :=
some "app (EmptyCollection.emptyCollection) (Std.DHashMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.DHashMap*)", displayShort := "" }
columnState :=
some "Std.DHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.isEmpty,
renderedStatement := "Std.DHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.DHashMap α β) : Bool",
isDeprecated := false })
selectedCellStates := #[
"Std.DHashMap.isEmpty_empty", Grove.Framework.Declaration.thm
{ name := `Std.DHashMap.isEmpty_empty,
renderedStatement := "Std.DHashMap.isEmpty_empty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} :\n ∅.isEmpty = true",
isSimp := true,
isDeprecated := false }
,
]
},
{
layerIdentifier := "Std.DHashMap.Raw"
rowState :=
some "app (EmptyCollection.emptyCollection) (Std.DHashMap.Raw*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.DHashMap.Raw*)", displayShort := "" }
columnState :=
some "Std.DHashMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.Raw.isEmpty,
renderedStatement := "Std.DHashMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} (m : Std.DHashMap.Raw α β) : Bool",
isDeprecated := false })
selectedCellStates := #[
"Std.DHashMap.Raw.isEmpty_emptyc", Grove.Framework.Declaration.thm
{ name := `Std.DHashMap.Raw.isEmpty_emptyc,
renderedStatement := "Std.DHashMap.Raw.isEmpty_emptyc.{u_1, u_2} {α : Type u_1} {β : α → Type u_2} [BEq α] [Hashable α] :\n ∅.isEmpty = true",
isSimp := false,
isDeprecated := true }
,
]
},
{
layerIdentifier := "Std.ExtDHashMap"
rowState :=
some "app (EmptyCollection.emptyCollection) (Std.ExtDHashMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtDHashMap*)", displayShort := "" }
columnState :=
some "Std.ExtDHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDHashMap.isEmpty,
renderedStatement := "Std.ExtDHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [EquivBEq α] [LawfulHashable α] (m : Std.ExtDHashMap α β) : Bool",
isDeprecated := false })
selectedCellStates := #[
]
},
{
layerIdentifier := "Std.DTreeMap"
rowState :=
some "app (EmptyCollection.emptyCollection) (Std.DTreeMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.DTreeMap*)", displayShort := "" }
columnState :=
some "Std.DTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.isEmpty,
renderedStatement := "Std.DTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap α β cmp) : Bool",
isDeprecated := false })
selectedCellStates := #[
"Std.DTreeMap.isEmpty_emptyc", Grove.Framework.Declaration.thm
{ name := `Std.DTreeMap.isEmpty_emptyc,
renderedStatement := "Std.DTreeMap.isEmpty_emptyc.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} :\n ∅.isEmpty = true",
isSimp := true,
isDeprecated := false }
,
]
},
{
layerIdentifier := "Std.DTreeMap.Raw"
rowState :=
some "app (EmptyCollection.emptyCollection) (Std.DTreeMap.Raw*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.DTreeMap.Raw*)", displayShort := "" }
columnState :=
some "Std.DTreeMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.Raw.isEmpty,
renderedStatement := "Std.DTreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) : Bool",
isDeprecated := false })
selectedCellStates := #[
"Std.DTreeMap.Raw.isEmpty_emptyc", Grove.Framework.Declaration.thm
{ name := `Std.DTreeMap.Raw.isEmpty_emptyc,
renderedStatement := "Std.DTreeMap.Raw.isEmpty_emptyc.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} :\n ∅.isEmpty = true",
isSimp := true,
isDeprecated := false }
,
]
},
{
layerIdentifier := "Std.ExtDTreeMap"
rowState :=
some "app (EmptyCollection.emptyCollection) (Std.ExtDTreeMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtDTreeMap*)", displayShort := "" }
columnState :=
some "Std.ExtDTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDTreeMap.isEmpty,
renderedStatement := "Std.ExtDTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.ExtDTreeMap α β cmp) : Bool",
isDeprecated := false })
selectedCellStates := #[
"Std.ExtDTreeMap.isEmpty_empty", Grove.Framework.Declaration.thm
{ name := `Std.ExtDTreeMap.isEmpty_empty,
renderedStatement := "Std.ExtDTreeMap.isEmpty_empty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} :\n ∅.isEmpty = true",
isSimp := true,
isDeprecated := false }
,
]
},
]
metadata := {
status := .bad
comment := "Missing for `ExtDHashMap`"
}
def table : Table.Data .subexpression .subexpression .declaration where
widgetId := "associative-create-then-query"
selectedRowAssociations := #["2cb3c441-9663-4ce7-9527-0f40fc29925a", "7743a485-024d-43b6-bd5f-ebd3182eb94d", "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d", ]
selectedColumnAssociations := #["01f88623-fa5f-4380-9772-b30f2fec5c94", "f084f852-af71-45b6-8ab3-d251a8144f72", ]
selectedLayers := #["Std.DHashMap", "Std.DHashMap.Raw", "Std.ExtDHashMap", "Std.DTreeMap", "Std.DTreeMap.Raw", "Std.ExtDTreeMap", ]
selectedCellOptions := #[
{
layerIdentifier := "Std.DHashMap"
rowValue := "2cb3c441-9663-4ce7-9527-0f40fc29925a"
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
selectedCellOptions := #["Std.DHashMap.isEmpty_emptyWithCapacity", ]
},
{
layerIdentifier := "Std.DHashMap.Raw"
rowValue := "2cb3c441-9663-4ce7-9527-0f40fc29925a"
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
selectedCellOptions := #["Std.DHashMap.Raw.isEmpty_emptyWithCapacity", ]
},
{
layerIdentifier := "Std.DHashMap"
rowValue := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
selectedCellOptions := #["Std.DHashMap.isEmpty_empty", ]
},
{
layerIdentifier := "Std.DHashMap.Raw"
rowValue := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
selectedCellOptions := #["Std.DHashMap.Raw.isEmpty_emptyc", ]
},
{
layerIdentifier := "Std.DTreeMap"
rowValue := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
selectedCellOptions := #["Std.DTreeMap.isEmpty_emptyc", ]
},
{
layerIdentifier := "Std.DTreeMap.Raw"
rowValue := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
selectedCellOptions := #["Std.DTreeMap.Raw.isEmpty_emptyc", ]
},
{
layerIdentifier := "Std.ExtDTreeMap"
rowValue := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
selectedCellOptions := #["Std.ExtDTreeMap.isEmpty_empty", ]
},
]
facts := #[
«2cb3c441-9663-4ce7-9527-0f40fc29925a:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap»,
«5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap»,
]
def restoreState : RestoreStateM Unit := do
addTable table

View File

@@ -0,0 +1,216 @@
import Grove.Framework
/-
This file is autogenerated by grove. You can manually edit it, for example to resolve merge
conflicts, but be careful.
-/
open Grove.Framework Widget
namespace GroveStdlib.Generated.«associative-creation-operations»
def «2cb3c441-9663-4ce7-9527-0f40fc29925a» : AssociationTable.Fact .subexpression where
widgetId := "associative-creation-operations"
factId := "2cb3c441-9663-4ce7-9527-0f40fc29925a"
rowId := "2cb3c441-9663-4ce7-9527-0f40fc29925a"
rowState := #["Std.DHashMap", "Std.DHashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.emptyWithCapacity,
renderedStatement := "Std.DHashMap.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.DHashMap α β",
isDeprecated := false }),"Std.DHashMap.Raw", "Std.DHashMap.Raw.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.Raw.emptyWithCapacity,
renderedStatement := "Std.DHashMap.Raw.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} (capacity : Nat := 8) :\n Std.DHashMap.Raw α β",
isDeprecated := false }),"Std.ExtDHashMap", "Std.ExtDHashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDHashMap.emptyWithCapacity,
renderedStatement := "Std.ExtDHashMap.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.ExtDHashMap α β",
isDeprecated := false }),"Std.DTreeMap", "Std.DTreeMap.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.empty,
renderedStatement := "Std.DTreeMap.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} :\n Std.DTreeMap α β cmp",
isDeprecated := false }),"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.Raw.empty,
renderedStatement := "Std.DTreeMap.Raw.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} :\n Std.DTreeMap.Raw α β cmp",
isDeprecated := false }),"Std.ExtDTreeMap", "Std.ExtDTreeMap.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDTreeMap.empty,
renderedStatement := "Std.ExtDTreeMap.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} :\n Std.ExtDTreeMap α β cmp",
isDeprecated := false }),"Std.HashMap", "Std.HashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashMap.emptyWithCapacity,
renderedStatement := "Std.HashMap.emptyWithCapacity.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.HashMap α β",
isDeprecated := false }),"Std.HashMap.Raw", "Std.HashMap.Raw.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashMap.Raw.emptyWithCapacity,
renderedStatement := "Std.HashMap.Raw.emptyWithCapacity.{u, v} {α : Type u} {β : Type v} (capacity : Nat := 8) :\n Std.HashMap.Raw α β",
isDeprecated := false }),"Std.ExtHashMap", "Std.ExtHashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtHashMap.emptyWithCapacity,
renderedStatement := "Std.ExtHashMap.emptyWithCapacity.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.ExtHashMap α β",
isDeprecated := false }),"Std.TreeMap", "Std.TreeMap.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.empty,
renderedStatement := "Std.TreeMap.empty.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} : Std.TreeMap α β cmp",
isDeprecated := false }),"Std.TreeMap.Raw", "Std.TreeMap.Raw.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.Raw.empty,
renderedStatement := "Std.TreeMap.Raw.empty.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} :\n Std.TreeMap.Raw α β cmp",
isDeprecated := false }),"Std.ExtTreeMap", "Std.ExtTreeMap.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeMap.empty,
renderedStatement := "Std.ExtTreeMap.empty.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} :\n Std.ExtTreeMap α β cmp",
isDeprecated := false }),"Std.HashSet", "Std.HashSet.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.emptyWithCapacity,
renderedStatement := "Std.HashSet.emptyWithCapacity.{u} {α : Type u} [BEq α] [Hashable α] (capacity : Nat := 8) :\n Std.HashSet α",
isDeprecated := false }),"Std.HashSet.Raw", "Std.HashSet.Raw.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.Raw.emptyWithCapacity,
renderedStatement := "Std.HashSet.Raw.emptyWithCapacity.{u} {α : Type u} (capacity : Nat := 8) : Std.HashSet.Raw α",
isDeprecated := false }),"Std.ExtHashSet", "Std.ExtHashSet.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtHashSet.emptyWithCapacity,
renderedStatement := "Std.ExtHashSet.emptyWithCapacity.{u} {α : Type u} [BEq α] [Hashable α] (capacity : Nat := 8) :\n Std.ExtHashSet α",
isDeprecated := false }),"Std.TreeSet", "Std.TreeSet.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.empty,
renderedStatement := "Std.TreeSet.empty.{u} {α : Type u} {cmp : αα → Ordering} : Std.TreeSet α cmp",
isDeprecated := false }),"Std.TreeSet.Raw", "Std.TreeSet.Raw.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.Raw.empty,
renderedStatement := "Std.TreeSet.Raw.empty.{u} {α : Type u} {cmp : αα → Ordering} : Std.TreeSet.Raw α cmp",
isDeprecated := false }),"Std.ExtTreeSet", "Std.ExtTreeSet.empty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeSet.empty,
renderedStatement := "Std.ExtTreeSet.empty.{u} {α : Type u} {cmp : αα → Ordering} : Std.ExtTreeSet α cmp",
isDeprecated := false }),]
metadata := {
status := .done
comment := ""
}
def «7743a485-024d-43b6-bd5f-ebd3182eb94d» : AssociationTable.Fact .subexpression where
widgetId := "associative-creation-operations"
factId := "7743a485-024d-43b6-bd5f-ebd3182eb94d"
rowId := "7743a485-024d-43b6-bd5f-ebd3182eb94d"
rowState := #["Std.DHashMap", "Std.DHashMap.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.ofList,
renderedStatement := "Std.DHashMap.ofList.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (l : List ((a : α) × β a)) : Std.DHashMap α β",
isDeprecated := false }),"Std.DHashMap.Raw", "Std.DHashMap.Raw.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.Raw.ofList,
renderedStatement := "Std.DHashMap.Raw.ofList.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (l : List ((a : α) × β a)) : Std.DHashMap.Raw α β",
isDeprecated := false }),"Std.ExtDHashMap", "Std.ExtDHashMap.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDHashMap.ofList,
renderedStatement := "Std.ExtDHashMap.ofList.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (l : List ((a : α) × β a)) : Std.ExtDHashMap α β",
isDeprecated := false }),"Std.DTreeMap", "Std.DTreeMap.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.ofList,
renderedStatement := "Std.DTreeMap.ofList.{u, v} {α : Type u} {β : α → Type v} (l : List ((a : α) × β a))\n (cmp : αα → Ordering := by exact compare) : Std.DTreeMap α β cmp",
isDeprecated := false }),"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.Raw.ofList,
renderedStatement := "Std.DTreeMap.Raw.ofList.{u, v} {α : Type u} {β : α → Type v} (l : List ((a : α) × β a))\n (cmp : αα → Ordering := by exact compare) : Std.DTreeMap.Raw α β cmp",
isDeprecated := false }),"Std.ExtDTreeMap", "Std.ExtDTreeMap.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDTreeMap.ofList,
renderedStatement := "Std.ExtDTreeMap.ofList.{u, v} {α : Type u} {β : α → Type v} (l : List ((a : α) × β a))\n (cmp : αα → Ordering := by exact compare) : Std.ExtDTreeMap α β cmp",
isDeprecated := false }),"Std.HashMap", "Std.HashMap.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashMap.ofList,
renderedStatement := "Std.HashMap.ofList.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (l : List (α × β)) :\n Std.HashMap α β",
isDeprecated := false }),"Std.HashMap.Raw", "Std.HashMap.Raw.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashMap.Raw.ofList,
renderedStatement := "Std.HashMap.Raw.ofList.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (l : List (α × β)) :\n Std.HashMap.Raw α β",
isDeprecated := false }),"Std.ExtHashMap", "Std.ExtHashMap.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtHashMap.ofList,
renderedStatement := "Std.ExtHashMap.ofList.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (l : List (α × β)) :\n Std.ExtHashMap α β",
isDeprecated := false }),"Std.TreeMap", "Std.TreeMap.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.ofList,
renderedStatement := "Std.TreeMap.ofList.{u, v} {α : Type u} {β : Type v} (l : List (α × β))\n (cmp : αα → Ordering := by exact compare) : Std.TreeMap α β cmp",
isDeprecated := false }),"Std.TreeMap.Raw", "Std.TreeMap.Raw.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.Raw.ofList,
renderedStatement := "Std.TreeMap.Raw.ofList.{u, v} {α : Type u} {β : Type v} (l : List (α × β))\n (cmp : αα → Ordering := by exact compare) : Std.TreeMap.Raw α β cmp",
isDeprecated := false }),"Std.ExtTreeMap", "Std.ExtTreeMap.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeMap.ofList,
renderedStatement := "Std.ExtTreeMap.ofList.{u, v} {α : Type u} {β : Type v} (l : List (α × β))\n (cmp : αα → Ordering := by exact compare) : Std.ExtTreeMap α β cmp",
isDeprecated := false }),"Std.HashSet", "Std.HashSet.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.ofList,
renderedStatement := "Std.HashSet.ofList.{u} {α : Type u} [BEq α] [Hashable α] (l : List α) : Std.HashSet α",
isDeprecated := false }),"Std.HashSet.Raw", "Std.HashSet.Raw.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.Raw.ofList,
renderedStatement := "Std.HashSet.Raw.ofList.{u} {α : Type u} [BEq α] [Hashable α] (l : List α) : Std.HashSet.Raw α",
isDeprecated := false }),"Std.ExtHashSet", "Std.ExtHashSet.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtHashSet.ofList,
renderedStatement := "Std.ExtHashSet.ofList.{u} {α : Type u} [BEq α] [Hashable α] (l : List α) : Std.ExtHashSet α",
isDeprecated := false }),"Std.TreeSet", "Std.TreeSet.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.ofList,
renderedStatement := "Std.TreeSet.ofList.{u} {α : Type u} (l : List α) (cmp : αα → Ordering := by exact compare) :\n Std.TreeSet α cmp",
isDeprecated := false }),"Std.TreeSet.Raw", "Std.TreeSet.Raw.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.Raw.ofList,
renderedStatement := "Std.TreeSet.Raw.ofList.{u} {α : Type u} (l : List α) (cmp : αα → Ordering := by exact compare) :\n Std.TreeSet.Raw α cmp",
isDeprecated := false }),"Std.ExtTreeSet", "Std.ExtTreeSet.ofList", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeSet.ofList,
renderedStatement := "Std.ExtTreeSet.ofList.{u} {α : Type u} (l : List α) (cmp : αα → Ordering := by exact compare) :\n Std.ExtTreeSet α cmp",
isDeprecated := false }),]
metadata := {
status := .done
comment := ""
}
def «5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d» : AssociationTable.Fact .subexpression where
widgetId := "associative-creation-operations"
factId := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
rowId := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
rowState := #["Std.DHashMap", "app (EmptyCollection.emptyCollection) (Std.DHashMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.DHashMap*)", displayShort := "" },"Std.DHashMap.Raw", "app (EmptyCollection.emptyCollection) (Std.DHashMap.Raw*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.DHashMap.Raw*)", displayShort := "" },"Std.ExtDHashMap", "app (EmptyCollection.emptyCollection) (Std.ExtDHashMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtDHashMap*)", displayShort := "" },"Std.DTreeMap", "app (EmptyCollection.emptyCollection) (Std.DTreeMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.DTreeMap*)", displayShort := "" },"Std.DTreeMap.Raw", "app (EmptyCollection.emptyCollection) (Std.DTreeMap.Raw*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.DTreeMap.Raw*)", displayShort := "" },"Std.ExtDTreeMap", "app (EmptyCollection.emptyCollection) (Std.ExtDTreeMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtDTreeMap*)", displayShort := "" },"Std.HashMap", "app (EmptyCollection.emptyCollection) (Std.HashMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.HashMap*)", displayShort := "" },"Std.HashMap.Raw", "app (EmptyCollection.emptyCollection) (Std.HashMap.Raw*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.HashMap.Raw*)", displayShort := "" },"Std.ExtHashMap", "app (EmptyCollection.emptyCollection) (Std.ExtHashMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtHashMap*)", displayShort := "" },"Std.TreeMap", "app (EmptyCollection.emptyCollection) (Std.TreeMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.TreeMap*)", displayShort := "" },"Std.TreeMap.Raw", "app (EmptyCollection.emptyCollection) (Std.TreeMap.Raw*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.TreeMap.Raw*)", displayShort := "" },"Std.ExtTreeMap", "app (EmptyCollection.emptyCollection) (Std.ExtTreeMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtTreeMap*)", displayShort := "" },"Std.HashSet", "app (EmptyCollection.emptyCollection) (Std.HashSet*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.HashSet*)", displayShort := "" },"Std.HashSet.Raw", "app (EmptyCollection.emptyCollection) (Std.HashSet.Raw*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.HashSet.Raw*)", displayShort := "" },"Std.ExtHashSet", "app (EmptyCollection.emptyCollection) (Std.ExtHashSet*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtHashSet*)", displayShort := "" },"Std.TreeSet", "app (EmptyCollection.emptyCollection) (Std.TreeSet*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.TreeSet*)", displayShort := "" },"Std.TreeSet.Raw", "app (EmptyCollection.emptyCollection) (Std.TreeSet.Raw*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.TreeSet.Raw*)", displayShort := "" },"Std.ExtTreeSet", "app (EmptyCollection.emptyCollection) (Std.ExtTreeSet*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtTreeSet*)", displayShort := "" },]
metadata := {
status := .done
comment := ""
}
def table : AssociationTable.Data .subexpression where
widgetId := "associative-creation-operations"
rows := #[
"2cb3c441-9663-4ce7-9527-0f40fc29925a", "empty", #["Std.DHashMap", "Std.DHashMap.emptyWithCapacity","Std.DHashMap.Raw", "Std.DHashMap.Raw.emptyWithCapacity","Std.ExtDHashMap", "Std.ExtDHashMap.emptyWithCapacity","Std.DTreeMap", "Std.DTreeMap.empty","Std.DTreeMap.Raw", "Std.DTreeMap.Raw.empty","Std.ExtDTreeMap", "Std.ExtDTreeMap.empty","Std.HashMap", "Std.HashMap.emptyWithCapacity","Std.HashMap.Raw", "Std.HashMap.Raw.emptyWithCapacity","Std.ExtHashMap", "Std.ExtHashMap.emptyWithCapacity","Std.TreeMap", "Std.TreeMap.empty","Std.TreeMap.Raw", "Std.TreeMap.Raw.empty","Std.ExtTreeMap", "Std.ExtTreeMap.empty","Std.HashSet", "Std.HashSet.emptyWithCapacity","Std.HashSet.Raw", "Std.HashSet.Raw.emptyWithCapacity","Std.ExtHashSet", "Std.ExtHashSet.emptyWithCapacity","Std.TreeSet", "Std.TreeSet.empty","Std.TreeSet.Raw", "Std.TreeSet.Raw.empty","Std.ExtTreeSet", "Std.ExtTreeSet.empty",],
"7743a485-024d-43b6-bd5f-ebd3182eb94d", "ofList", #["Std.DHashMap", "Std.DHashMap.ofList","Std.DHashMap.Raw", "Std.DHashMap.Raw.ofList","Std.ExtDHashMap", "Std.ExtDHashMap.ofList","Std.DTreeMap", "Std.DTreeMap.ofList","Std.DTreeMap.Raw", "Std.DTreeMap.Raw.ofList","Std.ExtDTreeMap", "Std.ExtDTreeMap.ofList","Std.HashMap", "Std.HashMap.ofList","Std.HashMap.Raw", "Std.HashMap.Raw.ofList","Std.ExtHashMap", "Std.ExtHashMap.ofList","Std.TreeMap", "Std.TreeMap.ofList","Std.TreeMap.Raw", "Std.TreeMap.Raw.ofList","Std.ExtTreeMap", "Std.ExtTreeMap.ofList","Std.HashSet", "Std.HashSet.ofList","Std.HashSet.Raw", "Std.HashSet.Raw.ofList","Std.ExtHashSet", "Std.ExtHashSet.ofList","Std.TreeSet", "Std.TreeSet.ofList","Std.TreeSet.Raw", "Std.TreeSet.Raw.ofList","Std.ExtTreeSet", "Std.ExtTreeSet.ofList",],
"5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d", "emptyCollection", #["Std.DHashMap", "app (EmptyCollection.emptyCollection) (Std.DHashMap*)","Std.DHashMap.Raw", "app (EmptyCollection.emptyCollection) (Std.DHashMap.Raw*)","Std.ExtDHashMap", "app (EmptyCollection.emptyCollection) (Std.ExtDHashMap*)","Std.DTreeMap", "app (EmptyCollection.emptyCollection) (Std.DTreeMap*)","Std.DTreeMap.Raw", "app (EmptyCollection.emptyCollection) (Std.DTreeMap.Raw*)","Std.ExtDTreeMap", "app (EmptyCollection.emptyCollection) (Std.ExtDTreeMap*)","Std.HashMap", "app (EmptyCollection.emptyCollection) (Std.HashMap*)","Std.HashMap.Raw", "app (EmptyCollection.emptyCollection) (Std.HashMap.Raw*)","Std.ExtHashMap", "app (EmptyCollection.emptyCollection) (Std.ExtHashMap*)","Std.TreeMap", "app (EmptyCollection.emptyCollection) (Std.TreeMap*)","Std.TreeMap.Raw", "app (EmptyCollection.emptyCollection) (Std.TreeMap.Raw*)","Std.ExtTreeMap", "app (EmptyCollection.emptyCollection) (Std.ExtTreeMap*)","Std.HashSet", "app (EmptyCollection.emptyCollection) (Std.HashSet*)","Std.HashSet.Raw", "app (EmptyCollection.emptyCollection) (Std.HashSet.Raw*)","Std.ExtHashSet", "app (EmptyCollection.emptyCollection) (Std.ExtHashSet*)","Std.TreeSet", "app (EmptyCollection.emptyCollection) (Std.TreeSet*)","Std.TreeSet.Raw", "app (EmptyCollection.emptyCollection) (Std.TreeSet.Raw*)","Std.ExtTreeSet", "app (EmptyCollection.emptyCollection) (Std.ExtTreeSet*)",],
]
facts := #[
«2cb3c441-9663-4ce7-9527-0f40fc29925a»,
«7743a485-024d-43b6-bd5f-ebd3182eb94d»,
«5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d»,
]
def restoreState : RestoreStateM Unit := do
addAssociationTable table

View File

@@ -0,0 +1,21 @@
import Grove.Framework
/-
This file is autogenerated by grove. You can manually edit it, for example to resolve merge
conflicts, but be careful.
-/
open Grove.Framework Widget
namespace GroveStdlib.Generated.«associative-modification-operations»
def table : AssociationTable.Data .subexpression where
widgetId := "associative-modification-operations"
rows := #[
]
facts := #[
]
def restoreState : RestoreStateM Unit := do
addAssociationTable table

View File

@@ -0,0 +1,445 @@
import Grove.Framework
/-
This file is autogenerated by grove. You can manually edit it, for example to resolve merge
conflicts, but be careful.
-/
open Grove.Framework Widget
namespace GroveStdlib.Generated.«associative-query-operations»
def «01f88623-fa5f-4380-9772-b30f2fec5c94» : AssociationTable.Fact .subexpression where
widgetId := "associative-query-operations"
factId := "01f88623-fa5f-4380-9772-b30f2fec5c94"
rowId := "01f88623-fa5f-4380-9772-b30f2fec5c94"
rowState := #["Std.DHashMap", "Std.DHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.isEmpty,
renderedStatement := "Std.DHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.DHashMap α β) : Bool",
isDeprecated := false }),"Std.DHashMap.Raw", "Std.DHashMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.Raw.isEmpty,
renderedStatement := "Std.DHashMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} (m : Std.DHashMap.Raw α β) : Bool",
isDeprecated := false }),"Std.ExtDHashMap", "Std.ExtDHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDHashMap.isEmpty,
renderedStatement := "Std.ExtDHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [EquivBEq α] [LawfulHashable α] (m : Std.ExtDHashMap α β) : Bool",
isDeprecated := false }),"Std.DTreeMap", "Std.DTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.isEmpty,
renderedStatement := "Std.DTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap α β cmp) : Bool",
isDeprecated := false }),"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.Raw.isEmpty,
renderedStatement := "Std.DTreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) : Bool",
isDeprecated := false }),"Std.ExtDTreeMap", "Std.ExtDTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDTreeMap.isEmpty,
renderedStatement := "Std.ExtDTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.ExtDTreeMap α β cmp) : Bool",
isDeprecated := false }),"Std.HashMap", "Std.HashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashMap.isEmpty,
renderedStatement := "Std.HashMap.isEmpty.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.HashMap α β) : Bool",
isDeprecated := false }),"Std.HashMap.Raw", "Std.HashMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashMap.Raw.isEmpty,
renderedStatement := "Std.HashMap.Raw.isEmpty.{u, v} {α : Type u} {β : Type v} (m : Std.HashMap.Raw α β) : Bool",
isDeprecated := false }),"Std.ExtHashMap", "Std.ExtHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtHashMap.isEmpty,
renderedStatement := "Std.ExtHashMap.isEmpty.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtHashMap α β) : Bool",
isDeprecated := false }),"Std.TreeMap", "Std.TreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.isEmpty,
renderedStatement := "Std.TreeMap.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering}\n (t : Std.TreeMap α β cmp) : Bool",
isDeprecated := false }),"Std.TreeMap.Raw", "Std.TreeMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.Raw.isEmpty,
renderedStatement := "Std.TreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering}\n (t : Std.TreeMap.Raw α β cmp) : Bool",
isDeprecated := false }),"Std.ExtTreeMap", "Std.ExtTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeMap.isEmpty,
renderedStatement := "Std.ExtTreeMap.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering}\n (t : Std.ExtTreeMap α β cmp) : Bool",
isDeprecated := false }),"Std.HashSet", "Std.HashSet.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.isEmpty,
renderedStatement := "Std.HashSet.isEmpty.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashSet α) : Bool",
isDeprecated := false }),"Std.HashSet.Raw", "Std.HashSet.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.Raw.isEmpty,
renderedStatement := "Std.HashSet.Raw.isEmpty.{u} {α : Type u} (m : Std.HashSet.Raw α) : Bool",
isDeprecated := false }),"Std.ExtHashSet", "Std.ExtHashSet.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtHashSet.isEmpty,
renderedStatement := "Std.ExtHashSet.isEmpty.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtHashSet α) : Bool",
isDeprecated := false }),"Std.TreeSet", "Std.TreeSet.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.isEmpty,
renderedStatement := "Std.TreeSet.isEmpty.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet α cmp) : Bool",
isDeprecated := false }),"Std.TreeSet.Raw", "Std.TreeSet.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.Raw.isEmpty,
renderedStatement := "Std.TreeSet.Raw.isEmpty.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet.Raw α cmp) : Bool",
isDeprecated := false }),"Std.ExtTreeSet", "Std.ExtTreeSet.isEmpty", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeSet.isEmpty,
renderedStatement := "Std.ExtTreeSet.isEmpty.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.ExtTreeSet α cmp) : Bool",
isDeprecated := false }),]
metadata := {
status := .done
comment := ""
}
def «f084f852-af71-45b6-8ab3-d251a8144f72» : AssociationTable.Fact .subexpression where
widgetId := "associative-query-operations"
factId := "f084f852-af71-45b6-8ab3-d251a8144f72"
rowId := "f084f852-af71-45b6-8ab3-d251a8144f72"
rowState := #["Std.DHashMap", "Std.DHashMap.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.size,
renderedStatement := "Std.DHashMap.size.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.DHashMap α β) : Nat",
isDeprecated := false }),"Std.DHashMap.Raw", "Std.DHashMap.Raw.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.Raw.size,
renderedStatement := "Std.DHashMap.Raw.size.{u, v} {α : Type u} {β : α → Type v} (self : Std.DHashMap.Raw α β) : Nat",
isDeprecated := false }),"Std.ExtDHashMap", "Std.ExtDHashMap.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDHashMap.size,
renderedStatement := "Std.ExtDHashMap.size.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [EquivBEq α] [LawfulHashable α] (m : Std.ExtDHashMap α β) : Nat",
isDeprecated := false }),"Std.DTreeMap", "Std.DTreeMap.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.size,
renderedStatement := "Std.DTreeMap.size.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap α β cmp) : Nat",
isDeprecated := false }),"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.Raw.size,
renderedStatement := "Std.DTreeMap.Raw.size.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) : Nat",
isDeprecated := false }),"Std.ExtDTreeMap", "Std.ExtDTreeMap.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDTreeMap.size,
renderedStatement := "Std.ExtDTreeMap.size.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.ExtDTreeMap α β cmp) : Nat",
isDeprecated := false }),"Std.HashMap", "Std.HashMap.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashMap.size,
renderedStatement := "Std.HashMap.size.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.HashMap α β) : Nat",
isDeprecated := false }),"Std.HashMap.Raw", "Std.HashMap.Raw.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashMap.Raw.size,
renderedStatement := "Std.HashMap.Raw.size.{u, v} {α : Type u} {β : Type v} (m : Std.HashMap.Raw α β) : Nat",
isDeprecated := false }),"Std.ExtHashMap", "Std.ExtHashMap.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtHashMap.size,
renderedStatement := "Std.ExtHashMap.size.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtHashMap α β) : Nat",
isDeprecated := false }),"Std.TreeMap", "Std.TreeMap.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.size,
renderedStatement := "Std.TreeMap.size.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering}\n (t : Std.TreeMap α β cmp) : Nat",
isDeprecated := false }),"Std.TreeMap.Raw", "Std.TreeMap.Raw.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.Raw.size,
renderedStatement := "Std.TreeMap.Raw.size.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering}\n (t : Std.TreeMap.Raw α β cmp) : Nat",
isDeprecated := false }),"Std.ExtTreeMap", "Std.ExtTreeMap.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeMap.size,
renderedStatement := "Std.ExtTreeMap.size.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering}\n (t : Std.ExtTreeMap α β cmp) : Nat",
isDeprecated := false }),"Std.HashSet", "Std.HashSet.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.size,
renderedStatement := "Std.HashSet.size.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashSet α) : Nat",
isDeprecated := false }),"Std.HashSet.Raw", "Std.HashSet.Raw.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.Raw.size,
renderedStatement := "Std.HashSet.Raw.size.{u} {α : Type u} (m : Std.HashSet.Raw α) : Nat",
isDeprecated := false }),"Std.ExtHashSet", "Std.ExtHashSet.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtHashSet.size,
renderedStatement := "Std.ExtHashSet.size.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashSet α) : Nat",
isDeprecated := false }),"Std.TreeSet", "Std.TreeSet.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.size,
renderedStatement := "Std.TreeSet.size.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet α cmp) : Nat",
isDeprecated := false }),"Std.TreeSet.Raw", "Std.TreeSet.Raw.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.Raw.size,
renderedStatement := "Std.TreeSet.Raw.size.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet.Raw α cmp) : Nat",
isDeprecated := false }),"Std.ExtTreeSet", "Std.ExtTreeSet.size", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeSet.size,
renderedStatement := "Std.ExtTreeSet.size.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.ExtTreeSet α cmp) : Nat",
isDeprecated := false }),]
metadata := {
status := .done
comment := ""
}
def «f4e6fa70-5aed-439d-aaad-5f4ced65bf7b» : AssociationTable.Fact .subexpression where
widgetId := "associative-query-operations"
factId := "f4e6fa70-5aed-439d-aaad-5f4ced65bf7b"
rowId := "f4e6fa70-5aed-439d-aaad-5f4ced65bf7b"
rowState := #["Std.DTreeMap", "Std.DTreeMap.any", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.any,
renderedStatement := "Std.DTreeMap.any.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap α β cmp) (p : (a : α) → β a → Bool) : Bool",
isDeprecated := false }),"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.any", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.Raw.any,
renderedStatement := "Std.DTreeMap.Raw.any.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) (p : (a : α) → β a → Bool) : Bool",
isDeprecated := false }),"Std.ExtDTreeMap", "Std.ExtDTreeMap.any", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDTreeMap.any,
renderedStatement := "Std.ExtDTreeMap.any.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtDTreeMap α β cmp) (p : (a : α) → β a → Bool) : Bool",
isDeprecated := false }),"Std.TreeMap", "Std.TreeMap.any", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.any,
renderedStatement := "Std.TreeMap.any.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} (t : Std.TreeMap α β cmp)\n (p : α → β → Bool) : Bool",
isDeprecated := false }),"Std.TreeMap.Raw", "Std.TreeMap.Raw.any", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.Raw.any,
renderedStatement := "Std.TreeMap.Raw.any.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering}\n (t : Std.TreeMap.Raw α β cmp) (p : α → β → Bool) : Bool",
isDeprecated := false }),"Std.ExtTreeMap", "Std.ExtTreeMap.any", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeMap.any,
renderedStatement := "Std.ExtTreeMap.any.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeMap α β cmp) (p : α → β → Bool) : Bool",
isDeprecated := false }),"Std.HashSet", "Std.HashSet.any", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.any,
renderedStatement := "Std.HashSet.any.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashSet α)\n (p : α → Bool) : Bool",
isDeprecated := false }),"Std.HashSet.Raw", "Std.HashSet.Raw.any", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.Raw.any,
renderedStatement := "Std.HashSet.Raw.any.{u} {α : Type u} (m : Std.HashSet.Raw α) (p : α → Bool) : Bool",
isDeprecated := false }),"Std.TreeSet", "Std.TreeSet.any", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.any,
renderedStatement := "Std.TreeSet.any.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet α cmp) (p : α → Bool) :\n Bool",
isDeprecated := false }),"Std.TreeSet.Raw", "Std.TreeSet.Raw.any", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.Raw.any,
renderedStatement := "Std.TreeSet.Raw.any.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet.Raw α cmp)\n (p : α → Bool) : Bool",
isDeprecated := false }),"Std.ExtTreeSet", "Std.ExtTreeSet.any", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeSet.any,
renderedStatement := "Std.ExtTreeSet.any.{u} {α : Type u} {cmp : αα → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeSet α cmp) (p : α → Bool) : Bool",
isDeprecated := false }),]
metadata := {
status := .bad
comment := "Missing for some containers"
}
def «c1d181f6-3204-4956-946f-e81619f9feb4» : AssociationTable.Fact .subexpression where
widgetId := "associative-query-operations"
factId := "c1d181f6-3204-4956-946f-e81619f9feb4"
rowId := "c1d181f6-3204-4956-946f-e81619f9feb4"
rowState := #["Std.DTreeMap", "Std.DTreeMap.all", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.all,
renderedStatement := "Std.DTreeMap.all.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap α β cmp) (p : (a : α) → β a → Bool) : Bool",
isDeprecated := false }),"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.all", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.Raw.all,
renderedStatement := "Std.DTreeMap.Raw.all.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) (p : (a : α) → β a → Bool) : Bool",
isDeprecated := false }),"Std.ExtDTreeMap", "Std.ExtDTreeMap.all", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDTreeMap.all,
renderedStatement := "Std.ExtDTreeMap.all.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtDTreeMap α β cmp) (p : (a : α) → β a → Bool) : Bool",
isDeprecated := false }),"Std.TreeMap", "Std.TreeMap.all", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.all,
renderedStatement := "Std.TreeMap.all.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} (t : Std.TreeMap α β cmp)\n (p : α → β → Bool) : Bool",
isDeprecated := false }),"Std.TreeMap.Raw", "Std.TreeMap.Raw.all", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.Raw.all,
renderedStatement := "Std.TreeMap.Raw.all.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering}\n (t : Std.TreeMap.Raw α β cmp) (p : α → β → Bool) : Bool",
isDeprecated := false }),"Std.ExtTreeMap", "Std.ExtTreeMap.all", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeMap.all,
renderedStatement := "Std.ExtTreeMap.all.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeMap α β cmp) (p : α → β → Bool) : Bool",
isDeprecated := false }),"Std.HashSet", "Std.HashSet.all", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.all,
renderedStatement := "Std.HashSet.all.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashSet α)\n (p : α → Bool) : Bool",
isDeprecated := false }),"Std.HashSet.Raw", "Std.HashSet.Raw.all", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.Raw.all,
renderedStatement := "Std.HashSet.Raw.all.{u} {α : Type u} (m : Std.HashSet.Raw α) (p : α → Bool) : Bool",
isDeprecated := false }),"Std.TreeSet", "Std.TreeSet.all", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.all,
renderedStatement := "Std.TreeSet.all.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet α cmp) (p : α → Bool) :\n Bool",
isDeprecated := false }),"Std.TreeSet.Raw", "Std.TreeSet.Raw.all", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.Raw.all,
renderedStatement := "Std.TreeSet.Raw.all.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet.Raw α cmp)\n (p : α → Bool) : Bool",
isDeprecated := false }),"Std.ExtTreeSet", "Std.ExtTreeSet.all", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeSet.all,
renderedStatement := "Std.ExtTreeSet.all.{u} {α : Type u} {cmp : αα → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeSet α cmp) (p : α → Bool) : Bool",
isDeprecated := false }),]
metadata := {
status := .bad
comment := "Missing for some containers"
}
def «efe57f41-7db7-4303-b3a6-5216a70c43ce» : AssociationTable.Fact .subexpression where
widgetId := "associative-query-operations"
factId := "efe57f41-7db7-4303-b3a6-5216a70c43ce"
rowId := "efe57f41-7db7-4303-b3a6-5216a70c43ce"
rowState := #["Std.DHashMap", "Std.DHashMap.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.getD,
renderedStatement := "Std.DHashMap.getD.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [LawfulBEq α]\n (m : Std.DHashMap α β) (a : α) (fallback : β a) : β a",
isDeprecated := false }),"Std.DHashMap.Raw", "Std.DHashMap.Raw.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.Raw.getD,
renderedStatement := "Std.DHashMap.Raw.getD.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α] [LawfulBEq α]\n (m : Std.DHashMap.Raw α β) (a : α) (fallback : β a) : β a",
isDeprecated := false }),"Std.ExtDHashMap", "Std.ExtDHashMap.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDHashMap.getD,
renderedStatement := "Std.ExtDHashMap.getD.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [LawfulBEq α] (m : Std.ExtDHashMap α β) (a : α) (fallback : β a) : β a",
isDeprecated := false }),"Std.DTreeMap", "Std.DTreeMap.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.getD,
renderedStatement := "Std.DTreeMap.getD.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n [Std.LawfulEqCmp cmp] (t : Std.DTreeMap α β cmp) (a : α) (fallback : β a) : β a",
isDeprecated := false }),"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.Raw.getD,
renderedStatement := "Std.DTreeMap.Raw.getD.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n [Std.LawfulEqCmp cmp] (t : Std.DTreeMap.Raw α β cmp) (a : α) (fallback : β a) : β a",
isDeprecated := false }),"Std.ExtDTreeMap", "Std.ExtDTreeMap.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDTreeMap.getD,
renderedStatement := "Std.ExtDTreeMap.getD.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n [Std.TransCmp cmp] [Std.LawfulEqCmp cmp] (t : Std.ExtDTreeMap α β cmp) (a : α) (fallback : β a) :\n β a",
isDeprecated := false }),"Std.HashMap", "Std.HashMap.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashMap.getD,
renderedStatement := "Std.HashMap.getD.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.HashMap α β) (a : α) (fallback : β) : β",
isDeprecated := false }),"Std.HashMap.Raw", "Std.HashMap.Raw.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashMap.Raw.getD,
renderedStatement := "Std.HashMap.Raw.getD.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (m : Std.HashMap.Raw α β)\n (a : α) (fallback : β) : β",
isDeprecated := false }),"Std.ExtHashMap", "Std.ExtHashMap.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtHashMap.getD,
renderedStatement := "Std.ExtHashMap.getD.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtHashMap α β) (a : α) (fallback : β) : β",
isDeprecated := false }),"Std.TreeMap", "Std.TreeMap.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.getD,
renderedStatement := "Std.TreeMap.getD.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} (t : Std.TreeMap α β cmp)\n (a : α) (fallback : β) : β",
isDeprecated := false }),"Std.TreeMap.Raw", "Std.TreeMap.Raw.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeMap.Raw.getD,
renderedStatement := "Std.TreeMap.Raw.getD.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering}\n (t : Std.TreeMap.Raw α β cmp) (a : α) (fallback : β) : β",
isDeprecated := false }),"Std.ExtTreeMap", "Std.ExtTreeMap.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeMap.getD,
renderedStatement := "Std.ExtTreeMap.getD.{u, v} {α : Type u} {β : Type v} {cmp : αα → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeMap α β cmp) (a : α) (fallback : β) : β",
isDeprecated := false }),"Std.HashSet", "Std.HashSet.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.getD,
renderedStatement := "Std.HashSet.getD.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet α) (a fallback : α) : α",
isDeprecated := false }),"Std.HashSet.Raw", "Std.HashSet.Raw.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.Raw.getD,
renderedStatement := "Std.HashSet.Raw.getD.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet.Raw α)\n (a fallback : α) : α",
isDeprecated := false }),"Std.ExtHashSet", "Std.ExtHashSet.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtHashSet.getD,
renderedStatement := "Std.ExtHashSet.getD.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashSet α) (a fallback : α) : α",
isDeprecated := false }),"Std.TreeSet", "Std.TreeSet.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.getD,
renderedStatement := "Std.TreeSet.getD.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet α cmp)\n (a fallback : α) : α",
isDeprecated := false }),"Std.TreeSet.Raw", "Std.TreeSet.Raw.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.Raw.getD,
renderedStatement := "Std.TreeSet.Raw.getD.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet.Raw α cmp)\n (a fallback : α) : α",
isDeprecated := false }),"Std.ExtTreeSet", "Std.ExtTreeSet.getD", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeSet.getD,
renderedStatement := "Std.ExtTreeSet.getD.{u} {α : Type u} {cmp : αα → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeSet α cmp) (a fallback : α) : α",
isDeprecated := false }),]
metadata := {
status := .done
comment := ""
}
def «e23b1119-3b57-433e-a68d-68fd70b9943d» : AssociationTable.Fact .subexpression where
widgetId := "associative-query-operations"
factId := "e23b1119-3b57-433e-a68d-68fd70b9943d"
rowId := "e23b1119-3b57-433e-a68d-68fd70b9943d"
rowState := #["Std.DHashMap", "Std.DHashMap.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.get,
renderedStatement := "Std.DHashMap.get.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [LawfulBEq α]\n (m : Std.DHashMap α β) (a : α) (h : a ∈ m) : β a",
isDeprecated := false }),"Std.DHashMap.Raw", "Std.DHashMap.Raw.Const.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DHashMap.Raw.Const.get,
renderedStatement := "Std.DHashMap.Raw.Const.get.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α]\n (m : Std.DHashMap.Raw α fun x => β) (a : α) (h : a ∈ m) : β",
isDeprecated := false }),"Std.ExtDHashMap", "Std.ExtDHashMap.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDHashMap.get,
renderedStatement := "Std.ExtDHashMap.get.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [LawfulBEq α] (m : Std.ExtDHashMap α β) (a : α) (h : a ∈ m) : β a",
isDeprecated := false }),"Std.DTreeMap", "Std.DTreeMap.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.get,
renderedStatement := "Std.DTreeMap.get.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} [Std.LawfulEqCmp cmp]\n (t : Std.DTreeMap α β cmp) (a : α) (h : a ∈ t) : β a",
isDeprecated := false }),"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.DTreeMap.Raw.get,
renderedStatement := "Std.DTreeMap.Raw.get.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering}\n [Std.LawfulEqCmp cmp] (t : Std.DTreeMap.Raw α β cmp) (a : α) (h : a ∈ t) : β a",
isDeprecated := false }),"Std.ExtDTreeMap", "Std.ExtDTreeMap.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtDTreeMap.get,
renderedStatement := "Std.ExtDTreeMap.get.{u, v} {α : Type u} {β : α → Type v} {cmp : αα → Ordering} [Std.TransCmp cmp]\n [Std.LawfulEqCmp cmp] (t : Std.ExtDTreeMap α β cmp) (a : α) (h : a ∈ t) : β a",
isDeprecated := false }),"Std.HashMap", "app (GetElem.getElem) (Std.HashMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (GetElem.getElem) (Std.HashMap*)", displayShort := "Std.HashMap[·]" },"Std.HashMap.Raw", "app (GetElem.getElem) (Std.HashMap.Raw*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (GetElem.getElem) (Std.HashMap.Raw*)", displayShort := "Std.HashMap.Raw[·]" },"Std.ExtHashMap", "app (GetElem.getElem) (Std.ExtHashMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (GetElem.getElem) (Std.ExtHashMap*)", displayShort := "Std.ExtHashMap[·]" },"Std.TreeMap", "app (GetElem.getElem) (Std.TreeMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (GetElem.getElem) (Std.TreeMap*)", displayShort := "Std.TreeMap[·]" },"Std.TreeMap.Raw", "app (GetElem.getElem) (Std.TreeMap.Raw*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (GetElem.getElem) (Std.TreeMap.Raw*)", displayShort := "Std.TreeMap.Raw[·]" },"Std.ExtTreeMap", "app (GetElem.getElem) (Std.ExtTreeMap*)", Grove.Framework.Subexpression.State.predicate
{ key := "app (GetElem.getElem) (Std.ExtTreeMap*)", displayShort := "Std.ExtTreeMap[·]" },"Std.HashSet", "Std.HashSet.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.get,
renderedStatement := "Std.HashSet.get.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet α) (a : α) (h : a ∈ m) : α",
isDeprecated := false }),"Std.HashSet.Raw", "Std.HashSet.Raw.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.HashSet.Raw.get,
renderedStatement := "Std.HashSet.Raw.get.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet.Raw α) (a : α)\n (h : a ∈ m) : α",
isDeprecated := false }),"Std.ExtHashSet", "Std.ExtHashSet.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtHashSet.get,
renderedStatement := "Std.ExtHashSet.get.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashSet α) (a : α) (h : a ∈ m) : α",
isDeprecated := false }),"Std.TreeSet", "Std.TreeSet.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.get,
renderedStatement := "Std.TreeSet.get.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet α cmp) (a : α)\n (h : a ∈ t) : α",
isDeprecated := false }),"Std.TreeSet.Raw", "Std.TreeSet.Raw.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.TreeSet.Raw.get,
renderedStatement := "Std.TreeSet.Raw.get.{u} {α : Type u} {cmp : αα → Ordering} (t : Std.TreeSet.Raw α cmp) (a : α)\n (h : a ∈ t) : α",
isDeprecated := false }),"Std.ExtTreeSet", "Std.ExtTreeSet.get", Grove.Framework.Subexpression.State.declaration
(Grove.Framework.Declaration.def
{ name := `Std.ExtTreeSet.get,
renderedStatement := "Std.ExtTreeSet.get.{u} {α : Type u} {cmp : αα → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeSet α cmp) (a : α) (h : a ∈ t) : α",
isDeprecated := false }),]
metadata := {
status := .bad
comment := "Should *Set have GetElem?"
}
def table : AssociationTable.Data .subexpression where
widgetId := "associative-query-operations"
rows := #[
"01f88623-fa5f-4380-9772-b30f2fec5c94", "isEmpty", #["Std.DHashMap", "Std.DHashMap.isEmpty","Std.DHashMap.Raw", "Std.DHashMap.Raw.isEmpty","Std.ExtDHashMap", "Std.ExtDHashMap.isEmpty","Std.DTreeMap", "Std.DTreeMap.isEmpty","Std.DTreeMap.Raw", "Std.DTreeMap.Raw.isEmpty","Std.ExtDTreeMap", "Std.ExtDTreeMap.isEmpty","Std.HashMap", "Std.HashMap.isEmpty","Std.HashMap.Raw", "Std.HashMap.Raw.isEmpty","Std.ExtHashMap", "Std.ExtHashMap.isEmpty","Std.TreeMap", "Std.TreeMap.isEmpty","Std.TreeMap.Raw", "Std.TreeMap.Raw.isEmpty","Std.ExtTreeMap", "Std.ExtTreeMap.isEmpty","Std.HashSet", "Std.HashSet.isEmpty","Std.HashSet.Raw", "Std.HashSet.Raw.isEmpty","Std.ExtHashSet", "Std.ExtHashSet.isEmpty","Std.TreeSet", "Std.TreeSet.isEmpty","Std.TreeSet.Raw", "Std.TreeSet.Raw.isEmpty","Std.ExtTreeSet", "Std.ExtTreeSet.isEmpty",],
"f084f852-af71-45b6-8ab3-d251a8144f72", "size", #["Std.DHashMap", "Std.DHashMap.size","Std.DHashMap.Raw", "Std.DHashMap.Raw.size","Std.ExtDHashMap", "Std.ExtDHashMap.size","Std.DTreeMap", "Std.DTreeMap.size","Std.DTreeMap.Raw", "Std.DTreeMap.Raw.size","Std.ExtDTreeMap", "Std.ExtDTreeMap.size","Std.HashMap", "Std.HashMap.size","Std.HashMap.Raw", "Std.HashMap.Raw.size","Std.ExtHashMap", "Std.ExtHashMap.size","Std.TreeMap", "Std.TreeMap.size","Std.TreeMap.Raw", "Std.TreeMap.Raw.size","Std.ExtTreeMap", "Std.ExtTreeMap.size","Std.HashSet", "Std.HashSet.size","Std.HashSet.Raw", "Std.HashSet.Raw.size","Std.ExtHashSet", "Std.ExtHashSet.size","Std.TreeSet", "Std.TreeSet.size","Std.TreeSet.Raw", "Std.TreeSet.Raw.size","Std.ExtTreeSet", "Std.ExtTreeSet.size",],
"f4e6fa70-5aed-439d-aaad-5f4ced65bf7b", "any", #["Std.DTreeMap", "Std.DTreeMap.any","Std.DTreeMap.Raw", "Std.DTreeMap.Raw.any","Std.ExtDTreeMap", "Std.ExtDTreeMap.any","Std.TreeMap", "Std.TreeMap.any","Std.TreeMap.Raw", "Std.TreeMap.Raw.any","Std.ExtTreeMap", "Std.ExtTreeMap.any","Std.HashSet", "Std.HashSet.any","Std.HashSet.Raw", "Std.HashSet.Raw.any","Std.TreeSet", "Std.TreeSet.any","Std.TreeSet.Raw", "Std.TreeSet.Raw.any","Std.ExtTreeSet", "Std.ExtTreeSet.any",],
"c1d181f6-3204-4956-946f-e81619f9feb4", "all", #["Std.DTreeMap", "Std.DTreeMap.all","Std.DTreeMap.Raw", "Std.DTreeMap.Raw.all","Std.ExtDTreeMap", "Std.ExtDTreeMap.all","Std.TreeMap", "Std.TreeMap.all","Std.TreeMap.Raw", "Std.TreeMap.Raw.all","Std.ExtTreeMap", "Std.ExtTreeMap.all","Std.HashSet", "Std.HashSet.all","Std.HashSet.Raw", "Std.HashSet.Raw.all","Std.TreeSet", "Std.TreeSet.all","Std.TreeSet.Raw", "Std.TreeSet.Raw.all","Std.ExtTreeSet", "Std.ExtTreeSet.all",],
"efe57f41-7db7-4303-b3a6-5216a70c43ce", "getD", #["Std.DHashMap", "Std.DHashMap.getD","Std.DHashMap.Raw", "Std.DHashMap.Raw.getD","Std.ExtDHashMap", "Std.ExtDHashMap.getD","Std.DTreeMap", "Std.DTreeMap.getD","Std.DTreeMap.Raw", "Std.DTreeMap.Raw.getD","Std.ExtDTreeMap", "Std.ExtDTreeMap.getD","Std.HashMap", "Std.HashMap.getD","Std.HashMap.Raw", "Std.HashMap.Raw.getD","Std.ExtHashMap", "Std.ExtHashMap.getD","Std.TreeMap", "Std.TreeMap.getD","Std.TreeMap.Raw", "Std.TreeMap.Raw.getD","Std.ExtTreeMap", "Std.ExtTreeMap.getD","Std.HashSet", "Std.HashSet.getD","Std.HashSet.Raw", "Std.HashSet.Raw.getD","Std.ExtHashSet", "Std.ExtHashSet.getD","Std.TreeSet", "Std.TreeSet.getD","Std.TreeSet.Raw", "Std.TreeSet.Raw.getD","Std.ExtTreeSet", "Std.ExtTreeSet.getD",],
"e23b1119-3b57-433e-a68d-68fd70b9943d", "getElem", #["Std.DHashMap", "Std.DHashMap.get","Std.DHashMap.Raw", "Std.DHashMap.Raw.Const.get","Std.ExtDHashMap", "Std.ExtDHashMap.get","Std.DTreeMap", "Std.DTreeMap.get","Std.DTreeMap.Raw", "Std.DTreeMap.Raw.get","Std.ExtDTreeMap", "Std.ExtDTreeMap.get","Std.HashMap", "app (GetElem.getElem) (Std.HashMap*)","Std.HashMap.Raw", "app (GetElem.getElem) (Std.HashMap.Raw*)","Std.ExtHashMap", "app (GetElem.getElem) (Std.ExtHashMap*)","Std.TreeMap", "app (GetElem.getElem) (Std.TreeMap*)","Std.TreeMap.Raw", "app (GetElem.getElem) (Std.TreeMap.Raw*)","Std.ExtTreeMap", "app (GetElem.getElem) (Std.ExtTreeMap*)","Std.HashSet", "Std.HashSet.get","Std.HashSet.Raw", "Std.HashSet.Raw.get","Std.ExtHashSet", "Std.ExtHashSet.get","Std.TreeSet", "Std.TreeSet.get","Std.TreeSet.Raw", "Std.TreeSet.Raw.get","Std.ExtTreeSet", "Std.ExtTreeSet.get",],
]
facts := #[
«01f88623-fa5f-4380-9772-b30f2fec5c94»,
«f084f852-af71-45b6-8ab3-d251a8144f72»,
«f4e6fa70-5aed-439d-aaad-5f4ced65bf7b»,
«c1d181f6-3204-4956-946f-e81619f9feb4»,
«efe57f41-7db7-4303-b3a6-5216a70c43ce»,
«e23b1119-3b57-433e-a68d-68fd70b9943d»,
]
def restoreState : RestoreStateM Unit := do
addAssociationTable table

View File

@@ -0,0 +1,31 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
import GroveStdlib.Std.CoreTypesAndOperations
import GroveStdlib.Std.LanguageConstructs
import GroveStdlib.Std.Libraries
import GroveStdlib.Std.OperatingSystemAbstractions
open Grove.Framework Widget
namespace GroveStdlib
namespace Std
def introduction : Node :=
.text "Welcome to the interactive Lean standard library outline!"
end Std
def std : Node :=
.section "stdlib" "The Lean standard library" #[
Std.introduction,
Std.coreTypesAndOperations,
Std.languageConstructs,
Std.libraries,
Std.operatingSystemAbstractions
]
end GroveStdlib

View File

@@ -0,0 +1,28 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
import Grove.Framework
import GroveStdlib.Std.CoreTypesAndOperations.BasicTypes
import GroveStdlib.Std.CoreTypesAndOperations.Containers
import GroveStdlib.Std.CoreTypesAndOperations.Numbers
import GroveStdlib.Std.CoreTypesAndOperations.StringsAndFormatting
open Grove.Framework Widget
namespace GroveStdlib.Std
namespace CoreTypesAndOperations
end CoreTypesAndOperations
def coreTypesAndOperations : Node :=
.section "core-types-and-operations" "Core types and operations" #[
CoreTypesAndOperations.basicTypes,
CoreTypesAndOperations.containers,
CoreTypesAndOperations.numbers,
CoreTypesAndOperations.stringsAndFormatting
]
end GroveStdlib.Std

View File

@@ -0,0 +1,19 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
import Grove.Framework
open Grove.Framework Widget
namespace GroveStdlib.Std.CoreTypesAndOperations
namespace BasicTypes
end BasicTypes
def basicTypes : Node :=
.section "basic-types" "Basic types" #[]
end GroveStdlib.Std.CoreTypesAndOperations

View File

@@ -0,0 +1,110 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
import Grove.Framework
open Grove.Framework Widget
namespace GroveStdlib.Std.CoreTypesAndOperations
namespace Containers
namespace SequentialContainers
end SequentialContainers
def sequentialContainers : Node :=
.section "sequential-containers" "Sequential containers" #[]
namespace AssociativeContainers
def associativeContainers : List Lean.Name :=
[`Std.DHashMap, `Std.DHashMap.Raw, `Std.ExtDHashMap, `Std.DTreeMap, `Std.DTreeMap.Raw, `Std.ExtDTreeMap, `Std.HashMap,
`Std.HashMap.Raw, `Std.ExtHashMap, `Std.TreeMap, `Std.TreeMap.Raw, `Std.ExtTreeMap, `Std.HashSet, `Std.HashSet.Raw, `Std.ExtHashSet,
`Std.TreeSet, `Std.TreeSet.Raw, `Std.ExtTreeSet]
def associativeQueryOperations : AssociationTable .subexpression associativeContainers where
id := "associative-query-operations"
title := "Associative query operations"
description := "Operations that take as input an associative container and return a 'single' piece of information (e.g., `GetElem` or `isEmpty`, but not `toList`)."
dataSources n :=
(DataSource.definitionsInNamespace n)
|>.map Subexpression.declaration
|>.or (DataSource.getElem n)
def associativeCreationOperations : AssociationTable .subexpression associativeContainers where
id := "associative-creation-operations"
title := "Associative creation operations"
description := "Operations that create a new associative container"
dataSources n :=
(DataSource.definitionsInNamespace n)
|>.map Subexpression.declaration
|>.or (DataSource.emptyCollection n)
def associativeModificationOperations : AssociationTable .subexpression associativeContainers where
id := "associative-modification-operations"
title := "Associative modification operations"
description := "Operations that both accept and return an associative container"
dataSources n :=
(DataSource.definitionsInNamespace n)
|>.map Subexpression.declaration
def associativeCreateThenQuery : Table .subexpression .subexpression .declaration associativeContainers where
id := "associative-create-then-query"
title := "Associative create then query"
description := "Lemmas that say what happens when creating a new associative container and then immediately querying from it"
rowsFrom := .table associativeCreationOperations
columnsFrom := .table associativeQueryOperations
cellData := .classic _ { relevantNamespaces := associativeContainers }
def allOperationsCovered : Assertion where
widgetId := "associative-all-operations-covered"
title := "All operations on associative containers covered"
description := "All operations on an associative container should appear in at least one of the tables"
check := do
let allValuesArray : Array String #[associativeQueryOperations, associativeCreationOperations, associativeModificationOperations].flatMapM valuesInAssociationTable
let allValues : Std.HashSet String := Std.HashSet.ofArray allValuesArray
let env Lean.getEnv
let mut numBad := 0
for (n, _) in env.constants do
if associativeContainers.any (fun namesp => namesp.isPrefixOf n) then
if !n.toString allValues then
numBad := numBad + 1
return #[{
assertionId := "all-covered"
description := "All operations should be covered"
passed := numBad == 0
message := if numBad = 0 then "All operations were covered" else s!"There were {numBad} operations that were not covered."
}]
end AssociativeContainers
open AssociativeContainers in
def associativeContainers : Node :=
.section "associative-containers" "Associative containers" #[
.associationTable associativeQueryOperations,
.associationTable associativeCreationOperations,
.associationTable associativeModificationOperations,
.table associativeCreateThenQuery,
.assertion allOperationsCovered
]
namespace PersistentDataStructures
end PersistentDataStructures
def persistentDataStructures : Node :=
.section "persistent-data-structures" "Persistent data structures" #[]
end Containers
def containers : Node :=
.section "containers" "Containers" #[
Containers.sequentialContainers,
Containers.associativeContainers,
Containers.persistentDataStructures
]
end GroveStdlib.Std.CoreTypesAndOperations

View File

@@ -0,0 +1,19 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
import Grove.Framework
open Grove.Framework Widget
namespace GroveStdlib.Std.CoreTypesAndOperations
namespace Numbers
end Numbers
def numbers : Node :=
.section "numbers" "Numbers" #[]
end GroveStdlib.Std.CoreTypesAndOperations

View File

@@ -0,0 +1,19 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
import Grove.Framework
open Grove.Framework Widget
namespace GroveStdlib.Std.CoreTypesAndOperations
namespace StringsAndFormatting
end StringsAndFormatting
def stringsAndFormatting : Node :=
.section "strings-and-formatting" "Strings and formatting" #[]
end GroveStdlib.Std.CoreTypesAndOperations

View File

@@ -0,0 +1,26 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
import Grove.Framework
import GroveStdlib.Std.LanguageConstructs.ComparisonOrderingHashing
import GroveStdlib.Std.LanguageConstructs.Monads
import GroveStdlib.Std.LanguageConstructs.RangesAndIterators
open Grove.Framework Widget
namespace GroveStdlib.Std
namespace LanguageConstructs
end LanguageConstructs
def languageConstructs : Node :=
.section "language-constructs" "Language constructs" #[
LanguageConstructs.comparisonOrderingHashing,
LanguageConstructs.monads,
LanguageConstructs.rangesAndIterators
]
end GroveStdlib.Std

View File

@@ -0,0 +1,19 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
import Grove.Framework
open Grove.Framework Widget
namespace GroveStdlib.Std.LanguageConstructs
namespace ComparisonOrderingHashing
end ComparisonOrderingHashing
def comparisonOrderingHashing : Node :=
.section "comparison-ordering-hashing" "Comparison, ordering, hashing" #[]
end GroveStdlib.Std.LanguageConstructs

View File

@@ -0,0 +1,19 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
import Grove.Framework
open Grove.Framework Widget
namespace GroveStdlib.Std.LanguageConstructs
namespace Monads
end Monads
def monads : Node :=
.section "monads" "Monads" #[]
end GroveStdlib.Std.LanguageConstructs

View File

@@ -0,0 +1,19 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
import Grove.Framework
open Grove.Framework Widget
namespace GroveStdlib.Std.LanguageConstructs
namespace RangesAndIterators
end RangesAndIterators
def rangesAndIterators : Node :=
.section "ranges-and-iterators" "Ranges and iterators" #[]
end GroveStdlib.Std.LanguageConstructs

View File

@@ -0,0 +1,24 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
import Grove.Framework
import GroveStdlib.Std.Libraries.DateAndTime
import GroveStdlib.Std.Libraries.RandomNumbers
open Grove.Framework Widget
namespace GroveStdlib.Std
namespace Libraries
end Libraries
def libraries : Node :=
.section "libraries" "Libraries" #[
Libraries.dateAndTime,
Libraries.randomNumbers
]
end GroveStdlib.Std

View File

@@ -0,0 +1,19 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
import Grove.Framework
open Grove.Framework Widget
namespace GroveStdlib.Std.Libraries
namespace DateAndTime
end DateAndTime
def dateAndTime : Node :=
.section "date-and-time" "Date and time" #[]
end GroveStdlib.Std.Libraries

View File

@@ -0,0 +1,19 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
import Grove.Framework
open Grove.Framework Widget
namespace GroveStdlib.Std.Libraries
namespace RandomNumbers
end RandomNumbers
def randomNumbers : Node :=
.section "random-numbers" "Random numbers" #[]
end GroveStdlib.Std.Libraries

View File

@@ -0,0 +1,30 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
import Grove.Framework
import GroveStdlib.Std.OperatingSystemAbstractions.AsynchronousIO
import GroveStdlib.Std.OperatingSystemAbstractions.BasicIO
import GroveStdlib.Std.OperatingSystemAbstractions.ConcurrencyAndParallelism
import GroveStdlib.Std.OperatingSystemAbstractions.EnvironmentFileSystemProcesses
import GroveStdlib.Std.OperatingSystemAbstractions.Locales
open Grove.Framework Widget
namespace GroveStdlib.Std
namespace OperatingSystemAbstractions
end OperatingSystemAbstractions
def operatingSystemAbstractions : Node :=
.section "operating-system-abstractions" "Operating system abstractions" #[
OperatingSystemAbstractions.asynchronousIO,
OperatingSystemAbstractions.basicIO,
OperatingSystemAbstractions.concurrencyAndParallelism,
OperatingSystemAbstractions.environmentFileSystemProcesses,
OperatingSystemAbstractions.locales
]
end GroveStdlib.Std

View File

@@ -0,0 +1,19 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
import Grove.Framework
open Grove.Framework Widget
namespace GroveStdlib.Std.OperatingSystemAbstractions
namespace AsynchronousIO
end AsynchronousIO
def asynchronousIO : Node :=
.section "asynchronous-io" "Asynchronous I/O" #[]
end GroveStdlib.Std.OperatingSystemAbstractions

View File

@@ -0,0 +1,19 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
import Grove.Framework
open Grove.Framework Widget
namespace GroveStdlib.Std.OperatingSystemAbstractions
namespace BasicIO
end BasicIO
def basicIO : Node :=
.section "basic-io" "Basic I/O" #[]
end GroveStdlib.Std.OperatingSystemAbstractions

View File

@@ -0,0 +1,19 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
import Grove.Framework
open Grove.Framework Widget
namespace GroveStdlib.Std.OperatingSystemAbstractions
namespace ConcurrencyAndParallelism
end ConcurrencyAndParallelism
def concurrencyAndParallelism : Node :=
.section "concurrency-and-parallelism" "Concurrency and parallelism" #[]
end GroveStdlib.Std.OperatingSystemAbstractions

View File

@@ -0,0 +1,19 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
import Grove.Framework
open Grove.Framework Widget
namespace GroveStdlib.Std.OperatingSystemAbstractions
namespace EnvironmentFileSystemProcesses
end EnvironmentFileSystemProcesses
def environmentFileSystemProcesses : Node :=
.section "environment-filesystem-processes" "Environment, file system, processes" #[]
end GroveStdlib.Std.OperatingSystemAbstractions

View File

@@ -0,0 +1,19 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
import Grove.Framework
open Grove.Framework Widget
namespace GroveStdlib.Std.OperatingSystemAbstractions
namespace Locales
end Locales
def locales : Node :=
.section "locales" "Locales" #[]
end GroveStdlib.Std.OperatingSystemAbstractions

18
doc/std/grove/Main.lean Normal file
View File

@@ -0,0 +1,18 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
import GroveStdlib.Std
import GroveStdlib.Generated
def config : Grove.Framework.Project.Configuration where
projectNamespace := `GroveStdlib
def project : Grove.Framework.Project where
config := config
rootNode := GroveStdlib.std
restoreState := GroveStdlib.Generated.restoreState
def main (args : List String) : IO UInt32 :=
Grove.Framework.main project #[`Init, `Std, `Lean] args

3
doc/std/grove/README.md Normal file
View File

@@ -0,0 +1,3 @@
# Standard library QA
This directory contains the [Grove](github.com/TwoFX/grove) data files for the standard library.

12
doc/std/grove/grove-local.sh Executable file
View File

@@ -0,0 +1,12 @@
#!/bin/sh
lake exe grove-stdlib --full metadata.json
cd .lake/packages/grove/frontend
npm install
cp ../../../../metadata.json public/metadata.json
if [ -f "../../../../invalidated.json" ]; then
cp ../../../../invalidated.json public/invalidated.json
GROVE_DATA_LOCATION=public/metadata.json GROVE_UPSTREAM_INVALIDATED_FACTS_LOCATION=public/invalidated.json npm run dev
else
GROVE_DATA_LOCATION=public/metadata.json npm run dev
fi

View File

@@ -0,0 +1,25 @@
{"version": "1.1.0",
"packagesDir": ".lake/packages",
"packages":
[{"url": "https://github.com/TwoFx/grove.git",
"type": "git",
"subDir": "backend",
"scope": "",
"rev": "3e8aabdea58c11813c5d3b7eeb187ded44ee9a34",
"name": "grove",
"manifestFile": "lake-manifest.json",
"inputRev": "master",
"inherited": false,
"configFile": "lakefile.toml"},
{"url": "https://github.com/leanprover/lean4-cli",
"type": "git",
"subDir": null,
"scope": "leanprover",
"rev": "1604206fcd0462da9a241beeac0e2df471647435",
"name": "Cli",
"manifestFile": "lake-manifest.json",
"inputRev": "main",
"inherited": true,
"configFile": "lakefile.toml"}],
"name": "grovestdlib",
"lakeDir": ".lake"}

View File

@@ -0,0 +1,18 @@
name = "grovestdlib"
version = "0.1.0"
defaultTargets = ["grove-stdlib"]
[[require]]
name = "grove"
git = "https://github.com/TwoFx/grove.git"
rev = "master"
subDir = "backend"
[[lean_lib]]
name = "GroveStdlib"
root = "GroveStdlib"
[[lean_exe]]
name = "grove-stdlib"
supportInterpreter = true
root = "Main"

View File

@@ -0,0 +1 @@
lean4

View File

@@ -0,0 +1,3 @@
#!/bin/sh
lake exe grove-stdlib --invalidated invalidated.json

View File

@@ -1,9 +1,16 @@
#!/usr/bin/env bash
set -euo pipefail
cmake --preset release -DUSE_LAKE=ON 1>&2
# We benchmark against stage 2 to test new optimizations.
timeout -s KILL 1h time bash -c 'mkdir -p build/release; cd build/release; cmake ../.. && make -j$(nproc) stage2' 1>&2
timeout -s KILL 1h time make -C build/release -j$(nproc) stage2 1>&2
export PATH=$PWD/build/release/stage2/bin:$PATH
# The extra opts used to be passed to the Makefile during benchmarking only but with Lake it is
# easier to configure them statically.
cmake -B build/release/stage2 -S src -DLEAN_EXTRA_LAKEFILE_TOML='weakLeanArgs=["-Dprofiler=true", "-Dprofiler.threshold=9999999", "--stats"]' 1>&2
cd tests/bench
timeout -s KILL 1h time temci exec --config speedcenter.yaml --in speedcenter.exec.velcom.yaml 1>&2
temci report run_output.yaml --reporter codespeed2

View File

@@ -5,8 +5,11 @@ set -euo pipefail
[ $# -eq 1 ] || (echo "usage: $0 <lean4 PR #>"; exit 1)
echo "Warning: the speedcenter is probably not listening on mathlib4-nightly-testing yet."
echo "If you're using this script, please contact @kim-em or @Kha to get this set up, and then remove this notice."
LEAN_PR=$1
PR_RESPONSE=$(gh api repos/leanprover-community/mathlib4/pulls -X POST -f head=lean-pr-testing-$LEAN_PR -f base=nightly-testing -f title="leanprover/lean4#$LEAN_PR benchmarking" -f draft=true -f body="ignore me")
PR_RESPONSE=$(gh api repos/leanprover-community/mathlib4-nightly-testing/pulls -X POST -f head=lean-pr-testing-$LEAN_PR -f base=nightly-testing -f title="leanprover/lean4#$LEAN_PR benchmarking" -f draft=true -f body="ignore me")
PR_NUMBER=$(echo "$PR_RESPONSE" | jq '.number')
echo "opened https://github.com/leanprover-community/mathlib4/pull/$PR_NUMBER"
gh api repos/leanprover-community/mathlib4/issues/$PR_NUMBER/comments -X POST -f body="!bench" > /dev/null
echo "opened https://github.com/leanprover-community/mathlib4-nightly-testing/pull/$PR_NUMBER"
gh api repos/leanprover-community/mathlib4-nightly-testing/issues/$PR_NUMBER/comments -X POST -f body="!bench" > /dev/null

View File

@@ -50,5 +50,4 @@ echo -n " -DLEANC_INTERNAL_LINKER_FLAGS='--sysroot ROOT -L ROOT/lib -Wl,-Bstatic
# when not using the above flags, link GMP dynamically/as usual. Always link ICU dynamically.
echo -n " -DLEAN_EXTRA_LINKER_FLAGS='-lgmp $(pkg-config --libs libuv) -lucrtbase'"
# do not set `LEAN_CC` for tests
echo -n " -DAUTO_THREAD_FINALIZATION=OFF -DSTAGE0_AUTO_THREAD_FINALIZATION=OFF"
echo -n " -DLEAN_TEST_VARS=''"

View File

@@ -3,6 +3,32 @@ import sys
import subprocess
import requests
def check_gh_auth():
"""Check if GitHub CLI is properly authenticated."""
try:
result = subprocess.run(["gh", "auth", "status"], capture_output=True, text=True)
if result.returncode != 0:
return False, result.stderr
return True, None
except FileNotFoundError:
return False, "GitHub CLI (gh) is not installed. Please install it first."
except Exception as e:
return False, f"Error checking authentication: {e}"
def handle_gh_error(error_output):
"""Handle GitHub CLI errors and provide helpful messages."""
if "Not Found (HTTP 404)" in error_output:
return "Repository not found or access denied. Please check:\n" \
"1. The repository name is correct\n" \
"2. You have access to the repository\n" \
"3. Your GitHub CLI authentication is valid"
elif "Bad credentials" in error_output or "invalid" in error_output.lower():
return "Authentication failed. Please run 'gh auth login' to re-authenticate."
elif "rate limit" in error_output.lower():
return "GitHub API rate limit exceeded. Please try again later."
else:
return f"GitHub API error: {error_output}"
def main():
if len(sys.argv) != 4:
print("Usage: ./push_repo_release_tag.py <repo> <branch> <version_tag>")
@@ -14,6 +40,13 @@ def main():
print(f"Error: Branch '{branch}' is not 'master' or 'main'.")
sys.exit(1)
# Check GitHub CLI authentication first
auth_ok, auth_error = check_gh_auth()
if not auth_ok:
print(f"Authentication error: {auth_error}")
print("\nTo fix this, run: gh auth login")
sys.exit(1)
# Get the `lean-toolchain` file content
lean_toolchain_url = f"https://raw.githubusercontent.com/{repo}/{branch}/lean-toolchain"
try:
@@ -43,12 +76,23 @@ def main():
for tag in existing_tags:
print(tag.replace("refs/tags/", ""))
sys.exit(1)
elif list_tags_output.returncode != 0:
# Handle API errors when listing tags
error_msg = handle_gh_error(list_tags_output.stderr)
print(f"Error checking existing tags: {error_msg}")
sys.exit(1)
# Get the SHA of the branch
get_sha_cmd = [
"gh", "api", f"repos/{repo}/git/ref/heads/{branch}", "--jq", ".object.sha"
]
sha_result = subprocess.run(get_sha_cmd, capture_output=True, text=True, check=True)
sha_result = subprocess.run(get_sha_cmd, capture_output=True, text=True)
if sha_result.returncode != 0:
error_msg = handle_gh_error(sha_result.stderr)
print(f"Error getting branch SHA: {error_msg}")
sys.exit(1)
sha = sha_result.stdout.strip()
# Create the tag
@@ -58,11 +102,20 @@ def main():
"-F", f"ref=refs/tags/{version_tag}",
"-F", f"sha={sha}"
]
subprocess.run(create_tag_cmd, capture_output=True, text=True, check=True)
create_result = subprocess.run(create_tag_cmd, capture_output=True, text=True)
if create_result.returncode != 0:
error_msg = handle_gh_error(create_result.stderr)
print(f"Error creating tag: {error_msg}")
sys.exit(1)
print(f"Successfully created and pushed tag '{version_tag}' to {repo}.")
except subprocess.CalledProcessError as e:
print(f"Error while creating/pushing tag: {e.stderr.strip() if e.stderr else e}")
error_msg = handle_gh_error(e.stderr.strip() if e.stderr else str(e))
print(f"Error while creating/pushing tag: {error_msg}")
sys.exit(1)
except Exception as e:
print(f"Unexpected error: {e}")
sys.exit(1)
if __name__ == "__main__":

View File

@@ -231,6 +231,43 @@ def get_next_version(version):
# Next version is always .0
return f"v{major}.{minor + 1}.0"
def get_latest_nightly_tag(github_token):
"""Get the most recent nightly tag from leanprover/lean4-nightly."""
api_url = "https://api.github.com/repos/leanprover/lean4-nightly/tags"
headers = {'Authorization': f'token {github_token}'} if github_token else {}
response = requests.get(api_url, headers=headers)
if response.status_code != 200:
return None
tags = response.json()
if not tags:
return None
# Return the most recent tag name
return tags[0]['name']
def update_lean_toolchain_in_branch(org_repo, branch, toolchain_content, github_token):
"""Update the lean-toolchain file in a specific branch."""
api_url = f"https://api.github.com/repos/{org_repo}/contents/lean-toolchain"
headers = {'Authorization': f'token {github_token}'} if github_token else {}
# First get the current file to get its SHA
response = requests.get(f"{api_url}?ref={branch}", headers=headers)
if response.status_code != 200:
return False
current_file = response.json()
file_sha = current_file['sha']
# Update the file
update_data = {
"message": f"chore: update lean-toolchain to {toolchain_content}",
"content": base64.b64encode(toolchain_content.encode('utf-8')).decode('utf-8'),
"sha": file_sha,
"branch": branch
}
response = requests.put(api_url, json=update_data, headers=headers)
return response.status_code in [200, 201]
def check_bump_branch_toolchain(url, bump_branch, github_token):
"""Check if the lean-toolchain file in bump branch starts with either 'leanprover/lean4:nightly-' or the next version."""
content = get_branch_content(url, bump_branch, "lean-toolchain", github_token)
@@ -262,6 +299,61 @@ def pr_exists_with_title(repo_url, title, github_token):
return pr['number'], pr['html_url']
return None
def check_proofwidgets4_release(repo_url, target_toolchain, github_token):
"""Check if ProofWidgets4 has a release tag that uses the target toolchain."""
api_base = repo_url.replace("https://github.com/", "https://api.github.com/repos/")
headers = {'Authorization': f'token {github_token}'} if github_token else {}
# Get all tags matching v0.0.* pattern
response = requests.get(f"{api_base}/git/matching-refs/tags/v0.0.", headers=headers)
if response.status_code != 200:
print(f" ❌ Could not fetch ProofWidgets4 tags")
return False
tags = response.json()
if not tags:
print(f" ❌ No v0.0.* tags found for ProofWidgets4")
return False
# Extract tag names and sort by version number (descending)
tag_names = []
for tag in tags:
ref = tag['ref']
if ref.startswith('refs/tags/v0.0.'):
tag_name = ref.replace('refs/tags/', '')
try:
# Extract the number after v0.0.
version_num = int(tag_name.split('.')[-1])
tag_names.append((version_num, tag_name))
except (ValueError, IndexError):
continue
if not tag_names:
print(f" ❌ No valid v0.0.* tags found for ProofWidgets4")
return False
# Sort by version number (descending) and take the most recent 10
tag_names.sort(reverse=True)
recent_tags = tag_names[:10]
# Check each recent tag to see if it uses the target toolchain
for version_num, tag_name in recent_tags:
toolchain_content = get_branch_content(repo_url, tag_name, "lean-toolchain", github_token)
if toolchain_content is None:
continue
if is_version_gte(toolchain_content.strip(), target_toolchain):
print(f" ✅ Found release {tag_name} using compatible toolchain (>= {target_toolchain})")
return True
# If we get here, no recent release uses the target toolchain
# Find the highest version number to suggest the next one
highest_version = max(version_num for version_num, _ in recent_tags)
next_version = highest_version + 1
print(f" ❌ No recent ProofWidgets4 release uses toolchain >= {target_toolchain}")
print(f" You will need to create and push a tag v0.0.{next_version}")
return False
def main():
parser = argparse.ArgumentParser(description="Check release status of Lean4 repositories")
parser.add_argument("toolchain", help="The toolchain version to check (e.g., v4.6.0)")
@@ -386,6 +478,12 @@ def main():
continue
print(f" ✅ On compatible toolchain (>= {toolchain})")
# Special handling for ProofWidgets4
if name == "ProofWidgets4":
if not check_proofwidgets4_release(url, toolchain, github_token):
repo_status[name] = False
continue
if check_tag:
tag_exists_initially = tag_exists(url, toolchain, github_token)
if not tag_exists_initially:
@@ -394,7 +492,7 @@ def main():
repo_status[name] = False
continue
else:
print(f" Tag {toolchain} does not exist. Running `script/push_repo_release_tag.py {org_repo} {branch} {toolchain}`...")
print(f" Tag {toolchain} does not exist. Running `script/push_repo_release_tag.py {org_repo} {branch} {toolchain}`...")
# Run the script to create the tag
subprocess.run(["script/push_repo_release_tag.py", org_repo, branch, toolchain])
@@ -417,7 +515,7 @@ def main():
repo_status[name] = False
continue
else:
print(f" Tag {toolchain} is not merged into stable. Running `script/merge_remote.py {org_repo} stable {toolchain}`...")
print(f" Tag {toolchain} is not merged into stable. Running `script/merge_remote.py {org_repo} stable {toolchain}`...")
# Run the script to merge the tag
subprocess.run(["script/merge_remote.py", org_repo, "stable", toolchain])
@@ -434,19 +532,49 @@ def main():
if check_bump:
next_version = get_next_version(toolchain)
bump_branch = f"bump/{next_version}"
if not branch_exists(url, bump_branch, github_token):
# For mathlib4, use the nightly-testing fork for bump branches
bump_org_repo = org_repo
bump_url = url
if name == "mathlib4":
bump_org_repo = "leanprover-community/mathlib4-nightly-testing"
bump_url = "https://github.com/leanprover-community/mathlib4-nightly-testing"
branch_created = False
if not branch_exists(bump_url, bump_branch, github_token):
if args.dry_run:
print(f" ❌ Bump branch {bump_branch} does not exist. Run `gh api -X POST /repos/{org_repo}/git/refs -f ref=refs/heads/{bump_branch} -f sha=$(gh api /repos/{org_repo}/git/refs/heads/{branch} --jq .object.sha)` to create it.")
latest_nightly = get_latest_nightly_tag(github_token)
nightly_note = f" (will set lean-toolchain to {latest_nightly})" if name in ["batteries", "mathlib4"] and latest_nightly else ""
print(f" ❌ Bump branch {bump_branch} does not exist. Run `gh api -X POST /repos/{bump_org_repo}/git/refs -f ref=refs/heads/{bump_branch} -f sha=$(gh api /repos/{org_repo}/git/refs/heads/{branch} --jq .object.sha)` to create it{nightly_note}.")
repo_status[name] = False
continue
print(f" Bump branch {bump_branch} does not exist. Creating it...")
result = run_command(f"gh api -X POST /repos/{org_repo}/git/refs -f ref=refs/heads/{bump_branch} -f sha=$(gh api /repos/{org_repo}/git/refs/heads/{branch} --jq .object.sha)", check=False)
print(f" Bump branch {bump_branch} does not exist. Creating it...")
result = run_command(f"gh api -X POST /repos/{bump_org_repo}/git/refs -f ref=refs/heads/{bump_branch} -f sha=$(gh api /repos/{org_repo}/git/refs/heads/{branch} --jq .object.sha)", check=False)
if result.returncode != 0:
print(f" ❌ Failed to create bump branch {bump_branch}")
repo_status[name] = False
continue
branch_created = True
print(f" ✅ Bump branch {bump_branch} exists")
if not check_bump_branch_toolchain(url, bump_branch, github_token):
# For batteries and mathlib4, update the lean-toolchain to the latest nightly
if branch_created and name in ["batteries", "mathlib4"]:
latest_nightly = get_latest_nightly_tag(github_token)
if latest_nightly:
nightly_toolchain = f"leanprover/lean4:{latest_nightly}"
print(f" ⮕ Updating lean-toolchain to {nightly_toolchain}...")
if update_lean_toolchain_in_branch(bump_org_repo, bump_branch, nightly_toolchain, github_token):
print(f" ✅ Updated lean-toolchain to {nightly_toolchain}")
else:
print(f" ❌ Failed to update lean-toolchain to {nightly_toolchain}")
repo_status[name] = False
continue
else:
print(f" ❌ Could not fetch latest nightly tag")
repo_status[name] = False
continue
if not check_bump_branch_toolchain(bump_url, bump_branch, github_token):
repo_status[name] = False
continue

View File

@@ -1,10 +1,10 @@
#!/usr/bin/env python3
"""
Generate release steps script for Lean4 repositories.
Execute release steps for Lean4 repositories.
This script helps automate the release process for Lean4 and its dependent repositories
by generating step-by-step instructions for updating toolchains, creating tags,
by actually executing the step-by-step instructions for updating toolchains, creating tags,
and managing branches.
Usage:
@@ -12,11 +12,11 @@ Usage:
Arguments:
version: The version to set in the lean-toolchain file (e.g., v4.6.0)
repo: A substring of the repository name as specified in release_repos.yml
repo: The repository name as specified in release_repos.yml
Example:
python3 release_steps.py v4.6.0 mathlib
python3 release_steps.py v4.6.0 batt
python3 release_steps.py v4.6.0 mathlib4
python3 release_steps.py v4.6.0 batteries
The script reads repository configurations from release_repos.yml in the same directory.
Each repository may have specific requirements for:
@@ -32,23 +32,124 @@ import yaml
import os
import sys
import re
import subprocess
import shutil
import json
from pathlib import Path
# Color functions for terminal output
def blue(text):
"""Blue text for 'I'm doing something' messages."""
return f"\033[94m{text}\033[0m"
def green(text):
"""Green text for 'successful step' messages."""
return f"\033[92m{text}\033[0m"
def red(text):
"""Red text for 'this looks bad' messages."""
return f"\033[91m{text}\033[0m"
def yellow(text):
"""Yellow text for warnings."""
return f"\033[93m{text}\033[0m"
def run_command(cmd, cwd=None, check=True, stream_output=False):
"""Run a shell command and return the result."""
print(blue(f"Running: {cmd}"))
try:
if stream_output:
# Stream output in real-time for long-running commands
result = subprocess.run(cmd, shell=True, cwd=cwd, check=check, text=True)
return result
else:
# Capture output for commands where we need to process the result
result = subprocess.run(cmd, shell=True, cwd=cwd, check=check,
capture_output=True, text=True)
if result.stdout:
# Command output in plain white (default terminal color)
print(result.stdout)
return result
except subprocess.CalledProcessError as e:
print(red(f"Error running command: {cmd}"))
print(red(f"Exit code: {e.returncode}"))
if not stream_output:
print(f"Stdout: {e.stdout}")
print(f"Stderr: {e.stderr}")
raise
def load_repos_config(file_path):
with open(file_path, "r") as f:
return yaml.safe_load(f)["repositories"]
def find_repo(repo_substring, config):
pattern = re.compile(re.escape(repo_substring), re.IGNORECASE)
matching_repos = [r for r in config if pattern.search(r["name"])]
def find_repo(repo_name, config):
matching_repos = [r for r in config if r["name"] == repo_name]
if not matching_repos:
print(f"Error: No repository matching '{repo_substring}' found in configuration.")
sys.exit(1)
if len(matching_repos) > 1:
print(f"Error: Multiple repositories matching '{repo_substring}' found in configuration: {', '.join(r['name'] for r in matching_repos)}")
print(red(f"Error: No repository named '{repo_name}' found in configuration."))
available_repos = [r["name"] for r in config]
print(yellow(f"Available repositories: {', '.join(available_repos)}"))
sys.exit(1)
return matching_repos[0]
def generate_script(repo, version, config):
def setup_downstream_releases_dir():
"""Create the downstream_releases directory if it doesn't exist."""
downstream_dir = Path("downstream_releases")
if not downstream_dir.exists():
print(blue(f"Creating {downstream_dir} directory..."))
downstream_dir.mkdir()
print(green(f"Created {downstream_dir} directory"))
return downstream_dir
def clone_or_update_repo(repo_url, repo_dir, downstream_dir):
"""Clone the repository if it doesn't exist, or update it if it does."""
repo_path = downstream_dir / repo_dir
if repo_path.exists():
print(blue(f"Repository {repo_dir} already exists, updating..."))
run_command("git fetch", cwd=repo_path)
print(green(f"Updated repository {repo_dir}"))
else:
print(blue(f"Cloning {repo_url} to {repo_path}..."))
run_command(f"git clone {repo_url}", cwd=downstream_dir)
print(green(f"Cloned repository {repo_dir}"))
return repo_path
def get_remotes_for_repo(repo_name):
"""Get the appropriate remotes for bump and nightly-testing branches based on repository."""
if repo_name == "mathlib4":
return "nightly-testing", "nightly-testing"
else:
return "origin", "origin"
def check_and_abort_merge(repo_path):
"""Check if repository is in the middle of a merge and abort it if so."""
merge_head_file = repo_path / ".git" / "MERGE_HEAD"
if merge_head_file.exists():
print(yellow(f"Repository {repo_path.name} is in the middle of a merge. Aborting merge..."))
run_command("git merge --abort", cwd=repo_path)
print(green("Merge aborted successfully"))
return True
# Also check git status for other merge-related states
try:
result = run_command("git status --porcelain=v1", cwd=repo_path, check=False)
if result.returncode == 0:
# Check for unmerged paths (indicated by 'UU', 'AA', etc. in git status)
for line in result.stdout.splitlines():
if len(line) >= 2 and line[:2] in ['UU', 'AA', 'DD', 'AU', 'UA', 'DU', 'UD']:
print(yellow(f"Repository {repo_path.name} has unmerged paths. Aborting merge..."))
run_command("git merge --abort", cwd=repo_path)
print(green("Merge aborted successfully"))
return True
except subprocess.CalledProcessError:
# If git status fails, we'll let the main process handle it
pass
return False
def execute_release_steps(repo, version, config):
repo_config = find_repo(repo, config)
repo_name = repo_config['name']
repo_url = repo_config['url']
@@ -59,92 +160,481 @@ def generate_script(repo, version, config):
requires_tagging = repo_config.get("toolchain-tag", True)
has_stable_branch = repo_config.get("stable-branch", True)
script_lines = [
f"cd {repo_dir}",
"git fetch",
f"git checkout {default_branch} && git pull",
f"git checkout -b bump_to_{version}",
f"echo leanprover/lean4:{version} > lean-toolchain",
]
# Setup downstream releases directory
downstream_dir = setup_downstream_releases_dir()
# Clone or update the repository
repo_path = clone_or_update_repo(repo_url, repo_dir, downstream_dir)
# Special remote setup for mathlib4
if repo_name == "mathlib4":
print(blue("Setting up special remotes for mathlib4..."))
try:
# Check if nightly-testing remote already exists
result = run_command("git remote get-url nightly-testing", cwd=repo_path, check=False)
if result.returncode != 0:
# Add the nightly-testing remote
run_command("git remote add nightly-testing https://github.com/leanprover-community/mathlib4-nightly-testing.git", cwd=repo_path)
print(green("Added nightly-testing remote"))
else:
print(green("nightly-testing remote already exists"))
# Fetch from the nightly-testing remote
run_command("git fetch nightly-testing", cwd=repo_path)
print(green("Fetched from nightly-testing remote"))
except subprocess.CalledProcessError as e:
print(red(f"Error setting up mathlib4 remotes: {e}"))
print(yellow("Continuing with default remote setup..."))
print(blue(f"\n=== Executing release steps for {repo_name} ==="))
# Check if repository is in the middle of a merge and abort it if necessary
check_and_abort_merge(repo_path)
# Execute the release steps
run_command(f"git checkout {default_branch} && git pull", cwd=repo_path)
# Special rc1 safety check for batteries and mathlib4 (before creating any branches)
if repo_name in ["batteries", "mathlib4"] and version.endswith('-rc1'):
print(blue("This repo has nightly-testing infrastructure"))
print(blue(f"Checking if nightly-testing can be safely merged into bump/{version.split('-rc')[0]}..."))
# Get the base version (e.g., v4.6.0 from v4.6.0-rc1)
base_version = version.split('-rc')[0]
bump_branch = f"bump/{base_version}"
# Determine which remote to use for bump and nightly-testing branches
bump_remote, nightly_remote = get_remotes_for_repo(repo_name)
try:
# Fetch latest changes from the appropriate remote
run_command(f"git fetch {bump_remote}", cwd=repo_path)
# Check if the bump branch exists
result = run_command(f"git show-ref --verify --quiet refs/remotes/{bump_remote}/{bump_branch}", cwd=repo_path, check=False)
if result.returncode != 0:
print(red(f"Bump branch {bump_remote}/{bump_branch} does not exist. Cannot perform safety check."))
print(yellow("Please ensure the bump branch exists before proceeding."))
return
# Create a temporary branch for testing the merge
temp_branch = f"temp-merge-test-{base_version}"
# Clean up any existing temp branch from previous runs
result = run_command(f"git show-ref --verify --quiet refs/heads/{temp_branch}", cwd=repo_path, check=False)
if result.returncode == 0:
print(blue(f"Cleaning up existing temp branch {temp_branch}..."))
# Make sure we're not on the temp branch before deleting it
run_command(f"git checkout {default_branch}", cwd=repo_path)
run_command(f"git branch -D {temp_branch}", cwd=repo_path)
print(green(f"Deleted existing temp branch {temp_branch}"))
run_command(f"git checkout -b {temp_branch} {bump_remote}/{bump_branch}", cwd=repo_path)
# Try to merge nightly-testing
try:
run_command(f"git merge {nightly_remote}/nightly-testing", cwd=repo_path)
# Check what files have changed compared to the bump branch
changed_files = run_command(f"git diff --name-only {bump_remote}/{bump_branch}..HEAD", cwd=repo_path)
# Filter out allowed changes
allowed_patterns = ['lean-toolchain', 'lake-manifest.json']
problematic_files = []
for file in changed_files.stdout.strip().split('\n'):
if file.strip(): # Skip empty lines
is_allowed = any(pattern in file for pattern in allowed_patterns)
if not is_allowed:
problematic_files.append(file)
# Clean up temporary branch and return to default branch
run_command(f"git checkout {default_branch}", cwd=repo_path)
run_command(f"git branch -D {temp_branch}", cwd=repo_path)
if problematic_files:
print(red("❌ Safety check failed!"))
print(red(f"Merging nightly-testing into {bump_branch} would result in changes to:"))
for file in problematic_files:
print(red(f" - {file}"))
print(yellow("\nYou need to make a PR merging the changes from nightly-testing into the bump branch first."))
print(yellow(f"Create a PR from nightly-testing targeting {bump_branch} to resolve these changes."))
return
else:
print(green("✅ Safety check passed - only lean-toolchain and/or lake-manifest.json would change"))
except subprocess.CalledProcessError:
# Merge failed due to conflicts - check which files are conflicted
print(blue("Merge failed, checking which files are affected..."))
# Get all changed files using git status
status_result = run_command("git status --porcelain", cwd=repo_path)
changed_files = []
for line in status_result.stdout.splitlines():
if line.strip(): # Skip empty lines
# Extract filename (skip the first 3 characters which are status codes)
changed_files.append(line[3:])
# Filter out allowed files
allowed_patterns = ['lean-toolchain', 'lake-manifest.json']
problematic_files = []
for file in changed_files:
is_allowed = any(pattern in file for pattern in allowed_patterns)
if not is_allowed:
problematic_files.append(file)
if problematic_files:
# There are changes in non-allowed files - fail the safety check
# First abort the merge to clean up the conflicted state
run_command("git merge --abort", cwd=repo_path)
run_command(f"git checkout {default_branch}", cwd=repo_path)
run_command(f"git branch -D {temp_branch}", cwd=repo_path)
print(red("❌ Safety check failed!"))
print(red(f"Merging nightly-testing into {bump_branch} would result in changes to:"))
for file in problematic_files:
print(red(f" - {file}"))
print(yellow("\nYou need to make a PR merging the changes from nightly-testing into the bump branch first."))
print(yellow(f"Create a PR from nightly-testing targeting {bump_branch} to resolve these changes."))
return
else:
# Only allowed files are changed - resolve them and continue
print(green(f"✅ Only allowed files changed: {', '.join(changed_files)}"))
print(blue("Resolving conflicts by taking nightly-testing version..."))
# For each changed allowed file, take the nightly-testing version
for file in changed_files:
run_command(f"git checkout --theirs {file}", cwd=repo_path)
# Complete the merge
run_command("git add .", cwd=repo_path)
run_command("git commit --no-edit", cwd=repo_path)
print(green("✅ Safety check passed - changes only in allowed files"))
# Clean up temporary branch and return to default branch
run_command(f"git checkout {default_branch}", cwd=repo_path)
run_command(f"git branch -D {temp_branch}", cwd=repo_path)
except subprocess.CalledProcessError as e:
# Ensure we're back on the default branch even if setup failed
try:
run_command(f"git checkout {default_branch}", cwd=repo_path)
except subprocess.CalledProcessError:
print(red(f"Cannot return to {default_branch} branch. Repository is in an inconsistent state."))
print(red("Please manually check the repository state and fix any issues."))
return
print(red(f"Error during safety check: {e}"))
print(yellow("Skipping safety check and proceeding with normal merge..."))
# Check if the branch already exists
branch_name = f"bump_to_{version}"
try:
# Check if branch exists locally
result = run_command(f"git show-ref --verify --quiet refs/heads/{branch_name}", cwd=repo_path, check=False)
if result.returncode == 0:
print(blue(f"Branch {branch_name} already exists, checking it out..."))
run_command(f"git checkout {branch_name}", cwd=repo_path)
print(green(f"Checked out existing branch {branch_name}"))
else:
print(blue(f"Creating new branch {branch_name}..."))
run_command(f"git checkout -b {branch_name}", cwd=repo_path)
print(green(f"Created new branch {branch_name}"))
except subprocess.CalledProcessError:
print(blue(f"Creating new branch {branch_name}..."))
run_command(f"git checkout -b {branch_name}", cwd=repo_path)
print(green(f"Created new branch {branch_name}"))
# Update lean-toolchain
print(blue("Updating lean-toolchain file..."))
toolchain_file = repo_path / "lean-toolchain"
with open(toolchain_file, "w") as f:
f.write(f"leanprover/lean4:{version}\n")
print(green(f"Updated lean-toolchain to leanprover/lean4:{version}"))
# Special cases for specific repositories
if repo_name == "repl":
script_lines.extend([
"lake update",
"cd test/Mathlib",
f"perl -pi -e 's/rev = \"v\\d+\\.\\d+\\.\\d+(-rc\\d+)?\"/rev = \"{version}\"/g' lakefile.toml",
f"echo leanprover/lean4:{version} > lean-toolchain",
"lake update",
"cd ../..",
"./test.sh"
])
run_command("lake update", cwd=repo_path, stream_output=True)
mathlib_test_dir = repo_path / "test" / "Mathlib"
run_command(f'perl -pi -e \'s/rev = "v\\d+\\.\\d+\\.\\d+(-rc\\d+)?"/rev = "{version}"/g\' lakefile.toml', cwd=mathlib_test_dir)
# Update lean-toolchain in test/Mathlib
print(blue("Updating test/Mathlib/lean-toolchain..."))
mathlib_toolchain = mathlib_test_dir / "lean-toolchain"
with open(mathlib_toolchain, "w") as f:
f.write(f"leanprover/lean4:{version}\n")
print(green(f"Updated test/Mathlib/lean-toolchain to leanprover/lean4:{version}"))
run_command("lake update", cwd=mathlib_test_dir, stream_output=True)
try:
result = run_command("./test.sh", cwd=repo_path, stream_output=True, check=False)
if result.returncode == 0:
print(green("Tests completed successfully"))
else:
print(red("Tests failed, but continuing with PR creation..."))
print(red(f"Test exit code: {result.returncode}"))
except subprocess.CalledProcessError as e:
print(red("Tests failed, but continuing with PR creation..."))
print(red(f"Test error: {e}"))
elif dependencies:
script_lines.append('perl -pi -e \'s/"v4\\.[0-9]+(\\.[0-9]+)?(-rc[0-9]+)?"/"' + version + '"/g\' lakefile.*')
script_lines.append("lake update")
run_command(f'perl -pi -e \'s/"v4\\.[0-9]+(\\.[0-9]+)?(-rc[0-9]+)?"/"' + version + '"/g\' lakefile.*', cwd=repo_path)
run_command("lake update", cwd=repo_path, stream_output=True)
script_lines.append("")
# Commit changes (only if there are changes)
print(blue("Checking for changes to commit..."))
try:
# Check if there are any changes to commit (staged or unstaged)
result = run_command("git status --porcelain", cwd=repo_path, check=False)
if result.stdout.strip(): # There are changes
print(blue("Committing changes..."))
run_command(f'git commit -am "chore: bump toolchain to {version}"', cwd=repo_path)
print(green(f"Committed changes: chore: bump toolchain to {version}"))
else:
print(green("No changes to commit - toolchain already up to date"))
except subprocess.CalledProcessError:
print(yellow("Failed to check for changes, attempting commit anyway..."))
try:
run_command(f'git commit -am "chore: bump toolchain to {version}"', cwd=repo_path)
except subprocess.CalledProcessError as e:
if "nothing to commit" in e.stderr:
print(green("No changes to commit - toolchain already up to date"))
else:
raise
script_lines.extend([
f'git commit -am "chore: bump toolchain to {version}"',
""
])
# Handle special merging cases
if version.endswith('-rc1') and repo_name in ["batteries", "mathlib4"]:
print(blue("This repo uses `bump/v4.X.0` branches for reviewed content from nightly-testing."))
# Determine which remote to use for bump branches
bump_remote, nightly_remote = get_remotes_for_repo(repo_name)
# Fetch latest changes to ensure we have the most up-to-date bump branch
print(blue(f"Fetching latest changes from {bump_remote}..."))
run_command(f"git fetch {bump_remote}", cwd=repo_path)
try:
print(blue(f"Merging {bump_remote}/bump/{version.split('-rc')[0]}..."))
run_command(f"git merge {bump_remote}/bump/{version.split('-rc')[0]}", cwd=repo_path)
print(green("Merge completed successfully"))
except subprocess.CalledProcessError:
# Merge failed due to conflicts - check which files are conflicted
print(blue("Merge conflicts detected, checking which files are affected..."))
# Get conflicted files using git status
status_result = run_command("git status --porcelain", cwd=repo_path)
conflicted_files = []
for line in status_result.stdout.splitlines():
if len(line) >= 2 and line[:2] in ['UU', 'AA', 'DD', 'AU', 'UA', 'DU', 'UD']:
# Extract filename (skip the first 3 characters which are status codes)
conflicted_files.append(line[3:])
# Filter out allowed files
allowed_patterns = ['lean-toolchain', 'lake-manifest.json']
problematic_files = []
for file in conflicted_files:
is_allowed = any(pattern in file for pattern in allowed_patterns)
if not is_allowed:
problematic_files.append(file)
if problematic_files:
# There are conflicts in non-allowed files - fail
print(red("❌ Merge failed!"))
print(red(f"Merging {bump_remote}/bump/{version.split('-rc')[0]} resulted in conflicts in:"))
for file in problematic_files:
print(red(f" - {file}"))
print(red("Please resolve these conflicts manually."))
return
else:
# Only allowed files are conflicted - resolve them automatically
print(green(f"✅ Only allowed files conflicted: {', '.join(conflicted_files)}"))
print(blue("Resolving conflicts automatically..."))
# Overwrite lean-toolchain with our target version
if 'lean-toolchain' in conflicted_files:
print(blue(f"Overwriting lean-toolchain with target version {version}"))
toolchain_file = repo_path / "lean-toolchain"
with open(toolchain_file, "w") as f:
f.write(f"leanprover/lean4:{version}\n")
# For other allowed files, take our version (since we want our changes)
for file in conflicted_files:
if file != 'lean-toolchain':
run_command(f"git checkout --ours {file}", cwd=repo_path)
# Run lake update to rebuild lake-manifest.json
print(blue("Running lake update to rebuild lake-manifest.json..."))
run_command("lake update", cwd=repo_path, stream_output=True)
# Complete the merge
run_command("git add .", cwd=repo_path)
run_command("git commit --no-edit", cwd=repo_path)
print(green("✅ Merge completed successfully with automatic conflict resolution"))
elif version.endswith('-rc1'):
# For all other repos with rc versions, merge nightly-testing
if repo_name in ["verso", "reference-manual"]:
print(yellow("This repo does development on nightly-testing: remember to rebase merge the PR."))
# Fetch latest changes to ensure we have the most up-to-date nightly-testing branch
print(blue("Fetching latest changes from origin..."))
run_command("git fetch origin", cwd=repo_path)
try:
print(blue("Merging origin/nightly-testing..."))
run_command("git merge origin/nightly-testing", cwd=repo_path)
print(green("Merge completed successfully"))
except subprocess.CalledProcessError:
# Merge failed due to conflicts - check which files are conflicted
print(blue("Merge conflicts detected, checking which files are affected..."))
# Get conflicted files using git status
status_result = run_command("git status --porcelain", cwd=repo_path)
conflicted_files = []
for line in status_result.stdout.splitlines():
if len(line) >= 2 and line[:2] in ['UU', 'AA', 'DD', 'AU', 'UA', 'DU', 'UD']:
# Extract filename (skip the first 3 characters which are status codes)
conflicted_files.append(line[3:])
# Filter out allowed files
allowed_patterns = ['lean-toolchain', 'lake-manifest.json']
problematic_files = []
for file in conflicted_files:
is_allowed = any(pattern in file for pattern in allowed_patterns)
if not is_allowed:
problematic_files.append(file)
if problematic_files:
# There are conflicts in non-allowed files - fail
print(red("❌ Merge failed!"))
print(red(f"Merging nightly-testing resulted in conflicts in:"))
for file in problematic_files:
print(red(f" - {file}"))
print(red("Please resolve these conflicts manually."))
return
else:
# Only allowed files are conflicted - resolve them automatically
print(green(f"✅ Only allowed files conflicted: {', '.join(conflicted_files)}"))
print(blue("Resolving conflicts automatically..."))
# For lean-toolchain and lake-manifest.json, keep our versions
for file in conflicted_files:
print(blue(f"Keeping our version of {file}"))
run_command(f"git checkout --ours {file}", cwd=repo_path)
# Complete the merge
run_command("git add .", cwd=repo_path)
run_command("git commit --no-edit", cwd=repo_path)
print(green("✅ Merge completed successfully with automatic conflict resolution"))
if re.search(r'rc\d+$', version) and repo_name in ["batteries", "mathlib4"]:
script_lines.extend([
"echo 'This repo has nightly-testing infrastructure'",
f"git merge origin/bump/{version.split('-rc')[0]}",
"echo 'Please resolve any conflicts.'",
"grep nightly-testing lakefile.* && echo 'Please ensure the lakefile does not include nightly-testing versions.'",
""
])
if re.search(r'rc\d+$', version) and repo_name in ["verso", "reference-manual"]:
script_lines.extend([
"echo 'This repo does development on nightly-testing: remember to rebase merge the PR.'",
f"git merge origin/nightly-testing",
"echo 'Please resolve any conflicts.'",
""
])
if repo_name != "Mathlib":
script_lines.extend([
"lake build && if lake check-test; then lake test; fi",
""
])
# Build and test (skip for Mathlib)
if repo_name not in ["mathlib4"]:
print(blue("Building project..."))
# Clean lake cache for a fresh build
print(blue("Cleaning lake cache..."))
run_command("rm -rf .lake", cwd=repo_path)
try:
run_command("lake build", cwd=repo_path, stream_output=True)
print(green("Build completed successfully"))
except subprocess.CalledProcessError as e:
print(red("Build failed, but continuing with PR creation..."))
print(red(f"Build error: {e}"))
# Check if lake check-test exists before running tests
print(blue("Running tests..."))
check_test_result = run_command("lake check-test", cwd=repo_path, check=False)
if check_test_result.returncode == 0:
try:
run_command("lake test", cwd=repo_path, stream_output=True)
print(green("Tests completed successfully"))
except subprocess.CalledProcessError as e:
print(red("Tests failed, but continuing with PR creation..."))
print(red(f"Test error: {e}"))
else:
print(yellow("lake check-test reports that there is no test suite"))
script_lines.extend([
'gh pr create --title "chore: bump toolchain to ' + version + '" --body ""',
"echo 'Please review the PR and merge or rebase it.'",
""
])
# Push the branch to remote before creating PR
print(blue("Checking remote branch status..."))
try:
# Check if branch exists on remote
result = run_command(f"git ls-remote --heads origin {branch_name}", cwd=repo_path, check=False)
if not result.stdout.strip():
print(blue(f"Pushing branch {branch_name} to remote..."))
run_command(f"git push -u origin {branch_name}", cwd=repo_path)
print(green(f"Successfully pushed branch {branch_name} to remote"))
else:
print(blue(f"Branch {branch_name} already exists on remote, pushing any new commits..."))
run_command(f"git push", cwd=repo_path)
print(green("Successfully pushed commits to remote"))
except subprocess.CalledProcessError:
print(red("Failed to push branch to remote. Please check your permissions and network connection."))
print(yellow(f"You may need to run: git push -u origin {branch_name}"))
return
return "\n".join(script_lines)
# Create pull request (only if one doesn't already exist)
print(blue("Checking for existing pull request..."))
try:
# Check if PR already exists for this branch
result = run_command(f'gh pr list --head {branch_name} --json number', cwd=repo_path, check=False)
if result.returncode == 0 and result.stdout.strip() != "[]":
print(green(f"Pull request already exists for branch {branch_name}"))
# Get the PR URL
pr_result = run_command(f'gh pr view {branch_name} --json url', cwd=repo_path, check=False)
if pr_result.returncode == 0:
pr_data = json.loads(pr_result.stdout)
print(green(f"PR URL: {pr_data.get('url', 'N/A')}"))
else:
# Create new PR
print(blue("Creating new pull request..."))
run_command(f'gh pr create --title "chore: bump toolchain to {version}" --body ""', cwd=repo_path)
print(green("Pull request created successfully!"))
except subprocess.CalledProcessError:
print(red("Failed to check for existing PR or create new PR."))
print(yellow("This could be due to:"))
print(yellow("1. GitHub CLI not authenticated"))
print(yellow("2. No push permissions to the repository"))
print(yellow("3. Network issues"))
print(f"Branch: {branch_name}")
print(f"Title: chore: bump toolchain to {version}")
print(yellow("Please create the PR manually if needed."))
def main():
parser = argparse.ArgumentParser(
description="Generate release steps script for Lean4 repositories.",
description="Execute release steps for Lean4 repositories.",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
%(prog)s v4.6.0 mathlib Generate steps for updating Mathlib to v4.6.0
%(prog)s v4.6.0 batt Generate steps for updating Batteries to v4.6.0
%(prog)s v4.6.0 mathlib4 Execute steps for updating Mathlib to v4.6.0
%(prog)s v4.6.0 batteries Execute steps for updating Batteries to v4.6.0
The script will generate shell commands to:
1. Update the lean-toolchain file
2. Create appropriate branches and commits
3. Create pull requests
The script will:
1. Create a downstream_releases/ directory
2. Clone or update the target repository
3. Update the lean-toolchain file
4. Create appropriate branches and commits
5. Build and test the project
6. Create pull requests
(Note that the steps of creating toolchain version tags, and merging these into `stable` branches,
are handled by `script/release_checklist.py`.)
"""
)
parser.add_argument("version", help="The version to set in the lean-toolchain file (e.g., v4.6.0)")
parser.add_argument("repo", help="A substring of the repository name as specified in release_repos.yml")
parser.add_argument("repo", help="The repository name as specified in release_repos.yml")
args = parser.parse_args()
config_path = os.path.join(os.path.dirname(__file__), "release_repos.yml")
config = load_repos_config(config_path)
script = generate_script(args.repo, args.version, config)
print(script)
execute_release_steps(args.repo, args.version, config)
if __name__ == "__main__":
main()

View File

@@ -10,7 +10,7 @@ endif()
include(ExternalProject)
project(LEAN CXX C)
set(LEAN_VERSION_MAJOR 4)
set(LEAN_VERSION_MINOR 22)
set(LEAN_VERSION_MINOR 23)
set(LEAN_VERSION_PATCH 0)
set(LEAN_VERSION_IS_RELEASE 0) # This number is 1 in the release revision, and 0 otherwise.
set(LEAN_SPECIAL_VERSION_DESC "" CACHE STRING "Additional version description like 'nightly-2018-03-11'")
@@ -58,9 +58,6 @@ option(USE_GITHASH "GIT_HASH" ON)
option(INSTALL_LICENSE "INSTALL_LICENSE" ON)
# When ON we install a copy of cadical
option(INSTALL_CADICAL "Install a copy of cadical" ON)
# When ON thread storage is automatically finalized, it assumes platform support pthreads.
# This option is important when using Lean as library that is invoked from a different programming language (e.g., Haskell).
option(AUTO_THREAD_FINALIZATION "AUTO_THREAD_FINALIZATION" ON)
# FLAGS for disabling optimizations and debugging
option(FREE_VAR_RANGE_OPT "FREE_VAR_RANGE_OPT" ON)
@@ -182,10 +179,6 @@ else()
string(APPEND LEAN_EXTRA_CXX_FLAGS " -D LEAN_MULTI_THREAD")
endif()
if(AUTO_THREAD_FINALIZATION AND NOT MSVC)
string(APPEND LEAN_EXTRA_CXX_FLAGS " -D LEAN_AUTO_THREAD_FINALIZATION")
endif()
# Set Module Path
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules")
@@ -540,12 +533,21 @@ else()
OUTPUT_VARIABLE GIT_SHA1
OUTPUT_STRIP_TRAILING_WHITESPACE)
message(STATUS "stage0 sha1: ${GIT_SHA1}")
# Now that we've prepared the information for the next stage, we can forget that we will use
# Lake in the future as we won't use it in this stage
set(USE_LAKE OFF)
else()
set(GIT_SHA1 "")
endif()
endif()
configure_file("${LEAN_SOURCE_DIR}/githash.h.in" "${LEAN_BINARY_DIR}/githash.h")
if(USE_LAKE AND ${STAGE} EQUAL 0)
# Now that we've prepared the information for the next stage, we can forget that we will use
# Lake in the future as we won't use it in this stage
set(USE_LAKE OFF)
endif()
# Windows uses ";" as a path separator. We use `LEAN_PATH_SEPARATOR` on scripts such as lean.mk.in
if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
set(LEAN_PATH_SEPARATOR ";")
@@ -641,8 +643,6 @@ else()
set(LEAN_OBJS ${LEAN_OBJS} $<TARGET_OBJECTS:library>)
add_subdirectory(library/constructions)
set(LEAN_OBJS ${LEAN_OBJS} $<TARGET_OBJECTS:constructions>)
add_subdirectory(library/compiler)
set(LEAN_OBJS ${LEAN_OBJS} $<TARGET_OBJECTS:compiler>)
# leancpp without `initialize` (see `leaninitialize` above)
add_library(leancpp_1 STATIC ${LEAN_OBJS})
@@ -821,6 +821,12 @@ if(LEAN_INSTALL_PREFIX)
set(CMAKE_INSTALL_PREFIX "${LEAN_INSTALL_PREFIX}/lean-${LEAN_VERSION_STRING}${LEAN_INSTALL_SUFFIX}")
endif()
if (STAGE GREATER 1)
# The build of stage2+ may depend on local changes made to src/ that are not reflected by the
# commit hash in stage1/bin/lean, so we make sure to disable the global cache
string(APPEND LEAN_EXTRA_LAKEFILE_TOML "\n\nenableArtifactCache = false")
endif()
# Escape for `make`. Yes, twice.
string(REPLACE "$" "\\\$$" CMAKE_EXE_LINKER_FLAGS_MAKE "${CMAKE_EXE_LINKER_FLAGS}")
configure_file(${LEAN_SOURCE_DIR}/stdlib.make.in ${CMAKE_BINARY_DIR}/stdlib.make)
@@ -847,6 +853,10 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
set(LAKE_LIB_PREFIX "lib")
endif()
if(USE_LAKE AND STAGE EQUAL 1)
configure_file(${LEAN_SOURCE_DIR}/lakefile.toml.in ${LEAN_SOURCE_DIR}/lakefile.toml)
if(USE_LAKE)
configure_file(${LEAN_SOURCE_DIR}/lakefile.toml.in ${CMAKE_BINARY_DIR}/lakefile.toml)
# copy for editing
if(STAGE EQUAL 1)
configure_file(${LEAN_SOURCE_DIR}/lakefile.toml.in ${LEAN_SOURCE_DIR}/lakefile.toml)
endif()
endif()

View File

@@ -6,41 +6,41 @@ Authors: Leonardo de Moura
module
prelude
import Init.Prelude
import Init.Notation
import Init.Tactics
import Init.TacticsExtra
import Init.ByCases
import Init.RCases
import Init.Core
import Init.Control
import Init.Data.Basic
import Init.WF
import Init.WFTactics
import Init.Data
import Init.System
import Init.Util
import Init.Dynamic
import Init.ShareCommon
import Init.MetaTypes
import Init.Meta
import Init.NotationExtra
import Init.SimpLemmas
import Init.PropLemmas
import Init.Hints
import Init.Conv
import Init.Guard
import Init.Simproc
import Init.SizeOfLemmas
import Init.BinderPredicates
import Init.Ext
import Init.Omega
import Init.MacroTrace
import Init.Grind
import Init.GrindInstances
import Init.While
import Init.Syntax
import Init.Internal
import Init.Try
import Init.BinderNameHint
import Init.Task
public import Init.Prelude
public import Init.Notation
public import Init.Tactics
public import Init.TacticsExtra
public import Init.ByCases
public import Init.RCases
public import Init.Core
public import Init.Control
public import Init.Data.Basic
public import Init.WF
public import Init.WFTactics
public import Init.Data
public import Init.System
public import Init.Util
public import Init.Dynamic
public import Init.ShareCommon
public import Init.MetaTypes
public import Init.Meta
public import Init.NotationExtra
public import Init.SimpLemmas
public import Init.PropLemmas
public import Init.Hints
public import Init.Conv
public import Init.Guard
public import Init.Simproc
public import Init.SizeOfLemmas
public import Init.BinderPredicates
public import Init.Ext
public import Init.Omega
public import Init.MacroTrace
public import Init.Grind
public import Init.GrindInstances
public import Init.While
public import Init.Syntax
public import Init.Internal
public import Init.Try
public import Init.BinderNameHint
public import Init.Task

View File

@@ -7,8 +7,10 @@ Authors: Joachim Breitner
module
prelude
import Init.Prelude
import Init.Tactics
public import Init.Prelude
public import Init.Tactics
public section
set_option linter.unusedVariables false in
/--
@@ -37,7 +39,7 @@ This gadget is supported by
* `simp`, `dsimp` and `rw` in the right-hand-side of an equation
* `simp` in the assumptions of congruence rules
It is ineffective in other positions (hyptheses of rewrite rules) or when used by other tactics
It is ineffective in other positions (hypotheses of rewrite rules) or when used by other tactics
(e.g. `apply`).
-/
@[simp , expose]

View File

@@ -6,7 +6,9 @@ Authors: Gabriel Ebner
module
prelude
import Init.NotationExtra
public import Init.NotationExtra
public section
namespace Lean

View File

@@ -6,7 +6,9 @@ Authors: Leonardo de Moura, Mario Carneiro
module
prelude
import Init.Classical
public import Init.Classical
public section
/-! # by_cases tactic and if-then-else support -/

View File

@@ -6,7 +6,9 @@ Authors: Leonardo de Moura, Mario Carneiro
module
prelude
import Init.PropLemmas
public import Init.PropLemmas
public section
universe u v
@@ -45,7 +47,7 @@ theorem em (p : Prop) : p ¬p :=
| Or.inr h, _ => Or.inr h
| _, Or.inr h => Or.inr h
| Or.inl hut, Or.inl hvf =>
have hne : u v := by simp [hvf, hut, true_ne_false]
have hne : u v := by simp [hvf, hut]
Or.inl hne
have p_implies_uv : p u = v :=
fun hp =>

View File

@@ -6,8 +6,10 @@ Authors: Leonardo de Moura, Mario Carneiro
module
prelude
import Init.Prelude
meta import Init.Prelude
public import Init.Prelude
public meta import Init.Prelude
public section
set_option linter.missingDocs true -- keep it documented
/-!

View File

@@ -6,13 +6,15 @@ Authors: Leonardo de Moura
module
prelude
import Init.Control.Basic
import Init.Control.State
import Init.Control.StateRef
import Init.Control.Id
import Init.Control.Except
import Init.Control.Reader
import Init.Control.Option
import Init.Control.Lawful
import Init.Control.StateCps
import Init.Control.ExceptCps
public import Init.Control.Basic
public import Init.Control.State
public import Init.Control.StateRef
public import Init.Control.Id
public import Init.Control.Except
public import Init.Control.Reader
public import Init.Control.Option
public import Init.Control.Lawful
public import Init.Control.StateCps
public import Init.Control.ExceptCps
public section

View File

@@ -6,8 +6,10 @@ Author: Leonardo de Moura, Sebastian Ullrich
module
prelude
import Init.Core
import Init.BinderNameHint
public import Init.Core
public import Init.BinderNameHint
public section
universe u v w

View File

@@ -6,9 +6,11 @@ Authors: Leonardo de Moura
module
prelude
import Init.Control.State
import Init.Control.Except
import Init.Data.ToString.Basic
public import Init.Control.State
public import Init.Control.Except
public import Init.Data.ToString.Basic
public section
universe u v
namespace EStateM

View File

@@ -8,9 +8,11 @@ The Except monad transformer.
module
prelude
import Init.Control.Basic
import Init.Control.Id
import Init.Coe
public import Init.Control.Basic
public import Init.Control.Id
public import Init.Coe
@[expose] public section
namespace Except
variable {ε : Type u}

View File

@@ -6,7 +6,9 @@ Authors: Leonardo de Moura
module
prelude
import Init.Control.Lawful.Basic
public import Init.Control.Lawful.Basic
public section
/-!
The Exception monad transformer using CPS style.

View File

@@ -8,7 +8,9 @@ The identity Monad.
module
prelude
import Init.Core
public import Init.Core
public section
universe u
@@ -62,4 +64,7 @@ protected def run (x : Id α) : α := x
instance [OfNat α n] : OfNat (Id α) n :=
inferInstanceAs (OfNat α n)
instance {m : Type u Type v} [Pure m] : MonadLiftT Id m where
monadLift x := pure x.run
end Id

View File

@@ -6,7 +6,9 @@ Authors: Sebastian Ullrich, Leonardo de Moura, Mario Carneiro
module
prelude
import Init.Control.Lawful.Basic
import Init.Control.Lawful.Instances
import Init.Control.Lawful.Lemmas
import Init.Control.Lawful.MonadLift
public import Init.Control.Lawful.Basic
public import Init.Control.Lawful.Instances
public import Init.Control.Lawful.Lemmas
public import Init.Control.Lawful.MonadLift
public section

View File

@@ -6,9 +6,11 @@ Authors: Sebastian Ullrich, Leonardo de Moura, Mario Carneiro
module
prelude
import Init.Ext
import Init.SimpLemmas
import Init.Meta
public import Init.Ext
public import Init.SimpLemmas
public import Init.Meta
public section
open Function
@@ -50,7 +52,7 @@ attribute [simp] id_map
(comp_map _ _ _).symm
theorem Functor.map_unit [Functor f] [LawfulFunctor f] {a : f PUnit} : (fun _ => PUnit.unit) <$> a = a := by
simp [map]
simp
/--
An applicative functor satisfies the laws of an applicative functor.

View File

@@ -6,11 +6,13 @@ Authors: Sebastian Ullrich, Leonardo de Moura, Mario Carneiro
module
prelude
import Init.Control.Lawful.Basic
import all Init.Control.Except
import all Init.Control.State
import Init.Control.StateRef
import Init.Ext
public import Init.Control.Lawful.Basic
public import all Init.Control.Except
public import all Init.Control.State
public import Init.Control.StateRef
public import Init.Ext
public section
open Function
@@ -67,7 +69,7 @@ protected theorem seqLeft_eq {α β ε : Type u} {m : Type u → Type v} [Monad
| Except.error _ => simp
| Except.ok _ =>
simp [bind_pure_comp]; apply bind_congr; intro b;
cases b <;> simp [comp, Except.map, const]
cases b <;> simp [Except.map, const]
protected theorem seqRight_eq [Monad m] [LawfulMonad m] (x : ExceptT ε m α) (y : ExceptT ε m β) : x *> y = const α id <$> x <*> y := by
change (x >>= fun _ => y) = (const α id <$> x) >>= fun f => f <$> y

View File

@@ -6,9 +6,11 @@ Authors: Kim Morrison
module
prelude
import Init.Control.Lawful.Basic
import Init.RCases
import Init.ByCases
public import Init.Control.Lawful.Basic
public import Init.RCases
public import Init.ByCases
public section
-- Mapping by a function with a left inverse is injective.
theorem map_inj_of_left_inverse [Functor m] [LawfulFunctor m] {f : α β}

View File

@@ -6,6 +6,8 @@ Authors: Paul Reichert
module
prelude
import Init.Control.Lawful.MonadLift.Basic
import Init.Control.Lawful.MonadLift.Lemmas
import Init.Control.Lawful.MonadLift.Instances
public import Init.Control.Lawful.MonadLift.Basic
public import Init.Control.Lawful.MonadLift.Lemmas
public import Init.Control.Lawful.MonadLift.Instances
public section

View File

@@ -6,7 +6,9 @@ Authors: Quang Dao
module
prelude
import Init.Control.Basic
public import Init.Control.Basic
public section
/-!
# LawfulMonadLift and LawfulMonadLiftT

View File

@@ -6,13 +6,16 @@ Authors: Quang Dao, Paul Reichert
module
prelude
import all Init.Control.Option
import all Init.Control.Except
import all Init.Control.ExceptCps
import all Init.Control.StateRef
import all Init.Control.StateCps
import Init.Control.Lawful.MonadLift.Lemmas
import Init.Control.Lawful.Instances
public import all Init.Control.Option
public import all Init.Control.Except
public import all Init.Control.ExceptCps
public import all Init.Control.StateRef
public import all Init.Control.StateCps
public import all Init.Control.Id
public import Init.Control.Lawful.MonadLift.Lemmas
public import Init.Control.Lawful.Instances
public section
universe u v w x
@@ -135,3 +138,11 @@ instance {ε : Type u} [Monad m] [LawfulMonad m] : LawfulMonadLift m (ExceptCpsT
simp only [bind_assoc]
end ExceptCpsT
namespace Id
instance [Monad m] [LawfulMonad m] : LawfulMonadLiftT Id m where
monadLift_pure a := by simp [monadLift]
monadLift_bind a f := by simp [monadLift]
end Id

View File

@@ -6,8 +6,10 @@ Authors: Quang Dao
module
prelude
import Init.Control.Lawful.Basic
import Init.Control.Lawful.MonadLift.Basic
public import Init.Control.Lawful.Basic
public import Init.Control.Lawful.MonadLift.Basic
public section
universe u v w

View File

@@ -6,9 +6,11 @@ Authors: Leonardo de Moura, Sebastian Ullrich
module
prelude
import Init.Data.Option.Basic
import Init.Control.Basic
import Init.Control.Except
public import Init.Data.Option.Basic
public import Init.Control.Basic
public import Init.Control.Except
public section
set_option linter.missingDocs true

View File

@@ -8,9 +8,11 @@ The Reader monad transformer for passing immutable State.
module
prelude
import Init.Control.Basic
import Init.Control.Id
import Init.Control.Except
public import Init.Control.Basic
public import Init.Control.Id
public import Init.Control.Except
public section
set_option linter.missingDocs true
@@ -50,4 +52,4 @@ instance ReaderT.tryFinally [MonadFinally m] : MonadFinally (ReaderT ρ m) where
A monad with access to a read-only value of type `ρ`. The value can be locally overridden by
`withReader`, but it cannot be mutated.
-/
@[reducible] def ReaderM (ρ : Type u) := ReaderT ρ Id
abbrev ReaderM (ρ : Type u) := ReaderT ρ Id

View File

@@ -8,9 +8,11 @@ The State monad transformer.
module
prelude
import Init.Control.Basic
import Init.Control.Id
import Init.Control.Except
public import Init.Control.Basic
public import Init.Control.Id
public import Init.Control.Except
public section
set_option linter.missingDocs true

View File

@@ -6,7 +6,9 @@ Authors: Leonardo de Moura
module
prelude
import Init.Control.Lawful.Basic
public import Init.Control.Lawful.Basic
public section
set_option linter.missingDocs true

View File

@@ -8,7 +8,9 @@ The State monad transformer using IO references.
module
prelude
import Init.System.ST
public import Init.System.ST
public section
set_option linter.missingDocs true

View File

@@ -8,8 +8,10 @@ Notation for operators defined at Prelude.lean
module
prelude
import Init.Tactics
meta import Init.Meta
public import Init.Tactics
public meta import Init.Meta
public section
namespace Lean.Parser.Tactic.Conv
@@ -260,7 +262,7 @@ resulting in `t'`, which becomes the new target subgoal. -/
syntax (name := convConvSeq) "conv" " => " convSeq : conv
/-- `· conv` focuses on the main conv goal and tries to solve it using `s`. -/
macro dot:patternIgnore("·" <|> ".") s:convSeq : conv => `(conv| {%$dot ($s) })
macro dot:patternIgnore("· " <|> ". ") s:convSeq : conv => `(conv| {%$dot ($s) })
/-- `fail_if_success t` fails if the tactic `t` succeeds. -/
@@ -321,7 +323,7 @@ macro_rules
| `(conv| repeat $seq) => `(conv| first | ($seq); repeat $seq | skip)
/--
Extracts `let` and `let_fun` expressions from within the target expression.
Extracts `let` and `have` expressions from within the target expression.
This is the conv mode version of the `extract_lets` tactic.
- `extract_lets` extracts all the lets from the target.
@@ -334,11 +336,17 @@ See also `lift_lets`, which does not extract lets as local declarations.
syntax (name := extractLets) "extract_lets " optConfig (ppSpace colGt (ident <|> hole))* : conv
/--
Lifts `let` and `let_fun` expressions within the target expression as far out as possible.
Lifts `let` and `have` expressions within the target expression as far out as possible.
This is the conv mode version of the `lift_lets` tactic.
-/
syntax (name := liftLets) "lift_lets " optConfig : conv
/--
Transforms `let` expressions into `have` expressions within the target expression when possible.
This is the conv mode version of the `let_to_have` tactic.
-/
syntax (name := letToHave) "let_to_have" : conv
/--
`conv => ...` allows the user to perform targeted rewriting on a goal or hypothesis,
by focusing on particular subexpressions.

View File

@@ -8,8 +8,10 @@ notation, basic datatypes and type classes
module
prelude
meta import Init.Prelude
import Init.SizeOf
public meta import Init.Prelude
public import Init.SizeOf
public section
set_option linter.missingDocs true -- keep it documented
@[expose] section
@@ -750,6 +752,8 @@ Unlike `x ≠ y` (which is notation for `Ne x y`), this is `Bool` valued instead
@[inherit_doc] infix:50 " != " => bne
macro_rules | `($x != $y) => `(binrel_no_prop% bne $x $y)
recommended_spelling "bne" for "!=" in [bne, «term_!=_»]
/-- `ReflBEq α` says that the `BEq` implementation is reflexive. -/
@@ -851,6 +855,8 @@ and asserts that `a` and `b` are not equal.
@[inherit_doc] infix:50 "" => Ne
macro_rules | `($x $y) => `(binrel% Ne $x $y)
recommended_spelling "ne" for "" in [Ne, «term__»]
section Ne

View File

@@ -6,43 +6,48 @@ Authors: Leonardo de Moura
module
prelude
import Init.Data.Basic
import Init.Data.Nat
import Init.Data.Bool
import Init.Data.BitVec
import Init.Data.Cast
import Init.Data.Char
import Init.Data.String
import Init.Data.List
import Init.Data.Int
import Init.Data.Array
import Init.Data.Array.Subarray.Split
import Init.Data.ByteArray
import Init.Data.FloatArray
import Init.Data.Fin
import Init.Data.UInt
import Init.Data.SInt
import Init.Data.Float
import Init.Data.Float32
import Init.Data.Option
import Init.Data.Ord
import Init.Data.Random
import Init.Data.ToString
import Init.Data.Range
import Init.Data.Hashable
import Init.Data.OfScientific
import Init.Data.Format
import Init.Data.Stream
import Init.Data.Prod
import Init.Data.AC
import Init.Data.Queue
import Init.Data.Sum
import Init.Data.BEq
import Init.Data.Subtype
import Init.Data.ULift
import Init.Data.PLift
import Init.Data.Zero
import Init.Data.NeZero
import Init.Data.Function
import Init.Data.RArray
import Init.Data.Vector
public import Init.Data.Basic
public import Init.Data.Nat
public import Init.Data.Bool
public import Init.Data.BitVec
public import Init.Data.Cast
public import Init.Data.Char
public import Init.Data.String
public import Init.Data.List
public import Init.Data.Int
public import Init.Data.Array
public import Init.Data.Array.Subarray.Split
public import Init.Data.ByteArray
public import Init.Data.FloatArray
public import Init.Data.Fin
public import Init.Data.UInt
public import Init.Data.SInt
public import Init.Data.Float
public import Init.Data.Float32
public import Init.Data.Option
public import Init.Data.Ord
public import Init.Data.Random
public import Init.Data.ToString
public import Init.Data.Range
public import Init.Data.Hashable
public import Init.Data.OfScientific
public import Init.Data.Format
public import Init.Data.Stream
public import Init.Data.Prod
public import Init.Data.AC
public import Init.Data.Queue
public import Init.Data.Sum
public import Init.Data.BEq
public import Init.Data.Subtype
public import Init.Data.ULift
public import Init.Data.PLift
public import Init.Data.Zero
public import Init.Data.NeZero
public import Init.Data.Function
public import Init.Data.RArray
public import Init.Data.Vector
public import Init.Data.Iterators
public import Init.Data.Range.Polymorphic
public import Init.Data.Slice
public section

View File

@@ -7,8 +7,10 @@ Authors: Dany Fabian
module
prelude
import Init.Classical
import Init.ByCases
public import Init.Classical
public import Init.ByCases
@[expose] public section
namespace Lean.Data.AC
inductive Expr
@@ -209,7 +211,7 @@ theorem Context.evalList_sort_congr
induction c generalizing a b with
| nil => simp [sort.loop, h₂]
| cons c _ ih =>
simp [sort.loop]; apply ih; simp [evalList_insert ctx h, evalList]
simp [sort.loop]; apply ih; simp [evalList_insert ctx h]
cases a with
| nil => apply absurd h₃; simp
| cons a as =>
@@ -282,7 +284,7 @@ theorem Context.toList_nonEmpty (e : Expr) : e.toList ≠ [] := by
simp [Expr.toList]
cases h : l.toList with
| nil => contradiction
| cons => simp [List.append]
| cons => simp
theorem Context.unwrap_isNeutral
{ctx : Context α}
@@ -328,13 +330,13 @@ theorem Context.eval_toList (ctx : Context α) (e : Expr) : evalList α ctx e.to
induction e with
| var x => rfl
| op l r ih₁ ih₂ =>
simp [evalList, Expr.toList, eval, ih₁, ih₂]
simp [Expr.toList, eval, ih₁, ih₂]
apply evalList_append <;> apply toList_nonEmpty
theorem Context.eval_norm (ctx : Context α) (e : Expr) : evalList α ctx (norm ctx e) = eval α ctx e := by
simp [norm]
cases h₁ : ContextInformation.isIdem ctx <;> cases h₂ : ContextInformation.isComm ctx <;>
simp_all [evalList_removeNeutrals, eval_toList, toList_nonEmpty, evalList_mergeIdem, evalList_sort]
simp_all [evalList_removeNeutrals, eval_toList, evalList_mergeIdem, evalList_sort]
theorem Context.eq_of_norm (ctx : Context α) (a b : Expr) (h : norm ctx a == norm ctx b) : eval α ctx a = eval α ctx b := by
have h := congrArg (evalList α ctx) (eq_of_beq h)

View File

@@ -6,27 +6,29 @@ Authors: Gabriel Ebner
module
prelude
import Init.Data.Array.Basic
import Init.Data.Array.QSort
import Init.Data.Array.BinSearch
import Init.Data.Array.InsertionSort
import Init.Data.Array.DecidableEq
import Init.Data.Array.Mem
import Init.Data.Array.Attach
import Init.Data.Array.BasicAux
import Init.Data.Array.Lemmas
import Init.Data.Array.TakeDrop
import Init.Data.Array.Bootstrap
import Init.Data.Array.GetLit
import Init.Data.Array.MapIdx
import Init.Data.Array.Set
import Init.Data.Array.Monadic
import Init.Data.Array.FinRange
import Init.Data.Array.Perm
import Init.Data.Array.Find
import Init.Data.Array.Lex
import Init.Data.Array.Range
import Init.Data.Array.Erase
import Init.Data.Array.Zip
import Init.Data.Array.InsertIdx
import Init.Data.Array.Extract
public import Init.Data.Array.Basic
public import Init.Data.Array.QSort
public import Init.Data.Array.BinSearch
public import Init.Data.Array.InsertionSort
public import Init.Data.Array.DecidableEq
public import Init.Data.Array.Mem
public import Init.Data.Array.Attach
public import Init.Data.Array.BasicAux
public import Init.Data.Array.Lemmas
public import Init.Data.Array.TakeDrop
public import Init.Data.Array.Bootstrap
public import Init.Data.Array.GetLit
public import Init.Data.Array.MapIdx
public import Init.Data.Array.Set
public import Init.Data.Array.Monadic
public import Init.Data.Array.FinRange
public import Init.Data.Array.Perm
public import Init.Data.Array.Find
public import Init.Data.Array.Lex
public import Init.Data.Array.Range
public import Init.Data.Array.Erase
public import Init.Data.Array.Zip
public import Init.Data.Array.InsertIdx
public import Init.Data.Array.Extract
public section

View File

@@ -6,10 +6,12 @@ Authors: Joachim Breitner, Mario Carneiro
module
prelude
import Init.Data.Array.Mem
import Init.Data.Array.Lemmas
import Init.Data.Array.Count
import all Init.Data.List.Attach
public import Init.Data.Array.Mem
public import Init.Data.Array.Lemmas
public import Init.Data.Array.Count
public import all Init.Data.List.Attach
public section
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
@@ -68,15 +70,15 @@ well-founded recursion mechanism to prove that the function terminates.
l.toArray.pmap f H = (l.pmap f (by simpa using H)).toArray := by
simp [pmap]
@[simp] theorem toList_attachWith {xs : Array α} {P : α Prop} {H : x xs, P x} :
@[simp, grind =] theorem toList_attachWith {xs : Array α} {P : α Prop} {H : x xs, P x} :
(xs.attachWith P H).toList = xs.toList.attachWith P (by simpa [mem_toList_iff] using H) := by
simp [attachWith]
@[simp] theorem toList_attach {xs : Array α} :
@[simp, grind =] theorem toList_attach {xs : Array α} :
xs.attach.toList = xs.toList.attachWith (· xs) (by simp [mem_toList_iff]) := by
simp [attach]
@[simp] theorem toList_pmap {xs : Array α} {P : α Prop} {f : a, P a β} {H : a xs, P a} :
@[simp, grind =] theorem toList_pmap {xs : Array α} {P : α Prop} {f : a, P a β} {H : a xs, P a} :
(xs.pmap f H).toList = xs.toList.pmap f (fun a m => H a (mem_def.mpr m)) := by
simp [pmap]
@@ -92,16 +94,16 @@ well-founded recursion mechanism to prove that the function terminates.
intro a m h₁ h₂
congr
@[simp] theorem pmap_empty {P : α Prop} (f : a, P a β) : pmap f #[] (by simp) = #[] := rfl
@[simp, grind =] theorem pmap_empty {P : α Prop} (f : a, P a β) : pmap f #[] (by simp) = #[] := rfl
@[simp] theorem pmap_push {P : α Prop} (f : a, P a β) (a : α) (xs : Array α) (h : b xs.push a, P b) :
@[simp, grind =] theorem pmap_push {P : α Prop} (f : a, P a β) (a : α) (xs : Array α) (h : b xs.push a, P b) :
pmap f (xs.push a) h =
(pmap f xs (fun a m => by simp at h; exact h a (.inl m))).push (f a (h a (by simp))) := by
simp [pmap]
@[simp] theorem attach_empty : (#[] : Array α).attach = #[] := rfl
@[simp, grind =] theorem attach_empty : (#[] : Array α).attach = #[] := rfl
@[simp] theorem attachWith_empty {P : α Prop} (H : x #[], P x) : (#[] : Array α).attachWith P H = #[] := rfl
@[simp, grind =] theorem attachWith_empty {P : α Prop} (H : x #[], P x) : (#[] : Array α).attachWith P H = #[] := rfl
@[simp] theorem _root_.List.attachWith_mem_toArray {l : List α} :
l.attachWith (fun x => x l.toArray) (fun x h => by simpa using h) =
@@ -122,11 +124,13 @@ theorem pmap_congr_left {p q : α → Prop} {f : ∀ a, p a → β} {g : ∀ a,
simp only [List.pmap_toArray, mk.injEq]
rw [List.pmap_congr_left _ h]
@[grind =]
theorem map_pmap {p : α Prop} {g : β γ} {f : a, p a β} {xs : Array α} (H) :
map g (pmap f xs H) = pmap (fun a h => g (f a h)) xs H := by
cases xs
simp [List.map_pmap]
@[grind =]
theorem pmap_map {p : β Prop} {g : b, p b γ} {f : α β} {xs : Array α} (H) :
pmap g (map f xs) H = pmap (fun a h => g (f a) h) xs fun _ h => H _ (mem_map_of_mem h) := by
cases xs
@@ -142,18 +146,18 @@ theorem attachWith_congr {xs ys : Array α} (w : xs = ys) {P : α → Prop} {H :
subst w
simp
@[simp] theorem attach_push {a : α} {xs : Array α} :
@[simp, grind =] theorem attach_push {a : α} {xs : Array α} :
(xs.push a).attach =
(xs.attach.map (fun x, h => x, mem_push_of_mem a h)).push a, by simp := by
cases xs
rw [attach_congr (List.push_toArray _ _)]
simp [Function.comp_def]
@[simp] theorem attachWith_push {a : α} {xs : Array α} {P : α Prop} {H : x xs.push a, P x} :
@[simp, grind =] theorem attachWith_push {a : α} {xs : Array α} {P : α Prop} {H : x xs.push a, P x} :
(xs.push a).attachWith P H =
(xs.attachWith P (fun x h => by simp at H; exact H x (.inl h))).push a, H a (by simp) := by
cases xs
simp [attachWith_congr (List.push_toArray _ _)]
simp
theorem pmap_eq_map_attach {p : α Prop} {f : a, p a β} {xs : Array α} (H) :
pmap f xs H = xs.attach.map fun x => f x.1 (H _ x.2) := by
@@ -189,38 +193,39 @@ theorem attachWith_map_subtype_val {p : α → Prop} {xs : Array α} (H : ∀ a
(xs.attachWith p H).map Subtype.val = xs := by
cases xs; simp
@[simp]
@[simp, grind]
theorem mem_attach (xs : Array α) : x, x xs.attach
| a, h => by
have := mem_map.1 (by rw [attach_map_subtype_val] <;> exact h)
rcases this with _, _, m, rfl
exact m
@[simp]
@[simp, grind]
theorem mem_attachWith {xs : Array α} {q : α Prop} (H) (x : {x // q x}) :
x xs.attachWith q H x.1 xs := by
cases xs
simp
@[simp]
@[simp, grind =]
theorem mem_pmap {p : α Prop} {f : a, p a β} {xs H b} :
b pmap f xs H (a : _) (h : a xs), f a (H a h) = b := by
simp only [pmap_eq_map_attach, mem_map, mem_attach, true_and, Subtype.exists, eq_comm]
@[grind]
theorem mem_pmap_of_mem {p : α Prop} {f : a, p a β} {xs H} {a} (h : a xs) :
f a (H a h) pmap f xs H := by
rw [mem_pmap]
exact a, h, rfl
@[simp]
@[simp, grind =]
theorem size_pmap {p : α Prop} {f : a, p a β} {xs H} : (pmap f xs H).size = xs.size := by
cases xs; simp
@[simp]
@[simp, grind =]
theorem size_attach {xs : Array α} : xs.attach.size = xs.size := by
cases xs; simp
@[simp]
@[simp, grind =]
theorem size_attachWith {p : α Prop} {xs : Array α} {H} : (xs.attachWith p H).size = xs.size := by
cases xs; simp
@@ -252,13 +257,13 @@ theorem attachWith_ne_empty_iff {xs : Array α} {P : α → Prop} {H : ∀ a ∈
xs.attachWith P H #[] xs #[] := by
cases xs; simp
@[simp]
@[simp, grind =]
theorem getElem?_pmap {p : α Prop} {f : a, p a β} {xs : Array α} (h : a xs, p a) (i : Nat) :
(pmap f xs h)[i]? = Option.pmap f xs[i]? fun x H => h x (mem_of_getElem? H) := by
cases xs; simp
-- The argument `f` is explicit to allow rewriting from right to left.
@[simp]
@[simp, grind =]
theorem getElem_pmap {p : α Prop} (f : a, p a β) {xs : Array α} (h : a xs, p a) {i : Nat}
(hi : i < (pmap f xs h).size) :
(pmap f xs h)[i] =
@@ -266,57 +271,59 @@ theorem getElem_pmap {p : α → Prop} (f : ∀ a, p a → β) {xs : Array α} (
(h _ (getElem_mem (@size_pmap _ _ p f xs h hi))) := by
cases xs; simp
@[simp]
@[simp, grind =]
theorem getElem?_attachWith {xs : Array α} {i : Nat} {P : α Prop} {H : a xs, P a} :
(xs.attachWith P H)[i]? = xs[i]?.pmap Subtype.mk (fun _ a => H _ (mem_of_getElem? a)) :=
getElem?_pmap ..
@[simp]
@[simp, grind =]
theorem getElem?_attach {xs : Array α} {i : Nat} :
xs.attach[i]? = xs[i]?.pmap Subtype.mk (fun _ a => mem_of_getElem? a) :=
getElem?_attachWith
@[simp]
@[simp, grind =]
theorem getElem_attachWith {xs : Array α} {P : α Prop} {H : a xs, P a}
{i : Nat} (h : i < (xs.attachWith P H).size) :
(xs.attachWith P H)[i] = xs[i]'(by simpa using h), H _ (getElem_mem (by simpa using h)) :=
getElem_pmap _ _ h
@[simp]
@[simp, grind =]
theorem getElem_attach {xs : Array α} {i : Nat} (h : i < xs.attach.size) :
xs.attach[i] = xs[i]'(by simpa using h), getElem_mem (by simpa using h) :=
getElem_attachWith h
@[simp] theorem pmap_attach {xs : Array α} {p : {x // x xs} Prop} {f : a, p a β} (H) :
@[simp, grind =] theorem pmap_attach {xs : Array α} {p : {x // x xs} Prop} {f : a, p a β} (H) :
pmap f xs.attach H =
xs.pmap (P := fun a => h : a xs, p a, h)
(fun a h => f a, h.1 h.2) (fun a h => h, H a, h (by simp)) := by
ext <;> simp
@[simp] theorem pmap_attachWith {xs : Array α} {p : {x // q x} Prop} {f : a, p a β} (H₁ H₂) :
@[simp, grind =] theorem pmap_attachWith {xs : Array α} {p : {x // q x} Prop} {f : a, p a β} (H₁ H₂) :
pmap f (xs.attachWith q H₁) H₂ =
xs.pmap (P := fun a => h : q a, p a, h)
(fun a h => f a, h.1 h.2) (fun a h => H₁ _ h, H₂ a, H₁ _ h (by simpa)) := by
ext <;> simp
@[grind =]
theorem foldl_pmap {xs : Array α} {P : α Prop} {f : (a : α) P a β}
(H : (a : α), a xs P a) (g : γ β γ) (x : γ) :
(xs.pmap f H).foldl g x = xs.attach.foldl (fun acc a => g acc (f a.1 (H _ a.2))) x := by
rw [pmap_eq_map_attach, foldl_map]
@[grind =]
theorem foldr_pmap {xs : Array α} {P : α Prop} {f : (a : α) P a β}
(H : (a : α), a xs P a) (g : β γ γ) (x : γ) :
(xs.pmap f H).foldr g x = xs.attach.foldr (fun a acc => g (f a.1 (H _ a.2)) acc) x := by
rw [pmap_eq_map_attach, foldr_map]
@[simp] theorem foldl_attachWith
@[simp, grind =] theorem foldl_attachWith
{xs : Array α} {q : α Prop} (H : a, a xs q a) {f : β { x // q x} β} {b} (w : stop = xs.size) :
(xs.attachWith q H).foldl f b 0 stop = xs.attach.foldl (fun b a, h => f b a, H _ h) b := by
subst w
rcases xs with xs
simp [List.foldl_attachWith, List.foldl_map]
@[simp] theorem foldr_attachWith
@[simp, grind =] theorem foldr_attachWith
{xs : Array α} {q : α Prop} (H : a, a xs q a) {f : { x // q x} β β} {b} (w : start = xs.size) :
(xs.attachWith q H).foldr f b start 0 = xs.attach.foldr (fun a acc => f a.1, H _ a.2 acc) b := by
subst w
@@ -337,7 +344,7 @@ theorem foldl_attach {xs : Array α} {f : β → α → β} {b : β} :
xs.attach.foldl (fun acc t => f acc t.1) b = xs.foldl f b := by
rcases xs with xs
simp only [List.attach_toArray, List.attachWith_mem_toArray, List.size_toArray,
List.length_pmap, List.foldl_toArray', mem_toArray, List.foldl_subtype]
List.foldl_toArray', mem_toArray, List.foldl_subtype]
congr
ext
simpa using fun a => List.mem_of_getElem? a
@@ -356,23 +363,25 @@ theorem foldr_attach {xs : Array α} {f : α → β → β} {b : β} :
xs.attach.foldr (fun t acc => f t.1 acc) b = xs.foldr f b := by
rcases xs with xs
simp only [List.attach_toArray, List.attachWith_mem_toArray, List.size_toArray,
List.length_pmap, List.foldr_toArray', mem_toArray, List.foldr_subtype]
List.foldr_toArray', mem_toArray, List.foldr_subtype]
congr
ext
simpa using fun a => List.mem_of_getElem? a
@[grind =]
theorem attach_map {xs : Array α} {f : α β} :
(xs.map f).attach = xs.attach.map (fun x, h => f x, mem_map_of_mem h) := by
cases xs
ext <;> simp
@[grind =]
theorem attachWith_map {xs : Array α} {f : α β} {P : β Prop} (H : (b : β), b xs.map f P b) :
(xs.map f).attachWith P H = (xs.attachWith (P f) (fun _ h => H _ (mem_map_of_mem h))).map
fun x, h => f x, h := by
cases xs
simp [List.attachWith_map]
@[simp] theorem map_attachWith {xs : Array α} {P : α Prop} {H : (a : α), a xs P a}
@[simp, grind =] theorem map_attachWith {xs : Array α} {P : α Prop} {H : (a : α), a xs P a}
{f : { x // P x } β} :
(xs.attachWith P H).map f = xs.attach.map fun x, h => f x, H _ h := by
cases xs <;> simp_all
@@ -393,6 +402,7 @@ theorem map_attach_eq_pmap {xs : Array α} {f : { x // x ∈ xs } → β} :
@[deprecated map_attach_eq_pmap (since := "2025-02-09")]
abbrev map_attach := @map_attach_eq_pmap
@[grind =]
theorem attach_filterMap {xs : Array α} {f : α Option β} :
(xs.filterMap f).attach = xs.attach.filterMap
fun x, h => (f x).pbind (fun b m => some b, mem_filterMap.mpr x, h, m) := by
@@ -400,6 +410,7 @@ theorem attach_filterMap {xs : Array α} {f : α → Option β} :
rw [attach_congr List.filterMap_toArray]
simp [List.attach_filterMap, List.map_filterMap, Function.comp_def]
@[grind =]
theorem attach_filter {xs : Array α} (p : α Bool) :
(xs.filter p).attach = xs.attach.filterMap
fun x => if w : p x.1 then some x.1, mem_filter.mpr x.2, w else none := by
@@ -409,7 +420,7 @@ theorem attach_filter {xs : Array α} (p : α → Bool) :
-- We are still missing here `attachWith_filterMap` and `attachWith_filter`.
@[simp]
@[simp, grind =]
theorem filterMap_attachWith {q : α Prop} {xs : Array α} {f : {x // q x} Option β} (H)
(w : stop = (xs.attachWith q H).size) :
(xs.attachWith q H).filterMap f 0 stop = xs.attach.filterMap (fun x, h => f x, H _ h) := by
@@ -417,7 +428,7 @@ theorem filterMap_attachWith {q : α → Prop} {xs : Array α} {f : {x // q x}
cases xs
simp [Function.comp_def]
@[simp]
@[simp, grind =]
theorem filter_attachWith {q : α Prop} {xs : Array α} {p : {x // q x} Bool} (H)
(w : stop = (xs.attachWith q H).size) :
(xs.attachWith q H).filter p 0 stop =
@@ -426,6 +437,7 @@ theorem filter_attachWith {q : α → Prop} {xs : Array α} {p : {x // q x} →
cases xs
simp [Function.comp_def, List.filter_map]
@[grind =]
theorem pmap_pmap {p : α Prop} {q : β Prop} {g : a, p a β} {f : b, q b γ} {xs} (H₁ H₂) :
pmap f (pmap g xs H₁) H₂ =
pmap (α := { x // x xs }) (fun a h => f (g a h) (H₂ (g a h) (mem_pmap_of_mem a.2))) xs.attach
@@ -433,7 +445,7 @@ theorem pmap_pmap {p : α → Prop} {q : β → Prop} {g : ∀ a, p a → β} {f
cases xs
simp [List.pmap_pmap, List.pmap_map]
@[simp] theorem pmap_append {p : ι Prop} {f : a : ι, p a α} {xs ys : Array ι}
@[simp, grind =] theorem pmap_append {p : ι Prop} {f : a : ι, p a α} {xs ys : Array ι}
(h : a xs ++ ys, p a) :
(xs ++ ys).pmap f h =
(xs.pmap f fun a ha => h a (mem_append_left ys ha)) ++
@@ -448,7 +460,7 @@ theorem pmap_append' {p : α → Prop} {f : ∀ a : α, p a → β} {xs ys : Arr
xs.pmap f h₁ ++ ys.pmap f h₂ :=
pmap_append _
@[simp] theorem attach_append {xs ys : Array α} :
@[simp, grind =] theorem attach_append {xs ys : Array α} :
(xs ++ ys).attach = xs.attach.map (fun x, h => x, mem_append_left ys h) ++
ys.attach.map fun x, h => x, mem_append_right xs h := by
cases xs
@@ -456,59 +468,62 @@ theorem pmap_append' {p : α → Prop} {f : ∀ a : α, p a → β} {xs ys : Arr
rw [attach_congr (List.append_toArray _ _)]
simp [List.attach_append, Function.comp_def]
@[simp] theorem attachWith_append {P : α Prop} {xs ys : Array α}
@[simp, grind =] theorem attachWith_append {P : α Prop} {xs ys : Array α}
{H : (a : α), a xs ++ ys P a} :
(xs ++ ys).attachWith P H = xs.attachWith P (fun a h => H a (mem_append_left ys h)) ++
ys.attachWith P (fun a h => H a (mem_append_right xs h)) := by
simp [attachWith, attach_append, map_pmap, pmap_append]
simp [attachWith]
@[simp] theorem pmap_reverse {P : α Prop} {f : (a : α) P a β} {xs : Array α}
@[simp, grind =] theorem pmap_reverse {P : α Prop} {f : (a : α) P a β} {xs : Array α}
(H : (a : α), a xs.reverse P a) :
xs.reverse.pmap f H = (xs.pmap f (fun a h => H a (by simpa using h))).reverse := by
induction xs <;> simp_all
@[grind =]
theorem reverse_pmap {P : α Prop} {f : (a : α) P a β} {xs : Array α}
(H : (a : α), a xs P a) :
(xs.pmap f H).reverse = xs.reverse.pmap f (fun a h => H a (by simpa using h)) := by
rw [pmap_reverse]
@[simp] theorem attachWith_reverse {P : α Prop} {xs : Array α}
@[simp, grind =] theorem attachWith_reverse {P : α Prop} {xs : Array α}
{H : (a : α), a xs.reverse P a} :
xs.reverse.attachWith P H =
(xs.attachWith P (fun a h => H a (by simpa using h))).reverse := by
cases xs
simp
@[grind =]
theorem reverse_attachWith {P : α Prop} {xs : Array α}
{H : (a : α), a xs P a} :
(xs.attachWith P H).reverse = (xs.reverse.attachWith P (fun a h => H a (by simpa using h))) := by
cases xs
simp
@[simp] theorem attach_reverse {xs : Array α} :
@[simp, grind =] theorem attach_reverse {xs : Array α} :
xs.reverse.attach = xs.attach.reverse.map fun x, h => x, by simpa using h := by
cases xs
rw [attach_congr List.reverse_toArray]
simp
@[grind =]
theorem reverse_attach {xs : Array α} :
xs.attach.reverse = xs.reverse.attach.map fun x, h => x, by simpa using h := by
cases xs
simp
@[simp] theorem back?_pmap {P : α Prop} {f : (a : α) P a β} {xs : Array α}
@[simp, grind =] theorem back?_pmap {P : α Prop} {f : (a : α) P a β} {xs : Array α}
(H : (a : α), a xs P a) :
(xs.pmap f H).back? = xs.attach.back?.map fun a, m => f a (H a m) := by
cases xs
simp
@[simp] theorem back?_attachWith {P : α Prop} {xs : Array α}
@[simp, grind =] theorem back?_attachWith {P : α Prop} {xs : Array α}
{H : (a : α), a xs P a} :
(xs.attachWith P H).back? = xs.back?.pbind (fun a h => some a, H _ (mem_of_back? h)) := by
cases xs
simp
@[simp]
@[simp, grind =]
theorem back?_attach {xs : Array α} :
xs.attach.back? = xs.back?.pbind fun a h => some a, mem_of_back? h := by
cases xs
@@ -526,7 +541,7 @@ theorem countP_attachWith {p : α → Prop} {q : α → Bool} {xs : Array α} {H
cases xs
simp
@[simp]
@[simp, grind =]
theorem count_attach [BEq α] {xs : Array α} {a : {x // x xs}} :
xs.attach.count a = xs.count a := by
rcases xs with xs
@@ -535,13 +550,13 @@ theorem count_attach [BEq α] {xs : Array α} {a : {x // x ∈ xs}} :
simp only [Subtype.beq_iff]
rw [List.countP_pmap, List.countP_attach (p := (fun x => x == a.1)), List.count]
@[simp]
@[simp, grind =]
theorem count_attachWith [BEq α] {p : α Prop} {xs : Array α} (H : a xs, p a) {a : {x // p x}} :
(xs.attachWith p H).count a = xs.count a := by
cases xs
simp
@[simp] theorem countP_pmap {p : α Prop} {g : a, p a β} {f : β Bool} {xs : Array α} (H₁) :
@[simp, grind =] theorem countP_pmap {p : α Prop} {g : a, p a β} {f : β Bool} {xs : Array α} (H₁) :
(xs.pmap g H₁).countP f =
xs.attach.countP (fun a, m => f (g a (H₁ a m))) := by
simp [pmap_eq_map_attach, countP_map, Function.comp_def]
@@ -690,7 +705,7 @@ and simplifies these to the function directly taking the value.
{f : { x // p x } Array β} {g : α Array β} (hf : x h, f x, h = g x) :
(xs.flatMap f) = xs.unattach.flatMap g := by
cases xs
simp only [List.size_toArray, List.flatMap_toArray, List.unattach_toArray, List.length_unattach,
simp only [List.flatMap_toArray, List.unattach_toArray,
mk.injEq]
rw [List.flatMap_subtype]
simp [hf]

View File

@@ -6,15 +6,17 @@ Authors: Leonardo de Moura
module
prelude
import Init.WFTactics
import Init.Data.Nat.Basic
import Init.Data.Fin.Basic
import Init.Data.UInt.BasicAux
import Init.Data.Repr
import Init.Data.ToString.Basic
import Init.GetElem
import all Init.Data.List.ToArrayImpl
import all Init.Data.Array.Set
public import Init.WFTactics
public import Init.Data.Nat.Basic
public import Init.Data.Fin.Basic
public import Init.Data.UInt.BasicAux
public import Init.Data.Repr
public import Init.Data.ToString.Basic
public import Init.GetElem
public import all Init.Data.List.ToArrayImpl
public import all Init.Data.Array.Set
public section
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
@@ -178,7 +180,7 @@ in-place when the reference to the array is unique.
This avoids overhead due to unboxing a `Nat` used as an index.
-/
@[extern "lean_array_uset"]
@[extern "lean_array_uset", expose]
def uset (xs : Array α) (i : USize) (v : α) (h : i.toNat < xs.size) : Array α :=
xs.set i.toNat v h
@@ -261,7 +263,7 @@ Examples:
* `#["red", "green", "blue", "brown"].swapIfInBounds 0 4 = #["red", "green", "blue", "brown"]`
* `#["red", "green", "blue", "brown"].swapIfInBounds 9 2 = #["red", "green", "blue", "brown"]`
-/
@[extern "lean_array_swap"]
@[extern "lean_array_swap", grind]
def swapIfInBounds (xs : Array α) (i j : @& Nat) : Array α :=
if h₁ : i < xs.size then
if h₂ : j < xs.size then swap xs i j
@@ -1022,7 +1024,7 @@ The optional parameters `start` and `stop` control the region of the array to wh
applied. Iteration proceeds from `start` (inclusive) to `stop` (exclusive), so `f` is not invoked
unless `start < stop`. By default, the entire array is used.
-/
@[inline]
@[inline, expose]
protected def forM {α : Type u} {m : Type v Type w} [Monad m] (f : α m PUnit) (as : Array α) (start := 0) (stop := as.size) : m PUnit :=
as.foldlM (fun _ => f) start stop
@@ -1788,7 +1790,7 @@ decreasing_by simp_wf; exact Nat.sub_succ_lt_self _ _ h
induction xs, i, h using Array.eraseIdx.induct with
| @case1 xs i h h' xs' ih =>
unfold eraseIdx
simp +zetaDelta [h', xs', ih]
simp +zetaDelta [h', ih]
| case2 xs i h h' =>
unfold eraseIdx
simp [h']
@@ -1806,6 +1808,7 @@ Examples:
* `#["apple", "pear", "orange"].eraseIdxIfInBounds 3 = #["apple", "pear", "orange"]`
* `#["apple", "pear", "orange"].eraseIdxIfInBounds 5 = #["apple", "pear", "orange"]`
-/
@[grind]
def eraseIdxIfInBounds (xs : Array α) (i : Nat) : Array α :=
if h : i < xs.size then xs.eraseIdx i h else xs
@@ -1916,6 +1919,7 @@ Examples:
* `#["tues", "thur", "sat"].insertIdxIfInBounds 3 "wed" = #["tues", "thur", "sat", "wed"]`
* `#["tues", "thur", "sat"].insertIdxIfInBounds 4 "wed" = #["tues", "thur", "sat"]`
-/
@[grind]
def insertIdxIfInBounds (as : Array α) (i : Nat) (a : α) : Array α :=
if h : i as.size then
insertIdx as i a

View File

@@ -6,9 +6,11 @@ Authors: Leonardo de Moura
module
prelude
import all Init.Data.Array.Basic
import Init.Data.Nat.Linear
import Init.NotationExtra
public import all Init.Data.Array.Basic
public import Init.Data.Nat.Linear
public import Init.NotationExtra
public section
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
set_option linter.indexVariables true -- Enforce naming conventions for index variables.

View File

@@ -6,9 +6,11 @@ Authors: Leonardo de Moura
module
prelude
import Init.Data.Array.Basic
import Init.Data.Int.DivMod.Lemmas
import Init.Omega
public import Init.Data.Array.Basic
public import Init.Data.Int.DivMod.Lemmas
public import Init.Omega
public section
universe u v
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.

View File

@@ -7,8 +7,10 @@ Authors: Mario Carneiro
module
prelude
import Init.Data.List.TakeDrop
import all Init.Data.Array.Basic
public import Init.Data.List.TakeDrop
public import all Init.Data.Array.Basic
public section
/-!
## Bootstrapping theorems about arrays
@@ -119,13 +121,13 @@ abbrev pop_toList := @Array.toList_pop
@[simp] theorem toList_empty : (#[] : Array α).toList = [] := rfl
@[simp, grind =] theorem append_empty {xs : Array α} : xs ++ #[] = xs := by
apply ext'; simp only [toList_append, toList_empty, List.append_nil]
apply ext'; simp only [toList_append, List.append_nil]
@[deprecated append_empty (since := "2025-01-13")]
abbrev append_nil := @append_empty
@[simp, grind =] theorem empty_append {xs : Array α} : #[] ++ xs = xs := by
apply ext'; simp only [toList_append, toList_empty, List.nil_append]
apply ext'; simp only [toList_append, List.nil_append]
@[deprecated empty_append (since := "2025-01-13")]
abbrev nil_append := @empty_append

View File

@@ -6,9 +6,11 @@ Authors: Kim Morrison
module
prelude
import all Init.Data.Array.Basic
import Init.Data.Array.Lemmas
import Init.Data.List.Nat.Count
public import all Init.Data.Array.Basic
public import Init.Data.Array.Lemmas
public import Init.Data.List.Nat.Count
public section
/-!
# Lemmas about `Array.countP` and `Array.count`.
@@ -223,7 +225,7 @@ theorem boole_getElem_le_count {xs : Array α} {i : Nat} {a : α} (h : i < xs.si
@[grind =]
theorem count_set {xs : Array α} {i : Nat} {a b : α} (h : i < xs.size) :
(xs.set i a).count b = xs.count b - (if xs[i] == b then 1 else 0) + (if a == b then 1 else 0) := by
simp [count_eq_countP, countP_set, h]
simp [count_eq_countP, countP_set]
variable [LawfulBEq α]
@@ -231,7 +233,7 @@ variable [LawfulBEq α]
simp [count_push]
@[simp] theorem count_push_of_ne {xs : Array α} (h : b a) : count a (xs.push b) = count a xs := by
simp_all [count_push, h]
simp_all [count_push]
theorem count_singleton_self {a : α} : count a #[a] = 1 := by simp
@@ -292,17 +294,17 @@ abbrev mkArray_count_eq_of_count_eq_size := @replicate_count_eq_of_count_eq_size
theorem count_le_count_map [BEq β] [LawfulBEq β] {xs : Array α} {f : α β} {x : α} :
count x xs count (f x) (map f xs) := by
rcases xs with xs
simp [List.count_le_count_map, countP_map]
simp [List.count_le_count_map]
theorem count_filterMap {α} [BEq β] {b : β} {f : α Option β} {xs : Array α} :
count b (filterMap f xs) = countP (fun a => f a == some b) xs := by
rcases xs with xs
simp [List.count_filterMap, countP_filterMap]
simp [List.count_filterMap]
theorem count_flatMap {α} [BEq β] {xs : Array α} {f : α Array β} {x : β} :
count x (xs.flatMap f) = sum (map (count x f) xs) := by
rcases xs with xs
simp [List.count_flatMap, countP_flatMap, Function.comp_def]
simp [List.count_flatMap, Function.comp_def]
theorem countP_replace {a b : α} {xs : Array α} {p : α Bool} :
(xs.replace a b).countP p =

View File

@@ -6,10 +6,12 @@ Authors: Leonardo de Moura
module
prelude
import all Init.Data.Array.Basic
import Init.Data.BEq
import Init.Data.List.Nat.BEq
import Init.ByCases
public import all Init.Data.Array.Basic
public import Init.Data.BEq
public import Init.Data.List.Nat.BEq
public import Init.ByCases
public section
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
@@ -23,7 +25,7 @@ private theorem rel_of_isEqvAux
induction i with
| zero => contradiction
| succ i ih =>
simp only [Array.isEqvAux, Bool.and_eq_true, decide_eq_true_eq] at heqv
simp only [Array.isEqvAux, Bool.and_eq_true] at heqv
by_cases hj' : j < i
next =>
exact ih _ heqv.right hj'

View File

@@ -6,10 +6,12 @@ Authors: Kim Morrison
module
prelude
import all Init.Data.Array.Basic
import Init.Data.Array.Lemmas
import Init.Data.List.Nat.Erase
import Init.Data.List.Nat.Basic
public import all Init.Data.Array.Basic
public import Init.Data.Array.Lemmas
public import Init.Data.List.Nat.Erase
public import Init.Data.List.Nat.Basic
public section
/-!
# Lemmas about `Array.eraseP`, `Array.erase`, and `Array.eraseIdx`.
@@ -206,7 +208,7 @@ theorem erase_eq_eraseP [LawfulBEq α] (a : α) (xs : Array α) : xs.erase a = x
theorem erase_ne_empty_iff [LawfulBEq α] {xs : Array α} {a : α} :
xs.erase a #[] xs #[] xs #[a] := by
rcases xs with xs
simp [List.erase_ne_nil_iff]
simp
theorem exists_erase_eq [LawfulBEq α] {a : α} {xs : Array α} (h : a xs) :
ys zs, a ys xs = ys.push a ++ zs xs.erase a = ys ++ zs := by
@@ -306,7 +308,7 @@ theorem erase_eq_iff [LawfulBEq α] {a : α} {xs : Array α} :
@[simp] theorem erase_replicate_self [LawfulBEq α] {a : α} :
(replicate n a).erase a = replicate (n - 1) a := by
simp only [ List.toArray_replicate, List.erase_toArray]
simp [List.erase_replicate]
simp
@[deprecated erase_replicate_self (since := "2025-03-18")]
abbrev erase_mkArray_self := @erase_replicate_self
@@ -352,7 +354,7 @@ theorem getElem?_eraseIdx_of_lt {xs : Array α} {i : Nat} (h : i < xs.size) {j :
theorem getElem?_eraseIdx_of_ge {xs : Array α} {i : Nat} (h : i < xs.size) {j : Nat} (h' : i j) :
(xs.eraseIdx i)[j]? = xs[j + 1]? := by
rw [getElem?_eraseIdx]
simp only [dite_eq_ite, ite_eq_right_iff]
simp only [ite_eq_right_iff]
intro h'
omega
@@ -380,11 +382,12 @@ theorem eraseIdx_ne_empty_iff {xs : Array α} {i : Nat} {h} : xs.eraseIdx i ≠
simp [h]
· simp
@[grind ]
theorem mem_of_mem_eraseIdx {xs : Array α} {i : Nat} {h} {a : α} (h : a xs.eraseIdx i) : a xs := by
rcases xs with xs
simpa using List.mem_of_mem_eraseIdx (by simpa using h)
grind_pattern mem_of_mem_eraseIdx => a xs.eraseIdx i
theorem eraseIdx_append_of_lt_size {xs : Array α} {k : Nat} (hk : k < xs.size) (ys : Array α) (h) :
eraseIdx (xs ++ ys) k = eraseIdx xs k ++ ys := by
rcases xs with l

View File

@@ -6,8 +6,10 @@ Authors: Kim Morrison
module
prelude
import Init.Data.Array.Lemmas
import Init.Data.List.Nat.TakeDrop
public import Init.Data.Array.Lemmas
public import Init.Data.List.Nat.TakeDrop
public section
/-!
# Lemmas about `Array.extract`
@@ -29,7 +31,7 @@ namespace Array
· simp
omega
· simp only [size_extract] at h₁ h₂
simp [h]
simp
theorem size_extract_le {as : Array α} {i j : Nat} :
(as.extract i j).size j - i := by
@@ -46,15 +48,45 @@ theorem size_extract_of_le {as : Array α} {i j : Nat} (h : j ≤ as.size) :
simp
omega
@[simp, grind =]
theorem extract_push {as : Array α} {b : α} {start stop : Nat} (h : stop as.size) :
@[grind =]
theorem extract_push {as : Array α} {b : α} {start stop : Nat} :
(as.push b).extract start stop =
if stop as.size then
as.extract start stop
else if start as.size then
(as.extract start as.size).push b
else #[] := by
split
· ext i h₁ h₂
· simp
omega
· simp only [size_extract, size_push] at h₁ h₂
simp only [getElem_extract, getElem_push]
rw [dif_pos (by omega)]
· split
· ext i h₁ h₂
· simp
omega
· simp only [size_extract, size_push] at h₁ h₂
simp only [getElem_extract, getElem_push]
split <;> rename_i h₃
· split
· rfl
· simp_all
omega
· split <;> rename_i h₄
· simp at h₄
omega
· rfl
· ext i h₁ h₂
· simp
omega
· simp at h₂
@[simp]
theorem extract_push_of_le {as : Array α} {b : α} {start stop : Nat} (h : stop as.size) :
(as.push b).extract start stop = as.extract start stop := by
ext i h₁ h
· simp
omega
· simp only [size_extract, size_push] at h₁ h₂
simp only [getElem_extract, getElem_push]
rw [dif_pos (by omega)]
rw [extract_push, if_pos h]
@[simp, grind =]
theorem extract_eq_pop {as : Array α} {stop : Nat} (h : stop = as.size - 1) :
@@ -162,7 +194,7 @@ theorem extract_sub_one {as : Array α} {i j : Nat} (h : j < as.size) :
@[simp]
theorem getElem?_extract_of_lt {as : Array α} {i j k : Nat} (h : k < min j as.size - i) :
(as.extract i j)[k]? = some (as[i + k]'(by omega)) := by
simp [getElem?_extract, h]
simp [h]
theorem getElem?_extract_of_succ {as : Array α} {j : Nat} :
(as.extract 0 (j + 1))[j]? = as[j]? := by

View File

@@ -6,8 +6,10 @@ Authors: François G. Dorais
module
prelude
import Init.Data.List.FinRange
import Init.Data.Array.OfFn
public import Init.Data.List.FinRange
public import Init.Data.Array.OfFn
public section
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
set_option linter.indexVariables true -- Enforce naming conventions for index variables.

View File

@@ -6,11 +6,13 @@ Authors: Kim Morrison
module
prelude
import Init.Data.List.Nat.Find
import all Init.Data.Array.Basic
import Init.Data.Array.Lemmas
import Init.Data.Array.Attach
import Init.Data.Array.Range
public import Init.Data.List.Nat.Find
public import all Init.Data.Array.Basic
public import Init.Data.Array.Lemmas
public import Init.Data.Array.Attach
public import Init.Data.Array.Range
public section
/-!
# Lemmas about `Array.findSome?`, `Array.find?, `Array.findIdx`, `Array.findIdx?`, `Array.idxOf`.
@@ -81,7 +83,7 @@ theorem find?_eq_findSome?_guard {xs : Array α} : find? p xs = findSome? (Optio
@[simp, grind =] theorem getElem_zero_filterMap {f : α Option β} {xs : Array α} (h) :
(xs.filterMap f)[0] = (xs.findSome? f).get (by cases xs; simpa [List.length_filterMap_eq_countP] using h) := by
cases xs; simp [ List.head_eq_getElem, getElem?_zero_filterMap]
cases xs; simp [ getElem?_zero_filterMap]
@[simp, grind =] theorem back?_filterMap {f : α Option β} {xs : Array α} : (xs.filterMap f).back? = xs.findSomeRev? f := by
cases xs; simp
@@ -122,7 +124,7 @@ theorem getElem_zero_flatten.proof {xss : Array (Array α)} (h : 0 < xss.flatten
theorem getElem_zero_flatten {xss : Array (Array α)} (h) :
(flatten xss)[0] = (xss.findSome? fun xs => xs[0]?).get (getElem_zero_flatten.proof h) := by
have t := getElem?_zero_flatten xss
simp [getElem?_eq_getElem, h] at t
simp at t
simp [ t]
@[grind =]
@@ -308,7 +310,7 @@ abbrev find?_flatten_eq_some := @find?_flatten_eq_some_iff
@[simp, grind =] theorem find?_flatMap {xs : Array α} {f : α Array β} {p : β Bool} :
(xs.flatMap f).find? p = xs.findSome? (fun x => (f x).find? p) := by
cases xs
simp [List.find?_flatMap, Array.flatMap_toArray]
simp [List.find?_flatMap]
theorem find?_flatMap_eq_none_iff {xs : Array α} {f : α Array β} {p : β Bool} :
(xs.flatMap f).find? p = none x xs, y f x, !p y := by
@@ -348,7 +350,7 @@ abbrev find?_mkArray_of_neg := @find?_replicate_of_neg
-- This isn't a `@[simp]` lemma since there is already a lemma for `l.find? p = none` for any `l`.
theorem find?_replicate_eq_none_iff {n : Nat} {a : α} {p : α Bool} :
(replicate n a).find? p = none n = 0 !p a := by
simp [ List.toArray_replicate, List.find?_replicate_eq_none_iff, Classical.or_iff_not_imp_left]
simp [ List.toArray_replicate, Classical.or_iff_not_imp_left]
@[deprecated find?_replicate_eq_none_iff (since := "2025-03-18")]
abbrev find?_mkArray_eq_none_iff := @find?_replicate_eq_none_iff
@@ -385,7 +387,7 @@ theorem find?_eq_some_iff_getElem {xs : Array α} {p : α → Bool} {b : α} :
/-! ### findIdx -/
@[grind =]
theorem findIdx_empty : findIdx p #[] = 0 := rfl
theorem findIdx_empty : findIdx p #[] = 0 := by simp
@[grind =]
theorem findIdx_singleton {a : α} {p : α Bool} :
@@ -488,7 +490,7 @@ theorem findIdx_push {xs : Array α} {a : α} {p : α → Bool} :
simp only [push_eq_append, findIdx_append]
split <;> rename_i h
· rfl
· simp [findIdx_singleton, Nat.add_comm]
· simp [Nat.add_comm]
theorem findIdx_le_findIdx {xs : Array α} {p q : α Bool} (h : x xs, p x q x) : xs.findIdx q xs.findIdx p := by
rcases xs with xs
@@ -553,7 +555,7 @@ theorem findIdx?_eq_some_of_exists {xs : Array α} {p : α → Bool} (h : ∃ x,
theorem findIdx?_eq_none_iff_findIdx_eq {xs : Array α} {p : α Bool} :
xs.findIdx? p = none xs.findIdx p = xs.size := by
rcases xs with xs
simp [List.findIdx?_eq_none_iff_findIdx_eq]
simp
theorem findIdx?_eq_guard_findIdx_lt {xs : Array α} {p : α Bool} :
xs.findIdx? p = Option.guard (fun i => i < xs.size) (xs.findIdx p) := by
@@ -798,7 +800,7 @@ The lemmas below should be made consistent with those for `findFinIdx?` (and pro
theorem idxOf?_eq_map_finIdxOf?_val [BEq α] {xs : Array α} {a : α} :
xs.idxOf? a = (xs.finIdxOf? a).map (·.val) := by
simp [idxOf?, finIdxOf?, findIdx?_eq_map_findFinIdx?_val]
simp [idxOf?, finIdxOf?]
@[grind =] theorem finIdxOf?_empty [BEq α] : (#[] : Array α).finIdxOf? a = none := by simp

View File

@@ -7,7 +7,9 @@ Authors: Leonardo de Moura
module
prelude
import Init.Data.Array.Basic
public import Init.Data.Array.Basic
public section
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
set_option linter.indexVariables true -- Enforce naming conventions for index variables.

View File

@@ -6,8 +6,10 @@ Authors: Kim Morrison
module
prelude
import Init.Data.Array.Lemmas
import Init.Data.List.Nat.InsertIdx
public import Init.Data.Array.Lemmas
public import Init.Data.List.Nat.InsertIdx
public section
/-!
# insertIdx
@@ -109,19 +111,19 @@ theorem getElem_insertIdx {xs : Array α} {x : α} {i k : Nat} (w : i ≤ xs.siz
else
xs[k-1]'(by simp [size_insertIdx] at h; omega) := by
cases xs
simp [List.getElem_insertIdx, w]
simp [List.getElem_insertIdx]
theorem getElem_insertIdx_of_lt {xs : Array α} {x : α} {i k : Nat} (w : i xs.size) (h : k < i) :
(xs.insertIdx i x)[k]'(by simp; omega) = xs[k] := by
simp [getElem_insertIdx, w, h]
simp [getElem_insertIdx, h]
theorem getElem_insertIdx_self {xs : Array α} {x : α} {i : Nat} (w : i xs.size) :
(xs.insertIdx i x)[i]'(by simp; omega) = x := by
simp [getElem_insertIdx, w]
simp [getElem_insertIdx]
theorem getElem_insertIdx_of_gt {xs : Array α} {x : α} {i k : Nat} (w : k xs.size) (h : k > i) :
(xs.insertIdx i x)[k]'(by simp; omega) = xs[k - 1]'(by omega) := by
simp [getElem_insertIdx, w, h]
simp [getElem_insertIdx]
rw [dif_neg (by omega), dif_neg (by omega)]
@[grind =]
@@ -135,7 +137,7 @@ theorem getElem?_insertIdx {xs : Array α} {x : α} {i k : Nat} (h : i ≤ xs.si
else
xs[k-1]? := by
cases xs
simp [List.getElem?_insertIdx, h]
simp [List.getElem?_insertIdx]
theorem getElem?_insertIdx_of_lt {xs : Array α} {x : α} {i k : Nat} (w : i xs.size) (h : k < i) :
(xs.insertIdx i x)[k]? = xs[k]? := by

View File

@@ -6,7 +6,9 @@ Authors: Leonardo de Moura
module
prelude
import Init.Data.Array.Basic
public import Init.Data.Array.Basic
public section
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
set_option linter.indexVariables true -- Enforce naming conventions for index variables.

View File

@@ -6,21 +6,23 @@ Authors: Mario Carneiro, Kim Morrison
module
prelude
import Init.Data.Nat.Lemmas
import Init.Data.List.Range
import all Init.Data.List.Control
import Init.Data.List.Nat.TakeDrop
import Init.Data.List.Nat.Modify
import Init.Data.List.Nat.Basic
import Init.Data.List.Monadic
import Init.Data.List.OfFn
import all Init.Data.Array.Bootstrap
import Init.Data.Array.Mem
import Init.Data.Array.DecidableEq
import Init.Data.Array.Lex.Basic
import Init.Data.Range.Lemmas
import Init.TacticsExtra
import Init.Data.List.ToArray
public import Init.Data.Nat.Lemmas
public import Init.Data.List.Range
public import all Init.Data.List.Control
public import Init.Data.List.Nat.TakeDrop
public import Init.Data.List.Nat.Modify
public import Init.Data.List.Nat.Basic
public import Init.Data.List.Monadic
public import Init.Data.List.OfFn
public import all Init.Data.Array.Bootstrap
public import Init.Data.Array.Mem
public import Init.Data.Array.DecidableEq
public import Init.Data.Array.Lex.Basic
public import Init.Data.Range.Lemmas
public import Init.TacticsExtra
public import Init.Data.List.ToArray
public section
/-!
## Theorems about `Array`.
@@ -125,9 +127,9 @@ theorem none_eq_getElem?_iff {xs : Array α} {i : Nat} : none = xs[i]? ↔ xs.si
simp
theorem getElem?_eq_none {xs : Array α} (h : xs.size i) : xs[i]? = none := by
simp [getElem?_eq_none_iff, h]
simp [h]
grind_pattern Array.getElem?_eq_none => xs.size i, xs[i]?
grind_pattern Array.getElem?_eq_none => xs.size, xs[i]?
@[simp] theorem getElem?_eq_getElem {xs : Array α} {i : Nat} (h : i < xs.size) : xs[i]? = some xs[i] :=
getElem?_pos ..
@@ -154,16 +156,16 @@ theorem getElem_eq_iff {xs : Array α} {i : Nat} {h : i < xs.size} : xs[i] = x
exact fun w => h, w, fun h => h.2
theorem getElem_eq_getElem?_get {xs : Array α} {i : Nat} (h : i < xs.size) :
xs[i] = xs[i]?.get (by simp [getElem?_eq_getElem, h]) := by
simp [getElem_eq_iff]
xs[i] = xs[i]?.get (by simp [h]) := by
simp
theorem getD_getElem? {xs : Array α} {i : Nat} {d : α} :
xs[i]?.getD d = if p : i < xs.size then xs[i]'p else d := by
if h : i < xs.size then
simp [h, getElem?_def]
simp [h]
else
have p : i xs.size := Nat.le_of_not_gt h
simp [getElem?_eq_none p, h]
simp [h]
@[simp] theorem getElem?_empty {i : Nat} : (#[] : Array α)[i]? = none := rfl
@@ -175,14 +177,14 @@ theorem getElem_push_lt {xs : Array α} {x : α} {i : Nat} (h : i < xs.size) :
@[simp] theorem getElem_push_eq {xs : Array α} {x : α} : (xs.push x)[xs.size] = x := by
simp only [push, getElem_toList, List.concat_eq_append]
rw [List.getElem_append_right] <;> simp [ getElem_toList, Nat.zero_lt_one]
rw [List.getElem_append_right] <;> simp
@[grind =] theorem getElem_push {xs : Array α} {x : α} {i : Nat} (h : i < (xs.push x).size) :
(xs.push x)[i] = if h : i < xs.size then xs[i] else x := by
by_cases h' : i < xs.size
· simp [getElem_push_lt, h']
· simp at h
simp [getElem_push_lt, Nat.le_antisymm (Nat.le_of_lt_succ h) (Nat.ge_of_not_lt h')]
simp [Nat.le_antisymm (Nat.le_of_lt_succ h) (Nat.ge_of_not_lt h')]
@[grind =] theorem getElem?_push {xs : Array α} {x} : (xs.push x)[i]? = if i = xs.size then some x else xs[i]? := by
simp [getElem?_def, getElem_push]
@@ -870,24 +872,24 @@ theorem elem_eq_mem [BEq α] [LawfulBEq α] {a : α} {xs : Array α} :
@[grind] theorem all_empty [BEq α] {p : α Bool} : (#[] : Array α).all p = true := by simp
/-- Variant of `any_push` with a side condition on `stop`. -/
@[simp, grind] theorem any_push' [BEq α] {xs : Array α} {a : α} {p : α Bool} (h : stop = xs.size + 1) :
@[simp, grind] theorem any_push' {xs : Array α} {a : α} {p : α Bool} (h : stop = xs.size + 1) :
(xs.push a).any p 0 stop = (xs.any p || p a) := by
cases xs
rw [List.push_toArray]
simp [h]
theorem any_push [BEq α] {xs : Array α} {a : α} {p : α Bool} :
theorem any_push {xs : Array α} {a : α} {p : α Bool} :
(xs.push a).any p = (xs.any p || p a) :=
any_push' (by simp)
/-- Variant of `all_push` with a side condition on `stop`. -/
@[simp, grind] theorem all_push' [BEq α] {xs : Array α} {a : α} {p : α Bool} (h : stop = xs.size + 1) :
@[simp, grind] theorem all_push' {xs : Array α} {a : α} {p : α Bool} (h : stop = xs.size + 1) :
(xs.push a).all p 0 stop = (xs.all p && p a) := by
cases xs
rw [List.push_toArray]
simp [h]
theorem all_push [BEq α] {xs : Array α} {a : α} {p : α Bool} :
theorem all_push {xs : Array α} {a : α} {p : α Bool} :
(xs.push a).all p = (xs.all p && p a) :=
all_push' (by simp)
@@ -906,7 +908,7 @@ theorem all_push [BEq α] {xs : Array α} {a : α} {p : α → Bool} :
abbrev getElem_set_eq := @getElem_set_self
@[simp] theorem getElem?_set_self {xs : Array α} {i : Nat} (h : i < xs.size) {v : α} :
(xs.set i v)[i]? = some v := by simp [getElem?_eq_getElem, h]
(xs.set i v)[i]? = some v := by simp [h]
@[deprecated getElem?_set_self (since := "2024-12-11")]
abbrev getElem?_set_eq := @getElem?_set_self
@@ -918,7 +920,7 @@ abbrev getElem?_set_eq := @getElem?_set_self
@[simp] theorem getElem?_set_ne {xs : Array α} {i : Nat} (h : i < xs.size) {v : α} {j : Nat}
(ne : i j) : (xs.set i v)[j]? = xs[j]? := by
by_cases h : j < xs.size <;> simp [getElem?_eq_getElem, getElem?_eq_none, Nat.ge_of_not_lt, ne, h]
by_cases h : j < xs.size <;> simp [ne, h]
@[grind] theorem getElem_set {xs : Array α} {i : Nat} (h' : i < xs.size) {v : α} {j : Nat}
(h : j < (xs.set i v).size) :
@@ -983,12 +985,13 @@ theorem mem_set {xs : Array α} {i : Nat} (h : i < xs.size) {a : α} :
simp [mem_iff_getElem]
exact i, (by simpa using h), by simp
@[grind ]
theorem mem_or_eq_of_mem_set
{xs : Array α} {i : Nat} {a b : α} {w : i < xs.size} (h : a xs.set i b) : a xs a = b := by
cases xs
simpa using List.mem_or_eq_of_mem_set (by simpa using h)
grind_pattern mem_or_eq_of_mem_set => a xs.set i b
/-! ### setIfInBounds -/
@[simp, grind] theorem setIfInBounds_empty {i : Nat} {a : α} :
@@ -1044,7 +1047,7 @@ theorem getElem?_setIfInBounds_self {xs : Array α} {i : Nat} {a : α} :
@[simp]
theorem getElem?_setIfInBounds_self_of_lt {xs : Array α} {i : Nat} {a : α} (h : i < xs.size) :
(xs.setIfInBounds i a)[i]? = some a := by
simp [getElem?_setIfInBounds, h]
simp [h]
@[deprecated getElem?_setIfInBounds_self (since := "2024-12-11")]
abbrev getElem?_setIfInBounds_eq := @getElem?_setIfInBounds_self
@@ -1088,7 +1091,7 @@ theorem mem_or_eq_of_mem_setIfInBounds
@[simp] theorem getD_getElem?_setIfInBounds {xs : Array α} {i : Nat} {v d : α} :
(xs.setIfInBounds i v)[i]?.getD d = if i < xs.size then v else d := by
by_cases h : i < xs.size <;>
simp [setIfInBounds, Nat.not_lt_of_le, h, getD_getElem?]
simp [setIfInBounds, h, ]
@[simp, grind =] theorem toList_setIfInBounds {xs : Array α} {i : Nat} {x : α} :
(xs.setIfInBounds i x).toList = xs.toList.set i x := by
@@ -1200,7 +1203,7 @@ where
mapM.map f xs i bs = (xs.toList.drop i).foldlM (fun bs a => bs.push <$> f a) bs := by
unfold mapM.map; split
· rw [ List.getElem_cons_drop_succ_eq_drop _]
simp only [aux (i + 1), map_eq_pure_bind, length_toList, List.foldlM_cons, bind_assoc,
simp only [aux (i + 1), map_eq_pure_bind, List.foldlM_cons, bind_assoc,
pure_bind]
rfl
· rw [List.drop_of_length_le (Nat.ge_of_not_lt _)]; rfl
@@ -1673,12 +1676,12 @@ theorem filterMap_eq_map' {f : α → β} (w : stop = as.size) :
filterMap (fun x => some (f x)) as 0 stop = map f as :=
filterMap_eq_map w
@[simp] theorem filterMap_some_fun : filterMap (some : α Option α) = id := by
theorem filterMap_some_fun : filterMap (some : α Option α) = id := by
funext xs
cases xs
simp
@[grind] theorem filterMap_some {xs : Array α} : filterMap some xs = xs := by
@[simp, grind] theorem filterMap_some {xs : Array α} : filterMap some xs = xs := by
cases xs
simp
@@ -1755,7 +1758,7 @@ theorem forall_mem_filterMap {f : α → Option β} {xs : Array α} {P : β →
theorem map_filterMap_of_inv {f : α Option β} {g : β α} (H : x : α, (f x).map g = some x) {xs : Array α} :
map g (filterMap f xs) = xs := by
simp only [map_filterMap, H, filterMap_some, id]
simp only [map_filterMap, H, filterMap_some]
@[grind ]
theorem forall_none_of_filterMap_eq_empty (h : filterMap f xs = #[]) : x xs, f x = none := by
@@ -1894,7 +1897,7 @@ theorem getElem?_append_left {xs ys : Array α} {i : Nat} (hn : i < xs.size) :
(xs ++ ys)[i]? = xs[i]? := by
have hn' : i < (xs ++ ys).size := Nat.lt_of_lt_of_le hn <|
size_append .. Nat.le_add_right ..
simp_all [getElem?_eq_getElem, getElem_append]
simp_all
theorem getElem?_append_right {xs ys : Array α} {i : Nat} (h : xs.size i) :
(xs ++ ys)[i]? = ys[i - xs.size]? := by
@@ -2025,7 +2028,7 @@ theorem append_eq_singleton_iff {xs ys : Array α} {x : α} :
xs ++ ys = #[x] (xs = #[] ys = #[x]) (xs = #[x] ys = #[]) := by
rcases xs with xs
rcases ys with ys
simp only [List.append_toArray, mk.injEq, List.append_eq_singleton_iff, toArray_eq_append_iff]
simp only [List.append_toArray, mk.injEq, List.append_eq_singleton_iff]
theorem singleton_eq_append_iff {xs ys : Array α} {x : α} :
#[x] = xs ++ ys (xs = #[] ys = #[x]) (xs = #[x] ys = #[]) := by
@@ -2351,7 +2354,7 @@ theorem flatMap_toArray {β} {f : α → Array β} {as : List α} :
theorem size_flatMap {xs : Array α} {f : α Array β} :
(xs.flatMap f).size = sum (map (fun a => (f a).size) xs) := by
rcases xs with l
simp [Function.comp_def]
simp
@[simp, grind] theorem mem_flatMap {f : α Array β} {b} {xs : Array α} : b xs.flatMap f a, a xs b f a := by
simp [flatMap_def, mem_flatten]
@@ -2569,7 +2572,7 @@ abbrev map_mkArray := @map_replicate
@[grind] theorem filter_replicate (w : stop = n) :
(replicate n a).filter p 0 stop = if p a then replicate n a else #[] := by
apply Array.ext'
simp only [w, toList_filter', toList_replicate, List.filter_replicate]
simp only [w]
split <;> simp_all
@[deprecated filter_replicate (since := "2025-03-18")]
@@ -2609,7 +2612,7 @@ abbrev filterMap_mkArray_of_some := @filterMap_replicate_of_some
@[simp] theorem filterMap_replicate_of_isSome {f : α Option β} (h : (f a).isSome) :
(replicate n a).filterMap f = replicate n (Option.get _ h) := by
match w : f a, h with
| some b, _ => simp [filterMap_replicate, h, w]
| some b, _ => simp [filterMap_replicate, w]
@[deprecated filterMap_replicate_of_isSome (since := "2025-03-18")]
abbrev filterMap_mkArray_of_isSome := @filterMap_replicate_of_isSome
@@ -2644,7 +2647,7 @@ abbrev flatten_mkArray_replicate := @flatten_replicate_replicate
theorem flatMap_replicate {f : α Array β} : (replicate n a).flatMap f = (replicate n (f a)).flatten := by
rw [ toList_inj]
simp [flatMap_toList, List.flatMap_replicate]
simp [List.flatMap_replicate]
@[deprecated flatMap_replicate (since := "2025-03-18")]
abbrev flatMap_mkArray := @flatMap_replicate
@@ -4142,7 +4145,7 @@ theorem getElem_modify_of_ne {xs : Array α} {i : Nat} (h : i ≠ j)
@[simp] theorem getElem_swap_right {xs : Array α} {i j : Nat} {hi hj} :
(xs.swap i j hi hj)[j]'(by simpa using hj) = xs[i] := by
simp [swap_def, getElem_set]
simp [swap_def]
@[simp] theorem getElem_swap_left {xs : Array α} {i j : Nat} {hi hj} :
(xs.swap i j hi hj)[i]'(by simpa using hi) = xs[j] := by
@@ -4439,7 +4442,7 @@ theorem size_uset {xs : Array α} {v : α} {i : USize} (h : i.toNat < xs.size) :
@[simp] theorem getD_eq_getD_getElem? {xs : Array α} {i : Nat} {d : α} :
xs.getD i d = xs[i]?.getD d := by
simp only [getD]; split <;> simp [getD_getElem?, *]
simp only [getD]; split <;> simp [*]
theorem getElem!_eq_getD [Inhabited α] {xs : Array α} {i} : xs[i]! = xs.getD i default := by
rfl
@@ -4467,13 +4470,13 @@ theorem getElem?_size_le {xs : Array α} {i : Nat} (h : xs.size ≤ i) : xs[i]?
simp [getElem?_neg, h]
theorem getElem_mem_toList {xs : Array α} {i : Nat} (h : i < xs.size) : xs[i] xs.toList := by
simp only [ getElem_toList, List.getElem_mem, ugetElem_eq_getElem]
simp only [ getElem_toList, List.getElem_mem]
theorem back!_eq_back? [Inhabited α] {xs : Array α} : xs.back! = xs.back?.getD default := by
simp [back!, back?, getElem!_def, Option.getD]; rfl
@[simp, grind] theorem back?_push {xs : Array α} {x : α} : (xs.push x).back? = some x := by
simp [back?, getElem?_toList]
simp [back?]
@[simp] theorem back!_push [Inhabited α] {xs : Array α} {x : α} : (xs.push x).back! = x := by
simp [back!_eq_back?]
@@ -4622,7 +4625,7 @@ theorem uset_toArray {l : List α} {i : USize} {a : α} {h : i.toNat < l.toArray
@[simp, grind =] theorem flatten_toArray {L : List (List α)} :
(L.toArray.map List.toArray).flatten = L.flatten.toArray := by
apply ext'
simp [Function.comp_def]
simp
end List
@@ -4714,7 +4717,7 @@ namespace List
intro h'
specialize ih (by omega)
have : as.length - (i + 1) + 1 = as.length - i := by omega
simp_all [ih]
simp_all
· simp only [size_toArray, Nat.not_lt] at h
have : as.length = 0 := by omega
simp_all
@@ -4725,7 +4728,7 @@ end List
namespace Array
@[deprecated size_toArray (since := "2024-12-11")]
theorem size_mk (as : List α) : (Array.mk as).size = as.length := by simp [size]
theorem size_mk (as : List α) : (Array.mk as).size = as.length := by simp
@[deprecated getElem?_eq_getElem (since := "2024-12-11")]
theorem getElem?_lt
@@ -4741,7 +4744,7 @@ theorem get?_eq_getElem? (xs : Array α) (i : Nat) : xs.get? i = xs[i]? := rfl
@[deprecated getElem?_eq_none (since := "2024-12-11")]
theorem getElem?_len_le (xs : Array α) {i : Nat} (h : xs.size i) : xs[i]? = none := by
simp [getElem?_eq_none, h]
simp [h]
@[deprecated getD_getElem? (since := "2024-12-11")] abbrev getD_get? := @getD_getElem?
@@ -4756,7 +4759,7 @@ set_option linter.deprecated false in
theorem get!_eq_getD_getElem? [Inhabited α] (xs : Array α) (i : Nat) :
xs.get! i = xs[i]?.getD default := by
by_cases p : i < xs.size <;>
simp [get!, getElem!_eq_getD, getD_eq_getD_getElem?, getD_getElem?, p]
simp [get!, getD_eq_getD_getElem?, p]
set_option linter.deprecated false in
@[deprecated get!_eq_getD_getElem? (since := "2025-02-12")] abbrev get!_eq_getElem? := @get!_eq_getD_getElem?

View File

@@ -6,5 +6,7 @@ Author: Kim Morrison
module
prelude
import Init.Data.Array.Lex.Basic
import Init.Data.Array.Lex.Lemmas
public import Init.Data.Array.Lex.Basic
public import Init.Data.Array.Lex.Lemmas
public section

View File

@@ -6,9 +6,14 @@ Author: Kim Morrison
module
prelude
public import Init.Core
import Init.Data.Array.Basic
import Init.Data.Nat.Lemmas
import Init.Data.Range
import Init.Data.Range.Polymorphic.Iterators
import Init.Data.Range.Polymorphic.Nat
import Init.Data.Iterators.Consumers
public section
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
@@ -24,9 +29,9 @@ Specifically, `Array.lex as bs lt` is true if
* there is an index `i` such that `lt as[i] bs[i]`, and for all `j < i`, `as[j] == bs[j]`.
-/
def lex [BEq α] (as bs : Array α) (lt : α α Bool := by exact (· < ·)) : Bool := Id.run do
for h : i in [0 : min as.size bs.size] do
-- TODO: `omega` should be able to find this itself.
have : i < min as.size bs.size := Membership.get_elem_helper h rfl
for h : i in 0...(min as.size bs.size) do
-- TODO: `get_elem_tactic` should be able to find this itself.
have : i < min as.size bs.size := Std.PRange.lt_upper_of_mem h
if lt as[i] bs[i] then
return true
else if as[i] != bs[i] then

View File

@@ -7,8 +7,13 @@ module
prelude
import all Init.Data.Array.Lex.Basic
import Init.Data.Array.Lemmas
import Init.Data.List.Lex
public import Init.Data.Array.Lex.Basic
public import Init.Data.Array.Lemmas
public import Init.Data.List.Lex
import Init.Data.Range.Polymorphic.Lemmas
import Init.Data.Range.Polymorphic.NatLemmas
public section
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
@@ -17,28 +22,55 @@ namespace Array
/-! ### Lexicographic ordering -/
@[simp, grind =] theorem _root_.List.lt_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray < l₂.toArray l₁ < l₂ := Iff.rfl
@[simp, grind =] theorem _root_.List.le_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray l₂.toArray l₁ l₂ := Iff.rfl
@[simp] theorem _root_.List.lt_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray < l₂.toArray l₁ < l₂ := Iff.rfl
@[simp] theorem _root_.List.le_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray l₂.toArray l₁ l₂ := Iff.rfl
@[simp, grind =] theorem lt_toList [LT α] {xs ys : Array α} : xs.toList < ys.toList xs < ys := Iff.rfl
@[simp, grind =] theorem le_toList [LT α] {xs ys : Array α} : xs.toList ys.toList xs ys := Iff.rfl
@[simp] theorem lt_toList [LT α] {xs ys : Array α} : xs.toList < ys.toList xs < ys := Iff.rfl
@[simp] theorem le_toList [LT α] {xs ys : Array α} : xs.toList ys.toList xs ys := Iff.rfl
grind_pattern _root_.List.lt_toArray => l₁.toArray < l₂.toArray
grind_pattern _root_.List.le_toArray => l₁.toArray l₂.toArray
grind_pattern lt_toList => xs.toList < ys.toList
grind_pattern le_toList => xs.toList ys.toList
protected theorem not_lt_iff_ge [LT α] {xs ys : Array α} : ¬ xs < ys ys xs := Iff.rfl
protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] {xs ys : Array α} :
protected theorem not_le_iff_gt [LT α] {xs ys : Array α} :
¬ xs ys ys < xs :=
Decidable.not_not
Classical.not_not
@[simp] theorem lex_empty [BEq α] {lt : α α Bool} {xs : Array α} : xs.lex #[] lt = false := by
simp [lex]
rw [lex, Std.PRange.forIn'_eq_match]
simp [Std.PRange.SupportsUpperBound.IsSatisfied]
private theorem cons_lex_cons.forIn'_congr_aux [Monad m] {as bs : ρ} {_ : Membership α ρ}
[ForIn' m ρ α inferInstance] (w : as = bs)
{b b' : β} (hb : b = b')
{f : (a' : α) a' as β m (ForInStep β)}
{g : (a' : α) a' bs β m (ForInStep β)}
(h : a m b, f a (by simpa [w] using m) b = g a m b) :
forIn' as b f = forIn' bs b' g := by
cases hb
cases w
have : f = g := by
ext a ha acc
apply h
cases this
rfl
private theorem cons_lex_cons [BEq α] {lt : α α Bool} {a b : α} {xs ys : Array α} :
(#[a] ++ xs).lex (#[b] ++ ys) lt =
(lt a b || a == b && xs.lex ys lt) := by
simp only [lex]
simp only [Std.Range.forIn'_eq_forIn'_range', size_append, List.size_toArray, List.length_singleton,
Nat.add_comm 1]
simp [Nat.add_min_add_right, List.range'_succ, getElem_append_left, List.range'_succ_left,
getElem_append_right]
simp only [lex, size_append, List.size_toArray, List.length_cons, List.length_nil, Nat.zero_add,
Nat.add_min_add_left, Nat.add_lt_add_iff_left, Std.PRange.forIn'_eq_forIn'_toList]
conv =>
lhs; congr; congr
rw [cons_lex_cons.forIn'_congr_aux Std.PRange.toList_eq_match rfl (fun _ _ _ => rfl)]
simp only [Std.PRange.SupportsUpperBound.IsSatisfied, bind_pure_comp, map_pure]
rw [cons_lex_cons.forIn'_congr_aux (if_pos (by omega)) rfl (fun _ _ _ => rfl)]
simp only [Std.PRange.toList_open_eq_toList_closed_of_isSome_succ? (lo := 0) (h := rfl),
Std.PRange.UpwardEnumerable.succ?, Nat.add_comm 1, Std.PRange.Nat.ClosedOpen.toList_succ_succ,
Option.get_some, List.forIn'_cons, List.size_toArray, List.length_cons, List.length_nil,
Nat.lt_add_one, getElem_append_left, List.getElem_toArray, List.getElem_cons_zero]
cases lt a b
· rw [bne]
cases a == b <;> simp
@@ -47,10 +79,17 @@ private theorem cons_lex_cons [BEq α] {lt : αα → Bool} {a b : α} {xs
@[simp, grind =] theorem _root_.List.lex_toArray [BEq α] {lt : α α Bool} {l₁ l₂ : List α} :
l₁.toArray.lex l₂.toArray lt = l₁.lex l₂ lt := by
induction l₁ generalizing l₂ with
| nil => cases l₂ <;> simp [lex]
| nil =>
cases l₂
· rw [lex, Std.PRange.forIn'_eq_match]
simp [Std.PRange.SupportsUpperBound.IsSatisfied]
· rw [lex, Std.PRange.forIn'_eq_match]
simp [Std.PRange.SupportsUpperBound.IsSatisfied]
| cons x l₁ ih =>
cases l₂ with
| nil => simp [lex]
| nil =>
rw [lex, Std.PRange.forIn'_eq_match]
simp [Std.PRange.SupportsUpperBound.IsSatisfied]
| cons y l₂ =>
rw [List.toArray_cons, List.toArray_cons y, cons_lex_cons, List.lex, ih]
@@ -92,7 +131,7 @@ instance [LT α] [Trans (· < · : αα → Prop) (· < ·) (· < ·)] :
Trans (· < · : Array α Array α Prop) (· < ·) (· < ·) where
trans h₁ h₂ := Array.lt_trans h₁ h₂
protected theorem lt_of_le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
protected theorem lt_of_le_of_lt [LT α]
[i₀ : Std.Irrefl (· < · : α α Prop)]
[i₁ : Std.Asymm (· < · : α α Prop)]
[i₂ : Std.Antisymm (¬ · < · : α α Prop)]
@@ -100,7 +139,7 @@ protected theorem lt_of_le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
{xs ys zs : Array α} (h₁ : xs ys) (h₂ : ys < zs) : xs < zs :=
List.lt_of_le_of_lt h₁ h₂
protected theorem le_trans [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_trans [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
@@ -108,7 +147,7 @@ protected theorem le_trans [DecidableEq α] [LT α] [DecidableLT α]
{xs ys zs : Array α} (h₁ : xs ys) (h₂ : ys zs) : xs zs :=
fun h₃ => h₁ (Array.lt_of_le_of_lt h₂ h₃)
instance [DecidableEq α] [LT α] [DecidableLT α]
instance [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
@@ -120,34 +159,34 @@ protected theorem lt_asymm [LT α]
[i : Std.Asymm (· < · : α α Prop)]
{xs ys : Array α} (h : xs < ys) : ¬ ys < xs := List.lt_asymm h
instance [DecidableEq α] [LT α] [DecidableLT α]
instance [LT α]
[Std.Asymm (· < · : α α Prop)] :
Std.Asymm (· < · : Array α Array α Prop) where
asymm _ _ := Array.lt_asymm
protected theorem le_total [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_total [LT α]
[i : Std.Total (¬ · < · : α α Prop)] (xs ys : Array α) : xs ys ys xs :=
List.le_total xs.toList ys.toList
@[simp] protected theorem not_lt [LT α]
{xs ys : Array α} : ¬ xs < ys ys xs := Iff.rfl
@[simp] protected theorem not_le [DecidableEq α] [LT α] [DecidableLT α]
{xs ys : Array α} : ¬ ys xs xs < ys := Decidable.not_not
@[simp] protected theorem not_le [LT α]
{xs ys : Array α} : ¬ ys xs xs < ys := Classical.not_not
protected theorem le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_of_lt [LT α]
[i : Std.Total (¬ · < · : α α Prop)]
{xs ys : Array α} (h : xs < ys) : xs ys :=
List.le_of_lt h
protected theorem le_iff_lt_or_eq [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_iff_lt_or_eq [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
[Std.Total (¬ · < · : α α Prop)]
{xs ys : Array α} : xs ys xs < ys xs = ys := by
simpa using List.le_iff_lt_or_eq (l₁ := xs.toList) (l₂ := ys.toList)
instance [DecidableEq α] [LT α] [DecidableLT α]
instance [LT α]
[Std.Total (¬ · < · : α α Prop)] :
Std.Total (· · : Array α Array α Prop) where
total := Array.le_total
@@ -162,7 +201,7 @@ instance [DecidableEq α] [LT α] [DecidableLT α]
{xs ys : Array α} : lex xs ys = false ys xs := by
cases xs
cases ys
simp [List.not_lt_iff_ge]
simp
instance [DecidableEq α] [LT α] [DecidableLT α] : DecidableLT (Array α) :=
fun xs ys => decidable_of_iff (lex xs ys = true) lex_eq_true_iff_lt
@@ -216,7 +255,7 @@ theorem lex_eq_false_iff_exists [BEq α] [PartialEquivBEq α] (lt : αα
cases l₂
simp_all [List.lex_eq_false_iff_exists]
protected theorem lt_iff_exists [DecidableEq α] [LT α] [DecidableLT α] {xs ys : Array α} :
protected theorem lt_iff_exists [LT α] {xs ys : Array α} :
xs < ys
(xs = ys.take xs.size xs.size < ys.size)
( (i : Nat) (h₁ : i < xs.size) (h₂ : i < ys.size),
@@ -226,7 +265,7 @@ protected theorem lt_iff_exists [DecidableEq α] [LT α] [DecidableLT α] {xs ys
cases ys
simp [List.lt_iff_exists]
protected theorem le_iff_exists [DecidableEq α] [LT α] [DecidableLT α]
protected theorem le_iff_exists [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)] {xs ys : Array α} :
@@ -246,7 +285,7 @@ theorem append_left_lt [LT α] {xs ys zs : Array α} (h : ys < zs) :
cases zs
simpa using List.append_left_lt h
theorem append_left_le [DecidableEq α] [LT α] [DecidableLT α]
theorem append_left_le [LT α]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]
@@ -270,7 +309,7 @@ protected theorem map_lt [LT α] [LT β]
cases ys
simpa using List.map_lt w h
protected theorem map_le [DecidableEq α] [LT α] [DecidableLT α] [DecidableEq β] [LT β] [DecidableLT β]
protected theorem map_le [LT α] [LT β]
[Std.Irrefl (· < · : α α Prop)]
[Std.Asymm (· < · : α α Prop)]
[Std.Antisymm (¬ · < · : α α Prop)]

Some files were not shown because too many files have changed in this diff Show More