Compare commits

...

149 Commits

Author SHA1 Message Date
Kim Morrison
358bb770f7 feat: insertMany_append lemmas for map variants 2025-04-30 18:53:44 +02:00
Kim Morrison
86db67c444 chore: add failing grind test (#8179) 2025-04-30 14:54:51 +00:00
Kim Morrison
a9f4170372 feat: lemmas about List/Array/Vector.contains (#8175)
This PR adds simp/grind lemmas about `List`/`Array`/`Vector.contains`.
In the presence of `LawfulBEq` these effectively already held, via
simplifying `contains` to `mem`, but now these also fire without
`LawfulBEq`.
2025-04-30 14:38:56 +00:00
Kim Morrison
7ffeacf967 chore: move Array.qsort to Basic file (#8177)
No change to content, just moving into a subdirectory, to ease keeping a
branch adding theorems in sync.
2025-04-30 13:32:05 +00:00
Kim Morrison
8a8b9e4556 chore: further cleanup of the if-normalization example (#8176) 2025-04-30 13:02:08 +00:00
Sebastian Ullrich
4c497eaa32 chore: disable #print axioms under the module system (#8174)
No need for extra tracking to enable it considering how easy it is to
opt out
2025-04-30 12:00:09 +00:00
Marc Huisinga
98b864d25b fix: broken import completion (#8164)
This PR fixes import completion being broken by the recent changes to
import syntax for the module system.

Fixes #8162.
2025-04-30 11:31:45 +00:00
Sebastian Ullrich
e2f757d5a7 feat: private import and import all (#8159)
This PR adds support for the following import variants to the
experimental module system:

* `private import`: Makes the imported constants available only in
non-exported contexts such as proofs. In particular, the import will not
be loaded, or required to exist at all, when the current module is
imported into other modules.
* `import all`: Makes non-exported information such as proofs of the
imported module available in non-exported contexts in the current
module. Main purpose is to allow for reasoning about imported
definitions when they would otherwise be opaque. TODO: adjust name
resolution so that imported `private` decls are accessible through
syntax.

They can be combined into `private import all`, which will likely be the
most common usage of `import all`.
2025-04-30 10:06:54 +00:00
Joachim Breitner
d16862fd33 feat: induction: allow complex arguments to motive in conclusion of eliminator (#8096)
This PR lets `induction` accept eliminator where the motive application
in the conclusion has complex arguments; these are abstracted over using
`kabstract` if possible. This feature will go well with unfolding
induction principles (#8088).
2025-04-30 08:56:17 +00:00
Siddharth
0f7eb710e2 feat: add bv-concat-extract normalization simprocs (#8077)
This PR adds simprocs to simplify appends of non-overlapping Bitvector
adds. We add a simproc instead of just a `simp` lemma to ensure that we
correctly rewrite bitvector appends. Since bitvector appends lead to
computation at the bitvector width level, it seems to be more stable to
write a simproc.

As I write this, I realize that I can maybe write the `simp` lemma using
`no_index` to recover the same behaviour, so I'll try that too.
2025-04-30 08:31:38 +00:00
Leonardo de Moura
a1989c2387 feat: infrastructure for creating stepwise proof terms in the commutative ring procedure in grind (#8170)
This PR adds the infrastructure for creating stepwise proof terms in the
commutative procedure used in `grind`.
2025-04-30 05:01:02 +00:00
Lean stage0 autoupdater
9168840e2b chore: update stage0 2025-04-30 04:03:29 +00:00
Mac Malone
de0187ab8b fix: lake: extern_lib loading in non-precompiled module builds (#8152)
This PR fixes a regression where non-precompiled module builds would
`--load-dynlib` package `extern_lib` targets.

A reappearance of #4565. Thanks to Daniil [on
Zulip](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Multiple.20extern_lib/near/514772675)
for the report! This was not caught by the old test due to the removal
of `extern_lib` from the FFI example.
2025-04-30 01:04:59 +00:00
Leonardo de Moura
0eb9671787 fix: proof term for Nullstellensatz certificate (#8168)
This PR fixes a bug when constructing the proof term for a
Nullstellensatz certificate produced by the new commutative ring
procedure in `grind`. The kernel was rejecting the proof term.
2025-04-30 01:03:57 +00:00
Leonardo de Moura
e0230d8377 perf: improve heuristics for commutative ring procedure in grind (#8167)
This PR improves the heuristics used to compute the basis and simplify
polynomials in the commutative procedure used in `grind`.
2025-04-29 22:35:36 +00:00
Markus Himmel
925e53fcba fix: include libuv outside of namespace (#8166)
This PR makes sure we never `#include <uv.h>` while inside a namespace,
which recent GCC versions don't seem to like.
2025-04-29 22:19:17 +00:00
Kim Morrison
a4f2c51049 chore: add failing grind +ring tests (#8163)
This PR adds some currently failing tests for `grind +ring`, resulting
in either kernel type mismatches (bugs) or a kernel deep recursion
(perhaps just a too-large problem).
2025-04-29 21:30:43 +00:00
Henrik Böving
7b6c16a44b feat: implement a Selector for async UDP (#8139)
This PR is a follow up to #8055 and implements a `Selector` for async
UDP in order to allow IO multiplexing using UDP sockets.

The technical approach taken for this PR is basically a copy of #8078
but adjusted for UDP. The libuv API gives the same guarantee that was
used in that PR.
2025-04-29 21:01:14 +00:00
Kim Morrison
febf6c10f0 fix: update Grind.CommRing to avoid constructing non-defeq NatCast instance (#8161)
This PR changes `Lean.Grind.CommRing` to inline the `NatCast` instance
(i.e. to be provided by the user) rather than constructing one from the
existing data. Without this change we can't construct instances in
Mathlib that `grind` can use.
2025-04-29 16:50:54 +00:00
Joachim Breitner
3d1d8fc1de feat: unfolding functional induction principles (#8088)
This PR adds the “unfolding” variant of the functional induction and
functional cases principles, under the name `foo.induct_unfolding` resp.
`foo.fun_cases_unfolding`. These theorems combine induction over the
structure of a recursive function with the unfolding of that function,
and should be more reliable, easier to use and more efficient than just
case-splitting and then rewriting with equational theorems.

For example  instead of
```
ackermann.induct
  (motive : Nat → Nat → Prop)
  (case1 : ∀ (m : Nat), motive 0 m)
  (case2 : ∀ (n : Nat), motive n 1 → motive (Nat.succ n) 0)
  (case3 : ∀ (n m : Nat), motive (n + 1) m → motive n (ackermann (n + 1) m) → motive (Nat.succ n) (Nat.succ m))
  (x x : Nat) : motive x x
```
one gets
```
ackermann.fun_cases_unfolding
  (motive : Nat → Nat → Nat → Prop)
  (case1 : ∀ (m : Nat), motive 0 m (m + 1))
  (case2 : ∀ (n : Nat), motive n.succ 0 (ackermann n 1))
  (case3 : ∀ (n m : Nat), motive n.succ m.succ (ackermann n (ackermann (n + 1) m)))
  (x✝ x✝¹ : Nat) : motive x✝ x✝¹ (ackermann x✝ x✝¹)
```
2025-04-29 16:43:06 +00:00
Rob23oba
b5cfd86a89 fix: Substring.isNat for empty string (#8067)
This PR fixes the behavior of `Substring.isNat` to disallow empty
strings.

Closes #8005
2025-04-29 15:54:29 +00:00
Henrik Böving
eaa5d3498c feat: implement a Selector for channels (#8150)
This PR is a follow up to #8055 and implements a Selector for
`Std.Channel` in order to allow
 multiplexing using channels.

There is one subtlety to the implementation: Suppose we are in a
situation where we run `select` in a loop on two channels. One of the
channels is always quiet while the other has data available occasionally
(however not always as this would trigger the `tryFn` fast path and hide
the issue). In this situation the select receivers that are enqueued on
the silent channel would usually just remain there indefinitely as
nothing ever happens, causing a memleak. To avoid this we want to make a
channel select clean up after itself, even if it fails.

In an imperative programming language we could implement the receive
queue as a doubly linked list and simply make each receive select
maintain a pointer to its element in the queue and then remove itself in
`O(1)` upon failure. As that is not possible in Lean trivially we
decided to go for another approach for now: simply filter the queue for
selects that have failed in `unregisterFn`. While this approach is
`O(n)` we expect the amount of receivers enqueued on a channel to not be
terribly large and thus this to be a reasonably fast operation compared
to the remaining overhead. If it ever ends up becoming an issue, we
could switch to an approach that uses a `TreeMap` with numbered
receivers instead at a certain wait queue size and go to `O(log(n))`.
2025-04-29 15:15:38 +00:00
Sebastian Ullrich
db35bbb1a0 test: disable flaky test 2025-04-29 17:34:10 +02:00
Tom Levy
877d51bb15 doc: fix time complexity of List.merge (#8116)
This PR fixes a mistake in documented time complexity of List.merge.

The running time would only be `O(min |l| |r|)` in the very specific
best case where all the elements in the shorter list are less than all
the elements in the longer list. The worst-case (and average-case) time
complexity is `O(|l| + |r|)`.

Also update the variables in the time complexity to match the names of
the parameters.
2025-04-29 11:02:44 +00:00
Sebastian Ullrich
b677702b02 chore: update stage0 2025-04-29 11:01:57 +02:00
Sebastian Ullrich
d544ca5174 chore: fix default of Import.isExported 2025-04-29 10:58:27 +02:00
Rob23oba
9f06aff834 feat: optimized division without remainder for Int and Nat (#8089)
This PR adds optimized division functions for `Int` and `Nat` when the
arguments are known to be divisible (such as when normalizing
rationals). These are backed by the gmp functions `mpz_divexact` and
`mpz_divexact_ui`. See also leanprover-community/batteries#1202.
2025-04-29 07:23:35 +00:00
Cameron Zwarich
2929d547dc fix: make the lcnf expr cache depend on the value of root, not just… (#8156)
This PR fixes a bug where the old compiler's lcnf conversion expr cache
was not including all of the relevant information in the key, leading to
terms inadvertently being erased. The `root` variable is used to
determine whether lambda arguments to applications should get let
bindings or not, which in turn affects later decisions about type
erasure (erase_irrelevant assumes that any non-atomic argument is
irrelevant).
2025-04-29 00:37:52 +00:00
Leonardo de Moura
245ed056a3 fix: grind +splitImp, arrow propagator, missing normalization rule (#8158)
This PR fixes the `grind +splitImp` and the arrow propagator. Given `p :
Prop`, the propagator was incorrectly assuming `A` was always a
proposition in an arrow `A -> p`. This PR also adds a missing
normalization rule to `grind`.
2025-04-28 22:59:43 +00:00
Sebastian Ullrich
eaf1c6b4e1 fix: replayConst with native_decide (#8157)
This PR fixes an incompatibility of `replayConst` as used by e.g.
`aesop` with `native_decide`-using tactics such as `bv_decide`
2025-04-28 20:35:15 +00:00
Cameron Zwarich
d1ed57e92a fix: support borrowed params in the new compiler (#8127)
This PR adds support for borrowed params in the new compiler, which
requires adding support for .mdata expressions to LCNF type handling.
2025-04-28 17:02:47 +00:00
Sebastian Ullrich
0afcda8654 chore: robustify Nix shell (#8141)
* use tarballs directly from releases.nixos.org instead of GitHub
zipballs
* build cadical from source like everyone else since it's so small
2025-04-28 15:08:32 +00:00
Markus Himmel
290507396a chore: Option.guard accepts Bool predicate instead of Prop predicate (#8144)
This PR changes the predicate for `Option.guard` to be `p : α → Bool`
instead of `p : α → Prop`. This brings it in line with other comparable
functions like `Option.filter`.
2025-04-28 13:57:07 +00:00
Kim Morrison
8b3d70d2ab chore: fix statements of HashMap.getKey_insert (#8146) 2025-04-28 13:56:39 +00:00
Kim Morrison
b2ea6b6a02 feat: initial @[grind] attributes for List/Array/Vector (#8136)
This PR adds an initial set of `@[grind]` annotations for
`List`/`Array`/`Vector`, enough to set up some regression tests using
`grind` in proofs about `List`. More annotations to follow.
2025-04-28 13:48:20 +00:00
Kim Morrison
d10d17ce03 chore: add HashMap/TreeMap.isSome_X simp lemmas (#8143)
These lemmas were previously only stated the other way round, but in
this direction they are both good simp lemmas, and good grind lemmas.
2025-04-28 13:48:06 +00:00
Joachim Breitner
bca36b2eba refactor: realizeConst: do not set declPrefix (#8107)
This PR makes `realizeConst` to not set a `declPrefix`. This allows the
realization of both `foo.eq_def` and `bar.eq_def`, where `foo` and `bar`
are mutually recursive, all attached to the same function's environment.
2025-04-28 13:43:52 +00:00
Kim Morrison
573d824b81 feat: add List.eraseDupsBy and basic lemmas (#8148)
This PR generalises `List.eraseDups` to allow for an arbitrary
comparison relation. Further, it proves `eraseDups_append : (as ++
bs).eraseDups = as.eraseDups ++ (bs.removeAll as).eraseDups`.
2025-04-28 11:12:41 +00:00
Kim Morrison
436ebdad78 feat: add List.findRev? and findSomeRev?, and simp lemmas (#8147)
This PR adds `List.findRev?` and `List.findSomeRev?`, for parity with
the existing Array API, and simp lemmas converting these into existing
operations.
2025-04-28 11:09:51 +00:00
Lean stage0 autoupdater
6c9158b5b7 chore: update stage0 2025-04-28 11:29:55 +00:00
Kim Morrison
ecf690f1f1 chore: failing test for grind (#8065)
This PR adds a (failing) test case for an obstacle I've been running
into setting up `grind` for `HashMap`.
2025-04-28 10:46:19 +00:00
Sebastian Ullrich
eb559d58a8 refactor: introduce VisibilityMap in Lean.Environment, use it to split base in preparation for private import (#8145) 2025-04-28 10:17:18 +00:00
Kim Morrison
0b634e59f0 chore: add @[simp] to HashMap.get_getKey? (#8140) 2025-04-28 09:07:21 +00:00
Rob23oba
747ea853b5 feat: extensional hash maps (#8004)
This PR adds extensional hash maps and hash sets under the names
`Std.ExtDHashMap`, `Std.ExtHashMap` and `Std.ExtHashSet`. Extensional
hash maps work like regular hash maps, except that they have
extensionality lemmas which make them easier to use in proofs. This
however makes it also impossible to regularly iterate over its entries.
2025-04-28 06:48:25 +00:00
Leonardo de Moura
2ba021ecc2 fix: equality propagation and simplification in the comm ring procedure (#8137)
This PR improves equality propagation (also known as theory combination)
and polynomial simplification for rings that do not implement the
`NoZeroNatDivisors` class. With these fixes, `grind` can now solve:
```lean
example [CommRing α] (a b c : α) (f : α → Nat)
  : a + b + c = 3 →
    a^2 + b^2 + c^2 = 5 →
    a^3 + b^3 + c^3 = 7 →
    f (a^4 + b^4) + f (9 - c^4) ≠ 1 := by
  grind +ring
```
This example uses the commutative ring procedure, the linear integer
arithmetic solver, and congruence closure.
For rings that implement `NoZeroNatDivisors`, a polynomial is now also
divided by the greatest common divisor (gcd) of its coefficients when it
is inserted into the basis.
2025-04-28 00:55:18 +00:00
Leonardo de Moura
b77e9edd44 feat: add checkInvariants to CommRing (#8135)
This PR implements the sanity check function `CommRing.checkInvariants`.
2025-04-27 21:43:10 +00:00
Sebastian Ullrich
1b1c05916f chore: refine module imports (#8120)
* bump whole imported module closure to private if necessary
* disallow import of non-`module` from `module`
2025-04-27 20:45:31 +00:00
Leonardo de Moura
9a5d961c5e fix: grind.debug true when using grind +ring (#8134)
This PR ensures that `set_option grind.debug true` works properly when
using `grind +ring`. It also adds the helper functions `mkPropEq` and
`mkExpectedPropHint`.
2025-04-27 20:28:08 +00:00
Leonardo de Moura
d6ad3e1a85 fix: monomial order in the CommRing module (#8133)
This PR fixes the monomial order used by the commutative ring procedure
in `grind`. The following new test now terminates quickly.
```lean
example [CommRing α] (a b c : α)
  : a + b + c = 3 →
    a^2 + b^2 + c^2 = 5 →
    a^3 + b^3 + c^3 = 7 →
    a^4 + b^4 + c^4 = 9 := by
  grind +ring
```
2025-04-27 19:05:12 +00:00
Leonardo de Moura
d73557321b feat: add grind (ringSteps := <num>) (#8131)
This PR adds a configuration option that controls the maximum number of
steps the commutative-ring procedure in `grind` performs.
2025-04-27 17:46:02 +00:00
Cameron Zwarich
36ed58351d fix: add support for builtin casesOn recursors to the new compiler (#8132)
This PR adds support for lowering `casesOn` for builtin types in the new
compiler.
2025-04-27 17:11:36 +00:00
Leonardo de Moura
26138a5362 feat: equality propagation for comm ring procedure in grind (#8128)
This PR implements equality propagation in the new commutative ring
procedure in `grind`. The idea is to propagate implied equalities back
to the `grind` core module that does congruence closure. In the
following example, the equalities: `x^2*y = 1` and `x*y^2 - y = 0` imply
that `y*x` is equal to `y*x*y`, which implies by congruence that `f
(y*x) = f (y*x*y)`.
```lean
example [CommRing α] (x y : α) (f : α → Nat) : x^2*y = 1 → x*y^2 - y = 0 → f (y*x) = f (y*x*y) := by
  grind +ring
```
2025-04-27 15:05:56 +00:00
Joachim Breitner
f9d191d7b8 fix: allow ascii <- in if let clauses (#8102)
This PR allows ASCII `<-` in `if let` clauses, for consistency with
bind, where both are allowed. Fixes #8098.
2025-04-27 13:17:58 +00:00
Kim Morrison
cf35e13c60 feat: use fun_induction in if-normalization example (#8129)
This PR updates the If-Normalization example, to separately give an
implementation and subsequently prove the spec (using fun_induction),
instead of previously building a term in the subtype directly. At the
same time, adds a (failing) `grind` test case illustrating a problem
with unused match witnesses.
2025-04-27 12:27:17 +00:00
Sebastian Ullrich
b6259e61f2 chore: update stage0 2025-04-27 07:41:07 +02:00
Sebastian Ullrich
965dca1625 feat: import private 2025-04-27 07:41:07 +02:00
Leonardo de Moura
c3a1669398 feat: process comm ring module todo-queue in grind (#8126)
This PR implements the main loop of the new commutative ring procedure
in `grind`. In the main loop, for each polynomial `p` in the todo queue,
the procedure:
- Simplifies it using the current basis.
- Computes critical pairs with polynomials already in the basis and adds
them to the queue.

After the queue is empty, the disequalities are re-simplified using the
new basis. `grind` can now solve examples such as:
```lean
example [CommRing α] (x y : α) : x*y*x = 1 → x*y*y = y → y = 1 := by
  grind +ring

example [CommRing α] (x y : α) : x^2*y = 1 → x*y^2 = y → y*x = 1 := by
  grind +ring

example (x y : BitVec 16) : x^2*y = 1 → x*y^2 = y → y*x = 1 := by
  grind +ring
```
2025-04-27 01:04:45 +00:00
Cameron Zwarich
c633725b3e fix: add support for the init attribute to the new compiler (#8125)
This PR adds support for the `init` attribute to the new compiler.
2025-04-27 01:01:44 +00:00
Cameron Zwarich
763a43c241 fix: correctly handle escaping functions in LCNF's elimDeadBranches pass (#8124)
This PR correctly handles escaping functions in the LCNF
elimDeadBranches pass, by setting all params to top instead of
potentially leaving them at their default bottom value.
2025-04-26 23:56:01 +00:00
Leonardo de Moura
d64ae32965 feat: generate Nullstellensatz proof terms in grind (#8122)
This PR implements the generation of compact proof terms for
Nullstellensatz certificates in the new commutative ring procedure in
`grind`. Some examples:
```lean
example [CommRing α] (x y : α) : x = 1 → y = 2 → 2*x + y = 4 := by
  grind +ring

example [CommRing α] [IsCharP α 7] (x y : α) : 3*x = 1 → 3*y = 2 → x + y = 1 := by
  grind +ring

example [CommRing α] [NoZeroNatDivisors α] (x y : α) : 3*x = 1 → 3*y = 2 → x + y = 1 := by
  grind +ring

example (x y z : BitVec 8) : z = y → (x + 1)*(x - 1)*y + y = z*x^2 + 1 → False := by
  grind +ring
```
2025-04-26 22:52:00 +00:00
Lean stage0 autoupdater
685aa9b359 chore: update stage0 2025-04-26 17:01:41 +00:00
Sebastian Ullrich
f285867137 perf: no need to register axioms outside of the module system (#8121) 2025-04-26 16:14:00 +00:00
Sebastian Ullrich
87dccb9d1b fix: restore what simp theorems are recorded as rfl (#8114)
#8090 accidentally affected `dsimp` applications even outside the module
system, restore previous extension data.
2025-04-26 16:09:20 +00:00
Sebastian Ullrich
82723489c9 fix: linter should have access to all messages, really (#8117)
Continuation of #8101
2025-04-26 15:23:07 +00:00
Leonardo de Moura
d81a922a20 feat: NoZeroNatDivisors helper class for grind (#8111)
This PR adds the helper type class `NoZeroNatDivisors` for the
commutative ring procedure in `grind`. Core only implements it for
`Int`. It can be instantiated in Mathlib for any type `A` that
implements `NoZeroSMulDivisors Nat A`.
See `findSimp?` and `PolyDerivation` for details on how this instance
impacts the commutative ring procedure.
2025-04-26 15:14:27 +00:00
Kim Morrison
18f8a18bfc chore: fix TreeMap deprecations (#8100)
This PR fixes some incorrect deprecations in TreeMap.
2025-04-26 13:10:05 +00:00
Sebastian Ullrich
4323507b91 fix: linter should have access to complete command message log (#8101)
This PR fixes a parallelism regression where linters that e.g. check for
errors in the command would no longer find such messages.

---------

Co-authored-by: damiano <adomani@gmail.com>
2025-04-26 11:36:21 +00:00
Sebastian Ullrich
20a9db6357 chore: CI: run Linux Lake in all configurations
Otherwise master never has a cache for it
2025-04-26 13:25:29 +02:00
Sebastian Ullrich
c268602795 fix: wf preprocess of ite (#8112)
`[wf_preprocess]` expects a dsimp theorem, which in `Init` temporarily
have a simplistic syntactic representation until a more robust solution
is implemented.
2025-04-26 07:30:45 +00:00
Leonardo de Moura
60ee8c2f76 chore: broken test after update stage0 (#8110)
This is a temporary fix for `master` after update stage0 breakage.

cc @Kha @nomeata
2025-04-26 00:02:23 +00:00
Lean stage0 autoupdater
882d1ab812 chore: update stage0 2025-04-25 21:29:05 +00:00
Sebastian Ullrich
62c6edffef feat: do not export theorem bodies (#8090)
This PR adjusts the experimental module system to elide theorem bodies
(i.e. proofs) from being imported into other modules.
2025-04-25 20:22:32 +00:00
Markus Himmel
6cdabf58c6 chore: deprecate some Int.ofNat_* lemmas (#8000)
This PR deprecates some `Int.ofNat_*` lemmas in favor of
`Int.natCast_*`.
2025-04-25 16:16:58 +00:00
Marc Huisinga
8195f70502 chore: revert "fix: trace nodes collapsing while file is elaborating (#8056)" (#8095)
This PR reverts #8056 because the implementation there has a bug that is
best fixed with a different approach, and which we should preferably
only merge next release cycle.
2025-04-25 09:59:41 +00:00
Joachim Breitner
3fe195a4a9 fix: FunInd with nested well-founded recurison and late fixed parameters (#8094)
This PR fixes the generation of functional induction principles for
functions with nested nested well-founded recursion and late fixed
parameters. This is a follow-up for #7166. Fixes #8093.
2025-04-25 09:20:27 +00:00
Rob23oba
416e07a68e fix: handle surrogate pairs correctly in Json.parse (#8080)
This PR fixes `Json.parse` to handle surrogate pairs correctly.

Closes #5445
2025-04-24 19:07:46 +00:00
Henrik Böving
406bda8807 feat: implement a Selector for async TCP (#8078)
This PR is a follow up to #8055 and implements a `Selector` for async
TCP in order to allow IO multiplexing using TCP sockets.

As we must not commit to actually fetching data from the socket buffer
this cannot be implemented by just racing on `recv?`. Instead we perform
a call to `uv_read_start` and pass an `alloc_cb` that allocates no
memory at all. According to the docs of
[`uv_alloc_cb`](https://docs.libuv.org/en/v1.x/handle.html#c.uv_alloc_cb)
this is guaranteed to give us a `UV_ENOBUFS` in the relevant callback.
Thus we can first run this "zero read" and then go into one of three
cases:
1. We get cancelled before the zero read completes, in this case just
cancel the zero read and give up.
2. The zero read completes and we loose the race for completing the
`select`, in this case just don't do anything anymore
3. The zero read completes and we win the race for completing the
`select`, in this case we perform the actual read on the socket. As we
know that data is available already (since the read callback of the zero
read is only triggered if data actually is available) we know that the
subsequent actual read should complete right away.

In this way we avoid any data loss if we loose the race.
2025-04-24 16:05:35 +00:00
Luisa Cicolini
bc032eec8d feat: add BitVec.sdivOverflow definition and lemmas for overflow in signed and unsigned division (#7671)
This PR contains the theorem proving that signed division x.toInt /
y.toInt only overflows when `x = intMin w` and `y = allOnes w` (for `0 <
w`).
To show that this is the *only* case in which overflow happens, we refer
to overflow for negation
(`BitVec.sdivOverflow_eq_negOverflow_of_neg_one`): in fact,
`x.toInt/(allOnes w).toInt = - x.toInt`, i.e., the overflow conditions
are the same as `negOverflow` for `x`, and then reason about the signs
of the operands with the respective theorems.
These BitVec theorems themselves rely on numerous `Int.ediv_*` theorems,
that carefully set the bounds of signed division for integers.

co-authored by @bollu, @tobiasgrosser
2025-04-24 15:27:18 +00:00
Rob23oba
e2b3daf1dd fix: simp?! and variants to do auto-unfolding (#8076)
This PR fixes `simp?!`, `simp_all?!` and `dsimp?!` to do auto-unfolding.

Closes #7927
2025-04-24 14:04:39 +00:00
Lean stage0 autoupdater
7344bcffd8 chore: update stage0 2025-04-24 14:21:10 +00:00
Markus Himmel
68d9d14d44 chore: do not use the coercion α → Option α in Init and Std (#8085)
This PR moves the coercion `α → Option α` to the new file
`Init.Data.Option.Coe`. This file may not be imported anywhere in `Init`
or `Std`.
2025-04-24 13:35:01 +00:00
Joachim Breitner
9fbdf847bd fix: FunInd: properly split mutual structural recursion with extra parameters (#8086)
This PR makes sure that the functional induction priciples for mutually
recursive structural functions with extra parameters are split deeply,
as expected.
2025-04-24 13:32:53 +00:00
Sebastian Ullrich
66c00d33d4 feat: environment constant data can be split into .olean.private (#8079)
This PR lays the `Environment` groundwork for not exporting (parts of)
declarations.
2025-04-24 13:04:31 +00:00
Sebastian Ullrich
96cda3f498 chore: CI: revert accidentally disabling Lake cache 2025-04-24 15:01:09 +02:00
Joachim Breitner
d38d9400d8 fix: avoid panic in functional induction principle for structural recursion (#8083)
This PR fixes #8081.
2025-04-24 11:58:29 +00:00
Markus Himmel
781c94f2cf chore: test that there are no orphaned modules (#8082)
This PR adds a test that makes sure that there are no orphaned modules.
2025-04-24 11:55:07 +00:00
Lean stage0 autoupdater
e00a2f63ec chore: update stage0 2025-04-24 10:54:10 +00:00
Paul Reichert
be66157583 fix: import all raw tree map modules into Std.Data (#8044)
This PR introduces the modules `Std.Data.DTreeMap.Raw`,
`Std.Data.TreeMap.Raw` and `Std.Data.TreeSet.Raw` and imports them into
`Std.Data`. All modules related to the raw tree maps are imported into
these new modules so that they are now a transitive dependency of `Std`.
2025-04-24 10:06:32 +00:00
Joachim Breitner
b2ed6ac939 refactor: WF: add eq_def theorem for ._unary (#8063)
This PR adds an `foo._unary.eq_def` theorem, so that unfolding
`foo._unary` works as expected. This will help with #8019.
2025-04-24 09:59:08 +00:00
Sebastian Ullrich
51defe5935 chore: disable nondeterministic test 2025-04-24 11:30:26 +02:00
Sebastian Ullrich
c8cdb57c4b feat: move non-essential metadata into .olean.server (#8068)
This PR ensures that for modules opted into the experimental module
system, we do not import module docstrings or declaration ranges.

Excluding declaration docstrings as well would require some more work to
make `[inherit_doc]` leave a mere reference to the other declaration
instead of copying its docstring eagerly.
2025-04-24 08:12:26 +00:00
Henrik Böving
58c7e5da94 feat: async IO multiplexing framework + implementation for timers (#8055)
This PR adds an implementation of an async IO multiplexing framework as
well as an implementation of it for the `Timer` API in order to
demonstrate it.

The main motivation is to have fair and data loss free multiplexing of
event sources.
To illustrate two situations where just naively racing two tasks that
read from an event source might be the wrong thing:
1. Suppose we are waiting on two channel reads that are continuously
being filled up. As the first channel will always be ready when we start
its receive function it will instantly resolve the race before the
second one can even try. Thus the path where we receive data from the
second channel gets starved. For this reason we want to try in random
order (for fairness) if the event sources already have data available
for us.
2. Suppose we are waiting on two socket reads and both happen to finish
at the same time. As we are now only going to select one of them to
execute further, we are going to loose data on the second one (unless
there is a user written buffering mechanism involved) as we are going to
disregard the buffer it received and do a new receive next time. For
this reason it is important to wait for an event source to be available
without committing to actually fetching some data until we know that
this particular event source is going to win the select race.

The implementation is inspired by the Oslo framework written by
@haesbaert as well as Go's
[`select`](https://go.dev/src/runtime/select.go) implementation. Given a
list of event sources to select one from it is going to:
1. Randomly shuffle them
2. Attempt to fetch data from them (in their new random order) without
blocking (for fairness). If any of them succeeds return right away.
3. If none has data available right away set all of them up to resolve a
promise. They will then race to win the right to resolve that promise.
Only the data source that wins the race is allowed to then actually
fetch data, ensuring that no other event source actually fetches data
and then fails to deliver it to the consumer.


Follow up PRs are going to add implementations of `Selector` for
`Std.Channel` as well as TCP and UDP sockets.

---------

Co-authored-by: Markus Himmel <markus@lean-fro.org>
2025-04-24 07:55:39 +00:00
Sebastian Ullrich
d5494a306c chore: CI: extend list of virtual merge checkout files 2025-04-24 08:43:42 +02:00
Kyle Miller
42ab5dfab0 fix: have runTermElabM reset local context when types of autobound implicits contain metavariables (#7952)
This PR makes two improvements to the local context when there are
autobound implicits in `variable`s. First, the local context no longer
has two copies of every variable (the local context is rebuilt if the
types of autobound implicits have metavariables). Second, these
metavariables get names using the same algorithm used by binders that
appear in declarations (with `mkForallFVars'` instead of
`mkForallFVars`).

This removes the last use of `Term.addAutoBoundImplicits'`, which
inherently has this variable duplication issue.
2025-04-24 03:29:10 +00:00
Max Carr
3d31b1f608 doc: fix typo in MetavarDecl docstring (#8069)
This PR fixes a typo (metavarible -> metavariable) in the docstring for
`MetavarDecl.type`
2025-04-23 22:00:13 +00:00
Leonardo de Moura
146df5ac74 feat: EqCnstr.mkNullCertExt (#8071)
This PR implements `EqCnstr.mkNullCertExt`. Given an implied polynomial
equation `p = 0`, it generates the certificate:
```
q₁ * h₁ + … + qₙ * hₙ
```  
for `d * p = 0`, where each `qᵢ`s are polynomials and each `hᵢ` is an
equational hypothesis of the form `lhsᵢ = rhsᵢ`. `d` is a numeral.
2025-04-23 19:41:46 +00:00
Sebastian Ullrich
7feb583b9e feat: enable experimental module system in Init (#8047) 2025-04-23 17:21:33 +00:00
Kim Morrison
50d18cdd75 chore: adding failing grind test (#8064)
This PR adds a failing `grind` test, showing a bug where grind is trying
to assign a metavariable incorrectly.
2025-04-23 14:47:38 +00:00
Lean stage0 autoupdater
92927cb4df chore: update stage0 2025-04-23 14:54:30 +00:00
Paul Reichert
57915af218 fix: reducing Nat.pow, kernel interprets constant as Nat literal (#8060)
This PR fixes a bug in the Lean kernel. During reduction of `Nat.pow`,
the kernel did not validate that the WHNF of the first argument is a
`Nat` literal before interpreting it as an `mpz` number. This PR adds
the missing check.

### Explanation

In `type_checker::reduce_pow`, an expression was interpreted as a `Nat`
literal without previously validating that it actually was a `Nat`
literal.

We (@TwoFX and me) noticed this while fuzzing the Lean kernel with GMP
and Mimalloc disabled. Until now, the fuzzer found one crash, leading us
to this issue.

What are the consequences? If GMP is disabled, the Lean kernel will
crash on some inputs after the memory allocator returns `null`. (MPZ
tries to clone the `.const` expression in disguise of a `Nat` literal
which accidentally has a size field indicating that the number has 88
trillion `mpz` digits. This is too much for every allocator.) If GMP is
enabled, it is possible to [prove
`False`](https://live.lean-lang.org/#codez=JYWwDg9gTgLgBAGQKYEMB2AoDATJAzOAcwDoBvAVwF84AuOABQFU1gYyq5AkwjgDkV4aAXjh5yaOAH04ggHxwIYJOIDCAGxQBnDcADGKVXGDjgBACoBPRdLgWrMABZK4ABjhJVGpC6wBaH3AApcg14AHcoViNCOAADPjZIULgACnjiRLgARlcADgBKOABWZwAmGLhQiHJVbDh9DQgK6ABrAG5YtIzU/nSIJOy4fKLnAGZyyursNAByGBx8G1pefi4GKAVaYVFxAA9pORM4PeFXBycAMXqvd08bKHIkX39TRzhmpCg0dzgoJGxyHRIDRwBzAYEwRooOBocggABGHzgCJgoSQTmyAD0cqMSnU0LVMdiACw5eYEegAeQA6gBCTbLBJ9FIkUjOaiAC/JAJfkBUyWHcKDhcAARABiIwAKyQOhgEjhKGwEjA6wgeCFSx0EBAIHQtVkcGwEAwcDgqiQ8FwOgMdGQ6GIABEpeooPxgBBxEI4MRcHg0A7LXBSEbjcG0CgQF4PTEQOYHCAADRB4NwexGGDAj3EX6EaooKAuBNJ40aFB4M3menEYulguFmCWCPCZLEFBgMApYgatAhWKmOAAbQAugUm53uzFKbT+0O8jWk6aAG7uei5sPp4SD2fB+f6B70kduseme5IYip9ZTvKJuCUIM2tDEACi6jhxGUmu1+OIqhMMDfvwAsikd7Ntg2B+gYFqqJeGB+HAyjOhojjAocADi/70IYwLYGCAqmtgGBimgkrSrK8qKsqeBYGc0BICARASEgACOEgAF4fI0dAshw4gnPScLmEGYh4BANREEGGhgN+8AADytHIUB4KoVGODRdGIX0Eh4FcSyXB4DZIgJxo6PY6CEF4vbdIySSuJkl7GlASR9oACYT0UxrHsQOQZIDsKDSnA0axhgQA)
because the kernel doesn't crash on a memory allocation and instead just
happily interprets the `.const` expression as a GMP number.

Importantly, this is _not_ a flaw in Lean's type theory. It is an
implementation bug in the built-in kernel, related to the efficient
reduction of `Nat.pow`, that will be fixed with this PR; see the test
file. Because Lean's kernel is relatively small, there are third-party
kernel implementations such as `lean4lean` and `nanoda`. `lean4lean`
catches the bogus proof, and looking at its code `nanoda` will, too, but
I haven't tried it yet.
2025-04-23 13:55:20 +00:00
Sebastian Ullrich
521a37f796 chore: rework module system import (#8062)
Ensure .server and .private are inspected only for `module`s and that
`module`s and non-`module`s interact correctly
2025-04-23 13:48:53 +00:00
Rob23oba
70bf2db056 fix: use one-field structures for Array.Perm and Vector.Perm (#7999)
This PR replaces `Array.Perm` and `Vector.Perm` with one-field
structures. This avoids dot notation for `List` to work like e.g.
`h.cons 3` where `h` is an `Array.Perm`.
2025-04-23 13:32:30 +00:00
Sebastian Ullrich
5c7a7d6406 chore: CI: reset reldebug check level 2025-04-23 14:31:59 +02:00
Marc Huisinga
55cb65c0fe fix: trace nodes collapsing while file is elaborating (#8056)
This PR fixes a bug where the trace nodes in the InfoView would close
while the file was still being elaborated.

Closes #8053.

The cause of this bug was that we didn't memorize interactive
diagnostics correctly, so the server would generate new RPC pointers in
every single `getInteractiveDiagnostics` RPC request, which lead to the
client resetting the UI.
2025-04-23 10:08:48 +00:00
Sebastian Ullrich
fbbf42e82f chore: fix reldebug preset (#8051)
Build with assertions, but without debug info
2025-04-23 10:05:11 +00:00
Sebastian Ullrich
8c8df274cf chore: fix enabling module system (#8057) 2025-04-23 09:31:08 +00:00
Sebastian Ullrich
2e42013555 chore: clarify m_cs_sz use with mimalloc (#8058)
We didn't feed correct data to `mi_free_size`, but it turns out it
discards it anyway.
2025-04-23 07:39:01 +00:00
Leonardo de Moura
dfa72d6c04 feat: infrastructure for computing Nullstellensatz certificates (#8059)
This PR adds infrastructure for computing Nullstellensatz certificates
in the comm ring procedure in `grind`.
2025-04-23 04:25:38 +00:00
Sebastian Ullrich
ad3ac150bc chore: remove lakefile copy in root and tests/ (#8054)
As we use a different Lean in these directories, using those copies
always results in a full rebuild
2025-04-22 16:03:12 +00:00
David Thrane Christiansen
5d82927d10 chore: move Lake DSL syntax into dedicated module (#8048)
This PR moves the Lake DSL syntax into a dedicated module with minimal
imports.

This allows modules outside of Lake/Lean to import Lake.DSL.Syntax
without crashing, because it reduces the transitive closure of these
modules' imports. This is needed for the reference manual to be able to
document the DSL syntax.

Additionally, the imports of `Lake.Build.Fetch` are decreased, which
reduces its import closure sufficiently to include docs for `FetchM` in
the reference manual.
2025-04-22 14:35:54 +00:00
Henrik Böving
8e1b9abb7a fix: missing wakeup in bounded channel try receive (#8052)
This PR fixes a small oversight in the wakeup mechanism of blocked
bounded channel senders that occurs when calling `tryRecv`.

Marked as `changelog-no` as this isn't released yet.
2025-04-22 14:32:59 +00:00
Sebastian Ullrich
be117c4738 fix: missing traces from realizeConst (#8050)
This PR fixes missing trace messages when produced inside `realizeConst`

Fixes #8049
2025-04-22 12:23:54 +00:00
Lean stage0 autoupdater
46526cc8fb chore: update stage0 2025-04-22 11:08:24 +00:00
Sebastian Ullrich
3ae41cb181 feat: allow use of experimental module system in Init (#7919) 2025-04-22 09:09:27 +00:00
Kim Morrison
2c6d634127 fix: make IntCast a field of Grind.CommRing (#8042)
This PR makes `IntCast` a field of `Lean.Grind.CommRing`, along with
additional axioms relating it to negation of `OfNat`. This allows use to
use existing instances which are not definitionally equal to the
previously given construction.

---------

Co-authored-by: Leonardo de Moura <leomoura@amazon.com>
2025-04-22 02:43:27 +00:00
Leonardo de Moura
ff336fb63c feat: Nullstellensatz certificates for the comm ring procedure in grind (#8043)
This PR adds `NullCert` type for representing Nullstellensatz
certificates that will be produced by the new commutative ring procedure
in `grind`.
2025-04-22 00:40:11 +00:00
Leonardo de Moura
9bdd11465c feat: improve denoteNum (#8040)
This PR modifies `denoteNum` to avoid `intCast`. It is too verbose in
pretty printing messages.
2025-04-21 18:29:23 +00:00
Sebastian Ullrich
791bba0091 feat: LLVM 15 -> 19 (#6063)
This PR updates the version of LLVM and clang used by and shipped with
Lean to 19.1.2

Fixes #5649
2025-04-21 17:18:18 +00:00
Sebastian Ullrich
d6c30a8a0a chore: disable build of old manual 2025-04-21 18:40:11 +02:00
Sebastian Ullrich
f86b192ec2 chore: fix Nix build 2025-04-21 18:40:11 +02:00
Sebastian Ullrich
e6771d7524 chore: update stage0 2025-04-21 18:40:11 +02:00
Sebastian Ullrich
da82cbd3d1 feat: module header keyword for enabling module system 2025-04-21 18:40:11 +02:00
Joachim Breitner
2386a3d7c7 chore: add RISC-V ast benchmark (#8035)
This PR adds a realistic large-inductive benchmark, taken from
https://github.com/opencompl/sail-riscv-lean
2025-04-21 15:46:38 +00:00
Henrik Böving
39f7380663 perf: fix linearity issue in bv_decide (#8036)
This PR fixes a linearity issue in `bv_decide`'s bitblaster, caused by
the fact that the higher order combinators `AIG.RefVec.zip` and
`AIG.RefVec.fold` were not being properly specialised.

Example benchmark `QF_BV/sage/app1/bench_1967.smt2`:
- before: https://share.firefox.dev/4cE86It
- after: https://share.firefox.dev/42L9chd
2025-04-21 13:51:21 +00:00
Kyle Miller
517899da7b feat: extract_lets and lift_lets tactics (#6432)
This PR implements tactics called `extract_lets` and `lift_lets` that
manipulate `let`/`let_fun` expressions. The `extract_lets` tactic
creates new local declarations extracted from any `let` and `let_fun`
expressions in the main goal. For top-level lets in the target, it is
like the `intros` tactic, but in general it can extract lets from deeper
subexpressions as well. The `lift_lets` tactic moves `let` and `let_fun`
expressions as far out of an expression as possible, but it does not
extract any new local declarations. The option `extract_lets +lift`
combines these behaviors.

This is a re-implementation of `extract_lets` and `lift_lets` from
mathlib. The new `extract_lets` is like doing `lift_lets; extract_lets`,
but it does not lift unextractable lets like `lift_lets`. The
`lift_lets; extract_lets` behavior is now handled by `extract_lets
+lift`. The new `lift_lets` tactic is a frontend to `extract_lets +lift`
machinery, which rather than creating new local definitions instead
represents the accumulated local declarations as top-level lets.

There are also conv tactics for both of these. The `extract_lets` has a
limitation due to the conv architecture; it can extract lets for a given
conv goal, but the local declarations don't survive outside conv. They
get zeta reduced immediately upon leaving conv.
2025-04-21 08:57:01 +00:00
Cameron Zwarich
02f7a1dd41 fix: correctly handle duplicate projections in the IR expand_reset_reuse pass (#8023)
This PR fixes the IR expand_reset_reuse pass to correctly handle
duplicate projections from the same base/index. This does not occur (at
least easily) with the old compiler, but it occurs when bootstrapping
Lean with the new compiler.
2025-04-21 03:27:32 +00:00
Leonardo de Moura
568a1b1a81 refactor: comm ring procedure in grind (#8034)
This PR makes the following modifications to the new comm ring procedure
in `grind`
1. Adds data-structures for representing equations (and their
justifications), basis, and queue of equations to be processed.
2. Adds `RingM` helper monad.
3. Adds equation simplification main loop
2025-04-21 02:53:43 +00:00
Leonardo de Moura
63cf571553 feat: add functions for converting ring reified terms back into Expr (#8033)
This PR adds functions for converting `CommRing` reified terms back into
Lean expressions.
2025-04-20 21:49:14 +00:00
Sebastian Ullrich
11f6326102 chore: un-orphan file (#8031)
This file is used in a test, which thus fails using `-DUSE_LAKE=ON`
2025-04-20 18:16:51 +00:00
Sebastian Ullrich
b5f191724d chore: stop taking constants from kernel env in synchronous case as well (#7915)
Makes the elaborator constant map truly independent of the kernel's in
preparation for the module system where declarations in the elab env may
in fact differ from the kernel env.
2025-04-20 17:56:14 +00:00
Leonardo de Moura
a49ad77754 feat: unsat comm ring equations in grind (#8032)
This PR adds support to `grind` for detecting unsatisfiable commutative
ring equations when the ring characteristic is known. Examples:
```lean
example (x : Int) : (x + 1)*(x - 1) = x^2 → False := by
  grind +ring

example (x y : Int) : (x + 1)*(x - 1)*y + y = y*x^2 + 1 → False := by
  grind +ring

example (x : UInt8) : (x + 1)*(x - 1) = x^2 → False := by
  grind +ring

example (x y : BitVec 8) : (x + 1)*(x - 1)*y + y = y*x^2 + 1 → False := by
  grind +ring
```
2025-04-20 17:26:46 +00:00
Kim Morrison
2cd874bd30 feat: additional List.findX lemmas (#8030)
This PR adds some missing lemmas about
`List/Array/Vector.findIdx?/findFinIdx?/findSome?/idxOf?`.
2025-04-20 08:08:53 +00:00
Leonardo de Moura
de27872f3f feat: basic CommRing support in grind (#8029)
This PR implements basic support for `CommRing` in `grind`. Terms are
already being reified and normalized. We still need to process the
equations, but `grind` can already prove simple examples such as:
```lean
open Lean.Grind in
example [CommRing α] (x : α) : (x + 1)*(x - 1) = x^2 - 1 := by
  grind +ring

open Lean.Grind in
example [CommRing α] [IsCharP α 256] (x : α) : (x + 16)*(x - 16) = x^2 := by
  grind +ring

example (x : Int) : (x + 1)*(x - 1) = x^2 - 1 := by
  grind +ring

example (x : UInt8) : (x + 16)*(x - 16) = x^2 := by
  grind +ring

example (x : Int) : (x + 1)^2 - 1 = x^2 + 2*x := by
  grind +ring

example (x : BitVec 8) : (x + 16)*(x - 16) = x^2 := by
  grind +ring

example (x : BitVec 8) : (x + 1)^2 - 1 = x^2 + 2*x := by
  grind +ring
```
2025-04-20 05:12:09 +00:00
Mac Malone
72e4f699c6 fix: lake: import-related bugs (#8026)
This PR fixes bugs in #7809 and #7909 that were not caught partially
because the `badImport` test had been disabled.

**Bugs Fixed:**

* Building by path no longer drops top-level logs.
* "bad import" errors are once again printed.
* Transitively imported precompiled modules are once again loaded during
elaboration.
2025-04-19 21:02:38 +00:00
Leonardo de Moura
876680001b feat: add Poly.simp? (#8027)
This PR adds `Poly.simp?` and improves the function for computing
S-polynomials.
2025-04-19 20:10:00 +00:00
JovanGerb
87930f59c3 fix: don't reset localInstances in delaboration (#8022)
This PR fixes a bug where pretty printing is done in a context with
cleared local instances. These were cleared since the local context is
updated during a name sanitization step, but preserving local instances
is valid since the modification to the local context only affects user
names.

This showed up when writing the mathlib delaborator for `max` and `min`
(https://github.com/leanprover-community/mathlib4/pull/23558#discussion_r2050787403)
2025-04-19 15:39:16 +00:00
Leonardo de Moura
f463b62ac3 feat: S-polynomials and cleanup (#8025)
This PR simplifies the `CommRing` monomials, and adds 
1. Monomial `lcm`
2. Monomial division
3. S-polynomials
2025-04-19 04:21:04 +00:00
Cameron Zwarich
9bb1e4f277 fix: correctly handle extern functions in the IR elim_dead_branches pass (#8017)
This PR makes the IR elim_dead_branches pass correctly handle extern
functions by considering them as having a top return value. This fix is
required to bootstrap the Init/ directory with the new compiler.
2025-04-18 17:28:32 +00:00
Sebastian Ullrich
a52e0c5ba5 chore: CI: bring back Lake build job (#8020)
Thanks to recent fixes
2025-04-18 13:42:27 +00:00
Joachim Breitner
02b206af9b fix: mkAppM to typecheck at .default transparency (#7957)
This PR ensures that `mkAppM` can be used to construct terms that are
only type-correct at at default transparency, even if we are in
`withReducible` (e.g. in simp), so that simp does not stumble over
simplifying `let` expression with simplifiable type.reliable.

Here is a reproducer of the issue this solves:
```
example (a b : Nat) (h : a = b):
  (let _ : id Bool := true; a) = (let _ : Bool := true; b) := by
  simp -zeta -zetaDelta [h]
```

This fixes #7826.
2025-04-18 09:23:51 +00:00
Joachim Breitner
e6343497a7 doc: RArray is now universe-polymorphic (#8018)
This PR adjusts the RArray docstring to the new reality from #8014.
2025-04-18 09:23:05 +00:00
Leonardo de Moura
27a7a0a2bd fix: CommRing multivariate polynomials (#8016)
This PR fixes several issues in the `CommRing` multivariate polynomial
library:
1. Replaces the previous array type with the universe polymorphic
`RArray`.
2. Properly eliminates cancelled monomials.
3. Sorts monomials in decreasing order.
4. Marks the parameter `p` of the `IsCharP` class as an output
parameter.
5. Adds `LawfulBEq` instances for the types `Power`, `Mon`, and `Poly`.
2025-04-18 04:34:05 +00:00
Cameron Zwarich
f163758bcf fix: correctly handle join points with no params in the IR elim_dead_branches pass (#8015)
This PR fixes the IR elim_dead_branches pass to correctly handle join
points with no params, which currently get considered unreachable. I was
not able to find an easy repro of this with the old compiler, but it
occurs when bootstrapping Lean with the new compiler.
2025-04-18 03:52:19 +00:00
Leonardo de Moura
32fe2391b9 feat: universe polymorphic RArray (#8014)
This PR makes `RArray` universe polymorphic.
2025-04-18 02:18:10 +00:00
Lean stage0 autoupdater
3cbffee94b chore: update stage0 2025-04-18 01:52:46 +00:00
Leonardo de Moura
807182d63e chore: allow RArray to be universe polymorphic (#8013)
This PR ensures that `RArray` can be made universe polymorphic. We need
an update-stage0 before finalizing this modification.
2025-04-18 01:10:44 +00:00
Lean stage0 autoupdater
a21377b9ec chore: update stage0 2025-04-18 00:52:57 +00:00
Leonardo de Moura
96fd2f195c feat: add debug.terminalTacticsAsSorry (#8012)
This PR adds the option `debug.terminalTacticsAsSorry`. When enabled,
terminal tactics such as `grind` and `omega` are replaced with `sorry`.
Useful for debugging and fixing bootstrapping issues.
2025-04-18 00:10:59 +00:00
Leonardo de Moura
5823d03283 feat: add IsCharP support to multivariate polynomial library (#8011)
This PR adds `IsCharP` support to the multivariate‑polynomial library in
`CommRing`.
2025-04-17 23:55:21 +00:00
1103 changed files with 26695 additions and 3739 deletions

View File

@@ -82,7 +82,7 @@ jobs:
- name: CI Merge Checkout
run: |
git fetch --depth=1 origin ${{ github.sha }}
git checkout FETCH_HEAD flake.nix flake.lock
git checkout FETCH_HEAD flake.nix flake.lock script/prepare-*
if: github.event_name == 'pull_request'
# (needs to be after "Checkout" so files don't get overridden)
- name: Setup emsdk
@@ -99,7 +99,6 @@ jobs:
if: matrix.cmultilib
- name: Cache
id: restore-cache
if: matrix.name != 'Linux Lake'
uses: actions/cache/restore@v4
with:
# NOTE: must be in sync with `save` below

View File

@@ -139,20 +139,21 @@ jobs:
let large = ${{ github.repository == 'leanprover/lean4' }};
const isPr = "${{ github.event_name }}" == "pull_request";
let matrix = [
/* TODO: to be updated to new LLVM
{
"name": "Linux LLVM",
"os": "ubuntu-latest",
"release": false,
"check-level": 2,
"shell": "nix develop .#oldGlibc -c bash -euxo pipefail {0}",
"llvm-url": "https://github.com/leanprover/lean-llvm/releases/download/15.0.1/lean-llvm-x86_64-linux-gnu.tar.zst",
"llvm-url": "https://github.com/leanprover/lean-llvm/releases/download/19.1.2/lean-llvm-x86_64-linux-gnu.tar.zst",
"prepare-llvm": "../script/prepare-llvm-linux.sh lean-llvm*",
"binary-check": "ldd -v",
// foreign code may be linked against more recent glibc
// reverse-ffi needs to be updated to link to LLVM libraries
"CTEST_OPTIONS": "-E 'foreign|leanlaketest_reverse-ffi'",
"CMAKE_OPTIONS": "-DLLVM=ON -DLLVM_CONFIG=${GITHUB_WORKSPACE}/build/llvm-host/bin/llvm-config"
},
}, */
{
// portable release build: use channel with older glibc (2.26)
"name": "Linux release",
@@ -160,25 +161,22 @@ jobs:
"release": true,
"check-level": 0,
"shell": "nix develop .#oldGlibc -c bash -euxo pipefail {0}",
"llvm-url": "https://github.com/leanprover/lean-llvm/releases/download/15.0.1/lean-llvm-x86_64-linux-gnu.tar.zst",
"llvm-url": "https://github.com/leanprover/lean-llvm/releases/download/19.1.2/lean-llvm-x86_64-linux-gnu.tar.zst",
"prepare-llvm": "../script/prepare-llvm-linux.sh lean-llvm*",
"binary-check": "ldd -v",
// foreign code may be linked against more recent glibc
"CTEST_OPTIONS": "-E 'foreign'"
},
// deactivated due to bugs
/*
{
"name": "Linux Lake",
"os": large ? "nscloud-ubuntu-22.04-amd64-4x8" : "ubuntu-latest",
// just a secondary PR build job for now
"check-level": isPr ? 0 : 3,
"check-level": 0,
// just a secondary build job for now until false positives can be excluded
"secondary": true,
"CMAKE_OPTIONS": "-DUSE_LAKE=ON",
// TODO: why does this fail?
"CTEST_OPTIONS": "-E 'scopedMacros'"
},
*/
{
"name": "Linux",
"os": large ? "nscloud-ubuntu-22.04-amd64-4x8" : "ubuntu-latest",
@@ -210,7 +208,7 @@ jobs:
"release": true,
"check-level": 2,
"shell": "bash -euxo pipefail {0}",
"llvm-url": "https://github.com/leanprover/lean-llvm/releases/download/15.0.1/lean-llvm-x86_64-apple-darwin.tar.zst",
"llvm-url": "https://github.com/leanprover/lean-llvm/releases/download/19.1.2/lean-llvm-x86_64-apple-darwin.tar.zst",
"prepare-llvm": "../script/prepare-llvm-macos.sh lean-llvm*",
"binary-check": "otool -L",
"tar": "gtar" // https://github.com/actions/runner-images/issues/2619
@@ -221,7 +219,7 @@ jobs:
"CMAKE_OPTIONS": "-DLEAN_INSTALL_SUFFIX=-darwin_aarch64",
"release": true,
"shell": "bash -euxo pipefail {0}",
"llvm-url": "https://github.com/leanprover/lean-llvm/releases/download/15.0.1/lean-llvm-aarch64-apple-darwin.tar.zst",
"llvm-url": "https://github.com/leanprover/lean-llvm/releases/download/19.1.2/lean-llvm-aarch64-apple-darwin.tar.zst",
"prepare-llvm": "../script/prepare-llvm-macos.sh lean-llvm*",
"binary-check": "otool -L",
"tar": "gtar", // https://github.com/actions/runner-images/issues/2619
@@ -242,7 +240,7 @@ jobs:
"CMAKE_OPTIONS": "-G \"Unix Makefiles\"",
// for reasons unknown, interactivetests are flaky on Windows
"CTEST_OPTIONS": "--repeat until-pass:2",
"llvm-url": "https://github.com/leanprover/lean-llvm/releases/download/15.0.1/lean-llvm-x86_64-w64-windows-gnu.tar.zst",
"llvm-url": "https://github.com/leanprover/lean-llvm/releases/download/19.1.2/lean-llvm-x86_64-w64-windows-gnu.tar.zst",
"prepare-llvm": "../script/prepare-llvm-mingw.sh lean-llvm*",
"binary-check": "ldd"
},
@@ -253,7 +251,7 @@ jobs:
"release": true,
"check-level": 2,
"shell": "nix develop .#oldGlibcAArch -c bash -euxo pipefail {0}",
"llvm-url": "https://github.com/leanprover/lean-llvm/releases/download/15.0.1/lean-llvm-aarch64-linux-gnu.tar.zst",
"llvm-url": "https://github.com/leanprover/lean-llvm/releases/download/19.1.2/lean-llvm-aarch64-linux-gnu.tar.zst",
"prepare-llvm": "../script/prepare-llvm-linux.sh lean-llvm*"
},
// Started running out of memory building expensive modules, a 2GB heap is just not that much even before fragmentation

View File

@@ -73,7 +73,7 @@ jobs:
with:
extra-conf: |
extra-sandbox-paths = /nix/var/cache/ccache?
substituters = file://${{ github.workspace }}/nix-store-cache-copy?priority=10&trusted=true https://cache.nixos.org
substituters = file://${{ github.workspace }}/nix-store-cache-copy?priority=10&trusted=true https://cache.nixos.org
- name: Prepare CCache Cache
run: |
sudo mkdir -m0770 -p /nix/var/cache/ccache
@@ -103,40 +103,10 @@ jobs:
paths: push-test/test-results.xml
if: always()
continue-on-error: true
- name: Build manual
run: |
nix build $NIX_BUILD_ARGS --update-input lean --no-write-lock-file ./doc#{lean-mdbook,leanInk,alectryon,inked} -o push-doc
nix build $NIX_BUILD_ARGS --update-input lean --no-write-lock-file ./doc
# https://github.com/netlify/cli/issues/1809
cp -r --dereference ./result ./dist
if: matrix.name == 'Nix Linux'
- name: Rebuild Nix Store Cache
run: |
rm -rf nix-store-cache || true
nix copy ./push-* --to file://$PWD/nix-store-cache?compression=none
- id: deploy-info
name: Compute Deployment Metadata
run: |
set -e
python3 -c 'import base64; print("alias="+base64.urlsafe_b64encode(bytes.fromhex("${{github.sha}}")).decode("utf-8").rstrip("="))' >> "$GITHUB_OUTPUT"
echo "message=`git log -1 --pretty=format:"%s"`" >> "$GITHUB_OUTPUT"
- name: Publish manual to Netlify
uses: nwtgck/actions-netlify@v3.0
id: publish-manual
with:
publish-dir: ./dist
production-branch: master
github-token: ${{ secrets.GITHUB_TOKEN }}
deploy-message: |
${{ github.event_name == 'pull_request' && format('pr#{0}: {1}', github.event.number, github.event.pull_request.title) || format('ref/{0}: {1}', github.ref_name, steps.deploy-info.outputs.message) }}
alias: ${{ steps.deploy-info.outputs.alias }}
enable-commit-comment: false
enable-pull-request-comment: false
github-deployment-environment: "lean-lang.org/lean4/doc"
fails-without-credentials: false
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: "b8e805d2-7e9b-4f80-91fb-a84d72fc4a68"
- name: Fixup CCache Cache
run: |
sudo chown -R $USER /nix/var/cache

View File

@@ -12,6 +12,8 @@ foreach(var ${vars})
get_property(currentHelpString CACHE "${var}" PROPERTY HELPSTRING)
if("${var}" MATCHES "STAGE0_(.*)")
list(APPEND STAGE0_ARGS "-D${CMAKE_MATCH_1}=${${var}}")
elseif("${var}" MATCHES "STAGE1_(.*)")
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")
@@ -77,26 +79,29 @@ if (USE_MIMALLOC)
list(APPEND EXTRA_DEPENDS mimalloc)
endif()
ExternalProject_add(stage0
SOURCE_DIR "${LEAN_SOURCE_DIR}/stage0"
SOURCE_SUBDIR src
BINARY_DIR stage0
# do not rebuild stage0 when git hash changes; it's not from this commit anyway
# (however, CI will override this as we need to embed the githash into the stage 1 library built
# by stage 0)
CMAKE_ARGS -DSTAGE=0 -DUSE_GITHASH=OFF ${PLATFORM_ARGS} ${STAGE0_ARGS}
BUILD_ALWAYS ON # cmake doesn't auto-detect changes without a download method
INSTALL_COMMAND "" # skip install
DEPENDS ${EXTRA_DEPENDS}
)
if (NOT STAGE1_PREV_STAGE)
ExternalProject_add(stage0
SOURCE_DIR "${LEAN_SOURCE_DIR}/stage0"
SOURCE_SUBDIR src
BINARY_DIR stage0
# do not rebuild stage0 when git hash changes; it's not from this commit anyway
# (however, CI will override this as we need to embed the githash into the stage 1 library built
# by stage 0)
CMAKE_ARGS -DSTAGE=0 -DUSE_GITHASH=OFF ${PLATFORM_ARGS} ${STAGE0_ARGS}
BUILD_ALWAYS ON # cmake doesn't auto-detect changes without a download method
INSTALL_COMMAND "" # skip install
DEPENDS ${EXTRA_DEPENDS}
)
list(APPEND EXTRA_DEPENDS stage0)
endif()
ExternalProject_add(stage1
SOURCE_DIR "${LEAN_SOURCE_DIR}"
SOURCE_SUBDIR src
BINARY_DIR stage1
CMAKE_ARGS -DSTAGE=1 -DPREV_STAGE=${CMAKE_BINARY_DIR}/stage0 -DPREV_STAGE_CMAKE_EXECUTABLE_SUFFIX=${STAGE0_CMAKE_EXECUTABLE_SUFFIX} ${CL_ARGS}
CMAKE_ARGS -DSTAGE=1 -DPREV_STAGE=${CMAKE_BINARY_DIR}/stage0 -DPREV_STAGE_CMAKE_EXECUTABLE_SUFFIX=${STAGE0_CMAKE_EXECUTABLE_SUFFIX} ${CL_ARGS} ${STAGE1_ARGS}
BUILD_ALWAYS ON
INSTALL_COMMAND ""
DEPENDS stage0
DEPENDS ${EXTRA_DEPENDS}
STEP_TARGETS configure
)
ExternalProject_add(stage2

View File

@@ -24,9 +24,9 @@
},
{
"name": "reldebug",
"displayName": "Release with debug info build config",
"displayName": "Release with assertions enabled",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
"CMAKE_BUILD_TYPE": "RelWithAssert"
},
"generator": "Unix Makefiles",
"binaryDir": "${sourceDir}/build/reldebug"

100
flake.lock generated
View File

@@ -1,112 +1,50 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1710146030,
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1710889954,
"narHash": "sha256-Pr6F5Pmd7JnNEMHHmspZ0qVqIBVxyZ13ik1pJtm2QXk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7872526e9c5332274ea5932a0c3270d6e4724f3b",
"type": "github"
"lastModified": 1745636243,
"narHash": "sha256-kbNvlQZf8wwok3d2X1kM/TlXH/MZ+03ZNv+IPPBx+DM=",
"rev": "f771eb401a46846c1aebd20552521b233dd7e18b",
"type": "tarball",
"url": "https://releases.nixos.org/nixos/unstable/nixos-25.05pre789333.f771eb401a46/nixexprs.tar.xz"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-cadical": {
"locked": {
"lastModified": 1740791350,
"narHash": "sha256-igS2Z4tVw5W/x3lCZeeadt0vcU9fxtetZ/RyrqsCRQ0=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "199169a2135e6b864a888e89a2ace345703c025d",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "199169a2135e6b864a888e89a2ace345703c025d",
"type": "github"
"type": "tarball",
"url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz"
}
},
"nixpkgs-old": {
"flake": false,
"locked": {
"lastModified": 1581379743,
"narHash": "sha256-i1XCn9rKuLjvCdu2UeXKzGLF6IuQePQKFt4hEKRU5oc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "34c7eb7545d155cc5b6f499b23a7cb1c96ab4d59",
"type": "github"
"lastModified": 1582018169,
"narHash": "sha256-qv1iK1IchpZKSeWL3NEs4U5Jl5QVyNHDdiMJvLOI4Yc=",
"type": "tarball",
"url": "https://releases.nixos.org/nixos/19.03/nixos-19.03.173691.34c7eb7545d/nixexprs.tar.xz"
},
"original": {
"owner": "NixOS",
"ref": "nixos-19.03",
"repo": "nixpkgs",
"type": "github"
"type": "tarball",
"url": "https://channels.nixos.org/nixos-19.03/nixexprs.tar.xz"
}
},
"nixpkgs-older": {
"flake": false,
"locked": {
"lastModified": 1523316493,
"narHash": "sha256-5qJS+i5ECICPAKA6FhPLIWkhPKDnOZsZbh2PHYF1Kbs=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "0b307aa73804bbd7a7172899e59ae0b8c347a62d",
"type": "github"
"lastModified": 1550657948,
"narHash": "sha256-BE0XqzNfzvhhtTXv37LyySyq4moL7z1i1hMvwbFNL/I=",
"type": "tarball",
"url": "https://releases.nixos.org/nixos/18.03/nixos-18.03.133402.cb0e20d6db9/nixexprs.tar.xz"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "0b307aa73804bbd7a7172899e59ae0b8c347a62d",
"type": "github"
"type": "tarball",
"url": "https://channels.nixos.org/nixos-18.03/nixexprs.tar.xz"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"nixpkgs-cadical": "nixpkgs-cadical",
"nixpkgs-old": "nixpkgs-old",
"nixpkgs-older": "nixpkgs-older"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",

View File

@@ -1,29 +1,22 @@
{
description = "Lean development flake. Not intended for end users.";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
# We use channels so we're not affected by GitHub's rate limits
inputs.nixpkgs.url = "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz";
# old nixpkgs used for portable release with older glibc (2.27)
inputs.nixpkgs-old.url = "github:NixOS/nixpkgs/nixos-19.03";
inputs.nixpkgs-old.url = "https://channels.nixos.org/nixos-19.03/nixexprs.tar.xz";
inputs.nixpkgs-old.flake = false;
# old nixpkgs used for portable release with older glibc (2.26)
inputs.nixpkgs-older.url = "github:NixOS/nixpkgs/0b307aa73804bbd7a7172899e59ae0b8c347a62d";
inputs.nixpkgs-older.url = "https://channels.nixos.org/nixos-18.03/nixexprs.tar.xz";
inputs.nixpkgs-older.flake = false;
# for cadical 2.1.2; sync with CMakeLists.txt by taking commit from https://www.nixhub.io/packages/cadical
inputs.nixpkgs-cadical.url = "github:NixOS/nixpkgs/199169a2135e6b864a888e89a2ace345703c025d";
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = inputs: inputs.flake-utils.lib.eachDefaultSystem (system:
outputs = inputs: builtins.foldl' inputs.nixpkgs.lib.attrsets.recursiveUpdate {} (builtins.map (system:
let
pkgs = import inputs.nixpkgs { inherit system; };
# An old nixpkgs for creating releases with an old glibc
pkgsDist-old = import inputs.nixpkgs-older { inherit system; };
# An old nixpkgs for creating releases with an old glibc
pkgsDist-old-aarch = import inputs.nixpkgs-old { localSystem.config = "aarch64-unknown-linux-gnu"; };
pkgsCadical = import inputs.nixpkgs-cadical { inherit system; };
cadical = if pkgs.stdenv.isLinux then
# use statically-linked cadical on Linux to avoid glibc versioning troubles
pkgsCadical.pkgsStatic.cadical.overrideAttrs { doCheck = false; }
else pkgsCadical.cadical;
lean-packages = pkgs.callPackage (./nix/packages.nix) { src = ./.; };
@@ -31,7 +24,7 @@
stdenv = pkgs.overrideCC pkgs.stdenv lean-packages.llvmPackages.clang;
} ({
buildInputs = with pkgs; [
cmake gmp libuv ccache cadical pkg-config
cmake gmp libuv ccache pkg-config
lean-packages.llvmPackages.llvm # llvm-symbolizer for asan/lsan
gdb
tree # for CI
@@ -67,15 +60,17 @@
GDB = pkgsDist.gdb;
});
in {
packages = {
packages.${system} = {
# to be removed when Nix CI is not needed anymore
inherit (lean-packages) cacheRoots test update-stage0-commit ciShell;
deprecated = lean-packages;
};
# The default development shell for working on lean itself
devShells.default = devShellWithDist pkgs;
devShells.oldGlibc = devShellWithDist pkgsDist-old;
devShells.oldGlibcAArch = devShellWithDist pkgsDist-old-aarch;
});
devShells.${system} = {
# The default development shell for working on lean itself
default = devShellWithDist pkgs;
oldGlibc = devShellWithDist pkgsDist-old;
oldGlibcAArch = devShellWithDist pkgsDist-old-aarch;
};
}) ["x86_64-linux" "aarch64-linux"]);
}

View File

@@ -194,7 +194,7 @@ with builtins; let
modCandidates = mapAttrs (mod: header:
let
deps = if header.errors == []
then map (m: m.module) header.imports
then map (m: m.module) header.result.imports
else abort "errors while parsing imports of ${mod}:\n${lib.concatStringsSep "\n" header.errors}";
in mkMod mod (map (dep: if modDepsMap ? ${dep} then modCandidates.${dep} else externalModMap.${dep}) deps)) modDepsMap;
expandGlob = g:
@@ -206,7 +206,7 @@ with builtins; let
# subset of `modCandidates` that is transitively reachable from `roots`
mods' = listToAttrs (map (e: { name = e.key; value = modCandidates.${e.key}; }) (genericClosure {
startSet = map (m: { key = m; }) (concatMap expandGlob roots);
operator = e: if modDepsMap ? ${e.key} then map (m: { key = m.module; }) (filter (m: modCandidates ? ${m.module}) modDepsMap.${e.key}.imports) else [];
operator = e: if modDepsMap ? ${e.key} then map (m: { key = m.module; }) (filter (m: modCandidates ? ${m.module}) modDepsMap.${e.key}.result.imports) else [];
}));
allLinkFlags = lib.foldr (shared: acc: acc ++ [ "-L${shared}" "-l${shared.linkName or shared.name}" ]) linkFlags allNativeSharedLibs;

View File

@@ -1,4 +1,5 @@
import Lean.Data.Lsp
import Lean.Elab.Import
open Lean
open Lean.Lsp
open Lean.JsonRpc
@@ -7,9 +8,7 @@ open Lean.JsonRpc
Tests language server memory use by repeatedly re-elaborate a given file.
NOTE: only works on Linux for now.
HACK: The line that is to be prepended with a space is hard-coded below to be sufficiently far down
not to touch the imports for usual files.
ot to touch the imports for usual files.
-/
def main (args : List String) : IO Unit := do
@@ -33,6 +32,8 @@ def main (args : List String) : IO Unit := do
Ipc.writeRequest 0, "initialize", { capabilities : InitializeParams }
let text IO.FS.readFile file
let (_, headerEndPos, _) Elab.parseImports text
let headerEndPos := FileMap.ofString text |>.leanPosToLspPos headerEndPos
let mut requestNo : Nat := 1
let mut versionNo : Nat := 1
Ipc.writeNotification "textDocument/didOpen", {
@@ -40,15 +41,14 @@ def main (args : List String) : IO Unit := do
for i in [0:iters.toNat!] do
if i > 0 then
versionNo := versionNo + 1
let pos := { line := 19, character := 0 }
let params : DidChangeTextDocumentParams := {
textDocument := {
uri := uri
version? := versionNo
}
contentChanges := #[TextDocumentContentChangeEvent.rangeChange {
start := pos
«end» := pos
start := headerEndPos
«end» := headerEndPos
} " "]
}
let params := toJson params

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env bash
set -uo pipefail
set -euxo pipefail
# run from root build directory (from inside nix-shell or otherwise defining GLIBC/ZLIB/GMP) as in
# ```
@@ -14,6 +14,7 @@ set -uo pipefail
else
ln -s llvm llvm-host
fi
mkdir -p stage0/lib
mkdir -p stage1/{bin,lib,lib/glibc,include/clang}
CP="cp -d" # preserve symlinks
# a C compiler!
@@ -25,6 +26,8 @@ cp -L llvm/bin/llvm-ar stage1/bin/
# dependencies of the above
$CP llvm/lib/lib{clang-cpp,LLVM}*.so* stage1/lib/
$CP $ZLIB/lib/libz.so* stage1/lib/
# also copy USE_LLVM deps into stage 0
$CP llvm/lib/libLLVM*.so* $ZLIB/lib/libz.so* stage0/lib/
# general clang++ dependency, breaks cross-library C++ exceptions if linked statically
$CP $GCC_LIB/lib/libgcc_s.so* stage1/lib/
# bundle libatomic (referenced by LLVM >= 15, and required by the lean executable to run)
@@ -39,18 +42,18 @@ $CP $GLIBC/lib/*crt* stage1/lib/
# runtime
(cd llvm; $CP --parents lib/clang/*/lib/*/{clang_rt.*.o,libclang_rt.builtins*} ../stage1)
$CP llvm/lib/*/lib{c++,c++abi,unwind}.* $GMP/lib/libgmp.a $LIBUV/lib/libuv.a stage1/lib/
# LLVM 15 appears to ship the dependencies in 'llvm/lib/<target-triple>/' and 'llvm/include/<target-triple>/'
# but clang-15 that we use to compile is linked against 'llvm/lib/' and 'llvm/include'
# LLVM 19 appears to ship the dependencies in 'llvm/lib/<target-triple>/' and 'llvm/include/<target-triple>/'
# but clang-19 that we use to compile is linked against 'llvm/lib/' and 'llvm/include'
# https://github.com/llvm/llvm-project/issues/54955
$CP llvm/lib/*/lib{c++,c++abi,unwind}.* llvm/lib/
$CP llvm-host/lib/*/lib{c++,c++abi,unwind}.* llvm-host/lib/
# libc++ headers are looked up in the host compiler's root, so copy over target-specific includes
$CP -r llvm/include/*-*-* llvm-host/include/
$CP -r llvm/include/*-*-* llvm-host/include/ || true
# glibc: use for linking (so Lean programs don't embed newer symbol versions), but not for running (because libc.so, librt.so, and ld.so must be compatible)!
$CP $GLIBC/lib/libc_nonshared.a stage1/lib/glibc
# libpthread_nonshared.a must be linked in order to be able to use `pthread_atfork(3)`. LibUV uses this function.
$CP $GLIBC/lib/libpthread_nonshared.a stage1/lib/glibc
for f in $GLIBC/lib/lib{c,dl,m,rt,pthread}-*; do b=$(basename $f); cp $f stage1/lib/glibc/${b%-*}.so; done
for f in $GLIBC/lib/{ld,lib{c,dl,m,rt,pthread}}-*; do b=$(basename $f); cp $f stage1/lib/glibc/${b%-*}.so; done
OPTIONS=()
echo -n " -DLEAN_STANDALONE=ON"
echo -n " -DCMAKE_CXX_COMPILER=$PWD/llvm-host/bin/clang++ -DLEAN_CXX_STDLIB='-Wl,-Bstatic -lc++ -lc++abi -Wl,-Bdynamic'"
@@ -64,7 +67,8 @@ fi
# use `-nostdinc` to make sure headers are not visible by default (in particular, not to `#include_next` in the clang headers),
# but do not change sysroot so users can still link against system libs
echo -n " -DLEANC_INTERNAL_FLAGS='--sysroot ROOT -nostdinc -isystem ROOT/include/clang' -DLEANC_CC=ROOT/bin/clang"
echo -n " -DLEANC_INTERNAL_LINKER_FLAGS='--sysroot ROOT -L ROOT/lib -L ROOT/lib/glibc ROOT/lib/glibc/libc_nonshared.a ROOT/lib/glibc/libpthread_nonshared.a -Wl,--as-needed -Wl,-Bstatic -lgmp -lunwind -luv -Wl,-Bdynamic -Wl,--no-as-needed -fuse-ld=lld'"
# ld.so is usually included by the libc.so linker script but we discard those
echo -n " -DLEANC_INTERNAL_LINKER_FLAGS='--sysroot ROOT -L ROOT/lib -L ROOT/lib/glibc ROOT/lib/glibc/libc_nonshared.a ROOT/lib/glibc/libpthread_nonshared.a -Wl,--as-needed -Wl,-Bstatic -lgmp -lunwind -luv -Wl,-Bdynamic ROOT/lib/glibc/ld.so -Wl,--no-as-needed -fuse-ld=lld'"
# when not using the above flags, link GMP dynamically/as usual
echo -n " -DLEAN_EXTRA_LINKER_FLAGS='-Wl,--as-needed -lgmp -luv -lpthread -ldl -lrt -Wl,--no-as-needed'"
# do not set `LEAN_CC` for tests

View File

@@ -191,10 +191,11 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules")
# Initialize CXXFLAGS.
set(CMAKE_CXX_FLAGS "${LEAN_EXTRA_CXX_FLAGS} -DLEAN_BUILD_TYPE=\"${CMAKE_BUILD_TYPE}\" -DLEAN_EXPORTING")
set(CMAKE_CXX_FLAGS_DEBUG "-DLEAN_DEBUG -DLEAN_TRACE")
set(CMAKE_CXX_FLAGS_DEBUG "-DLEAN_DEBUG")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-DNDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-DNDEBUG")
set(CMAKE_CXX_FLAGS_RELWITHASSERT "-DLEAN_DEBUG")
# SPLIT_STACK
if (SPLIT_STACK)
@@ -221,6 +222,7 @@ elseif (MSVC)
set(CMAKE_CXX_FLAGS_DEBUG "/Od /Zi ${CMAKE_CXX_FLAGS_DEBUG}")
set(CMAKE_CXX_FLAGS_MINSIZEREL "/Os /Zc:inline ${CMAKE_CXX_FLAGS_MINSIZEREL}")
set(CMAKE_CXX_FLAGS_RELEASE "/O2 /Oi /Oy /Zc:inline ${CMAKE_CXX_FLAGS_RELEASE}")
set(CMAKE_CXX_FLAGS_RELWITHASSERT "/O2 /Oi /Oy /Zc:inline ${CMAKE_CXX_FLAGS_RELWITHASSERT}")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/O2 /Oi /Zi ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
set(LEAN_EXTRA_LINKER_FLAGS "/LTCG:INCREMENTAL ${LEAN_EXTRA_LINKER_FLAGS}")
set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} ${LEAN_EXTRA_LINKER_FLAGS}")
@@ -240,11 +242,13 @@ if (NOT MSVC)
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os ${CMAKE_CXX_FLAGS_MINSIZEREL}")
endif ()
set(CMAKE_CXX_FLAGS_RELEASE "-O3 ${CMAKE_CXX_FLAGS_RELEASE}")
set(CMAKE_CXX_FLAGS_RELWITHASSERT "-O3 ${CMAKE_CXX_FLAGS_RELWITHASSERT}")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g3 -fno-omit-frame-pointer ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
elseif (MULTI_THREAD)
set(CMAKE_CXX_FLAGS_DEBUG "/MTd ${CMAKE_CXX_FLAGS_DEBUG}")
set(CMAKE_CXX_FLAGS_MINSIZEREL "/MT ${CMAKE_CXX_FLAGS_MINSIZEREL}")
set(CMAKE_CXX_FLAGS_RELEASE "/MT ${CMAKE_CXX_FLAGS_RELEASE}")
set(CMAKE_CXX_FLAGS_RELWITHASSERT "/MT ${CMAKE_CXX_FLAGS_RELWITHASSERT}")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MT ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
endif ()
@@ -365,8 +369,8 @@ if(LLVM)
execute_process(COMMAND ${LLVM_CONFIG} --version COMMAND_ERROR_IS_FATAL ANY OUTPUT_VARIABLE LLVM_CONFIG_VERSION ECHO_OUTPUT_VARIABLE OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REGEX MATCH "^[0-9]*" LLVM_CONFIG_MAJOR_VERSION ${LLVM_CONFIG_VERSION})
message(STATUS "Found 'llvm-config' at '${LLVM_CONFIG}' with version '${LLVM_CONFIG_VERSION}', major version '${LLVM_CONFIG_MAJOR_VERSION}'")
if (NOT LLVM_CONFIG_MAJOR_VERSION STREQUAL "15")
message(FATAL_ERROR "Unable to find llvm-config version 15. Found invalid version '${LLVM_CONFIG_MAJOR_VERSION}'")
if (NOT LLVM_CONFIG_MAJOR_VERSION STREQUAL "19")
message(FATAL_ERROR "Unable to find llvm-config version 19. Found invalid version '${LLVM_CONFIG_MAJOR_VERSION}'")
endif()
# -DLEAN_LLVM is used to conditionally compile Lean features that depend on LLVM
string(APPEND CMAKE_CXX_FLAGS " -D LEAN_LLVM")
@@ -843,6 +847,4 @@ endif()
if(USE_LAKE AND STAGE EQUAL 1)
configure_file(${LEAN_SOURCE_DIR}/lakefile.toml.in ${LEAN_SOURCE_DIR}/lakefile.toml)
configure_file(${LEAN_SOURCE_DIR}/lakefile.toml.in ${LEAN_SOURCE_DIR}/../tests/lakefile.toml)
configure_file(${LEAN_SOURCE_DIR}/lakefile.toml.in ${LEAN_SOURCE_DIR}/../lakefile.toml)
endif()

View File

@@ -3,6 +3,8 @@ Copyright (c) 2014 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
import Init.Prelude
import Init.Notation

View File

@@ -4,6 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Joachim Breitner
-/
module
prelude
import Init.Prelude
import Init.Tactics

View File

@@ -3,6 +3,8 @@ Copyright (c) 2021 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Gabriel Ebner
-/
module
prelude
import Init.NotationExtra

View File

@@ -3,6 +3,8 @@ Copyright (c) 2024 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura, Mario Carneiro
-/
module
prelude
import Init.Classical

View File

@@ -3,6 +3,8 @@ Copyright (c) 2020 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura, Mario Carneiro
-/
module
prelude
import Init.PropLemmas

View File

@@ -3,6 +3,8 @@ Copyright (c) 2020 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura, Mario Carneiro
-/
module
prelude
import Init.Prelude
set_option linter.missingDocs true -- keep it documented
@@ -307,9 +309,6 @@ instance boolToSort : CoeSort Bool Prop where
instance decPropToBool (p : Prop) [Decidable p] : CoeDep Prop p Bool where
coe := decide p
instance optionCoe {α : Type u} : Coe α (Option α) where
coe := some
instance subtypeCoe {α : Sort u} {p : α Prop} : CoeOut (Subtype p) α where
coe v := v.val

View File

@@ -3,6 +3,8 @@ Copyright (c) 2016 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
import Init.Control.Basic
import Init.Control.State

View File

@@ -3,6 +3,8 @@ Copyright (c) 2020 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura, Sebastian Ullrich
-/
module
prelude
import Init.Core
import Init.BinderNameHint

View File

@@ -3,6 +3,8 @@ Copyright (c) 2019 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
import Init.Control.State
import Init.Control.Except

View File

@@ -5,6 +5,8 @@ Authors: Jared Roesch, Sebastian Ullrich
The Except monad transformer.
-/
module
prelude
import Init.Control.Basic
import Init.Control.Id

View File

@@ -3,6 +3,8 @@ Copyright (c) 2021 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
import Init.Control.Lawful.Basic

View File

@@ -5,6 +5,8 @@ Authors: Sebastian Ullrich
The identity Monad.
-/
module
prelude
import Init.Core

View File

@@ -3,6 +3,8 @@ Copyright (c) 2021 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Sebastian Ullrich, Leonardo de Moura, Mario Carneiro
-/
module
prelude
import Init.Control.Lawful.Basic
import Init.Control.Lawful.Instances

View File

@@ -3,6 +3,8 @@ Copyright (c) 2021 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Sebastian Ullrich, Leonardo de Moura, Mario Carneiro
-/
module
prelude
import Init.SimpLemmas
import Init.Meta
@@ -142,6 +144,7 @@ class LawfulMonad (m : Type u → Type v) [Monad m] : Prop extends LawfulApplica
export LawfulMonad (bind_pure_comp bind_map pure_bind bind_assoc)
attribute [simp] pure_bind bind_assoc bind_pure_comp
attribute [grind] pure_bind
@[simp] theorem bind_pure [Monad m] [LawfulMonad m] (x : m α) : x >>= pure = x := by
show x >>= (fun a => pure (id a)) = x

View File

@@ -3,6 +3,8 @@ Copyright (c) 2021 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Sebastian Ullrich, Leonardo de Moura, Mario Carneiro
-/
module
prelude
import Init.Control.Lawful.Basic
import Init.Control.Except

View File

@@ -3,6 +3,8 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kim Morrison
-/
module
prelude
import Init.Control.Lawful.Basic
import Init.RCases

View File

@@ -3,6 +3,8 @@ Copyright (c) 2017 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura, Sebastian Ullrich
-/
module
prelude
import Init.Data.Option.Basic
import Init.Control.Basic
@@ -98,7 +100,7 @@ Handles failures by treating them as exceptions of type `Unit`.
-/
@[always_inline, inline] protected def tryCatch (x : OptionT m α) (handle : Unit OptionT m α) : OptionT m α := OptionT.mk do
let some a x | handle ()
pure a
pure <| some a
instance : MonadExceptOf Unit (OptionT m) where
throw := fun _ => OptionT.fail

View File

@@ -5,6 +5,8 @@ Authors: Sebastian Ullrich
The Reader monad transformer for passing immutable State.
-/
module
prelude
import Init.Control.Basic
import Init.Control.Id

View File

@@ -5,6 +5,8 @@ Authors: Leonardo de Moura, Sebastian Ullrich
The State monad transformer.
-/
module
prelude
import Init.Control.Basic
import Init.Control.Id

View File

@@ -3,6 +3,8 @@ Copyright (c) 2021 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
import Init.Control.Lawful.Basic

View File

@@ -5,6 +5,8 @@ Authors: Leonardo de Moura, Sebastian Ullrich
The State monad transformer using IO references.
-/
module
prelude
import Init.System.ST

View File

@@ -5,6 +5,8 @@ Authors: Leonardo de Moura
Notation for operators defined at Prelude.lean
-/
module
prelude
import Init.Tactics
import Init.Meta
@@ -318,6 +320,25 @@ syntax "repeat " convSeq : conv
macro_rules
| `(conv| repeat $seq) => `(conv| first | ($seq); repeat $seq | skip)
/--
Extracts `let` and `let_fun` 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.
- `extract_lets x y z` extracts all the lets from the target and uses `x`, `y`, and `z` for the first names.
Using `_` for a name leaves it unnamed.
Limitation: the extracted local declarations do not persist outside of the `conv` goal.
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.
This is the conv mode version of the `lift_lets` tactic.
-/
syntax (name := liftLets) "lift_lets " optConfig : conv
/--
`conv => ...` allows the user to perform targeted rewriting on a goal or hypothesis,
by focusing on particular subexpressions.

View File

@@ -5,6 +5,8 @@ Authors: Leonardo de Moura
notation, basic datatypes and type classes
-/
module
prelude
import Init.Prelude
import Init.SizeOf
@@ -21,6 +23,8 @@ which applies to all applications of the function).
theorem id_def {α : Sort u} (a : α) : id a = a := rfl
attribute [grind] id
/--
`flip f a b` is `f b a`. It is useful for "point-free" programming,
since it can sometimes be used to avoid introducing variables.
@@ -936,6 +940,34 @@ term.
theorem eqRec_heq {α : Sort u} {φ : α Sort v} {a a' : α} : (h : a = a') (p : φ a) HEq (Eq.recOn (motive := fun x _ => φ x) h p) p
| rfl, p => HEq.refl p
/--
Heterogenous equality with an `Eq.rec` application on the left is equivalent to a heterogenous
equality on the original term.
-/
theorem eqRec_heq_iff {α : Sort u} {a : α} {motive : (b : α) a = b Sort v}
{b : α} {refl : motive a (Eq.refl a)} {h : a = b} {c : motive b h} :
HEq (@Eq.rec α a motive refl b h) c HEq refl c :=
h.rec (fun _ => id, id) c
/--
Heterogenous equality with an `Eq.rec` application on the right is equivalent to a heterogenous
equality on the original term.
-/
theorem heq_eqRec_iff {α : Sort u} {a : α} {motive : (b : α) a = b Sort v}
{b : α} {refl : motive a (Eq.refl a)} {h : a = b} {c : motive b h} :
HEq c (@Eq.rec α a motive refl b h) HEq c refl :=
h.rec (fun _ => id, id) c
/--
Moves an cast using `Eq.rec` from the function to the argument.
Note: because the motive isn't reliably detected by unification,
it needs to be provided as an explicit parameter.
-/
theorem apply_eqRec {α : Sort u} {a : α} (motive : (b : α) a = b Sort v)
{b : α} {h : a = b} {c : motive a (Eq.refl a) β} {d : motive b h} :
@Eq.rec α a (fun b h => motive b h β) c b h d = c (h.symm d) := by
cases h; rfl
/--
If casting a term with `Eq.rec` to another type makes it equal to some other term, then the two
terms are heterogeneously equal.
@@ -981,7 +1013,7 @@ theorem HEq.comm {a : α} {b : β} : HEq a b ↔ HEq b a := Iff.intro HEq.symm H
theorem heq_comm {a : α} {b : β} : HEq a b HEq b a := HEq.comm
@[symm] theorem Iff.symm (h : a b) : b a := Iff.intro h.mpr h.mp
theorem Iff.comm: (a b) (b a) := Iff.intro Iff.symm Iff.symm
theorem Iff.comm : (a b) (b a) := Iff.intro Iff.symm Iff.symm
theorem iff_comm : (a b) (b a) := Iff.comm
@[symm] theorem And.symm : a b b a := fun ha, hb => hb, ha
@@ -1146,12 +1178,12 @@ theorem dif_eq_if (c : Prop) {h : Decidable c} {α : Sort u} (t : α) (e : α) :
| isTrue _ => rfl
| isFalse _ => rfl
instance {c t e : Prop} [dC : Decidable c] [dT : Decidable t] [dE : Decidable e] : Decidable (if c then t else e) :=
instance {c t e : Prop} [dC : Decidable c] [dT : Decidable t] [dE : Decidable e] : Decidable (if c then t else e) :=
match dC with
| isTrue _ => dT
| isFalse _ => dE
instance {c : Prop} {t : c Prop} {e : ¬c Prop} [dC : Decidable c] [dT : h, Decidable (t h)] [dE : h, Decidable (e h)] : Decidable (if h : c then t h else e h) :=
instance {c : Prop} {t : c Prop} {e : ¬c Prop} [dC : Decidable c] [dT : h, Decidable (t h)] [dE : h, Decidable (e h)] : Decidable (if h : c then t h else e h) :=
match dC with
| isTrue hc => dT hc
| isFalse hc => dE hc
@@ -1867,9 +1899,7 @@ protected abbrev hrecOn
(f : (a : α) motive (Quot.mk r a))
(c : (a b : α) (p : r a b) HEq (f a) (f b))
: motive q :=
Quot.recOn q f fun a b p => eq_of_heq <|
have p₁ : HEq (Eq.ndrec (f a) (sound p)) (f a) := eqRec_heq (sound p) (f a)
HEq.trans p₁ (c a b p)
Quot.recOn q f fun a b p => eq_of_heq (eqRec_heq_iff.mpr (c a b p))
end
end Quot
@@ -2232,6 +2262,27 @@ theorem funext {α : Sort u} {β : α → Sort v} {f g : (x : α) → β x}
show extfunApp (Quot.mk eqv f) = extfunApp (Quot.mk eqv g)
exact congrArg extfunApp (Quot.sound h)
/--
Like `Quot.liftOn q f h` but allows `f a` to "know" that `q = Quot.mk r a`.
-/
protected abbrev Quot.pliftOn {α : Sort u} {r : α α Prop}
(q : Quot r)
(f : (a : α) q = Quot.mk r a β)
(h : (a b : α) (h h'), r a b f a h = f b h') : β :=
q.rec (motive := fun q' => q = q' β) f
(fun a b p => funext fun h' =>
(apply_eqRec (motive := fun b _ => q = b)).trans
(@h a b (h'.trans (sound p).symm) h' p)) rfl
/--
Like `Quotient.liftOn q f h` but allows `f a` to "know" that `q = Quotient.mk s a`.
-/
protected abbrev Quotient.pliftOn {α : Sort u} {s : Setoid α}
(q : Quotient s)
(f : (a : α) q = Quotient.mk s a β)
(h : (a b : α) (h h'), a b f a h = f b h') : β :=
Quot.pliftOn q f h
instance Pi.instSubsingleton {α : Sort u} {β : α Sort v} [ a, Subsingleton (β a)] :
Subsingleton ( a, β a) where
allEq f g := funext fun a => Subsingleton.elim (f a) (g a)

View File

@@ -3,6 +3,8 @@ Copyright (c) 2016 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
import Init.Data.Basic
import Init.Data.Nat

View File

@@ -4,6 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Dany Fabian
-/
module
prelude
import Init.Classical
import Init.ByCases

View File

@@ -3,6 +3,8 @@ Copyright (c) 2017 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Gabriel Ebner
-/
module
prelude
import Init.Data.Array.Basic
import Init.Data.Array.QSort

View File

@@ -3,6 +3,8 @@ Copyright (c) 2021 Floris van Doorn. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Joachim Breitner, Mario Carneiro
-/
module
prelude
import Init.Data.Array.Mem
import Init.Data.Array.Lemmas

View File

@@ -3,6 +3,8 @@ Copyright (c) 2018 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
import Init.WFTactics
import Init.Data.Nat.Basic
@@ -38,11 +40,11 @@ namespace Array
/-! ### Preliminary theorems -/
@[simp] theorem size_set {xs : Array α} {i : Nat} {v : α} (h : i < xs.size) :
@[simp, grind] theorem size_set {xs : Array α} {i : Nat} {v : α} (h : i < xs.size) :
(set xs i v h).size = xs.size :=
List.length_set ..
@[simp] theorem size_push {xs : Array α} (v : α) : (push xs v).size = xs.size + 1 :=
@[simp, grind] theorem size_push {xs : Array α} (v : α) : (push xs v).size = xs.size + 1 :=
List.length_concat ..
theorem ext {xs ys : Array α}
@@ -108,7 +110,7 @@ theorem mem_def {a : α} {as : Array α} : a ∈ as ↔ a ∈ as.toList :=
@[simp] theorem mem_toArray {a : α} {l : List α} : a l.toArray a l := by
simp [mem_def]
@[simp] theorem getElem_mem {xs : Array α} {i : Nat} (h : i < xs.size) : xs[i] xs := by
@[simp, grind] theorem getElem_mem {xs : Array α} {i : Nat} (h : i < xs.size) : xs[i] xs := by
rw [Array.mem_def, getElem_toList]
apply List.getElem_mem
@@ -192,7 +194,7 @@ Examples:
def pop (xs : Array α) : Array α where
toList := xs.toList.dropLast
@[simp] theorem size_pop {xs : Array α} : xs.pop.size = xs.size - 1 := by
@[simp, grind] theorem size_pop {xs : Array α} : xs.pop.size = xs.size - 1 := by
match xs with
| [] => rfl
| a::as => simp [pop, Nat.succ_sub_succ_eq_sub, size]
@@ -834,7 +836,7 @@ some 10
def findSomeM? {α : Type u} {β : Type v} {m : Type v Type w} [Monad m] (f : α m (Option β)) (as : Array α) : m (Option β) := do
for a in as do
match ( f a) with
| some b => return b
| some b => return some b
| _ => pure
return none
@@ -865,7 +867,7 @@ some 1
def findM? {α : Type} [Monad m] (p : α m Bool) (as : Array α) : m (Option α) := do
for a in as do
if ( p a) then
return a
return some a
return none
/--
@@ -1173,7 +1175,7 @@ def find? {α : Type u} (p : α → Bool) (as : Array α) : Option α :=
Id.run do
for a in as do
if p a then
return a
return some a
return none
/--

View File

@@ -3,6 +3,8 @@ Copyright (c) 2022 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
import Init.Data.Array.Basic
import Init.Data.Nat.Linear

View File

@@ -3,6 +3,8 @@ Copyright (c) 2019 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
import Init.Data.Array.Basic
import Init.Data.Int.DivMod.Lemmas

View File

@@ -4,6 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro
-/
module
prelude
import Init.Data.List.TakeDrop
@@ -110,19 +112,19 @@ abbrev pop_toList := @Array.toList_pop
@[simp] theorem toList_empty : (#[] : Array α).toList = [] := rfl
@[simp] theorem append_empty {xs : Array α} : xs ++ #[] = xs := by
@[simp, grind] theorem append_empty {xs : Array α} : xs ++ #[] = xs := by
apply ext'; simp only [toList_append, toList_empty, List.append_nil]
@[deprecated append_empty (since := "2025-01-13")]
abbrev append_nil := @append_empty
@[simp] theorem empty_append {xs : Array α} : #[] ++ xs = xs := by
@[simp, grind] theorem empty_append {xs : Array α} : #[] ++ xs = xs := by
apply ext'; simp only [toList_append, toList_empty, List.nil_append]
@[deprecated empty_append (since := "2025-01-13")]
abbrev nil_append := @empty_append
@[simp] theorem append_assoc {xs ys zs : Array α} : xs ++ ys ++ zs = xs ++ (ys ++ zs) := by
@[simp, grind _=_] theorem append_assoc {xs ys zs : Array α} : xs ++ ys ++ zs = xs ++ (ys ++ zs) := by
apply ext'; simp only [toList_append, List.append_assoc]
@[simp] theorem appendList_eq_append {xs : Array α} {l : List α} : xs.appendList l = xs ++ l := rfl

View File

@@ -3,6 +3,8 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kim Morrison
-/
module
prelude
import Init.Data.Array.Lemmas
import Init.Data.List.Nat.Count

View File

@@ -3,6 +3,8 @@ Copyright (c) 2022 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
import Init.Data.Array.Basic
import Init.Data.BEq

View File

@@ -3,6 +3,8 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kim Morrison
-/
module
prelude
import Init.Data.Array.Lemmas
import Init.Data.List.Nat.Erase

View File

@@ -3,6 +3,8 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kim Morrison
-/
module
prelude
import Init.Data.Array.Lemmas
import Init.Data.List.Nat.TakeDrop

View File

@@ -3,6 +3,8 @@ Copyright (c) 2024 François G. Dorais. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: François G. Dorais
-/
module
prelude
import Init.Data.List.FinRange
import Init.Data.Array.OfFn

View File

@@ -3,6 +3,8 @@ Copyright (c) 2024 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kim Morrison
-/
module
prelude
import Init.Data.List.Nat.Find
import Init.Data.Array.Lemmas
@@ -21,6 +23,14 @@ open Nat
/-! ### findSome? -/
@[simp, grind] theorem findSome?_empty : (#[] : Array α).findSome? f = none := rfl
@[simp, grind] theorem findSome?_push {xs : Array α} : (xs.push a).findSome? f = (xs.findSome? f).or (f a) := by
cases xs; simp [List.findSome?_append]
@[grind]
theorem findSome?_singleton {a : α} {f : α Option β} : #[a].findSome? f = f a := by
simp
@[simp] theorem findSomeRev?_push_of_isSome {xs : Array α} (h : (f a).isSome) : (xs.push a).findSomeRev? f = f a := by
cases xs; simp_all
@@ -28,7 +38,7 @@ open Nat
cases xs; simp_all
theorem exists_of_findSome?_eq_some {f : α Option β} {xs : Array α} (w : xs.findSome? f = some b) :
a, a xs f a = b := by
a, a xs f a = some b := by
cases xs; simp_all [List.exists_of_findSome?_eq_some]
@[simp] theorem findSome?_eq_none_iff : findSome? p xs = none x xs, p x = none := by
@@ -129,6 +139,8 @@ abbrev findSome?_mkArray_of_isNone := @findSome?_replicate_of_isNone
/-! ### find? -/
@[simp] theorem find?_empty : find? p #[] = none := rfl
@[simp] theorem find?_singleton {a : α} {p : α Bool} :
#[a].find? p = if p a then some a else none := by
simp [singleton_eq_toArray_singleton]
@@ -157,6 +169,9 @@ theorem find?_eq_some_iff_append {xs : Array α} :
exact as.toList, l, by simpa using congrArg Array.toList h',
by simpa using h
theorem find?_push {xs : Array α} : (xs.push a).find? p = (xs.find? p).or (if p a then some a else none) := by
cases xs; simp
@[simp]
theorem find?_push_eq_some {xs : Array α} :
(xs.push a).find? p = some b xs.find? p = some b (xs.find? p = none (p a a = b)) := by
@@ -331,6 +346,11 @@ theorem find?_eq_some_iff_getElem {xs : Array α} {p : α → Bool} {b : α} :
/-! ### findIdx -/
@[simp] theorem findIdx_empty : findIdx p #[] = 0 := rfl
theorem findIdx_singleton {a : α} {p : α Bool} :
#[a].findIdx p = if p a then 0 else 1 := by
simp
theorem findIdx_of_getElem?_eq_some {xs : Array α} (w : xs[xs.findIdx p]? = some y) : p y := by
rcases xs with xs
exact List.findIdx_of_getElem?_eq_some (by simpa using w)
@@ -411,6 +431,13 @@ theorem findIdx_append {p : α → Bool} {xs ys : Array α} :
rcases ys with ys
simp [List.findIdx_append]
theorem findIdx_push {xs : Array α} {a : α} {p : α Bool} :
(xs.push a).findIdx p = if xs.findIdx p < xs.size then xs.findIdx p else xs.size + if p a then 0 else 1 := by
simp only [push_eq_append, findIdx_append]
split <;> rename_i h
· rfl
· simp [findIdx_singleton, 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
simp_all [List.findIdx_le_findIdx]
@@ -439,6 +466,9 @@ theorem false_of_mem_extract_findIdx {xs : Array α} {p : α → Bool} (h : x
/-! ### findIdx? -/
@[simp] theorem findIdx?_empty : (#[] : Array α).findIdx? p = none := by simp
theorem findIdx?_singleton {a : α} {p : α Bool} :
#[a].findIdx? p = if p a then some 0 else none := by
simp
@[simp]
theorem findIdx?_eq_none_iff {xs : Array α} {p : α Bool} :
@@ -506,6 +536,13 @@ theorem of_findIdx?_eq_none {xs : Array α} {p : α → Bool} (w : xs.findIdx? p
rcases ys with ys
simp [List.findIdx?_append]
theorem findIdx?_push {xs : Array α} {a : α} {p : α Bool} :
(xs.push a).findIdx? p = (xs.findIdx? p).or (if p a then some xs.size else none) := by
simp only [push_eq_append, findIdx?_append]
split <;> rename_i h
· simp only [findIdx?_singleton, if_pos h, Option.map_some, Nat.zero_add]
· simp only [findIdx?_singleton, if_neg h, Option.map_none]
theorem findIdx?_flatten {xss : Array (Array α)} {p : α Bool} :
xss.flatten.findIdx? p =
(xss.findIdx? (·.any p)).map
@@ -563,6 +600,9 @@ theorem findIdx?_eq_some_le_of_findIdx?_eq_some {xs : Array α} {p q : α → Bo
/-! ### findFinIdx? -/
@[simp] theorem findFinIdx?_empty {p : α Bool} : findFinIdx? p #[] = none := by simp
theorem findFinIdx?_singleton {a : α} {p : α Bool} :
#[a].findFinIdx? p = if p a then some 0, by simp else none := by
simp
-- We can't mark this as a `@[congr]` lemma since the head of the RHS is not `findFinIdx?`.
theorem findFinIdx?_congr {p : α Bool} {xs ys : Array α} (w : xs = ys) :
@@ -593,6 +633,21 @@ theorem findFinIdx?_eq_some_iff {xs : Array α} {p : α → Bool} {i : Fin xs.si
· rintro h, w
exact i, i.2, h, fun j hji => w j, by omega hji, rfl
theorem findFinIdx?_push {xs : Array α} {a : α} {p : α Bool} :
(xs.push a).findFinIdx? p =
((xs.findFinIdx? p).map (Fin.castLE (by simp))).or (if p a then some xs.size, by simp else none) := by
simp only [findFinIdx?_eq_pmap_findIdx?, findIdx?_push, Option.pmap_or]
split <;> rename_i h _ <;> split <;> simp [h]
theorem findFinIdx?_append {xs ys : Array α} {p : α Bool} :
(xs ++ ys).findFinIdx? p =
((xs.findFinIdx? p).map (Fin.castLE (by simp))).or
((ys.findFinIdx? p).map (Fin.natAdd xs.size) |>.map (Fin.cast (by simp))) := by
simp only [findFinIdx?_eq_pmap_findIdx?, findIdx?_append, Option.pmap_or]
split <;> rename_i h _
· simp [h, Option.pmap_map, Option.map_pmap, Nat.add_comm]
· simp [h]
@[simp]
theorem isSome_findFinIdx? {xs : Array α} {p : α Bool} :
(xs.findFinIdx? p).isSome = xs.any p := by

View File

@@ -4,6 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
import Init.Data.Array.Basic

View File

@@ -3,6 +3,8 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kim Morrison
-/
module
prelude
import Init.Data.Array.Lemmas
import Init.Data.List.Nat.InsertIdx

View File

@@ -3,6 +3,8 @@ Copyright (c) 2018 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
import Init.Data.Array.Basic

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,8 @@ Copyright (c) 2024 Lean FRO. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Kim Morrison
-/
module
prelude
import Init.Data.Array.Lex.Basic
import Init.Data.Array.Lex.Lemmas

View File

@@ -3,6 +3,8 @@ Copyright (c) 2024 Lean FRO. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Kim Morrison
-/
module
prelude
import Init.Data.Array.Basic
import Init.Data.Nat.Lemmas

View File

@@ -3,6 +3,8 @@ Copyright (c) 2024 Lean FRO. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Kim Morrison
-/
module
prelude
import Init.Data.Array.Lemmas
import Init.Data.List.Lex

View File

@@ -3,6 +3,8 @@ Copyright (c) 2022 Mario Carneiro. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro, Kim Morrison
-/
module
prelude
import Init.Data.Array.Lemmas
import Init.Data.Array.Attach
@@ -64,7 +66,7 @@ theorem mapFinIdx_spec {xs : Array α} {f : (i : Nat) → α → (h : i < xs.siz
@[simp] theorem getElem?_mapFinIdx {xs : Array α} {f : (i : Nat) α (h : i < xs.size) β} {i : Nat} :
(xs.mapFinIdx f)[i]? =
xs[i]?.pbind fun b h => f i b (getElem?_eq_some_iff.1 h).1 := by
xs[i]?.pbind fun b h => some <| f i b (getElem?_eq_some_iff.1 h).1 := by
simp only [getElem?_def, size_mapFinIdx, getElem_mapFinIdx]
split <;> simp_all
@@ -153,7 +155,7 @@ theorem mk_mem_zipIdx_iff_le_and_getElem?_sub {k i : Nat} {x : α} {xs : Array
/-- Variant of `mk_mem_zipIdx_iff_le_and_getElem?_sub` specialized at `k = 0`,
to avoid the inequality and the subtraction. -/
theorem mk_mem_zipIdx_iff_getElem? {x : α} {i : Nat} {xs : Array α} :
(x, i) xs.zipIdx xs[i]? = x := by
(x, i) xs.zipIdx xs[i]? = some x := by
rw [mk_mem_zipIdx_iff_le_and_getElem?_sub]
simp

View File

@@ -3,6 +3,8 @@ Copyright (c) 2022 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura, Joachim Breitner
-/
module
prelude
import Init.Data.Array.Basic
import Init.Data.Nat.Linear

View File

@@ -3,6 +3,8 @@ Copyright (c) 2024 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kim Morrison
-/
module
prelude
import Init.Data.Array.Lemmas
import Init.Data.Array.Attach

View File

@@ -3,6 +3,8 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kim Morrison
-/
module
prelude
import Init.Data.Array.Lemmas
import Init.Data.List.OfFn

View File

@@ -3,6 +3,8 @@ Copyright (c) 2024 Lean FRO. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kim Morrison
-/
module
prelude
import Init.Data.List.Nat.Perm
import Init.Data.Array.Lemmas
@@ -20,56 +22,91 @@ open List
This is a wrapper around `List.Perm`, and for now has much less API.
For more complicated verification, use `perm_iff_toList_perm` and the `List` API.
-/
def Perm (as bs : Array α) : Prop :=
as.toList ~ bs.toList
structure Perm (as bs : Array α) : Prop where
of_toList_perm ::
toList : as.toList ~ bs.toList
@[inherit_doc] scoped infixl:50 " ~ " => Perm
theorem perm_iff_toList_perm {as bs : Array α} : as ~ bs as.toList ~ bs.toList := Iff.rfl
theorem perm_iff_toList_perm {as bs : Array α} : as ~ bs as.toList ~ bs.toList :=
Perm.toList, Perm.of_toList_perm
@[simp] theorem perm_toArray (as bs : List α) : as.toArray ~ bs.toArray as ~ bs := by
end Array
namespace List
open Array
theorem perm_iff_toArray_perm {as bs : List α} : as ~ bs as.toArray ~ bs.toArray := by
simp [perm_iff_toList_perm]
theorem Perm.of_toArray_perm {as bs : List α} : as.toArray ~ bs.toArray as ~ bs :=
perm_iff_toArray_perm.mpr
theorem Perm.toArray {as bs : List α} : as ~ bs as.toArray ~ bs.toArray :=
perm_iff_toArray_perm.mp
end List
namespace Array
open List
@[simp, refl] protected theorem Perm.refl (xs : Array α) : xs ~ xs := by
cases xs
simp
simp [perm_iff_toList_perm]
protected theorem Perm.rfl {xs : Array α} : xs ~ xs := .refl _
theorem Perm.of_eq {xs ys : Array α} (h : xs = ys) : xs ~ ys := h .rfl
@[symm]
protected theorem Perm.symm {xs ys : Array α} (h : xs ~ ys) : ys ~ xs := by
cases xs; cases ys
simp only [perm_toArray] at h
simpa using h.symm
simp only [perm_iff_toList_perm] at h
simpa [perm_iff_toList_perm] using h.symm
protected theorem Perm.trans {xs ys zs : Array α} (h₁ : xs ~ ys) (h₂ : ys ~ zs) : xs ~ zs := by
cases xs; cases ys; cases zs
simp only [perm_toArray] at h₁ h₂
simpa using h₁.trans h₂
simp only [perm_iff_toList_perm] at h₁ h₂
simpa [perm_iff_toList_perm] using h₁.trans h₂
instance : Trans (Perm (α := α)) (Perm (α := α)) (Perm (α := α)) where
trans h₁ h₂ := Perm.trans h₁ h₂
theorem perm_comm {xs ys : Array α} : xs ~ ys ys ~ xs := Perm.symm, Perm.symm
theorem Perm.length_eq {xs ys : Array α} (p : xs ~ ys) : xs.size = ys.size := by
theorem Perm.size_eq {xs ys : Array α} (p : xs ~ ys) : xs.size = ys.size := by
cases xs; cases ys
simp only [perm_toArray] at p
simp only [perm_iff_toList_perm] at p
simpa using p.length_eq
@[deprecated Perm.size_eq (since := "2025-04-17")]
abbrev Perm.length_eq := @Perm.size_eq
theorem Perm.mem_iff {a : α} {xs ys : Array α} (p : xs ~ ys) : a xs a ys := by
rcases xs with xs
rcases ys with ys
simp at p
simp only [perm_iff_toList_perm] at p
simpa using p.mem_iff
theorem Perm.push (x y : α) {xs ys : Array α} (p : xs ~ ys) :
theorem Perm.append {xs ys as bs : Array α} (p₁ : xs ~ ys) (p : as ~ bs) :
xs ++ as ~ ys ++ bs := by
cases xs; cases ys; cases as; cases bs
simp only [append_toArray, perm_iff_toList_perm] at p₁ p₂
exact p₁.append p₂
theorem Perm.push (x : α) {xs ys : Array α} (p : xs ~ ys) :
xs.push x ~ ys.push x := by
rw [push_eq_append_singleton]
exact p.append .rfl
theorem Perm.push_comm (x y : α) {xs ys : Array α} (p : xs ~ ys) :
(xs.push x).push y ~ (ys.push y).push x := by
cases xs; cases ys
simp only [perm_toArray] at p
simp only [push_toArray, List.append_assoc, singleton_append, perm_toArray]
exact p.append (Perm.swap' _ _ Perm.nil)
simp only [perm_iff_toList_perm] at p
simp only [push_toArray, List.append_assoc, singleton_append, perm_iff_toList_perm]
exact p.append (Perm.swap ..)
theorem swap_perm {xs : Array α} {i j : Nat} (h₁ : i < xs.size) (h₂ : j < xs.size) :
xs.swap i j ~ xs := by
@@ -81,10 +118,10 @@ namespace Perm
set_option linter.indexVariables false in
theorem extract {xs ys : Array α} (h : xs ~ ys) {lo hi : Nat}
(wlo : i, i < lo xs[i]? = ys[i]?) (whi : i, hi i xs[i]? = ys[i]?) :
(xs.extract lo hi) ~ (ys.extract lo hi) := by
xs.extract lo hi ~ ys.extract lo hi := by
rcases xs with xs
rcases ys with ys
simp_all only [perm_toArray, List.getElem?_toArray, List.extract_toArray,
simp_all only [perm_iff_toList_perm, List.getElem?_toArray, List.extract_toArray,
List.extract_eq_drop_take]
apply List.Perm.take_of_getElem? (w := fun i h => by simpa using whi (lo + i) (by omega))
apply List.Perm.drop_of_getElem? (w := wlo)

View File

@@ -1,68 +1,9 @@
/-
Copyright (c) 2019 Microsoft Corporation. All rights reserved.
Copyright (c) 2024 Lean FRO. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
Authors: Kim Morrison
-/
module
prelude
import Init.Data.Vector.Basic
import Init.Data.Ord
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
-- We do not enable `linter.indexVariables` because it is helpful to name index variables `lo`, `mid`, `hi`, etc.
namespace Array
private def qpartition {n} (as : Vector α n) (lt : α α Bool) (lo hi : Nat)
(hlo : lo < n := by omega) (hhi : hi < n := by omega) : {n : Nat // lo n} × Vector α n :=
let mid := (lo + hi) / 2
let as := if lt as[mid] as[lo] then as.swap lo mid else as
let as := if lt as[hi] as[lo] then as.swap lo hi else as
let as := if lt as[mid] as[hi] then as.swap mid hi else as
let pivot := as[hi]
let rec loop (as : Vector α n) (i j : Nat)
(ilo : lo i := by omega) (jh : j < n := by omega) (w : i j := by omega) :=
if h : j < hi then
if lt as[j] pivot then
loop (as.swap i j) (i+1) (j+1)
else
loop as i (j+1)
else
(i, ilo, as.swap i hi)
loop as lo lo
/--
Sorts an array using the Quicksort algorithm.
The optional parameter `lt` specifies an ordering predicate. It defaults to `LT.lt`, which must be
decidable to be used for sorting. Use `Array.qsortOrd` to sort the array according to the `Ord α`
instance.
The optional parameters `low` and `high` delimit the region of the array that is sorted. Both are
inclusive, and default to sorting the entire array.
-/
@[inline] def qsort (as : Array α) (lt : α α Bool := by exact (· < ·))
(low := 0) (high := as.size - 1) : Array α :=
let rec @[specialize] sort {n} (as : Vector α n) (lo hi : Nat)
(hlo : lo < n := by omega) (hhi : hi < n := by omega) :=
if h₁ : lo < hi then
let mid, hmid, as := qpartition as lt lo hi
if h₂ : mid hi then
as
else
sort (sort as lo mid) (mid+1) hi
else as
if h : as.size = 0 then
as
else
let low := min low (as.size - 1)
let high := min high (as.size - 1)
sort as, rfl low high |>.toArray
set_option linter.unusedVariables.funArgs false in
/--
Sorts an array using the Quicksort algorithm, using `Ord.compare` to compare elements.
-/
def qsortOrd [ord : Ord α] (xs : Array α) : Array α :=
xs.qsort fun x y => compare x y |>.isLT
end Array
import Init.Data.Array.QSort.Basic

View File

@@ -0,0 +1,81 @@
/-
Copyright (c) 2019 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
import Init.Data.Vector.Basic
import Init.Data.Ord
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
-- We do not enable `linter.indexVariables` because it is helpful to name index variables `lo`, `mid`, `hi`, etc.
namespace Array
/--
Internal implementation of `Array.qsort`.
`qpartition as lt lo hi hlo hhi` returns a pair `(⟨m, h₁, h₂⟩, as')` where
`as'` is a permutation of `as` and `m` is a number such that:
- `lo ≤ m`
- `m < n`
- `∀ i, lo ≤ i → i < m → lt as[i] as[m]`
- `∀ j, m < j → j < hi → !lt as[j] as[m]`
It does so by first swapping the elements at indices `lo`, `mid := (lo + hi) / 2`, and `hi`
if necessary so that the middle (pivot) element is at index `hi`.
We then iterate from `j = lo` to `j = hi`, with a pointer `i` starting at `lo`, and
swapping each element which is less than the pivot to position `i`, and then incrementing `i`.
-/
def qpartition {n} (as : Vector α n) (lt : α α Bool) (lo hi : Nat)
(hlo : lo < n := by omega) (hhi : hi < n := by omega) : {m : Nat // lo m m < n} × Vector α n :=
let mid := (lo + hi) / 2
let as := if lt as[mid] as[lo] then as.swap lo mid else as
let as := if lt as[hi] as[lo] then as.swap lo hi else as
let as := if lt as[mid] as[hi] then as.swap mid hi else as
let pivot := as[hi]
let rec loop (as : Vector α n) (i j : Nat)
(ilo : lo i := by omega) (jh : j < n := by omega) (w : i j := by omega) :=
if h : j < hi then
if lt as[j] pivot then
loop (as.swap i j) (i+1) (j+1)
else
loop as i (j+1)
else
(i, ilo, by omega, as.swap i hi)
loop as lo lo
/--
In-place quicksort.
`qsort as lt low high` sorts the subarray `as[low:high+1]` in-place using `lt` to compare elements.
-/
@[inline] def qsort (as : Array α) (lt : α α Bool := by exact (· < ·))
(low := 0) (high := as.size - 1) : Array α :=
let rec @[specialize] sort {n} (as : Vector α n) (lo hi : Nat)
(hlo : lo < n := by omega) (hhi : hi < n := by omega) :=
if h₁ : lo < hi then
let mid, hmid, as := qpartition as lt lo hi
if h₂ : mid hi then
as
else
sort (sort as lo mid) (mid+1) hi
else as
if h : as.size = 0 then
as
else
let low := min low (as.size - 1)
let high := min high (as.size - 1)
sort as.toVector low high |>.toArray
set_option linter.unusedVariables.funArgs false in
/--
Sort an array using `compare` to compare elements.
-/
def qsortOrd [ord : Ord α] (xs : Array α) : Array α :=
xs.qsort fun x y => compare x y |>.isLT
end Array

View File

@@ -3,6 +3,8 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kim Morrison
-/
module
prelude
import Init.Data.Array.Lemmas
import Init.Data.Array.OfFn

View File

@@ -3,6 +3,8 @@ Copyright (c) 2020 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura, Mario Carneiro
-/
module
prelude
import Init.Tactics

View File

@@ -3,6 +3,8 @@ Copyright (c) 2020 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
import Init.Data.Array.Basic

View File

@@ -4,6 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: David Thrane Christiansen
-/
module
prelude
import Init.Data.Array.Basic
import Init.Data.Array.Subarray

View File

@@ -3,6 +3,8 @@ Copyright (c) 2024 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
module
prelude
import Init.Data.Array.Lemmas
import Init.Data.List.Nat.TakeDrop

View File

@@ -3,6 +3,8 @@ Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kim Morrison
-/
module
prelude
import Init.Data.Array.TakeDrop
import Init.Data.List.Zip
@@ -323,7 +325,7 @@ theorem map_zipWithAll {δ : Type _} {f : α → β} {g : Option γ → Option
simp [List.map_zipWithAll]
@[simp] theorem zipWithAll_replicate {a : α} {b : β} {n : Nat} :
zipWithAll f (replicate n a) (replicate n b) = replicate n (f a b) := by
zipWithAll f (replicate n a) (replicate n b) = replicate n (f (some a) (some b)) := by
simp [ List.toArray_replicate]
@[deprecated zipWithAll_replicate (since := "2025-03-18")]

View File

@@ -3,6 +3,8 @@ Copyright (c) 2022 Mario Carneiro. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro, Markus Himmel
-/
module
prelude
import Init.Data.Bool

View File

@@ -3,6 +3,8 @@ Copyright (c) 2016 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
import Init.Data.Nat.Basic
import Init.Data.Fin.Basic

View File

@@ -3,6 +3,8 @@ Copyright (c) 2024 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kim Morrison
-/
module
prelude
import Init.Data.BitVec.Basic
import Init.Data.BitVec.Bitblast

View File

@@ -3,6 +3,8 @@ Copyright (c) 2024 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Joe Hendrix, Wojciech Nawrocki, Leonardo de Moura, Mario Carneiro, Alex Keizer, Harun Khan, Abdalrhman M Mohamed, Siddharth Bhat
-/
module
prelude
import Init.Data.Fin.Basic
import Init.Data.Nat.Bitwise.Lemmas
@@ -767,6 +769,15 @@ SMT-Lib name: `bvnego`.
def negOverflow {w : Nat} (x : BitVec w) : Bool :=
x.toInt == - 2 ^ (w - 1)
/--
Checks whether the signed division of `x` by `y` results in overflow.
For BitVecs `x` and `y` with nonzero width, this only happens if `x = intMin` and `y = allOnes w`.
SMT-LIB name: `bvsdivo`.
-/
def sdivOverflow {w : Nat} (x y : BitVec w) : Bool :=
(2 ^ (w - 1) x.toInt / y.toInt) || (x.toInt / y.toInt < - 2 ^ (w - 1))
/- ### reverse -/
/-- Reverses the bits in a bitvector. -/

View File

@@ -3,6 +3,8 @@ Copyright (c) 2024 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Joe Hendrix, Wojciech Nawrocki, Leonardo de Moura, Mario Carneiro, Alex Keizer, Harun Khan, Abdalrhman M Mohamed
-/
module
prelude
import Init.Data.Fin.Basic

View File

@@ -3,6 +3,8 @@ Copyright (c) 2024 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Harun Khan, Abdalrhman M Mohamed, Joe Hendrix, Siddharth Bhat
-/
module
prelude
import Init.Data.BitVec.Folds
import Init.Data.Nat.Mod
@@ -1356,9 +1358,41 @@ theorem negOverflow_eq {w : Nat} (x : BitVec w) :
rcases w with _|w
· simp [toInt_of_zero_length, Int.min_eq_right]
· suffices - 2 ^ w = (intMin (w + 1)).toInt by simp [beq_eq_decide_eq, toInt_inj, this]
simp only [toInt_intMin, Nat.add_one_sub_one, Int.ofNat_emod, Int.neg_inj]
simp only [toInt_intMin, Nat.add_one_sub_one, Int.natCast_emod, Int.neg_inj]
rw_mod_cast [Nat.mod_eq_of_lt (by simp [Nat.pow_lt_pow_succ])]
/--
Prove that signed division `x.toInt / y.toInt` only overflows when `x = intMin w` and `y = allOnes w` (for `0 < w`).
-/
theorem sdivOverflow_eq {w : Nat} (x y : BitVec w) :
(sdivOverflow x y) = (decide (0 < w) && (x = intMin w) && (y = allOnes w)) := by
rcases w with _|w
· simp [sdivOverflow, of_length_zero]
· have yle := le_two_mul_toInt (x := y)
have ylt := two_mul_toInt_lt (x := y)
-- if y = allOnes (w + 1), thus y.toInt = -1,
-- the division overflows iff x = intMin (w + 1), as for negation
by_cases hy : y = allOnes (w + 1)
· simp [sdivOverflow_eq_negOverflow_of_eq_allOnes, negOverflow_eq, hy, beq_eq_decide_eq]
· simp only [sdivOverflow, hy, bool_to_prop]
have := BitVec.neg_two_pow_le_toInt_ediv (x := x) (y := y)
simp only [Nat.add_one_sub_one] at this
by_cases hx : 0 x.toInt
· by_cases hy' : 0 y.toInt
· have := BitVec.toInt_ediv_toInt_lt_of_nonneg_of_nonneg
(x := x) (y := y) (by omega) (by omega)
simp only [Nat.add_one_sub_one] at this; simp; omega
· have := BitVec.toInt_ediv_toInt_nonpos_of_nonneg_of_nonpos
(x := x) (y := y) (by omega) (by omega)
simp; omega
· by_cases hy' : 0 y.toInt
· have := BitVec.toInt_ediv_toInt_nonpos_of_nonpos_of_nonneg
(x := x) (y := y) (by omega) (by omega)
simp; omega
· have := BitVec.toInt_ediv_toInt_lt_of_nonpos_of_lt_neg_one
(x := x) (y := y) (by omega) (by rw [ toInt_inj, toInt_allOnes] at hy; omega)
simp only [Nat.add_one_sub_one] at this; simp; omega
theorem umulOverflow_eq {w : Nat} (x y : BitVec w) :
umulOverflow x y =
(0 < w && BitVec.twoPow (w * 2) w x.zeroExtend (w * 2) * y.zeroExtend (w * 2)) := by
@@ -1540,7 +1574,7 @@ theorem sdiv_ne_intMin_of_ne_intMin {x y : BitVec w} (h : x ≠ intMin w) :
theorem toInt_eq_neg_toNat_neg_of_msb_true {x : BitVec w} (h : x.msb = true) :
x.toInt = -((-x).toNat) := by
simp only [toInt_eq_msb_cond, h, reduceIte, toNat_neg, Int.ofNat_emod]
simp only [toInt_eq_msb_cond, h, reduceIte, toNat_neg, Int.natCast_emod]
norm_cast
rw [Nat.mod_eq_of_lt]
· omega
@@ -1635,7 +1669,7 @@ theorem toInt_sdiv_of_ne_or_ne (a b : BitVec w) (h : a ≠ intMin w b ≠ -1
(a.sdiv b).toInt = -((-a).toNat / b.toNat) := by
simp only [sdiv_eq, ha, hb, udiv_eq]
rw [toInt_eq_neg_toNat_neg_of_nonpos]
· rw [neg_neg, toNat_udiv, toNat_neg, Int.ofNat_emod, Int.neg_inj]
· rw [neg_neg, toNat_udiv, toNat_neg, Int.natCast_emod, Int.neg_inj]
norm_cast
· rw [neg_eq_zero_iff]
by_cases h' : -a / b = 0#w
@@ -1778,9 +1812,23 @@ theorem extractLsb'_mul {w len} {x y : BitVec w} (hlen : len ≤ w) :
(x * y).extractLsb' 0 len = (x.extractLsb' 0 len) * (y.extractLsb' 0 len) := by
simp [ setWidth_eq_extractLsb' hlen, setWidth_mul _ _ hlen]
/-- Adding bitvectors that are zero in complementary positions equals concatenation.
We add a `no_index` annotation to `HAppend.hAppend` such that the width `v + w`
does not act as a key in the discrimination tree.
This is important to allow matching, when the type of the result of append
`x : BitVec 3` and `y : BitVec 4` has been reduced to `x ++ y : BitVec 7`.
-/
theorem append_zero_add_zero_append {v w : Nat} {x : BitVec v} {y : BitVec w} :
(HAppend.hAppend (γ := BitVec (no_index _)) x 0#w) +
(HAppend.hAppend (γ := BitVec (no_index _)) 0#v y)
= x ++ y := by
rw [add_eq_or_of_and_eq_zero] <;> ext i <;> simp
/-- Adding bitvectors that are zero in complementary positions equals concatenation. -/
theorem append_add_append_eq_append {v w : Nat} {x : BitVec v} {y : BitVec w} :
(x ++ 0#w) + (0#v ++ y) = x ++ y := by
theorem zero_append_add_append_zero {v w : Nat} {x : BitVec v} {y : BitVec w} :
(HAppend.hAppend (γ := BitVec (no_index _)) 0#v y) +
(HAppend.hAppend (γ := BitVec (no_index _)) x 0#w)
= x ++ y := by
rw [add_eq_or_of_and_eq_zero] <;> ext i <;> simp
/-- Heuristically, `y <<< x` is much larger than `x`,
@@ -1796,4 +1844,10 @@ theorem add_shiftLeft_eq_or_shiftLeft {x y : BitVec w} :
have : i < 2^i := by exact Nat.lt_two_pow_self
omega
/-- Heuristically, `y <<< x` is much larger than `x`,
and hence low bits of `y <<< x`. Thus, `(y <<< x) + x = (y <<< x) ||| x.` -/
theorem shiftLeft_add_eq_shiftLeft_or {x y : BitVec w} :
(y <<< x) + x = (y <<< x) ||| x := by
rw [BitVec.add_comm, add_shiftLeft_eq_or_shiftLeft, or_comm]
end BitVec

View File

@@ -3,6 +3,8 @@ Copyright (c) 2023 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Joe Hendrix, Harun Khan
-/
module
prelude
import Init.Data.BitVec.Lemmas
import Init.Data.Nat.Lemmas

View File

@@ -4,6 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Joe Hendrix, Harun Khan, Alex Keizer, Abdalrhman M Mohamed, Siddharth Bhat
-/
module
prelude
import Init.Data.Bool
import Init.Data.BitVec.Basic
@@ -21,6 +23,9 @@ set_option linter.missingDocs true
namespace BitVec
@[simp] theorem mk_zero : BitVec.ofFin (w := w) 0, h = 0#w := rfl
@[simp] theorem ofNatLT_zero : BitVec.ofNatLT (w := w) 0 h = 0#w := rfl
@[simp] theorem getLsbD_ofFin (x : Fin (2^n)) (i : Nat) :
getLsbD (BitVec.ofFin x) i = x.val.testBit i := rfl
@@ -136,6 +141,8 @@ theorem toNat_ne_iff_ne {n} {x y : BitVec n} : x.toNat ≠ y.toNat ↔ x ≠ y :
@[bitvec_to_nat] theorem toNat_eq {x y : BitVec n} : x = y x.toNat = y.toNat :=
Iff.intro (congrArg BitVec.toNat) eq_of_toNat_eq
theorem toNat_inj {x y : BitVec n} : x.toNat = y.toNat x = y := toNat_eq.symm
@[bitvec_to_nat] theorem toNat_ne {x y : BitVec n} : x y x.toNat y.toNat := by
rw [Ne, toNat_eq]
@@ -613,10 +620,10 @@ theorem toInt_eq_toNat_bmod (x : BitVec n) : x.toInt = Int.bmod x.toNat (2^n) :=
simp only [toInt_eq_toNat_cond]
split
next g =>
rw [Int.bmod_pos] <;> simp only [Int.ofNat_emod, toNat_mod_cancel]
rw [Int.bmod_pos] <;> simp only [Int.natCast_emod, toNat_mod_cancel]
omega
next g =>
rw [Int.bmod_neg] <;> simp only [Int.ofNat_emod, toNat_mod_cancel]
rw [Int.bmod_neg] <;> simp only [Int.natCast_emod, toNat_mod_cancel]
omega
theorem toInt_neg_of_msb_true {x : BitVec w} (h : x.msb = true) : x.toInt < 0 := by
@@ -632,12 +639,12 @@ theorem toInt_nonneg_of_msb_false {x : BitVec w} (h : x.msb = false) : 0 ≤ x.t
@[simp] theorem toInt_one_of_lt {w : Nat} (h : 1 < w) : (1#w).toInt = 1 := by
rw [toInt_eq_msb_cond]
simp only [msb_one, show w 1 by omega, decide_false, Bool.false_eq_true, reduceIte,
toNat_ofNat, Int.ofNat_emod]
toNat_ofNat, Int.natCast_emod]
norm_cast
apply Nat.mod_eq_of_lt
apply Nat.one_lt_two_pow (by omega)
/-- Prove equality of bitvectors in terms of nat operations. -/
/-- Prove equality of bitvectors in terms of integer operations. -/
theorem eq_of_toInt_eq {x y : BitVec n} : x.toInt = y.toInt x = y := by
intro eq
simp only [toInt_eq_toNat_cond] at eq
@@ -2541,7 +2548,7 @@ where
simp [getElem_signExtend, Nat.le_sub_one_of_lt hv]
omega
have H : 2^w 2^v := Nat.pow_le_pow_right (by omega) (by omega)
simp only [this, toNat_setWidth, Int.natCast_add, Int.ofNat_emod, Int.natCast_mul]
simp only [this, toNat_setWidth, Int.natCast_add, Int.natCast_emod, Int.natCast_mul]
by_cases h : x.msb
<;> norm_cast
<;> simp [h, Nat.mod_eq_of_lt (Nat.lt_of_lt_of_le x.isLt H), -Int.natCast_pow]
@@ -3864,7 +3871,7 @@ theorem le_zero_iff {x : BitVec w} : x ≤ 0#w ↔ x = 0#w := by
theorem lt_one_iff {x : BitVec w} (h : 0 < w) : x < 1#w x = 0#w := by
constructor
· intro h₂
rw [lt_def, toNat_ofNat, Int.ofNat_lt, Int.ofNat_emod, Int.ofNat_one, Int.natCast_pow,
rw [lt_def, toNat_ofNat, Int.ofNat_lt, Int.natCast_emod, Int.ofNat_one, Int.natCast_pow,
Int.ofNat_two, @Int.emod_eq_of_lt 1 (2^w) (by omega) (by omega)] at h₂
simp [toNat_eq, show x.toNat = 0 by omega]
· simp_all
@@ -4143,6 +4150,110 @@ theorem sdiv_self {x : BitVec w} :
rcases x.msb with msb | msb <;> simp
· rcases x.msb with msb | msb <;> simp [h]
/-- Unsigned division never overflows. -/
theorem toNat_div_toNat_lt {w : Nat} {x y : BitVec w} :
x.toNat / y.toNat < 2 ^ w := by
have hy : y.toNat = 0 y.toNat = 1 1 < y.toNat := by omega
rcases hy with hy|hy|hy
· simp [hy]; omega
· simp [hy]; omega
· rw [Nat.div_lt_iff_lt_mul (k := y.toNat) (x := x.toNat) (y := 2 ^ w) (by omega), show x.toNat = x.toNat * 1 by omega]
apply Nat.mul_lt_mul_of_le_of_lt (by omega) (by omega) (by omega)
/-- Non-overflowing signed division bounds when numerator is nonneg, denominator is nonneg. -/
theorem toInt_ediv_toInt_lt_of_nonneg_of_nonneg {w : Nat} {x y : BitVec w} (hx : 0 x.toInt) (hy : 0 y.toInt) :
x.toInt / y.toInt < 2 ^ (w - 1) := by
rcases w with _|w
· simp [of_length_zero]
· have xle := le_two_mul_toInt (x := x); have xlt := two_mul_toInt_lt (x := x)
by_cases hy' : y.toInt = 1
· simp [hy', Int.ediv_one]; omega
· by_cases hx' : x.toInt = 0
· simp only [hx', Int.zero_ediv, Nat.add_one_sub_one, gt_iff_lt]
norm_cast
exact Nat.two_pow_pos (w := w)
· have := Int.ediv_lt_self_of_pos_of_ne_one (x := x.toInt) (y := y.toInt) (by omega) (by omega)
simp; omega
/-- Non-overflowing signed division bounds when numerator is nonpos, denominator is nonneg. -/
theorem toInt_ediv_toInt_nonpos_of_nonpos_of_nonneg {w : Nat} {x y : BitVec w} (hx : x.toInt 0) (hy : 0 y.toInt) :
x.toInt / y.toInt 0 := by
rcases w with _|w
· simp [of_length_zero]
· by_cases hx' : x.toInt = 0
· simp [hx']
· by_cases hy' : y.toInt = 0
· simp [hy']
· have := Int.ediv_neg_of_neg_of_pos (a := x.toInt) (b := y.toInt) (by omega) (by omega)
simp; omega
/-- Non-overflowing signed division bounds when numerator is nonneg, denominator is nonpos. -/
theorem toInt_ediv_toInt_nonpos_of_nonneg_of_nonpos {w : Nat} {x y : BitVec w} (hx : 0 x.toInt) (hy : y.toInt 0) :
x.toInt / y.toInt 0 := by
rcases w with _|w
· simp [of_length_zero]
· by_cases hy' : y.toInt = -1
· simp [hy']; omega
· have := Int.ediv_nonpos_of_nonneg_of_nonpos (a := x.toInt) (b := y.toInt) (by omega) (by omega)
simp; omega
/-- Given the definition of ediv/emod for signed integer division (https://dl.acm.org/doi/pdf/10.1145/128861.128862)
we have that for two integers `x` and `y`: `x/y = q ↔ x.ediv y = q ↔ r = x.emod y`
and in particular: `-1/y = q ↔ -1.ediv y = q ↔ r = -1.emod y`.
from which it follows that:
(-1)/0 = 0
(-1)/y = -1 when 0 < y
(-1)/(-5) = 1 when y < 0
-/
theorem neg_one_ediv_toInt_eq {w : Nat} {y : BitVec w} :
(-1) / y.toInt = if y.toInt = 0 then 0 else if 0 < y.toInt then -1 else 1 := by
rcases w with _|_|w
· simp [of_length_zero]
· cases eq_zero_or_eq_one y
· case _ h => simp [h]
· case _ h => simp [h]
· by_cases 0 < y.toInt
· simp [Int.sign_eq_one_of_pos (a := y.toInt) (by omega), Int.neg_one_ediv]
omega
· by_cases hy : y.toInt = 0
· simp [hy]
· simp [Int.sign_eq_neg_one_of_neg (a := y.toInt) (by omega), Int.neg_one_ediv]
omega
/-- Non-overflowing signed division bounds when numerator is nonpos, denominator is less than -1. -/
theorem toInt_ediv_toInt_lt_of_nonpos_of_lt_neg_one {w : Nat} {x y : BitVec w} (hx : x.toInt 0) (hy : y.toInt < -1) :
x.toInt / y.toInt < 2 ^ (w - 1) := by
rcases w with _|_|w
· simp [of_length_zero]
· have hy := eq_zero_or_eq_one (a := y)
simp [ toInt_inj, toInt_zero, toInt_one] at hy
omega
· have xle := le_two_mul_toInt (x := x); have xlt := two_mul_toInt_lt (x := x)
have hx' : x.toInt = 0 x.toInt = - 1 x.toInt < - 1 := by omega
rcases hx' with hx'|hx'|hx'
· simp [hx']; omega
· have := BitVec.neg_one_ediv_toInt_eq (y := y)
simp only [toInt_allOnes, Nat.lt_add_left_iff_pos, Nat.zero_lt_succ, reduceIte,
Int.reduceNeg] at this
simp [hx', this]
omega
· have := Int.ediv_lt_natAbs_self_of_lt_neg_one_of_lt_neg_one (x := x.toInt) (y := y.toInt) (by omega) hy
simp; omega
/-- Signed division of (x y : BitVec w) is always -2 ^ w ≤ x.toInt / y.toInt. -/
theorem neg_two_pow_le_toInt_ediv {x y : BitVec w} :
- 2 ^ (w - 1) x.toInt / y.toInt := by
have xlt := @toInt_lt w x; have lex := @le_toInt w x
by_cases hx : 0 x.toInt <;> by_cases hy : 0 y.toInt
· have := Int.ediv_nonneg_of_nonneg_of_nonneg (x := x.toInt) (y := y.toInt) hx hy
omega
· have := Int.neg_self_le_ediv_of_nonneg_of_nonpos (x := x.toInt) (y := y.toInt) hx (by omega)
omega
· have := Int.self_le_ediv_of_nonpos_of_nonneg (x := x.toInt) (y := y.toInt) (by omega) hy
omega
· have := Int.ediv_nonneg_of_nonpos_of_nonpos (a := x.toInt) (b := y.toInt) (by omega) (by omega)
omega
/-! ### smtSDiv -/
theorem smtSDiv_eq (x y : BitVec w) : smtSDiv x y =
@@ -4945,7 +5056,7 @@ theorem toInt_intMin_le (x : BitVec w) :
cases w
case zero => simp [toInt_intMin, @of_length_zero x]
case succ w =>
simp only [toInt_intMin, Nat.add_one_sub_one, Int.ofNat_emod]
simp only [toInt_intMin, Nat.add_one_sub_one, Int.natCast_emod]
have : 0 < 2 ^ w := Nat.two_pow_pos w
rw [Int.emod_eq_of_lt (by omega) (by omega)]
rw [BitVec.toInt_eq_toNat_bmod]
@@ -5140,6 +5251,22 @@ theorem sub_le_sub_iff_le {x y z : BitVec w} (hxz : z ≤ x) (hyz : z ≤ y) :
BitVec.toNat_sub_of_le (by rw [BitVec.le_def]; omega)]
omega
theorem sdiv_neg_one {w : Nat} {x : BitVec w} :
x.toInt / -1 = -x.toInt := by
rcases w with _|w
· simp [of_length_zero]
· simp [toInt_allOnes]
theorem sdivOverflow_eq_negOverflow_of_eq_allOnes {w : Nat} {x y : BitVec w} (hy : y = allOnes w) :
sdivOverflow x y = negOverflow x := by
rcases w with _|w
· simp [sdivOverflow, negOverflow, of_length_zero]
· have xle := le_two_mul_toInt (x := x); have xlt := two_mul_toInt_lt (x := x)
simp only [sdivOverflow, hy, show ¬2 ^ w < x.toInt by omega, negOverflow]
by_cases hx : x.toInt = - 2 ^ w
· simp [hx]
· simp [show ¬x.toInt == -2 ^ w by simp only [beq_iff_eq, hx, not_false_eq_true]]; omega
theorem two_pow_le_toInt_mul_toInt_iff {x y : BitVec w} :
2 ^ (w - 1) x.toInt * y.toInt
(signExtend (w * 2) (intMax w)).slt (signExtend (w * 2) x * signExtend (w * 2) y) := by

View File

@@ -3,6 +3,8 @@ Copyright (c) 2023 F. G. Dorais. No rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: F. G. Dorais
-/
module
prelude
import Init.NotationExtra

View File

@@ -3,5 +3,7 @@ Copyright (c) 2019 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
-/
module
prelude
import Init.Data.ByteArray.Basic

View File

@@ -3,6 +3,8 @@ Copyright (c) 2019 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
-/
module
prelude
import Init.Data.Array.Basic
import Init.Data.Array.Subarray

View File

@@ -3,6 +3,8 @@ Copyright (c) 2014 Mario Carneiro. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro, Gabriel Ebner
-/
module
prelude
import Init.Coe

View File

@@ -3,6 +3,8 @@ Copyright (c) 2016 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
import Init.Data.Char.Basic
import Init.Data.Char.Lemmas

View File

@@ -3,6 +3,8 @@ Copyright (c) 2016 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
-/
module
prelude
import Init.Data.UInt.BasicAux

View File

@@ -3,6 +3,8 @@ Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
import Init.Data.Char.Basic
import Init.Data.UInt.Lemmas

View File

@@ -3,6 +3,8 @@ Copyright (c) 2017 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
-/
module
prelude
import Init.Data.Fin.Basic
import Init.Data.Fin.Log2

View File

@@ -3,6 +3,8 @@ Copyright (c) 2016 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura, Robert Y. Lewis, Keeley Hoek, Mario Carneiro
-/
module
prelude
import Init.Data.Nat.Bitwise.Basic

View File

@@ -3,6 +3,8 @@ Copyright (c) 2024 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel
-/
module
prelude
import Init.Data.Nat.Bitwise
import Init.Data.Fin.Basic

View File

@@ -3,6 +3,8 @@ Copyright (c) 2023 François G. Dorais. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: François G. Dorais
-/
module
prelude
import Init.Data.Nat.Linear
import Init.Control.Lawful.Basic

View File

@@ -3,6 +3,8 @@ Copyright (c) 2024 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Joe Hendrix
-/
module
prelude
import Init.PropLemmas
import Init.Data.Fin.Basic

View File

@@ -3,6 +3,8 @@ Copyright (c) 2022 Mario Carneiro. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro, Leonardo de Moura
-/
module
prelude
import Init.Data.Fin.Basic
import Init.Data.Nat.Lemmas
@@ -410,6 +412,14 @@ theorem succ_succ_ne_one (a : Fin n) : Fin.succ (Fin.succ a) ≠ 1 :=
@[simp] theorem coe_cast (h : n = m) (i : Fin n) : (i.cast h : Nat) = i := rfl
@[simp] theorem cast_castLE {k m n} (km : k m) (mn : m = n) (i : Fin k) :
Fin.cast mn (i.castLE km) = i.castLE (mn km) :=
Fin.ext (by simp)
@[simp] theorem cast_castLT {k m n} (i : Fin k) (h : (i : Nat) < m) (mn : m = n) :
Fin.cast mn (i.castLT h) = i.castLT (mn h) :=
Fin.ext (by simp)
@[simp] theorem cast_zero [NeZero n] [NeZero m] (h : n = m) : Fin.cast h 0 = 0 := rfl
@[simp] theorem cast_last {n' : Nat} {h : n + 1 = n' + 1} : (last n).cast h = last n' :=

View File

@@ -3,6 +3,8 @@ Copyright (c) 2022 Henrik Böving. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Henrik Böving
-/
module
prelude
import Init.Data.Nat.Log2

View File

@@ -3,6 +3,8 @@ Copyright (c) 2020 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
import Init.Core
import Init.Data.Int.Basic

View File

@@ -3,6 +3,8 @@ Copyright (c) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
module
prelude
import Init.Core
import Init.Data.Int.Basic

View File

@@ -3,5 +3,7 @@ Copyright (c) 2020 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
-/
module
prelude
import Init.Data.FloatArray.Basic

View File

@@ -3,6 +3,8 @@ Copyright (c) 2020 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
-/
module
prelude
import Init.Data.Array.Basic
import Init.Data.Float

View File

@@ -3,6 +3,8 @@ Copyright (c) 2018 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
-/
module
prelude
import Init.Data.Format.Basic
import Init.Data.Format.Macro

View File

@@ -3,6 +3,8 @@ Copyright (c) 2018 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
-/
module
prelude
import Init.Control.State
import Init.Data.Int.Basic

View File

@@ -3,6 +3,8 @@ Copyright (c) 2020 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
-/
module
prelude
import Init.Data.Format.Basic
import Init.Data.Array.Basic

View File

@@ -3,6 +3,8 @@ Copyright (c) 2020 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
-/
module
prelude
import Init.Data.Format.Basic
import Init.Data.ToString.Macro

View File

@@ -3,6 +3,8 @@ Copyright (c) 2021 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
-/
module
prelude
import Init.Data.Format.Macro
import Init.Data.Format.Instances

View File

@@ -4,6 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kim Morrison
-/
module
prelude
import Init.Core

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