Commit graph

36794 commits

Author SHA1 Message Date
Kim Morrison
62e9d73f8b
chore: revert BitVec/Lemmas grind proofs; too many bootstrapping difficulties (#9006) 2025-06-26 03:04:01 +00:00
Sofia Rodrigues
b15cfadde8
feat: monadic interface for asynchronous operations in Std (#8003)
This PR adds a new monadic interface for `Async` operations.

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

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

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

### Explicit `yield` points

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

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

Would become:

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

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

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

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

### Infinite chain of Tasks

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

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

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

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

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

### The current monad

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

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

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

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

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

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

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

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

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

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

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

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

---------

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

co-authored with @tobiasgrosser and @bollu

---------

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

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

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

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

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

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

---------

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

---------

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

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

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

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

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

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

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

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

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

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

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

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

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

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

---------

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

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

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

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

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

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

It is a reasonable policy for a Lean project to say that all simp
invocation should be so that this linter does not complain. Often it is
just a matter of explicitly disabling some simp theorems from the
default simp set, to make it clear and robust that in this call, we do
not want them to trigger. But given that often such simp call happen to
work, it’s too pedantic to impose it on everyone.
2025-06-23 07:36:21 +00:00