This PR introduces a `coinductive` keyword, that can be used to define
coinductive predicates via a syntax identical to the one for `inductive`
keyword. The machinery relies on the implementation of elaboration of
inductive types and extracts an endomap on the appropriate space of the
predicates from the definition that is then fed to the
`PartialFixpoint`. Upon elaborating definitions, all the constructors
are declared through automatically generated lemmas.
For example, infinite sequence of transitions in a relation, can be
given by the following:
```lean4
section
variable (α : Type)
coinductive infSeq (r : α → α → Prop) : α → Prop where
| step : r a b → infSeq r b → infSeq r a
/--
info: infSeq.coinduct (α : Type) (r : α → α → Prop) (pred : α → Prop) (hyp : ∀ (x : α), pred x → ∃ b, r x b ∧ pred b)
(x✝ : α) : pred x✝ → infSeq α r x✝
-/
#guard_msgs in
#check infSeq.coinduct
/--
info: infSeq.step (α : Type) (r : α → α → Prop) {a b : α} : r a b → infSeq α r b → infSeq α r a
-/
#guard_msgs in
#check infSeq.step
end
```
The machinery also supports `mutual` blocks, as well as mixing inductive
and coinductive predicate definitions:
```lean4
mutual
coinductive tick : Prop where
| mk : ¬tock → tick
inductive tock : Prop where
| mk : ¬tick → tock
end
/--
info: tick.mutual_induct (pred_1 pred_2 : Prop) (hyp_1 : pred_1 → pred_2 → False) (hyp_2 : (pred_1 → False) → pred_2) :
(pred_1 → tick) ∧ (tock → pred_2)
-/
#guard_msgs in
#check tick.mutual_induct
```
---------
Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>
This PR changes how Lean proves the equational theorems for structural
recursion. The core idea is to let-bind the `f` argument to `brecOn` and
rewriting `.brecOn` with an unfolding theorem. This means no extra case
split for the `.rec` in `.brecOn` is needed, and `simp` doesn't change
the `f` argument which can break the definitional equality with the
defined function. With this, we can prove the unfolding theorem first,
and derive the equational theorems from that, like for all other ways of
defining recursive functions.
Backs out the changes from #10415, the old strategy works well with the
new goals.
Fixes#5667Fixes#10431Fixes#10195Fixes#2962
This PR fixes a broken link to the firefox profile definitions in one of
the comments.
The `profile.js` file was renamed to `profile.ts` while the rest of the
url remained the same.
This PR fixes an oversight in the RC insertion phase in the code
generator.
If the code generator encounters a `let` that is unused (which is
perfectly reasonable as at this
phase we are in an impure IR and as such allow for side effects to
happen so we cannot remove all
unused `let`) it didn't insert a `dec` instruction for this variable.
This has previously gone
unnoticed because at this point in the compiler basically all unused
lets are removed already
anyways. However with the `IO`/`ST` token erasure coming up they will be
very frequent.
This PR implements the basic tactics for the new `grind` interactive
mode. While many additional `grind` tactics will be added later, the
foundational framework is already operational. The following `grind`
tactics are currently implemented: `skip`, `done`, `finish`, `lia`, and
`ring`.
This PR also removes the notion of `grind` fallback procedure since it
is subsumed by the new framework. Examples:
```lean
example (x y : Nat) : x ≥ y + 1 → x > 0 := by
grind => skip; lia; done
open Lean Grind
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
```
This PR records extra mod uses that previously caused wrong unnecessary
import reports from shake.
---------
Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
This PR fixes one potential source of inlay hint flakiness.
In the old `IO.waitAny` implementation, we could rely on the fact that
if all tasks in the list were finished, `IO.waitAny` would pick the
first finished one. In the new implementation (#9732), this isn't the
case anymore for fairness reasons, but this also means that in
`IO.AsyncList.getFinishedPrefixWithTimeout`, it can happen that we don't
scan the full finished command snapshot prefix because we pick the
timeout task before the finished snapshot task. This is likely the cause
of a flaky test failure
[here](https://github.com/leanprover/lean4/actions/runs/18215430028/job/51863870111),
where the inlay hint test yielded no result (the timeout task has an
edit delay of 0ms in the first inlay hint request that is emitted,
finishes immediately and can thus immediately cause the finished prefix
to be skipped with the new `waitAny` implementation).
This PR fixes this issue by adding a `hasFinished` check before the
`waitAny` to ensure that we always scan the finished prefix and don't
need to rely on a brittle invariant that doesn't hold anymore. It also
converts some `Task.get`s to `IO.wait` for safety so that the compiler
can't re-order them.
This PR disables `{name}` suggestions for `.anonymous` and adds syntax
suggestions.
When the provided name can't be resolved, the `{name}` role suggests
fully-qualified variants. But if the name is a syntax error, it
attempted to suggest names that had `.anonymous` as a suffix; the
resulting list of suggestions of all names in Lean's environment
overloaded the language server.
This PR "monomorphizes" the structure `Std.PRange shape α`, replacing it
with nine distinct structures `Std.Rcc`, `Std.Rco`, `Std.Rci` etc., one
for each possible shape of a range's bounds. This change was necessary
because the shape polymorphism is detrimental to attempts of automation.
**BREAKING CHANGE:** While range/slice notation itself is unchanged,
this essentially breaks the entire remaining (polymorphic) range and
slice API except for the dot-notation(`toList`, `iter`, ...). It is not
possible to deprecate old declarations that were formulated in a
shape-polymorphic way that is not available anymore.
This PR explicitly tries to synthesize synthetic MVars in `mspec`. Doing
so resolves a bug triggered by use of the loop invariant lemma for
`Std.PRange`.
This PR reduces the aggressiveness of the dead let eliminator from
lambda RC.
The motivation for this is that all other passes in lambda RC respect
impurity but the dead let eliminator still operates under the assumption
of purity. There is a couple of motivations for the elim dead let
elaborator:
- unused projections introduced by the ToIR translation
- the elim dead branch pass introducing new opportunities
- closed term extraction introducing new opportunities
This PR significantly improves the test coverage of the language server,
providing at least a single basic test for every request that is used by
the client. It also implements infrastructure for testing all of these
requests, e.g. the ability to run interactive tests in a project context
and refactors the interactive test runner to be more maintainable.
Finally, it also fixes a small bug with the recently implemented unknown
identifier code actions for auto-implicits (#10442) that was discovered
in testing, where the "import all unambiguous unknown identifiers" code
action didn't work correctly on auto-implicit identifiers.
This PR cuts some edges from the import graph.
Specifically:
- `TreeMap` and `HashMap` no longer depend on `String`, so now the
expensive things are all in parallel instead of partially in sequence
- `Omega` no longer relies on `List` lemmas
- The section of the import graph between `Init.Omega` and
`Init.Data.Bitvec.Lemmas` is cleaned up a bit
This PR fixes a bug in the unknown identifier code actions where it
would yield non-sensical suggestions for nested `open` declarations like
`open Foo.Bar`.
This PR removes superfluous `Monad` instances from the spec lemmas of
the `MonadExceptOf` lifting framework.
It also adds a bit of documentation and more tracing to `mvcgen`.
Fixes#10564.
This PR ensures that even if a type is marked as `irreducible` the
compiler can see through it in
order to discover functions hidden behind type aliases.
This PR fixes a bad error message due to elaborating partial syntax with
Verso docstrings.
When elaborating partial syntax, the elaborator sometimes attempts to
add a docstring for a declaration that it didn't parse a name for. The
name defaults to anonymous, but inserting the docs for the anonymous
name throws a panic about being on the wrong async branch.
With this change, the reported error is the expected parser error
instead, which is much friendlier.
This PR adds infrastructure for the upcoming `grind` tactic mode, which
will be similar to the `conv` mode. The goal is to extend `grind` from a
terminal tactic into an interactive mode: `grind => …`.
It will serve as the foundation for `ungrind`, the process of converting
an expensive (and potentially fragile) `grind` proof into a robust
script. This mode will include tactics for expensive reasoning steps
such as cutsat model-based search, Gröbner basis computation,
E-matching, case splits, and more.
It will also provide robust, succinct references to facts and terms:
labels, structural matches, and anchors (e.g., `#abcd`).
This PR adds the necessary infrastructure for recording elaboration
dependencies that may not be apparent from the resulting environment
such as notations and other metaprograms. An adapted version of `shake`
from Mathlib is added to `script/` but may be moved to another location
or repo in the future.
This PR implements support for negative constraints in `grind order`.
Examples:
```lean
open Lean Grind
example [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsLinearPreorder α]
(a b c d : α) : a ≤ b → ¬ (c ≤ b) → ¬ (d ≤ c) → d < a → False := by
grind -linarith (splits := 0)
example [LE α] [Std.IsLinearPreorder α]
(a b c d : α) : a ≤ b → ¬ (c ≤ b) → ¬ (d ≤ c) → ¬ (a ≤ d) → False := by
grind -linarith (splits := 0)
example [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsLinearPreorder α] [CommRing α] [OrderedRing α]
(a b c d : α) : a - b ≤ 5 → ¬ (c ≤ b) → ¬ (d ≤ c + 2) → d ≤ a - 8 → False := by
grind -linarith (splits := 0)
```
This PR implements support for positive constraints in `grind order`.
The new module can already solve problems such as:
```lean
example [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α]
(a b c : α) : a ≤ b → b ≤ c → c < a → False := by
grind
example [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α]
(a b c d : α) : a ≤ b → b ≤ c → c < d → d ≤ a → False := by
grind
example [LE α] [Std.IsPreorder α]
(a b c : α) : a ≤ b → b ≤ c → a ≤ c := by
grind
example [LE α] [Std.IsPreorder α]
(a b c d : α) : a ≤ b → b ≤ c → c ≤ d → a ≤ d := by
grind
```
It also generalizes support for offset constraints in `grind` to rings.
The new module implements theory propagation and reduces the number of
case splits required to solve problems:
```lean
example [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] [Ring α] [OrderedRing α]
(a b : α) : a ≤ 5 → b ≤ 8 → a > 6 ∨ b > 10 → False := by
grind -linarith (splits := 0)
example [LE α] [LT α] [Std.LawfulOrderLT α] [Std.IsPreorder α] [CommRing α] [OrderedRing α]
(a b c : α) : a + b*c + 2*c ≤ 5 → a + c > 5 - c - c*b → False := by
grind -linarith (splits := 0)
example (a b : Int) (h : a + b > 5) : (if a + b ≤ 0 then b else a) = a := by
grind -linarith -cutsat (splits := 0)
```
We still need to implement support for negated constraints.
This PR implements the function for adding new edges to the graph used
by `grind order`. The graph maintains the transitive closure of all
asserted constraints.
This PR ensures that `SPred` proof mode tactics such as `mspec`,
`mintro`, etc. immediately replace the main goal when entering the proof
mode. This prevents `No goals to be solved` errors.