Allow `simproc`s to be declared without setting the `[simproc]`
attribute. A `simproc` declaration is function + pattern.
Motivation: allow them to be provided as arguments to `simp` **and** `simp only`.
TODO: track their use in `simp`.
TODO: builtin simprocs
Motivations:
- We can simplify the big mutual recursion and the implementation.
- We can implement the support for `match`-expressions in the `pre` method.
- It is easier to define and simplify `Simprocs`.
The example was looping with the new `simp` reduction strategy. Here
is the looping trace.
```
List.reverseAux (List.reverseAux as []) bs
==> rewrite using reverseAux_reverseAux
List.reverseAux [] (List.reverseAux (List.reverseAux as []) bs)
==> unfold reverseAux
List.reverseAux (List.reverseAux as []) bs
==> rewrite using reverseAux_reverseAux
List.reverseAux [] (List.reverseAux (List.reverseAux as []) bs)
==> ...
```
See new test for example that takes exponential time without new simp
theorems.
TODO: replace auxiliary theorems with simprocs as soon as we implement them.
This removes checks in `Lean.Meta.reduceNat?` that caused it to fail on
terms it could handle because they contain meta variables in arguments.
This lead to those operations being reduced using their equational
definitions and slow performance on large patterns:
```
set_option profiler true
set_option profiler.threshold 1
def testMod (x:Nat) :=
match x with
| 128 % 1024 => true
| _ => false
-- elaboration took 3.02ms
def testMul (x:Nat) :=
match x with
| 128 * 1 => true
| _ => false
-- type checking took 11.1ms
-- compilation of testMul.match_1 took 313ms
-- compilation of testMul took 65.7ms
-- elaboration took 58.9ms
```
Performance is slower on `testMul` than `testMod` because `whnf` ends up
evaluateing `128 * 1` using Peano arithmetic while `128 % 1024` is able
to avoid that treatment since `128 < 1024`.
This makes hover info, go to definition, etc work for the `h` in `cases
h : e`. The implementation is similar to that used for the `generalize h
: e = x` tactic.
#2966 was the `@[extern]` bug that prompted development of the
`test_extern` command, but then we merged the fix to #2966 without
updating the tests to use `test_extern`.
# Summary
This makes a small addition to our take on the LSP protocol
in the form of supporting snippet text edits.
It has been discussed
[here](https://github.com/microsoft/language-server-protocol/issues/592)
on the LSP issue tracker for a while,
but seems unlikely to be added anytime soon.
This feature was requested by @PatrickMassot for the purposes
of supporting Lean code templates in code actions and widgets.
---------
Co-authored-by: David Thrane Christiansen <david@davidchristiansen.dk>
This PR fixes the documentation error in "Extended Setup Notes", where
the path of builded binary is pointed to
`./build/bin/foo`, but the truly path is `./lake/build/bin/foo`.
---
Closes#3094 (`RFC` or `bug` issue number fixed by this PR, if any)
There were no `quot_precheck` instances registered for the expression
tree elaborators, which prevented them from being usable in a `notation`
expansion without turning off the quotation prechecker.
Users can evaluate whether `set_option quotPrecheck false` is still
necessary for their `notation` definitions.
given that we now use the PR description as the commit message, the PR
template should point that out. Also, a `# Summary` is relatively
strange in a commit message, so removed it.
---------
Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
Switches from encoding `let_fun` using an annotated `(fun x : t => b) v`
expression to a function application `letFun v (fun x : t => b)`.
---------
Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
Getting the original PR number from a `workflow_run` cleanly and
reliably seems to be
basically impossible. See
<https://github.com/orgs/community/discussions/25220> for a discussion.
So for now let’s go back to the working state, even though it’s
deprecated and throws warnings.
This prompts users opening the workspace (on a new device) for the first
time to install the lean extension
# Summary
Link to `RFC` or `bug` issue: N/A
#3066 is causing CI failures, e.g.
[here](https://github.com/leanprover/lean4/actions/runs/7202184616/job/19619827364).
Although there are plenty of examples of using `await` in a Github
workflow script block, the error *seems* to be about this. This refactor
hopefully works around that, but I'm still uncertain of a root cause.
This fixe a surprisingly embarrassing bug introduced by me in
fa26d222cb (maybe while testing).
Enable more debug output while we are at it, to find out why sometimes
`context.payload.workflow_run.pull_requests[0]` is undefined.
If a user deleted `lakefile.olean` manually without deleting
`lakefile.olean.lock`, Lake would still attempt to load it and thus
produce an error. Now it should properly re-elaborate the configuration
file.
This adds a `test_extern` command.
Usage:
```
import Lean.Util.TestExtern
test_extern Nat.add 17 37
```
This:
* Checks that the head symbol has an `@[extern]` attribute.
* Writes down `t == t'`, where `t` is the term provided, and `t'` is the
reference implementation (specifically, `t` with the head symbol
unfolded).
* Tries to reduce this to `true`, and complains if this fails.
Note that the type of the term must have a `BEq` instance for this to
work: there's a self-explanatory error message if it isn't available.
the workflow is triggered not only by pull-request-CI-runs but also by
others. These should be skipped.
Also, no need to query the Github API to get the pull request number and
head sha, they are part of the payload, it seems.
Since the vscode-lean4 setup guide allows us to provide information on
setting up Lean 4 tailored to the user's operating system, this PR
adjusts the quickstart guide to reference the vscode-lean4 setup guide
instead.
This definition was clearly meant to be in the `List` namespace, but it
is also in a `namespace Lean` so it ended up as `Lean.List.toSMap`
instead of `List.toSMap`. It would be nice if #3031 made this
unnecessary, but for now this seems to be the convention.
I noticed this because of another side effect: it defines `Lean.List` as
a namespace, which means that
```lean
import Std
namespace Lean
open List
#check [1] <+ [2]
```
does not work as expected, it opens the `Lean.List` namespace instead of
the `List` namespace. Should there be a regression test to ensure that
the `Lean.List` namespace (and maybe others) are not accidentally
created? (Unfortunately this puts a bit of a damper on #3031.)
In particular:
* Do not use deprecated `potiuk/get-workflow-origin`.
* Use a bare checkout to push PR to `pr-releases`
* Replace `script/most-recent-nightly-tag.sh` by a one-liner inside the
workflow, so that th workflow is self-contained
Fixes an issue reported on Zulip; see the test case.
* Modifies the `MonadBacktrack` instance for `SimpM` to also backtrack
the `UsedSimps` field.
* When calling the discharger, `saveState`, and then `restoreState` if
something goes wrong.
I'm not certain that it makes sense to restore the `MetaM` state if
discharging fails. I can easily change this to more conservatively just
backtrack the `UsedSimps` after failed discharging.
Changes the implementation of `List.all` and `List.any` so they
short-circuit. The implementations are tail-recursive.
This replaces https://github.com/leanprover/std4/pull/392, which was
going to do this with `@[csimp]`.
until around 7fe6881 the way to define well-founded recursions was to
specify a `WellFoundedRelation` on the argument explicitly. This was
rather low-level, for example one had to predict the packing of multiple
arguments into `PProd`s, the packing of mutual functions into `PSum`s,
and the cliques that were calculated.
Then the current `termination_by` syntax was introduced, where you
specify the termination argument at a higher level (one clause per
functions, unpacked arguments), and the `WellFoundedRelation` is found
using type class resolution.
The old syntax was kept around as `termination_by'`. This is not used
anywhere in the lean, std, mathlib or the theorem-proving-in-lean
repositories,
and three occurrences I found in the wild can do without
In particular, it should be possible to express anything that the old
syntax
supported also with the new one, possibly requiring a helper type with a
suitable instance, or the following generic wrapper that now lives in
std
```
def wrap {α : Sort u} {r : α → α → Prop} (h : WellFounded r) (x : α) : {x : α // Acc r x}
```
Since the old syntax is unused, has an unhelpful name and relies on
internals, this removes the support. Now is a good time before the
refactoring that's planned in #2921.
The test suite was updated without particular surprises.
The parametric `terminationHint` parser is gone, which means we can
match on syntax more easily now, in `expandDecreasingBy?`.
This Github action automatically updates `stage0` on `master` if
`src/stdlib_flags.h` and `stage0/src/stdlib_flags.h`
are out of sync there.
It bypasses the merge queue to be quick, this way, an out-of-date stage0
on on
master should only exist for a few minutes.
Needs access to a _deploy SSH key_ with write permission.
The elaborator is prone to duplicate terms, including recursive calls,
even if the user only wrote a single one. This duplication is wasteful
if we run the tactics on duplicated calls, and confusing in the output
of GuessLex. So prune the list of recursive calls, and remove those
where another call exists that has the same goal and context that is no
more specific.
Implements "gaps" in string literals. These are escape sequences of the
form `"\" newline whitespace+` that have the interpretation of an empty
string. For example,
```
"this is \
a string"
```
is equivalent to `"this is a string"`. These are modeled after string
continuations in
[Rust](https://doc.rust-lang.org/beta/reference/tokens.html#string-literals).
Implements RFC #2838
before code like
def dup (a : Nat) (b : Nat := a) := a + b
def rec : Nat → Nat
| 0 => 1
| n+1 => dup (dup (dup (rec n)))
decreasing_by decreasing_tactic
would run the `decreasing_tactic` 8 tims, because the recursive call
`rec n` gets duplicate due to the default paramter. Similar effects can
be observed due to dependent types or tactics like `cases`.
This is wasteful, and is confusing to the user when they use
`decreasing_by` interactively. Therfore, we now go through the proof
obligations (MVars) and if solving one would imply solving another one,
we assign the mvars to each other accordingly.
This PR is a sibling of #3004.
I found the documentation page hard to parse, so I figured I should fix
this. It's mostly indentation (e.g. in lists), some line breaks and
making URLs clickable.
With
set_option showInferredTerminationBy true
this prints a message like
Inferred termination argument:
termination_by
ackermann n m => (sizeOf n, sizeOf m)
it tries hard to use names that
* match the names that the user used, if present
* have no daggers (so that it can be copied)
* do not shadow each other
* do not shadow anything from the environment (just to be nice)
it does so by appending sufficient `'` to the name.
Some of the emitted `sizeOf` calls are unnecessary, but they are needed
sometimes with dependent parameters. A follow-up PR will not emit them
for non-dependent arguments, so that in most cases the output is pretty.
Somewhen down the road we also want a code action, maybe triggered by
`termination_by?`. This should come after #2921, as that simplifies that
feature (no need to merge termination arguments from different cliques
for example.)
by showing the matrix of calls and measures, and what we know about that
call (=, <, ≤, ?), e.g.
guessLexFailures.lean:27:0-33:31: error: Could not find a decreasing
measure.
The arguments relate at each recursive call as follows:
(<, ≤, =: relation proved, ? all proofs failed, _: no proof attempted)
x1 x2 x3
1) 29:6-25 = = =
2) 30:6-23 = ? <
3) 31:6-23 < _ _
Please use `termination_by` to specify a decreasing measure
It’s a bit more verbose for mutual functions.
It will use the user-specified argument names for functions written
```
foo (n : Nat) := …
```
but not with pattern matching like
```
foo : Nat → …
| n => …
```
This can be refined later and separately (and maybe right away in
`expandMatchAltsWhereDecls`).
This is pure refactoring: Instead of solving each subgoal as we
encounter it while traversing the syntax tree, we leave the `MVar`
there, at the end collect them all using `getMVarsNoDelayed`, and then
solve them.
This is a refactoring preparing for two upcoming changes:
* removing unexpected duplicate goals that can arise from term
duplication
* running interactive tactics on all, not each goal (#2921)
In order to not regress with error locations, we have to associated the
`TermElabM`’s syntax refernce with the `MVar` somehow. I do this using
the existing `mkRecAppWithSyntax` expression annotation, on the `MVar`’s
type. Alternatives would be stack another `StateT` on the traversal
and accumulate `Array (MVarId, Syntax)` explicitly, but that did not
seem to be more appealing.
This sets the build directory to `build/release` for the "CMake Tools
for Visual Studio Code" extension documented at
https://vector-of-bool.github.io/docs/vscode-cmake-tools/settings.html#cmake-builddirectory.
It also sets the generator to `make`, since otherwise it tries `Ninja`
which doesn't work.
Without these settings, the extension runs configure in a bad place at
startup.
This does *not* add the cmake tools extension to the default workspace
configuration; the goal is simply to prevent bad behavior for users who
already have the extension enabled.
# Summary
Screenshot of this in action:

Link to `RFC` or `bug` issue: N/A, this is not a bug nor a user-visible
feature.
Now that we're, at least temporarily, relying more on the Nix CI,
replace some old hacks of mine with better solutions people have figured
out in the meantime.
Cachix support could probably be dropped at this point but it doesn't
really hurt.
In order to familiarize myself with this code, and so that the next
person has an easier time, I
* added docstrings explaining what I found out these things to
* rewrote the syntax expansion functions using syntax pattern matches,
to the extend possible
else I see
```
[ 69%] Building CXX object runtime/CMakeFiles/leanrt.dir/platform.cpp.o
/home/jojo/build/lean/lean4/src/runtime/io.cpp:509:75: warning: 'static_assert' with no message is a C++17 extension [-Wc++17-extensions]
static_assert(sizeof(std::chrono::milliseconds::rep) <= sizeof(uint64));
^
, ""
/home/jojo/build/lean/lean4/src/runtime/io.cpp:517:74: warning: 'static_assert' with no message is a C++17 extension [-Wc++17-extensions]
static_assert(sizeof(std::chrono::nanoseconds::rep) <= sizeof(uint64));
^
, ""
2 warnings generated.
```
when building
CI will now run on _any_ manually added label; hard to avoid.
Fun fact: Because the `toolchain-available` label is added by a github
action with the default token, it will _not_ trigger the workflow. Lucky
coincidence.
Following up on #2986, stop running the test suite in ci.yml in quick
mode; the test suite is run in the Nix job, and we do not need to run it
twice.
With a cold nix cache, when `lean` is rebuilt, not much changes, as both
jobs take ~20mins. But when `lean` is unchanged, the nix build should
be faster, and shaving off the (currently) 4mins in the CI.yaml run
should get us to a green PR sooner.
Another benefit is that we get the PR release sooner and even get it
when the test suite fails, which can be useful if you want to test
mathlib or other things before fixing the lean test suite.
which also removes an error condition at the use site.
While I am at it, I rename a parameter in `GuessLex` that I forgot to
rename earlier.
The effect will be user-visible (in obscure corner cases) with #2960, so
I’ll have the test there.
A few places would benefit from a `lambdaTelescopeBounded` that
garantees the result has the right length (eta-expanding when
necessary). I’ll look into that separately, and left TODOs here.
The goal of this change is to run a trimmed-down CI on PRs by default,
but allows opt-in the full CI as necessary.
### Specification
The CI workflow runs in “quick” mode if it was triggered from a pull
request, and that pull request does not have the `full-ci` label set.
In “quick” mode the build matrix contains fewer jobs. At the moment
only:
* Linux-release, to get the PR releases.
In non-quick mode everything should be as before.
### Implementation notes
I created a `configure` job that combines all the previous `set-` jobs,
I guess this is faster than firing up separate jobs.
The matrix is calculated in this job; this seems to be the cleanest way
to get a dynamic matrix going (experiments using `exclude` failed). The
downside is that the matrix is now in JSON rather than Yaml syntax. The
upside is that we can (later) make it’s calculation simpler, e.g. set
default `shell` values etc.
I was not able to make it so that CI runs when the `full-ci` label is
added, but don’t do anything otherwise. I think it can be done with
another workflow listening to `labeled` and then triggering this one,
but let’s do that separately. For now, add the label and then push (or
close and reopen).
The checks
```
if: matrix.build-stage2 || matrix.check-stage3
if: matrix.check-stage3
```
were dead code, we did not have these fields in the matrix anymore, so I
replaced them with
```
if: matrix.test-speedcenter
```
Now that there is a helpful message at the point of use when
`supportInterpreter` is required, we don't need to clutter every
`lakefile` with the advice.
there is a little dance with `if: success()` because otherwise a failed
`build` job would make this new job skipped, not failed, and I fear
skipped means ok when it is a required job.
So let’s make sure this job actually fails.
Also turn this into a proper check, run when a PR is opened or edited.
I took the liberty to rename the workflow file and name, so that one
doesn't have to look inside to guess what the workflow is doing.
If here is only one plausible measure, there is no point having the
`GuessLex` code see if it
is terminating, running all the tactics, only for the `MkFix` code then
run the tactics again.
So if there is only one plausible measure (non-mutual recursion with
only one varying
parameter), just use that measure.
Side benefit: If the function isn’t terminating, more detailed error
messages are shown
(failing proof goals), located at the recursive calls.
Removes the `CI` option from the `math` template. Since the template
does not currently generate a GitHub workflow, it does not do anything
out of the box except add unnecessary complexity.
The `math` template is also now tested in `tests/init` (minus the
Mathlib `require`).
This improves Lean’s capabilities to guess the termination measure for
well-founded
recursion, by also trying lexicographic orders. For example:
def ackermann (n m : Nat) := match n, m with
| 0, m => m + 1
| .succ n, 0 => ackermann n 1
| .succ n, .succ m => ackermann n (ackermann (n + 1) m)
now just works.
The module docstring of `Lean.Elab.PreDefinition.WF.GuessLex` tells the
technical story.
Fixes#2837
Closes#2548.
Later packages and libraries in the dependency tree are now preferred
over earlier ones. That is, the later ones "shadow" the earlier ones.
Such an ordering is more consistent with how declarations generally work
in programming languages.
This will break any package that relied on the previous ordering.
Also includes a related fix to `findModule?` that mistakenly treated
executable roots as importable.
Improves executable handling in `lake exe` and `lake init`:
* `lake exe <target>` now parses `target` like a build target (as the
help text states it should) rather than as a basic name.
* `lake new foo.bar [std]` now generates executables named `foo-bar`.
* `lake new foo.bar exe` now properly creates `foo/bar.lean`.
these are compagnions to `MatcherApp.addArg` and `CasesOnApp.addArg`
when one only has an
expression (which may not be a type) to transform, but not a concret
values.
This is a prerequisite for guessing lexicographic order (#2874). Keeping
this on a separate PR because it’s sizable, and has a clear independent
specification.
This is an additional safety net on top of #2749: it protects users that
circumvent the build system (e.g. with `lake env`) as well as obviates
the need for TOCTOU-like race condition checks in the build system.
The check is activated by `CHECK_OLEAN_VERSION=ON`, which now defaults
to `OFF` as the sensible default for local development. When activated,
`USE_GITHASH=ON` is also force-enabled for stage 0 in order to make sure
that stage 1 can load its own core library.
This PR adds per-package server options to resolve#2455. It is based on
the previous work in #2456, but takes a different approach: options are
loaded for the specific file in the file worker when `print-paths` is
called, instead of loading them in the watchdog with a separate Lake
command. This change addresses review comments made in #2456.
In doing so, it introduces two new Lake config fields:
- `leanOptions`: `-D` flag options that are passed to both the language
server and `lean` when building.
- `moreServerOptions`: `-D` flag options that are passed to the language
server.
Since `print-paths` must also accept a file path to compute the options
for that file, this PR is changing the API for `print-paths`. As there
have been numerous complaints about the name `print-paths`, I also
decided to change it to `setup-file` in this PR, since it would break
compatibility with the old Lake API anyways.
This PR deprecates the Lakefile field `moreServerArgs` in favor of
`moreGlobalServerArgs`, as suggested in the review for #2456.
Fixes#2455
---------
Co-authored-by: digama0 <mcarneir@andrew.cmu.edu>
This was a Lean 3 pretty printer option. While this pretty printer
option tends to lead to confusing situations when set, it has been
frequently requested. [It is
possible](https://github.com/leanprover-community/mathlib4/pull/7910) to
implement this pretty printer option as a user, but it comes with some
artifacts -- for instance, expressions in hovers are not beta reduced.
Adding this as a core pp option is cleanest.
(We should consider having hooks into the tactic evaluator to allow
users to transform the tactic state between tactics. This would enable
beta reducing the entire local context for real, which would be useful
for teaching.)
Closes#715
We noticed at
https://github.com/leanprover/lean4/pull/2923#discussion_r1400468371
that this instance is not used. It's arguably also incorrect (as it
doesn't backtrack the `usedTheorems` field).
Seems better to just remove to avoid confusion.
Evidence that this is dead code:
* After deleting the instance, calling `saveState` in the `SimpM` monad
raises an error `failed to synthesize instance MonadBacktrack PUnit
SimpM`.
* Understanding the `MonadBacktrack` monad leads one to believe that
would have happened, via the fact that the only instances for
`MonadBacktrack` are either concrete instances (e.g. for `MetaM`,
`TacticM`, etc), or a single lifting instance `instance [MonadBacktrack
s m] [Monad m] : MonadBacktrack s (ExceptT ε m)`. (This is good and
correct behaviour: lifting instances for `MonadBacktrack` would be hard
to model.)
* Mathlib builds after the instance is removed.
Potential evidence that I have not sought, because we don't have
sufficient tooling:
* Compiling Lean/Std/Mathlib with a debugger, breaking on entering this
code.
This PR adds basic auto-completion support for imports. Since it still
lacks Lake support for accurate completion suggestions (cc @tydeu - we
already know what needs to be done), it falls back to traversing the
`LEAN_SRC_PATH` for available imports.
Three kinds of import completion requests are supported:
- Completion of the full `import` command. Triggered when requesting
completions in an empty space within the header.
- Known issue: It is possible to trigger this completion within a
comment in the header. Fixing this would require architecture for
parsing some kind of sub-syntax between individual commands.
- Completion of the full module name after an incomplete `import`
command.
- Completion of a partial module name with a trailing dot.
Since the set of imports is potentially expensive to compute, they are
cached for 10 seconds after the last import auto-completion request.
Closes#2655.
### Changes
This PR also makes the following changes:
- To support completions on the trailing dot, the `import` syntax was
adjusted to provide partial syntax when a trailing dot is used.
- `FileWorker.lean` was refactored lightly with some larger definitions
being broken apart.
- The `WorkerState` gained two new fields:
- `currHeaderStx` tracks the current header syntax, as opposed to
tracking only the initial header syntax in `initHeaderStx`. When the
header syntax changes, a task is launched that restarts the file worker
after a certain delay to avoid constant restarts while editing the
header. During this time period, we may still want to serve import
auto-completion requests, so we need to know the up-to-date header
syntax.
- `importCachingTask?` contains a task that computes the set of
available imports.
- `determineLakePath` has moved to a new file `Lean/Util/LakePath.lean`
as it is now needed both in `ImportCompletion.lean` and
`FileWorker.lean`.
- `forEachModuleIn` from `Lake/Config/Blob.lean` has moved to
`Lean/Util/Path.lean` as it is a generally useful utility function that
was useful for traversing the `LEAN_SRC_PATH` as well.
### Tests
Unfortunately, this PR lacks tests since the set of imports available in
`tests/lean/interactive` will not be stable. In the future, I will add
support for testing LSP requests in full project setups, which is when
tests for import auto-completion will be added as well.
there were wrong italics, missing backticks, missing indentation and I
took the liberty to replace `[here]` links with link targets that better
tell the reader what to expect when clicking there.
The `packMutual` code ought to reliably replace all recursive calls to
the functions in `preDefs`, even when they are under- or over-applied.
Therefore eta-expand if need rsp. keep extra arguments around.
Needs a tweak to `Meta.transform` to avoid mistaking the `f` in
`f x1 x2` as a zero-arity application.
Includes a test case.
This fixes#2628 and #2883.
This didn't work before
```
def f (n : Nat) : Nat :=
match n with
| 0 => 0
| n + 1 => (f) n
```
because the `RecApp` metadata marker gets in the way. More practically
relevant, such code is to be produced when using `rw` or `simp` in
recursive theorems (see included test case).
We can fix this by preprocessing the definitions and floating the
`.mdata` marker out of applications.
For structural recursion, there already exists a `preprocess` function;
this now also floats out `.mdata` markers.
For well-founded recursion, this introduces an analogous `preprocess`
function.
Fixes#2810.
One test case output changes: With the `.mdata` out of the way, we get a
different error message. Seems fine.
Alternative approaches are:
* Leaving the `.mdata` marker where it is, and looking around it.
Tried in #2813, but not nice (many many places where `withApp` etc.
need to be adjusted).
* Moving the `.mdata` _inside_ the application, so that `withApp` still
works. Tried in #2814. Also not nice, the invariant that the `.mdata`
is around the `.const` is tedious to maintain.
the code stumbled over recursive functions whose type doesn’t have
enough manifest foralls, like:
```
def FunType := Nat → Nat
mutual
def foo : FunType
| .zero => 0
| .succ n => bar n
def bar : FunType
| .zero => 0
| .succ n => foo n
end
termination_by foo n => n; bar n => n
```
This can be fixed by using `whnf` in appropriate places, to expose the
`.forall` constructor.
Fixes#2925, comes with test case.
`script/most-recent-nightly-tag.sh` determines the most recent nightly
release in your current git history.
Previously it was assuming that you had a `nightly` remote, to pull tags
from. Now it just pulls directly from the repository by URL.
This only really shows up when the `decreasing_tactic` fails with
multiple goals, as in
```
macro_rules
| `(tactic|decreasing_tactic) => `(tactic| by_cases (2 > 1))
def foo (n : Nat) : Nat := foo (n - 1)
termination_by foo n => n
```
where we now get
```
unsolved goals
case inl
n: Nat
h✝: 2 > 1
⊢ (invImage (fun a => a) instWellFoundedRelation).1 (n - 1) n
case inr
n: Nat
h✝: ¬2 > 1
⊢ (invImage (fun a => a) instWellFoundedRelation).1 (n - 1) n
```
rather than
```
LeanProject.lean:3:27
unsolved goals
case inl
n: Nat
h✝: 2 > 1
⊢ (invImage (fun a => a) instWellFoundedRelation).1 (n - 1) n
LeanProject.lean:3:27
unsolved goals
case inr
n: Nat
h✝: ¬2 > 1
⊢ (invImage (fun a => a) instWellFoundedRelation).1 (n - 1) n
```
The effect is neglectible, but the code is a bit nicer, so why not,
before someone looks at it again and wonders whether the goals are
reported separately for a reason.
Some beginners have trouble finding the `if h : c then t else e`
(`dite`) version of `ite`. This augments `ite`'s docstring to mention
the dependent version.
This implements a request handler for the `textDocument/rename` LSP
request, enabling renames via F2. It handles both local renames (e.g.
`let x := 1; x` to `let y := 1; y`) as well as global renames
(definitions).
Unfortunately it does not work for "orphan" files outside a project, as
it uses ilean data for the current file and this does not seem to be
saved for orphan files. As a result, the test file does not work,
although one can manually test the implementation against a project such
as mathlib. (This issue already exists for the "references" request,
e.g. ctrl click on the first `x` in `let x := 1; x` takes you to the
second one only if you are not in an orphan file.)
* Fixesleanprover-community/mathlib4#7124
Modifies `cleanup` so that it takes (1) an array of additional fvarids
to preserve and (2) a flag to control whether to include indirect
propositions.
(This is wanted in mathlib for the `extract_goal` tactic.)
previously, it would ignore a recursive call that has extra arguments,
which can happen when the recursive functions return something of
function type. Therefore just leave them extra arguments in place.
Fixes#2883.
In the previous doc-string, the sentence
> "If any of the selected tactic applications fail, it will call
`failed` with the main goal mvar."
was false both for `Location.wildcard` (where it should have said "If
all", not "If any") or for `Location.targets` (where `failed` is never
called).
Add documentation comments with examples to `universe`, `open`,
`export`, and `variable`.
The documentation shows up when hovering over keywords, hopefully
improving the experience for beginners.
Because `Decidable` carries data,
when writing `@[simp]` lemmas which include a `Decidable` instance on the LHS,
it is best to use `{_ : Decidable p}` rather than `[Decidable p]`
so that non-canonical instances can be found via unification rather than
typeclass search.
(Previously this behaviour was often being hidden by the default `decide :=
true` in `simp`.)
We were checking out the synthetic merge commit between the PR `HEAD`
and `master`, and this was then breaking the logic to determine which
nightly-testing branches to use in Mathlib and Std.
previously, only the WellFounded code was making use of the error
location in the RecApp-metadata. We can do the same for structural
recursion. This way,
```
def f (n : Nat) : Nat :=
match n with
| 0 => 0
| n + 1 => f (n + 1)
```
will show the error with squiggly lines under `f (n + 1)`, and not at
`def f`.
`simp` was previously swallowing runtime exceptions and masking an
issue with this example.
`runT` is defined by well-founded recursion, but reducing the ground
term `runT x` takes a long time when `decide := true`.
Remark PR #2722 changes the `decide` default value to `false`.
When `decide := true`, we should probably have better diagnostics /
error messages for this kind of situation.
This is the same flag that the C test uses. Previously this was hidden
in the Lean compiler itself but now that the optimization pass is phased
out of the compiler we need to put it here.
Co-authored-by: Henrik Böving <hargonix@gmail.com>
In LLVM builds the Cmake CC is necessarily clang -> leanc will be able
to act on LLVM bitcode files if configured this way.
Co-authored-by: Siddharth <siddu.druid@gmail.com>
The notation `a ∈ as` for Arrays was previously only defined with
`DecidableEq` on the elements, for (apparently) no good reason. This
drops this requirements (by using `a ∈ as.data`), and simplifies a bunch
of proofs by simply lifting the corresponding proof from lists.
Also, `sizeOf_lt_of_mem` was defined, but not set up to be picked up by
`decreasing_trivial` in the same way that the corresponding List lemma
was set up, so this adds the tactic setup.
The definition for `a ∈ as` is intentionally not defeq to `a ∈ as.data`
so that the termination tactics for Arrays don’t spuriously apply when
recursing through lists.
This commit also removes parameter `simpleReduce` from discrimination
trees, and take WHNF configuration options.
Reason: it is more dynamic now. For example, the simplifier
will be able to use different configurations for discrimination tree insertion
and retrieval. We need this feature to address issues #2669 and #2281
This commit also removes the dead Meta.Config field `zetaNonDep`.
* feat: replay constants into an Environment
* suggestions from code review
* chore: make Environment.add private
* patch Lake to use Environment.add via extern
I initially expected `Name`s to always faithfully represent internal data, in particular that a name with macro scopes would have a form such as ```foo._@.Module._hyg.1``, and that tombstones would only appear in types that represent pretty-printed output such as as `String` or `Format`. However, that is not what happens. We have `sanitizeNames` which rewrites the `userName` field of local hypotheses to be `Name.str .anonymous "blah✝"`.
Then in the server code, we put these into `names : Array Name`e. This works fine for displaying in the infoview, but if we try to deserialize an `InteractiveHypothesisBundle` inside an RPC method for widget purposes, the `FromJson Name` instance blows up in `String.toName`.
I think my preferred solution is to, rather than 'fix' `String.toName` to accept these names with tombstones, stop pretending that they are actual `Name`s and re-type `InteractiveHypothesisBundle.names : Array String`. This should be a backwards-compatible change w.r.t. infoview code as the JSON representation is a string in either case. It is not backwards compatible w.r.t. meta code that uses this field.
Before, Lean would simply emit the message "tag not found". With this
change, it also tells the user what they could have written that would
be accepted.
* fix: make XML parser handle trailing whitespace in opening tags
* fix: make XML parser handle comments correctly
---------
Co-authored-by: György Kurucz <me@kuruczgy.com>
* fix: `withCollectingNewGoalsFrom`
do not collect old goals
* fix: update occurs check
* test: fix test `run/492.lean`
* docs: add docstring to `elabTermWithHoles`
* test: `refineFiltersOldMVars`
* test: fix `expected.out` name
* test: fix `expected.out` filename and line numbers
* docs: use long ascii dash instead of em dash
Co-authored-by: Scott Morrison <scott@tqft.net>
* docs: fix long line, mention lean4#2502
* docs: a couple more long lines
* test: fix line numbers
---------
Co-authored-by: Scott Morrison <scott@tqft.net>
* chore: add release notes for #2470 and #2480
* chore: begin development cycle for 4.2.0
* chore: add Lake-related release notes for v4.1.0
---------
Co-authored-by: Mac Malone <tydeu@hatpress.net>
* `weakLeanc/LinkArgs` for libs/mods/exes
* `weakArgs`/``extraDepTrace` for `buildO`
* include Lean trace when compiler is part of Lean toolchain
* do not include system-dependent file paths (e.g., `-I`) in dep trace
* step logging for cloud release fetching
* do not include cloud release bundle in trace
* `Package.afterReleaseSync/Async` utilities
* also cleanup `Package.recComputeDeps`
It seems that before, if `$src` isn’t a file, but a directory, that it
would contain `Bar.lean` directly, and not `Foo/Bar.lean`. This seemd
odd and would not allow dependencies to be included easily.
This obviates the need to play weak linkage games when
we build `lean.h.bc` from `lean.h`. We perform the following steps:
1. We remove the `static` modifier from all definitions in `lean.h`.
This makes all definitions have `extern` linkage. Thus, when we build
a `lean.h.bc` using `clang`, we will actually get definitions
(instead of an empty file)
2. We build `lean.h.bc` from `lean.h` using `clang`.
3. When it comes time to link, we link
`current_module.bc := LLVMLinkModules2(current_module.bc, lean.h.bc)`.
4. We loop over every symbol that arrived from `lean.h.bc`
in `current_module.bc` and we then set this symbol to have
`internal` linkage. This simulates the effect of
`#include <lean.h>` where every definition in `lean.h`
has internal linkage.
This yajna, one hopes, pleases the linker gods.
The previous type was
```
Lean.instFromJsonProd.{u, v} {α β : Type (max u v)} [FromJson α] [FromJson β] :
FromJson (α × β)
```
where universe metavariable assignment assigned the wrong universe to both types!
The test is flaky due to the presence of a fixed 'sleep()'.
The LLVM backend has introduced a performance
regression in Lake which causes this test to fail, as the
current sleep duration of 3s is insufficient.
Further investigation into the performance regression is pending.
We decided to disable the `leanlaketest_116` entirely on account
of the test being flaky by construction
(https://github.com/leanprover/lean4/pull/2358#issuecomment-1655371232).
* remove |- as an alias for ⊢
* revert false positive |->
* fix docstring
* undo previous changes
* [unchecked] use suggestion
* next attempt
* add test
* move Measure to Nat namespace
We could (and maybe should) also move various other declarations to namespaces, like measure. However, measure seems to be used a lot in termination_by statements, so that requires other fixes as well. Measure seems to be almost unused
* fix
* delete Measure and SizeOfRef instead
* feat: allow upper case single character identifiers when relaxedAutoImplicit false
* update tests
* fix tests
* fix another test
---------
Co-authored-by: Scott Morrison <scott.morrison@anu.edu.au>
If `deps` or `depRoots` are too large, bash will carsh when executing
the modified script. This is because there are OS-level limits on the
size of environment variables. This commit changes the script so that
`deps` and `depRoots` are written to files instead of being passed as
environment variables.
```
open Lean Meta
-- Docs text:
-- The let-expression `let x : Nat := 2; Nat.succ x` is represented as
def old : Expr :=
Expr.letE `x (.const `Nat []) (.lit (.natVal 2)) (.bvar 0) true
elab "old" : term => return old
#check old -- let x := 2; x : Nat
#reduce old -- 2
def new : Expr :=
Expr.letE `x (.const `Nat []) (.lit (.natVal 2)) (.app (.const `Nat.succ []) (.bvar 0)) true
elab "new" : term => return new
#check new -- let x := 2; Nat.succ x : Nat
#reduce new -- 3
```
* feat: add --target flag for LLVM backend to build objects of a different architecture
* chore: remove dead comment
* Update src/Lean/Compiler/IR/EmitLLVM.lean
Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
* chore: normalize indentation in src/util/shell.cpp
* chore: strip trailing whitespace
Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
* feat: `funext` no arg tactic
Description of funext tactic includes behavior that is not implemented. This implements the behavior.
* fix
* feat: test new funext tactic
* use repeat for clarity of intent
Previously `decreasing_with` failed if `simp_wf` closes the goal on its
own. This can cause undesired regressions when new `simp` lemmas are
introduced.
Closes#2018.
Rename `le_or_eq_or_le_succ` `le_or_eq_of_le_succ`. We need to change
its name in `Std/Data/Array/Init/Lemmas` and `Std/Data/Array/Lemmas`.
Co-authored-by: Bulhwi Cha <chabulhwi@semmalgil.com>
Closes#2004.
In porting the bugfix from
6eb852e28f,
I noticed that the LLVM backend was incorrectly generating declaration
initializers (in `callIODeclInitFn`), by assuming the return type of the
initializer is the return type of the declaration. Rather, it must be be
`lean_object`, since the initializer returns an `IO a` value which must be unpacked.
TODO: stop using the `getOrCreateFunction` pattern pervasively.
perform the `create` at the right location, and the `get`
at the correct location.
The goal is to address the regression
```
example : (0 : Nat) + 0 = 0 :=
show 0 + 0 = 0 from rfl
```
introduced by fedf235cba
Note that we should only *try to* unify the types. Otherwise, we would
produce another regression.
```
example : Int :=
show Nat from 0
```
cc @kha
In Lean 4, we have support for typing constraints of the form
```
(?m ...).1 =?= v
```
where the type of `?m ...` is a structure with a single field.
This kind of constraint is reduced to `?m ... =?= ⟨v⟩`
This feature is implemented by the function `isDefEqSingleton`.
As far as I remember, Lean 3 does not implement this feature.
This commit disables this feature if the structure is a class.
The goal is to avoid the generation of counterintuitive instances by
typing inference.
For example, in the example at issue #2011, the following weird
instance was being generated for `Zero (f x)`
```
(@Zero.mk (f x✝) ((@instZero I (fun i => f i) fun i => inst✝¹ i).1 x✝)
```
where `inst✝¹` is the local instance `[∀ i, Zero (f i)]`
Note that this instance is definitinally equal to the expected nicer
instance `inst✝¹ x✝`.
However, the nasty instance trigger nasty unification higher order
constraints later.
Note that a few tests broke because different error messages were
produced. The new error messages seem better. I do not expect this
change to affect Mathlib4 since Lean 3 does not have this feature.
Replace complex debouncing logic in watchdog with single `IO.sleep` in
worker `didChange` handler, replace redundant header change logic in
watchdog with special exit code from worker.
This adds `lean.h.bc`, a LLVM bitcode file of the Lean
runtime that is to be inlined. This is programatically generated.
1. This differs from the previous `libleanrt.ll`, since it produces an
LLVM bitcode file, versus a textual IR file. The bitcode file
is faster to parse and build an in-memory LLVM module from.
2. We build `lean.h.bc` by adding it as a target to `shell`,
which ensures that it is always built.
3. We eschew the need for:
```cpp
```
which causes breakage in the build, since changing the meaning of
`static` messes with definitions in the C++ headers.
Instead, we build `lean.h.bc` by copying everything in
`src/include/lean/lean.h`, renaming `inline` to
`__attribute__(alwaysinline)` [which forces LLVM to generate
`alwaysinline` annotations], then running the `-O3` pass pipeline
to get reasonably optimised IR, and will be perfectly inlined
when linked into the generated LLVM code by
`src/Lean/Compiler/IR/EmitLLVM.lean`.
Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
It may look like a simple optimization but affects the inlining
heuristics. Example:
```
fun f ... := ...
let x_1 := f
let x_2 := x_1 a
let x_3 := x_1 b
...
```
Before this commit, `f` was not being marked as being used multiple times.
We cannot effectively test without an `update-stage0` since the LCNF
representation is different and incompatible with the one in the
.olean files.
One of the passes is not terminating (probably `simp`) when compiling
stage2.
`MVarId.congr?` and `MVarId.hcongr?` should return `none` if an
exception is thrown while applying congruence theorem.
`MVarId.hcongr?` should try `eq_of_heq` before trying to apply
`hcongr` theorem.
closes#1787
BTW: Lean 4 `congr` tactic is applying `assumption`. Lean 3 version does not.
closes#609
Context: trying to improve Lean startup time.
Remark: it didn't seem to make a difference in practice. We should
investigate more.
cc @kha @gebener
When inductives are indirectly mutually recursive, say `inductive T | t
(args: List T)` instead of `inductive T | t (arg : T)`, Lean would fail
to find an instance of Hashable for `T` because it was not yet defined.
This commit makes sure that the deriving handler adds a needed Hashable T
instance to the local scope so that Hashable.hash can be resolved
recursively.
This is a low-level system for registering LSP code actions.
Developers can register their own code actions.
In future commits I am going to add features on top of this.
TODO: after we delete old code generator, we should replace
`@[alwaysInline, inline]` with `@[alwaysInline]`.
Remainder: we want the old code generator to ignore `@[alwaysInline]`
annotations, in particular, the new ones on `instance` commands that
are actually annotations for the instance methods.
In the new code generator, we are going to lambda lift the instance
methods before saving the code at the end of the base phase. The goal is to make instance
ligth weight and cheap to inline. The anotation `@[inline]` is going
to be an annotation for the lambda lifted methods.
We need a better heuristic for deciding which functions in instances
should be eagerly lambda lifted. Otherwise, it will have to keep
chasing which instances we have to annotate with `[inline]`.
The current link goes to doc/dev#init, where there is nothing
about initialization. This PR fixes the link so that it points
to the initialization section lower down on the ffi page.
Added recursion cases to the diff algorithm for projections and mdata.
Previously, these would be rendered as the entire expression being different but we can do better
by checking if the recursion args are the same.
With mdata, these are entirely ignored by the diff algorithm.
This is not a perfect solution, but ensures the non-termination does
not happen. The changes also make it easier to prove termination in
the future.
TODO: validate UTF8 input?
closes#1690
Potential problem: if elaboration of subterms is delayed the order the new metavariables are created may not match the order they
appear in the `.lean` file. We should tell users to prefer tagged goals.
closes#1682
It reduces the code generated for functions using a bunch
of quotations. For example, the size of
`Lean.Elab.Term.Do.ToTerm.matchNestedTermResult` went from 2348 to 1507
It helps preserving let-declaration names in pure code, but it is not
very useful for monadic let-decls (e.g., `let x <- act`). The binder
names are often lost we eliminating the abstraction layers.
It addresses the code explosion issue with the old optimization.
For example, the resulting size for `Lean.Json.Parser.escapedChar`
went from 31593 to 361.
The `[inlineIfReduce]` at `List.toArrayAux` is currently very
expensive, and this example produces a deep recursion when inlining
the `List.toArrayAux` applications.
The previous implementation was using the following heuristic
```lean
-- heuristic: use non-dependent arrows only if possible for whole group to avoid
-- noisy mix like `(α : Type) → Type → (γ : Type) → ...`.
let dependent := curNames.any fun n => hasIdent n.getId stxBody
```
The result produced by this heuristic was **not** producing an
accidental name capture, but I agree
it was confusing to have `∀ (a : True), ∃ a, a = a : Prop` instead of
`True → ∃ a, a = a : Prop` since there is no dependency.
AFAICT, all examples affected by this commit have a better output now.
cc @digma0 @kha
The previous implementation had a few issues:
- Function (and join point) declarations were being inserted into two different hashmaps.
- `borrow` information was not available for parameters.
- No proper erase functions.
I got a panic error message today in VS Code because of this function.
It is weird because, as far as I can tell, this function is only used by
the `register_simp_attr` macro, and this macro was not being used in
the files I was editing.
I think the fix is resonable for a `Syntax.missing` case.
cc @gebner
* doc: add documentation on functors.
* fix: make comments green
* minor tweaks
* doc: add section on Applicatives.
* doc: add some more info on the laws from Mario.
* doc: add law list and move lazy evaluation up so the chapter ends properly.
* doc: Add something on seqLeft and seqRight.
* doc: add section on monads.
* doc: fix some typos.
* doc: switch to LeanInk for chaper on Monads.
* doc: remove old files.
* doc: fix mdbook test errors.
* doc: add part 4: readers
* doc: add section on State monads
* doc: fix some typos and add some more details.
* doc: fix typos and add some CR feedback.
* doc: add Except monad section.
* doc: add info on monad transformers.
* Delete transformers.lean.md
* doc: fix some typos.
* doc: fix typos and move forward reference to monad lifting.
* doc: Update `State` to `StateM`
* doc: fix references to State to become StateM.
* doc: generalize indexOf implementation.
* doc: add chapter on monad laws and move "law" sections to this chapter to avoid redundancy.
* doc: add theorem
* Delete laws.lean.md
* doc: fix some typos.
* doc: fix broken link.
* doc: fox typos.
* fix: language changed from "us" to "you".
* doc: fix code review comments.
* doc: some word smithing
* doc: some word smithing and sample simplification.
* doc: add bad_option_map example.
* doc: add side note on `return` statement and fix heading level consistency.
* Add `withReader` info
* doc: change language from us, our, your, we, we'll, we've to "you"
* doc: add some forward links.
* doc: put spaces around colon in function arguments like "(x : List Nat)"
* doc:
Add backticks on map
Remove commands on multiline structure instance
Fix centerdot
Add "one of"
* doc: Remove info about Functor in other languages.
* doc:
add info on <$> being left associative
remove another forward reference to monad
fix typo `operatoions`
remove unneccesary parens after <$>
* doc:
fix Type u -> Type v
fix you -> your
use `let val? ← IO.getEnv name`
in Readers call it "context" rather than "state".
* doc: fix withReader docs
use 'context' to describe the ReaderM state.
remove "trivial"
type inference => Lean
"abstract classes" => "abstract structures"
remove unnecessary parens
* doc: fix bug in explanation of `let x ← readerFunc2`
Fix explanation of equivalence between `def f (a : Nat) : String` and `def f : Nat → String`
* doc: move hasSomeItemGreaterThan to Except.lean
Add validateList List.anyM example.
fix `def f (a : Nat) : String` language.
* doc: fix "What transformation are you referring to"
* doc: fix typo.
* doc: add missing period.
* doc: fix validateList
* doc: explain `λ` notation.
* doc: reword the map, seq, bind comparison.
* doc: fix some more 'reader state' to 'reader context' language
* doc: fix wrote statement about return only works in do blocks.
* doc: fix typo
Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
* doc: improve language
Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
* doc: fix typo
Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
* Add info on what a do block is doing for you.
* doc: define definitionally equal
* doc: make `readerFunc3.run env` canonical.
* doc: remove unnecessary parens.
* doc: fix typos
* doc: make List.map a bit more clear in the intro to Functors.
* doc: simplify readerFunc3WithReader
* doc: switch to svg for diagram so it works better on dark themes.
* doc: align nodes in diagram and convert to svg.
* doc: simplify playGame using while true.
* doc: drop confusing statement about "definitionally equal"
* doc: switch to `import Lean.Data.HashMap`
* doc: fix typo "operatoins"
* doc: update diagram to add more info and polish the intro paragraphs so they better match the actual contents of each chapter.
* doc: fix typo
* doc: fix typo.
Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
Lean.Meta.forEachExpr should be general over monads rather than restricted to the MetaM monad.
This is similar to the generalisation of Lean.Meta.transform
`charToHex` is an auxiliary function used at `Char.quoteCore` for
converting ASCII control characters into `\x` notation.
Its name was misleading.
Closes#1404
Motivation: it is not very useful anymore, and more importantly it
breaks all the time because it is affected by how many internal ids
are created by Lean.
* doc: Add explanations to MetavarContext
The explanations were taken from Leo's talk at the ICERM
Mathlib porting hackathon.
* Update src/Lean/MetavarContext.lean
Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
* add my understanding of what LocalInstances represents
* Update src/Lean/MetavarContext.lean
Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
Co-authored-by: Leonardo de Moura <leonardo@microsoft.com>
* doc: Add explanations to MetavarContext
The explanations were taken from Leo's talk at the ICERM
Mathlib porting hackathon.
* doc: Add documentation for Declaration
This is explanations taken from Leo's talk given
at the post ICERM Mathlib porting hackathon.
* Update src/Lean/Declaration.lean
Co-authored-by: Scott Morrison <scott@tqft.net>
* Update src/Lean/Declaration.lean
Co-authored-by: Scott Morrison <scott@tqft.net>
* Update src/Lean/MetavarContext.lean
Co-authored-by: Scott Morrison <scott@tqft.net>
* fix depth comment
Co-authored-by: Scott Morrison <scott@tqft.net>
We don't try to reuse the cache contents between different `isDefEq`
calls. Thus, we can cache more results and ignore whether the state of
the metavariable context affects them or not.
Closes#1102
see #1248
This commit adds a small hack to fix the term info for the following `do`-elements
```lean
let (x, y) := ...
let (x, y) ← ...
let mut (x, y) ← ...
let some x ← ... | ...
```
We want to be able to update `InfoState` at `AttrM` which is just an
alias for `CoreM`.
I considered defining `AttrM` as `StateRefT InfoState CoreM`, but this
is problematic because we also want to invoke `AttrM` monadic
actions from `MetaM`.
Closes#1350
> Heather suggested changing the calc tactic (not the term) such that if
the final RHS does not defeq match the goal RHS, it returns a final
inequality as a subgoal.
Closes#1342
This commit fixes bug reported by Patrick Massot.
It happened when using `macro_rules` and `elab_rules` for the same
`SyntaxNodeKind`.
It also fixes missing error messages when there is more than one
elaboration functions and there is `abortTactic` exception.
Remark: this commit also changes the evaluation order. Macros are
now tried before elaboration rules. The motivation is that macros are
already applied before elaboration functions in the term elaborator.
Add support for operators that may not have homogeneous instances for
all types. For example, we have `HPow Nat Nat Nat` and `HPow Int Nat Int`,
but we don't have `HPow Int Int Int`.
Note that test for issue #1200 broke.
The bug fixed by this commit was allowing the example to be elaborated
correctly :(
Initially, the type of the discriminant is not available, and
`.none (α:=α)` can only be elaborated when the expected type is of the
form `C ...`. Lean then tries to elaborate the alternatives, learn
that the discriminant should be `Option ?m`, and fails because the
patterns still have metavariables after elaboration. Before the bug
fix, `resumePostpone` was **not** restoring the metavariable context,
and the assingnment would stay there. With this information, Lean
can now elaborate `.none (α:=α)`.
Although the bug had a positive impact in this case, it produced
incorrect behavior in other examples.
The fixed example looks reasonable. Thus, we will not reopen
issue #1200
Motivation: make sure the behavior is consistent with other arithmetic
operators.
This commit also removes the instance
```
instance : HMod (Fin n) Nat (Fin n) where
hMod := Fin.modn
```
because we have a coercion from `Fin n` to `Nat`.
Thus, given `a : Fin n` and `b : Nat`, `a % b` is ambiguous.
We need this refinement for declarations such as
```
def add_one {X} [Trait X] [One (Trait.R X)] [HAdd X (Trait.R X) X] (x : X) : X := x + (One.one : (Trait.R X))
```
from test 948.lean
The old error message said:
```
throwError "invalid `▸` notation,
expected type{indentExpr expectedType}\ndoes contain
equation left-hand-side nor right-hand-side{indentExpr heqType}"
```
The phrase `does contain ... nor ..` seems gramatically incorrect.
What was (probably) intended was `does **not** contain ... nor ...`.
We take the opportunity to clean up the error message and
be clearer that the equality does not contain the expected result type.
In order to guarantee termination of type class synthesis when resolving
coercions, a good rule of thumb is that the instances should not
introduce metavariables (during TC synthesis). For common coercion type
classes this means:
- `Coe T S`, `CoeTail T S`: the variables of `T` must be a subset of those of `S`
- `CoeHead T S`: the variables of `S` must be a subset of those of `T`
If these rules are not followed, we can easily get nontermination. In
this case: `CoeTC Foo Syntax` is reduced to `CoeTC Foo (TSyntax ?m_1)`
using the (dangerous) `Coe (TSyntax k) Syntax` instance, to which we can
then apply the otherwise fine `Coe (TSyntax [k]) (TSyntax (k'::ks))`
coercion infinitely often.
When solving `a.i =?= b.i`, we first reduce `a` and `b` without using
delta reduction. If at least one become a structure, we reduce the
projection. Otherwise, we try to solve `a =?= b`, only reduce `a.i`
and `b.i` if it fails.
* [ ] Put an X between the brackets on this line if you have done all of the following:
* Check that your issue is not already [filed](https://github.com/leanprover/lean4/issues).
* Reduce the issue to a minimal, self-contained, reproducible test case. Avoid dependencies to mathlib4 or std4.
### Description
[Clear and concise description of the issue]
### Context
[Broader context that the issue occured in. If there was any prior discussion on [the Lean Zulip](https://leanprover.zulipchat.com), link it here as well.]
### Steps to Reproduce
1.
2.
3.
**Expected behavior:** [Clear and concise description of what you expect to happen]
**Actual behavior:** [Clear and concise description of what actually happens]
### Versions
[Output of `#eval Lean.versionString` or of `lean --version` in the folder that the issue occured in]
[OS version]
### Additional Information
[Additional information, configuration or data that might be necessary to reproduce the issue]
### Impact
Add :+1: to [issues you consider important](https://github.com/leanprover/lean4/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc). If others are impacted by this issue, please ask them to add :+1: to it.
Clear and detailed description of the proposal. Consider the following questions:
- **User Experience**: How does this feature improve the user experience?
- **Beneficiaries**: Which Lean users and projects benefit most from this feature/change?
- **Maintainability**: Will this change streamline code maintenance or simplify its structure?
### Community Feedback
Ideas should be discussed on [the Lean Zulip](https://leanprover.zulipchat.com) prior to submitting a proposal. Summarize all prior discussions and link them here.
### Impact
Add :+1: to [issues you consider important](https://github.com/leanprover/lean4/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc). If others benefit from the changes in this proposal being added, please ask them to add :+1: to it.
* Ensure your PR follows the [External Contribution Guidelines](https://github.com/leanprover/lean4/blob/master/CONTRIBUTING.md).
* Please make sure the PR has excellent documentation and tests. If we label it `missing documentation` or `missing tests` then it needs fixing!
* Include the link to your `RFC` or `bug` issue in the description.
* If the issue does not already have approval from a developer, submit the PR as draft.
* The PR title/description will become the commit message. Keep it up-to-date as the PR evolves.
* If you rebase your PR onto `nightly-with-mathlib` then CI will test Mathlib against your PR.
* You can manage the `awaiting-review`, `awaiting-author`, and `WIP` labels yourself, by writing a comment containing one of these labels on its own line.
* Remove this section, up to and including the `---` before submitting.
---
Closes #0000 (`RFC` or `bug` issue number fixed by this PR, if any)
echo "... and Mathlib has a 'nightly-testing-$MOST_RECENT_NIGHTLY' branch."
MESSAGE=""
else
echo "... but Mathlib does not yet have a 'nightly-testing-$MOST_RECENT_NIGHTLY' branch."
MESSAGE="- ❗ Mathlib CI can not be attempted yet, as the 'nightly-testing-$MOST_RECENT_NIGHTLY' branch does not exist there yet. We will retry when you push more commits. It may be necessary to rebase onto 'nightly' tomorrow."
fi
else
echo "The most recently nightly tag on this branch has SHA: $NIGHTLY_SHA"
// check first commit only (and only once) since later commits might be intended to be squashed away
if (!/^(feat|fix|doc|style|refactor|test|chore|perf): .*[^.]($|\n\n)/.test(commits[0].commit.message)) {
await github.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: 'Thanks for your contribution! Please make sure to follow our [Commit Convention](https://leanprover.github.io/lean4/doc/dev/commit_convention.html).',
Thank you for your interest in contributing to Lean! There are many ways to contribute and we appreciate all of them.
In the past, we accepted most pull requests. This practice produced hard to maintain code, performance problems, and bugs. In order to improve the quality and maintainability of our codebase, we've established the following guidelines for external contributions.
## Bug reports
Helpful links
-------
Bug reports as new issues are always welcome. Please check the existing [issues](https://github.com/leanprover/lean4/issues) first.
Reduce the issue to a self-contained, reproducible test case.
If you have the chance, before reporting a bug, please search existing issues, as it's possible that
someone else has already reported your error.
If you're not sure if something is a bug or not, feel free to file a bug anyway. You may also want to discuss it with the Lean
community using the [lean4 Zulip channel](https://leanprover.zulipchat.com/#narrow/stream/270676-lean4).
Simple fixes for **typos and clear bugs** are welcome.
**Start with an Issue**: Before submitting a PR, always open an issue discussing the problem you wish to solve or the feature you'd like to add. Use the prefix `RFC:` (request for comments) if you are proposing a new feature. Ask for feedback from other users. Take the time to summarize all the feedback. This allows the maintainers to evaluate your proposal more efficiently. When creating a RFC, consider the following questions:
## Documentation
- **User Experience**: How does this feature improve the user experience?
Tutorial-like examples are very welcome.
They are useful for finding rough edges and bugs in Lean 4, for highlighting new features, and for showing how to use Lean.
If you want to store your tutorial in the Lean 4 repository to make sure future changes will not break it, we suggest the following workflow:
* Contact one of the Lean developers on Zulip, and check whether your tutorial is a good match for the Lean 4 repository.
* Send bug reports and report rough edges. We will work with you until the tutorial looks great.
* Add plenty of comments and make sure others will be able to follow it.
* Create a pull request in the Lean 4 repository. After merging, we will link it to the official documentation and make sure it becomes part of our test suite.
- **Beneficiaries**: Which Lean users and projects do benefit most from this feature/change?
You can use `.lean` or `.md` files to create your tutorial. The `.md` files are ideal when you want to format your prose using markdown. For an example, see [this `.md` file](https://github.com/leanprover/lean4/blob/master/doc/lean3changes.md).
- **Community Feedback**: Have you sought feedback or insights from other Lean users?
Contributions to the reference manual are also welcome, but since Lean 4 is changing rapidly, please contact us first using Zulip
to find out which parts are stable enough to document. We will work with you to get this kind of
pull request merged. We are also happy to meet using Zoom, Skype or Google hangout to coordinate this kind of effort.
- **Maintainability**: Will this change streamline code maintenance or simplify its structure?
As Lean 4 matures, other forms of documentation (e.g., doc-strings) will be welcome too.
**Understand the Project**: Familiarize yourself with the project, existing issues, and latest commits. Ensure your contribution aligns with the project's direction and priorities.
## "Help wanted"
**Stay Updated**: Regularly fetch and merge changes from the main branch to ensure your branch is up-to-date and can be smoothly integrated.
For issues marked as [`help wanted`](https://github.com/leanprover/lean4/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22), pull requests (PR) are welcome and we will work with you to get a PR merged. Some of these issues are nontrivial. If you are interested, please consider adding comments to the issue and/or messaging the Lean developers in [Zulip](https://leanprover.zulipchat.com/#).
**Help wanted**: We have issues tagged with ["help wanted"](https://github.com/leanprover/lean4/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22), if you want to contribute to the project, please take a look at them. If you are interested in one of them, post comments, ask questions, and engage with the core developers there.
## Unexpected Pull Requests
Quality Over Quantity:
-----
We have very few core developers, and we cannot review arbitrary pull requests (PRs). Moreover, many features involve subtle tradeoffs, and it may require significant time and energy to even assess a proposed design. We suggest the following workflow:
**Focused Changes**: Each PR should address a single, clearly-defined issue or feature. Avoid making multiple unrelated changes in a single PR.
* First, discuss your idea with the Lean community on Zulip. Ask the community to help collect examples, document the requirements, and detect complications.
* If there is broad support, create a detailed issue for it on the Lean 4 repository at GitHub, and tag the issue with `RFC`.
* Ask the community for help documenting the requirements, and for collecting examples and concerns.
* Wait for one of the core developers to give you a "go ahead". At this point, the core developers will work with you to make sure your PR gets merged.
**Write Tests**: Every new feature or bug fix should come with relevant tests. This ensures the robustness and reliability of the contribution.
We don't want to waste your time by you implementing a feature and then us not being able to merge it.
**Documentation**: Update relevant documentation, including comments in the code, to explain the logic and reasoning behind your changes.
## How to Contribute
Coding Standards:
----
* Always follow the [commit convention](https://leanprover.github.io/lean4/doc/dev/commit_convention.html).
* Follow the style of the surrounding code. When in doubt, look at other files using the particular syntax as well.
* Make sure your code is documented.
* New features or bug fixes should come with appropriate tests.
* Ensure all tests work before submitting a PR; see [Development Setup](https://leanprover.github.io/lean4/doc/make/index.html#development-setup) and [Fixing Tests](https://leanprover.github.io/lean4/doc/dev/fixing_tests.html).
**Follow the Code Style**: Ensure that your code follows the established coding style of the project.
**Lean on Lean**: Use Lean's built-in features and libraries effectively, avoiding reinventions.
**Performance**: Make sure that your changes do not introduce performance regressions. If possible, optimize the solution for speed and resource usage.
PR Submission:
---
**Descriptive Title and Summary**: The PR title should briefly explain the purpose of the PR. The summary should give more detailed information on what changes are made and why. Links to Zulip threads are not acceptable as a summary. You are responsible for summarizing the discussion, and getting support for it.
**Follow the commit convention**: Pull requests are squash merged, and the
commit message is taken from the pull request title and body, so make sure they adhere to the [commit convention](https://github.com/leanprover/lean4/blob/master/doc/dev/commit_convention.md). Put questions and extra information, which should not be part of the final commit message, into a first comment rather than the Pull Request description.
Because the change will be squashed, there is no need to polish the commit messages and history on the branch.
**Link to Relevant Issues**: Reference any issues that your PR addresses to provide context.
**Stay Responsive**: Once the PR is submitted, stay responsive to feedback and be prepared to make necessary revisions. We will close any PR that has been inactive (no response or updates from the submitter) for more than a month.
Reviews and Feedback:
----
**Be Patient**: Given the limited number of full-time maintainers and the volume of PRs, reviews may take some time.
**Engage Constructively**: Always approach feedback positively and constructively. Remember, reviews are about ensuring the best quality for the project, not personal criticism.
**Continuous Integration**: Ensure that all CI checks pass on your PR. Failed checks will delay the review process. The maintainers will not check PRs containing failures.
What to Expect:
----
**Not All PRs Get Merged**: While we appreciate every contribution, not all PRs will be merged. Ensure your changes align with the project's goals and quality standards.
**Feedback is a Gift**: It helps improve the project and can also help you grow as a developer or contributor.
**Community Involvement**: Engage with the Lean community on our communication channels. This can lead to better collaboration and understanding of the project's direction.
If the well-founded relation you want to use is not the one that the
`WellFoundedRelation` type class would infer for your termination argument,
you can use `WellFounded.wrap` from the std libarary to explicitly give one:
```diff
-termination_by' ⟨r, hwf⟩
+termination_by _ x => hwf.wrap x
```
* Support snippet edits in LSP `TextEdit`s. See `Lean.Lsp.SnippetString` for more details.
* Deprecations and changes in the widget API.
- `Widget.UserWidgetDefinition` is deprecated in favour of `Widget.Module`. The annotation `@[widget]` is deprecated in favour of `@[widget_module]`. To migrate a definition of type `UserWidgetDefinition`, remove the `name` field and replace the type with `Widget.Module`. Removing the `name` results in a title bar no longer being drawn above your panel widget. To add it back, draw it as part of the component using `<details open=true><summary class='mv2 pointer'>{name}</summary>{rest_of_widget}</details>`. See an example migration [here](https://github.com/leanprover/std4/pull/475/files#diff-857376079661a0c28a53b7ff84701afabbdf529836a6944d106c5294f0e68109R43-R83).
- The new command `show_panel_widgets` allows displaying always-on and locally-on panel widgets.
- `RpcEncodable` widget props can now be stored in the infotree.
- See [RFC 2963](https://github.com/leanprover/lean4/issues/2963) for more details and motivation.
* If no usable lexicographic order can be found automatically for a termination proof, explain why.
See [feat: GuessLex: if no measure is found, explain why](https://github.com/leanprover/lean4/pull/2960).
* Option to print [inferred termination argument](https://github.com/leanprover/lean4/pull/3012).
With `set_option showInferredTerminationBy true` you will get messages like
```
Inferred termination argument:
termination_by
ackermann n m => (sizeOf n, sizeOf m)
```
for automatically generated `termination_by` clauses.
* More detailed error messages for [invalid mutual blocks](https://github.com/leanprover/lean4/pull/2949).
* [Multiple](https://github.com/leanprover/lean4/pull/2923) [improvements](https://github.com/leanprover/lean4/pull/2969) to the output of `simp?` and `simp_all?`.
* Tactics with `withLocation *` [no longer fail](https://github.com/leanprover/lean4/pull/2917) if they close the main goal.
* Implementation of a `test_extern` command for writing tests for `@[extern]` and `@[implemented_by]` functions.
Usage is
```
import Lean.Util.TestExtern
test_extern Nat.add 17 37
```
The head symbol must be the constant with the `@[extern]` or `@[implemented_by]` attribute. The return type must have a `DecidableEq` instance.
Bug fix for [eager evaluation of default value](https://github.com/leanprover/lean4/pull/3043) in `Option.getD`.
Avoid [panic in `leanPosToLspPos`](https://github.com/leanprover/lean4/pull/3071) when file source is unavailable.
Improve [short-circuiting behavior](https://github.com/leanprover/lean4/pull/2972) for `List.all` and `List.any`.
Several Lake bug fixes: [#3036](https://github.com/leanprover/lean4/issues/3036), [#3064](https://github.com/leanprover/lean4/issues/3064), [#3069](https://github.com/leanprover/lean4/issues/3069).
v4.4.0
---------
* Lake and the language server now support per-package server options using the `moreServerOptions` config field, as well as options that apply to both the language server and `lean` using the `leanOptions` config field. Setting either of these fields instead of `moreServerArgs` ensures that viewing files from a dependency uses the options for that dependency. Additionally, `moreServerArgs` is being deprecated in favor of the `moreGlobalServerArgs` field. See PR [#2858](https://github.com/leanprover/lean4/pull/2858).
A Lakefile with the following deprecated package declaration:
```lean
def moreServerArgs := #[
"-Dpp.unicode.fun=true"
]
def moreLeanArgs := moreServerArgs
package SomePackage where
moreServerArgs := moreServerArgs
moreLeanArgs := moreLeanArgs
```
... can be updated to the following package declaration to use per-package options:
* [`pp.beta`` to apply beta reduction when pretty printing](https://github.com/leanprover/lean4/pull/2864).
* [Embed and check githash in .olean](https://github.com/leanprover/lean4/pull/2766).
* [Guess lexicographic order for well-founded recursion](https://github.com/leanprover/lean4/pull/2874).
* [Allow trailing comma in tuples, lists, and tactics](https://github.com/leanprover/lean4/pull/2643).
Bug fixes for [#2628](https://github.com/leanprover/lean4/issues/2628), [#2883](https://github.com/leanprover/lean4/issues/2883),
[#2810](https://github.com/leanprover/lean4/issues/2810), [#2925](https://github.com/leanprover/lean4/issues/2925), and [#2914](https://github.com/leanprover/lean4/issues/2914).
**Lake:**
* `lake init .` and a bare `lake init` and will now use the current directory as the package name. [#2890](https://github.com/leanprover/lean4/pull/2890)
* `lake new` and `lake init` will now produce errors on invalid package names such as `..`, `foo/bar`, `Init`, `Lean`, `Lake`, and `Main`. See issue [#2637](https://github.com/leanprover/lean4/issues/2637) and PR [#2890](https://github.com/leanprover/lean4/pull/2890).
* `lean_lib` no longer converts its name to upper camel case (e.g., `lean_lib bar` will include modules named `bar.*` rather than `Bar.*`). See issue [#2567](https://github.com/leanprover/lean4/issues/2567) and PR [#2889](https://github.com/leanprover/lean4/pull/2889).
* Lean and Lake now properly support non-identifier library names (e.g., `lake new 123-hello` and `import «123Hello»` now work correctly). See issue [#2865](https://github.com/leanprover/lean4/issues/2865) and PR [#2889](https://github.com/leanprover/lean4/pull/2888).
* Lake now filters the environment extensions loaded from a compiled configuration (`lakefile.olean`) to include only those relevant to Lake's workspace loading process. This resolves segmentation faults caused by environment extension type mismatches (e.g., when defining custom elaborators via `elab` in configurations). See issue [#2632](https://github.com/leanprover/lean4/issues/2632) and PR [#2896](https://github.com/leanprover/lean4/pull/2896).
* Cloud releases will now properly be re-unpacked if the build directory is removed. See PR [#2928](https://github.com/leanprover/lean4/pull/2928).
* Lake's `math` template has been simplified. See PR [#2930](https://github.com/leanprover/lean4/pull/2930).
* `lake exe <target>` now parses `target` like a build target (as the help text states it should) rather than as a basic name. For example, `lake exe @mathlib/runLinter` should now work. See PR [#2932](https://github.com/leanprover/lean4/pull/2932).
* `lake new foo.bar [std]` now generates executables named `foo-bar` and `lake new foo.bar exe` properly creates `foo/bar.lean`. See PR [#2932](https://github.com/leanprover/lean4/pull/2932).
* Later packages and libraries in the dependency tree are now preferred over earlier ones. That is, the later ones "shadow" the earlier ones. Such an ordering is more consistent with how declarations generally work in programming languages. This will break any package that relied on the previous ordering. See issue [#2548](https://github.com/leanprover/lean4/issues/2548) and PR [#2937](https://github.com/leanprover/lean4/pull/2937).
* Executable roots are no longer mistakenly treated as importable. They will no longer be picked up by `findModule?`. See PR [#2937](https://github.com/leanprover/lean4/pull/2937).
v4.3.0
---------
* `simp [f]` does not unfold partial applications of `f` anymore. See issue [#2042](https://github.com/leanprover/lean4/issues/2042).
To fix proofs affected by this change, use `unfold f` or `simp (config := { unfoldPartialApp := true }) [f]`.
* By default, `simp` will no longer try to use Decidable instances to rewrite terms. In particular, not all decidable goals will be closed by `simp`, and the `decide` tactic may be useful in such cases. The `decide` simp configuration option can be used to locally restore the old `simp` behavior, as in `simp (config := {decide := true})`; this includes using Decidable instances to verify side goals such as numeric inequalities.
* Many bug fixes:
* [Add left/right actions to term tree coercion elaborator and make `^`` a right action](https://github.com/leanprover/lean4/pull/2778)
* [Fix for #2775, don't catch max recursion depth errors](https://github.com/leanprover/lean4/pull/2790)
* [Reduction of `Decidable` instances very slow when using `cases` tactic](https://github.com/leanprover/lean4/issues/2552)
* [`simp` not rewriting in binder](https://github.com/leanprover/lean4/issues/1926)
* [`simp` unfolding `let` even with `zeta := false` option](https://github.com/leanprover/lean4/issues/2669)
* [`simp` (with beta/zeta disabled) and discrimination trees](https://github.com/leanprover/lean4/issues/2281)
* [unknown free variable introduced by `rw ... at h`](https://github.com/leanprover/lean4/issues/2711)
* [`dsimp` doesn't use `rfl` theorems which consist of an unapplied constant](https://github.com/leanprover/lean4/issues/2685)
* [`dsimp` does not close reflexive equality goals if they are wrapped in metadata](https://github.com/leanprover/lean4/issues/2514)
* [`rw [h]` uses `h` from the environment in preference to `h` from the local context](https://github.com/leanprover/lean4/issues/2729)
* [missing `withAssignableSyntheticOpaque` for `assumption` tactic](https://github.com/leanprover/lean4/issues/2361)
* [ignoring default value for field warning](https://github.com/leanprover/lean4/issues/2178)
* [Cancel outstanding tasks on document edit in the language server](https://github.com/leanprover/lean4/pull/2648).
* [Remove unnecessary `%` operations in `Fin.mod` and `Fin.div`](https://github.com/leanprover/lean4/pull/2688)
* [Avoid `DecidableEq` in `Array.mem`](https://github.com/leanprover/lean4/pull/2774)
* [Ensure `USize.size` unifies with `?m + 1`](https://github.com/leanprover/lean4/issues/1926)
* [Improve compatibility with emacs eglot client](https://github.com/leanprover/lean4/pull/2721)
**Lake:**
* [Sensible defaults for `lake new MyProject math`](https://github.com/leanprover/lean4/pull/2770)
* Changed `postUpdate?` configuration option to a `post_update` declaration. See the `post_update` syntax docstring for more information on the new syntax.
* [A manifest is automatically created on workspace load if one does not exists.](https://github.com/leanprover/lean4/pull/2680).
* The `:=` syntax for configuration declarations (i.e., `package`, `lean_lib`, and `lean_exe`) has been deprecated. For example, `package foo := {...}` is deprecated.
* [support for overriding package URLs via `LAKE_PKG_URL_MAP`](https://github.com/leanprover/lean4/pull/2709)
* Moved the default build directory (e.g., `build`), default packages directory (e.g., `lake-packages`), and the compiled configuration (e.g., `lakefile.olean`) into a new dedicated directory for Lake outputs, `.lake`. The cloud release build archives are also stored here, fixing [#2713](https://github.com/leanprover/lean4/issues/2713).
* Update manifest format to version 7 (see [lean4#2801](https://github.com/leanprover/lean4/pull/2801) for details on the changes).
* Deprecate the `manifestFile` field of a package configuration.
* There is now a more rigorous check on `lakefile.olean` compatibility (see [#2842](https://github.com/leanprover/lean4/pull/2842) for more details).
v4.2.0
---------
* [isDefEq cache for terms not containing metavariables.](https://github.com/leanprover/lean4/pull/2644).
* Make [`Environment.mk`](https://github.com/leanprover/lean4/pull/2604) and [`Environment.add`](https://github.com/leanprover/lean4/pull/2642) private, and add [`replay`](https://github.com/leanprover/lean4/pull/2617) as a safer alternative.
* `IO.Process.output` no longer inherits the standard input of the caller.
* [Do not inhibit caching](https://github.com/leanprover/lean4/pull/2612) of default-level `match` reduction.
* [List the valid case tags](https://github.com/leanprover/lean4/pull/2629) when the user writes an invalid one.
* The derive handler for `DecidableEq` [now handles](https://github.com/leanprover/lean4/pull/2591) mutual inductive types.
* [Show path of failed import in Lake](https://github.com/leanprover/lean4/pull/2616).
* [Fix linker warnings on macOS](https://github.com/leanprover/lean4/pull/2598).
* **Lake:** Add `postUpdate?` package configuration option. Used by a package to specify some code which should be run after a successful `lake update` of the package or one of its downstream dependencies. ([lake#185](https://github.com/leanprover/lake/issues/185))
* Improvements to Lake startup time ([#2572](https://github.com/leanprover/lean4/pull/2572), [#2573](https://github.com/leanprover/lean4/pull/2573))
* `refine e` now replaces the main goal with metavariables which were created during elaboration of `e` and no longer captures pre-existing metavariables that occur in `e` ([#2502](https://github.com/leanprover/lean4/pull/2502)).
* This is accomplished via changes to `withCollectingNewGoalsFrom`, which also affects `elabTermWithHoles`, `refine'`, `calc` (tactic), and `specialize`. Likewise, all of these now only include newly-created metavariables in their output.
* Previously, both newly-created and pre-existing metavariables occurring in `e` were returned inconsistently in different edge cases, causing duplicated goals in the infoview (issue [#2495](https://github.com/leanprover/lean4/issues/2495)), erroneously closed goals (issue [#2434](https://github.com/leanprover/lean4/issues/2434)), and unintuitive behavior due to `refine e` capturing previously-created goals appearing unexpectedly in `e` (no issue; see PR).
v4.1.0
---------
* The error positioning on missing tokens has been [improved](https://github.com/leanprover/lean4/pull/2393). In particular, this should make it easier to spot errors in incomplete tactic proofs.
* After elaborating a configuration file, Lake will now cache the configuration to a `lakefile.olean`. Subsequent runs of Lake will import this OLean instead of elaborating the configuration file. This provides a significant performance improvement (benchmarks indicate that using the OLean cuts Lake's startup time in half), but there are some important details to keep in mind:
+ Lake will regenerate this OLean after each modification to the `lakefile.lean` or `lean-toolchain`. You can also force a reconfigure by passing the new `--reconfigure` / `-R` option to `lake`.
+ Lake configuration options (i.e., `-K`) will be fixed at the moment of elaboration. Setting these options when `lake` is using the cached configuration will have no effect. To change options, run `lake` with `-R` / `--reconfigure`.
+ **The `lakefile.olean` is a local configuration and should not be committed to Git. Therefore, existing Lake packages need to add it to their `.gitignore`.**
* The signature of `Lake.buildO` has changed, `args` has been split into `weakArgs` and `traceArgs`. `traceArgs` are included in the input trace and `weakArgs` are not. See Lake's [FFI example](src/lake/examples/ffi/lib/lakefile.lean) for a demonstration of how to adapt to this change.
* The signatures of `Lean.importModules`, `Lean.Elab.headerToImports`, and `Lean.Elab.parseImports`
have [changed](https://github.com/leanprover/lean4/pull/2480) from taking `List Import` to `Array Import`.
* There is now [an `occs` field](https://github.com/leanprover/lean4/pull/2470)
in the configuration object for the `rewrite` tactic,
allowing control of which occurrences of a pattern should be rewritten.
This was previously a separate argument for `Lean.MVarId.rewrite`,
and this has been removed in favour of an additional field of `Rewrite.Config`.
It was not previously accessible from user tactics.
v4.0.0
---------
* [`Lean.Meta.getConst?` has been renamed](https://github.com/leanprover/lean4/pull/2454).
We have renamed `getConst?` to `getUnfoldableConst?` (and `getConstNoEx?` to `getUnfoldableConstNoEx?`).
These were not intended to be part of the public API, but downstream projects had been using them
(sometimes expecting different behaviour) incorrectly instead of `Lean.getConstInfo`.
* [`dsimp` / `simp` / `simp_all` now fail by default if they make no progress](https://github.com/leanprover/lean4/pull/2336).
This can be overridden with the `(config := { failIfUnchanged := false })` option.
This change was made to ease manual use of `simp` (with complicated goals it can be hard to tell if it was effective)
and to allow easier flow control in tactics internally using `simp`.
See the [summary discussion](https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/simp.20fails.20if.20no.20progress/near/380153295)
on zulip for more details.
* [`simp_all` now preserves order of hypotheses](https://github.com/leanprover/lean4/pull/2334).
In order to support the `failIfUnchanged` configuration option for `dsimp` / `simp` / `simp_all`
the way `simp_all` replaces hypotheses has changed.
In particular it is now more likely to preserve the order of hypotheses.
See [`simp_all` reorders hypotheses unnecessarily](https://github.com/leanprover/lean4/pull/2334).
(Previously all non-dependent propositional hypotheses were reverted and reintroduced.
Now only such hypotheses which were changed, or which come after a changed hypothesis,
are reverted and reintroduced.
This has the effect of preserving the ordering amongst the non-dependent propositional hypotheses,
but now any dependent or non-propositional hypotheses retain their position amongst the unchanged
non-dependent propositional hypotheses.)
This may affect proofs that use `rename_i`, `case ... =>`, or `next ... =>`.
`this` is now a regular identifier again that is implicitly introduced by anonymous `have :=` for the remainder of the tactic block. It used to be a keyword that was visible in all scopes and led to unexpected behavior when explicitly used as a binder name.
* [Show typeclass and tactic names in profile output](https://github.com/leanprover/lean4/pull/2170).
* [Make `calc` require the sequence of relation/proof-s to have the same indentation](https://github.com/leanprover/lean4/pull/1844),
and [add `calc` alternative syntax allowing underscores `_` in the first relation](https://github.com/leanprover/lean4/pull/1844).
The flexible indentation in `calc` was often used to align the relation symbols:
```lean
example (x y : Nat) : (x + y) * (x + y) = x * x + y * x + x * y + y * y :=
calc
(x + y) * (x + y) = (x + y) * x + (x + y) * y := by rw [Nat.mul_add]
-- improper indentation
_ = x * x + y * x + (x + y) * y := by rw [Nat.add_mul]
_ = x * x + y * x + (x * y + y * y) := by rw [Nat.add_mul]
_ = x * x + y * x + x * y + y * y := by rw [←Nat.add_assoc]
```
This is no longer legal. The new syntax puts the first term right after the `calc` and each step has the same indentation:
```lean
example (x y : Nat) : (x + y) * (x + y) = x * x + y * x + x * y + y * y :=
calc (x + y) * (x + y)
_ = (x + y) * x + (x + y) * y := by rw [Nat.mul_add]
_ = x * x + y * x + (x + y) * y := by rw [Nat.add_mul]
_ = x * x + y * x + (x * y + y * y) := by rw [Nat.add_mul]
_ = x * x + y * x + x * y + y * y := by rw [←Nat.add_assoc]
```
* Update Lake to latest prerelease.
* [Make go-to-definition on a typeclass projection application go to the instance(s)](https://github.com/leanprover/lean4/pull/1767).
* [Include timings in trace messages when `profiler` is true](https://github.com/leanprover/lean4/pull/1995).
* [Pretty-print signatures in hover and `#check <ident>`](https://github.com/leanprover/lean4/pull/1943).
* [Introduce parser memoization to avoid exponential behavior](https://github.com/leanprover/lean4/pull/1799).
* [feat: allow `doSeq` in `let x <- e | seq`](https://github.com/leanprover/lean4/pull/1809).
* [Add hover/go-to-def/refs for options](https://github.com/leanprover/lean4/pull/1783).
* [Add empty type ascription syntax `(e :)`](https://github.com/leanprover/lean4/pull/1797).
* [Make tokens in `<|>` relevant to syntax match](https://github.com/leanprover/lean4/pull/1744).
* [Add `linter.deprecated` option to silence deprecation warnings](https://github.com/leanprover/lean4/pull/1768).
* `simp` can track information and can print an equivalent `simp only`. [PR #1626](https://github.com/leanprover/lean4/pull/1626).
* Enforce uniform indentation in tactic blocks / do blocks. See issue [#1606](https://github.com/leanprover/lean4/issues/1606).
* Moved `AssocList`, `HashMap`, `HashSet`, `RBMap`, `RBSet`, `PersistentArray`, `PersistentHashMap`, `PersistentHashSet` to the Lean package. The [standard library](https://github.com/leanprover/std4) contains versions that will evolve independently to simplify bootstrapping process.
* Standard library moved to the [std4 GitHub repository](https://github.com/leanprover/std4).
* `InteractiveGoals` now has information that a client infoview can use to show what parts of the goal have changed after applying a tactic. [PR #1610](https://github.com/leanprover/lean4/pull/1610).
* `match`-syntax notation now checks for unused alternatives. See issue [#1371](https://github.com/leanprover/lean4/issues/1371).
* Auto-completion for structure instance fields. Example:
```lean
example : Nat × Nat := {
f -- HERE
}
```
`fst` now appears in the list of auto-completion suggestions.
* Auto-completion for dotted identifier notation. Example:
```lean
example : Nat :=
.su -- HERE
```
`succ` now appears in the list of auto-completion suggestions.
* `nat_lit` is not needed anymore when declaring `OfNat` instances. See issues [#1389](https://github.com/leanprover/lean4/issues/1389) and [#875](https://github.com/leanprover/lean4/issues/875). Example:
```lean
inductive Bit where
| zero
| one
instance inst0 : OfNat Bit 0 where
ofNat := Bit.zero
instance : OfNat Bit 1 where
ofNat := Bit.one
example : Bit := 0
example : Bit := 1
```
* Add `[elabAsElim]` attribute (it is called `elab_as_eliminator` in Lean 3). Motivation: simplify the Mathlib port to Lean 4.
* `Trans` type class now accepts relations in `Type u`. See this [Zulip issue](https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Calc.20mode/near/291214574).
* Accept unescaped keywords as inductive constructor names. Escaping can often be avoided at use sites via dot notation.
```lean
inductive MyExpr
| let : ...
def f : MyExpr → MyExpr
| .let ... => .let ...
```
* Throw an error message at parametric local instances such as `[Nat -> Decidable p]`. The type class resolution procedure
cannot use this kind of local instance because the parameter does not have a forward dependency.
This check can be disabled using `set_option checkBinderAnnotations false`.
* Add option `pp.showLetValues`. When set to `false`, the info view hides the value of `let`-variables in a goal.
By default, it is `true` when visualizing tactic goals, and `false` otherwise.
See [issue #1345](https://github.com/leanprover/lean4/issues/1345) for additional details.
* Add option `warningAsError`. When set to true, warning messages are treated as errors.
* Support dotted notation and named arguments in patterns. Example:
```lean
def getForallBinderType (e : Expr) : Expr :=
match e with
| .forallE (binderType := type) .. => type
| _ => panic! "forall expected"
```
* "jump-to-definition" now works for function names embedded in the following attributes
`@[builtinTactic parserName]`, `@[builtinTermElab parserName]`, and `@[builtinCommandElab parserName]`.
See [issue #1350](https://github.com/leanprover/lean4/issues/1350).
* Improve `MVarId` methods discoverability. See [issue #1346](https://github.com/leanprover/lean4/issues/1346).
We still have to add similar methods for `FVarId`, `LVarId`, `Expr`, and other objects.
Many existing methods have been marked as deprecated.
* Add attribute `[deprecated]` for marking deprecated declarations. Examples:
```lean
def g (x : Nat) := x + 1
-- Whenever `f` is used, a warning message is generated suggesting to use `g` instead.
@[deprecated g]
def f (x : Nat) := x + 1
#check f 0 -- warning: `f` has been deprecated, use `g` instead
-- Whenever `h` is used, a warning message is generated.
@[deprecated]
def h (x : Nat) := x + 1
#check h 0 -- warning: `h` has been deprecated
```
* Add type `LevelMVarId` (and abbreviation `LMVarId`) for universe level metavariable ids.
Motivation: prevent meta-programmers from mixing up universe and expression metavariable ids.
* Improve `calc` term and tactic. See [issue #1342](https://github.com/leanprover/lean4/issues/1342).
* [Relaxed antiquotation parsing](https://github.com/leanprover/lean4/pull/1272) further reduces the need for explicit `$x:p` antiquotation kind annotations.
* Add support for computed fields in inductives. Example:
```lean
inductive Exp
| var (i : Nat)
| app (a b : Exp)
with
@[computedField] hash : Exp → Nat
| .var i => i
| .app a b => a.hash * b.hash + 1
```
The result of the `Exp.hash` function is then stored as an extra "computed" field in the `.var` and `.app` constructors;
`Exp.hash` accesses this field and thus runs in constant time (even on dag-like values).
* Update `a[i]` notation. It is now based on the typeclass
```lean
class GetElem (cont : Type u) (idx : Type v) (elem : outParam (Type w)) (dom : outParam (cont → idx → Prop)) where
getElem (xs : cont) (i : idx) (h : dom xs i) : Elem
See discussion on [Zulip](https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/String.2EgetOp/near/287855425).
Examples:
```lean
example (a : Array Int) (i : Nat) : Int :=
a[i] -- Error: failed to prove index is valid ...
example (a : Array Int) (i : Nat) (h : i < a.size) : Int :=
a[i] -- Ok
example (a : Array Int) (i : Nat) : Int :=
a[i]! -- Ok
example (a : Array Int) (i : Nat) : Option Int :=
a[i]? -- Ok
example (a : Array Int) (h : a.size = 2) : Int :=
a[0]'(by rw [h]; decide) -- Ok
example (a : Array Int) (h : a.size = 2) : Int :=
have : 0 < a.size := by rw [h]; decide
have : 1 < a.size := by rw [h]; decide
a[0] + a[1] -- Ok
example (a : Array Int) (i : USize) (h : i.toNat < a.size) : Int :=
a[i] -- Ok
```
The `get_elem_tactic` is defined as
```lean
macro "get_elem_tactic" : tactic =>
`(first
| get_elem_tactic_trivial
| fail "failed to prove index is valid, ..."
)
```
The `get_elem_tactic_trivial` auxiliary tactic can be extended using `macro_rules`. By default, it tries `trivial`, `simp_arith`, and a special case for `Fin`. In the future, it will also try `linarith`.
You can extend `get_elem_tactic_trivial` using `my_tactic` as follows
Note that `Idx`'s type in `GetElem` does not depend on `Cont`. So, you cannot write the instance `instance : GetElem (Array α) (Fin ??) α fun xs i => ...`, but the Lean library comes equipped with the following auxiliary instance:
```lean
instance [GetElem cont Nat elem dom] : GetElem cont (Fin n) elem fun xs i => dom xs i where
* `exists` tactic is now takes a comma separated list of terms.
@@ -243,7 +841,7 @@ Unreleased
`Foo : {Foo : Type u} → List Foo → Type`.
* Fix syntax hightlighting for recursive declarations. Example
* Fix syntax highlighting for recursive declarations. Example
```lean
inductive List (α : Type u) where
| nil : List α -- `List` is not highlighted as a variable anymore
@@ -296,7 +894,7 @@ Unreleased
...
```
* Remove support for `{}` annotation from inductive datatype contructors. This annotation was barely used, and we can control the binder information for parameter bindings using the new inductive family indices to parameter promotion. Example: the following declaration using `{}`
* Remove support for `{}` annotation from inductive datatype constructors. This annotation was barely used, and we can control the binder information for parameter bindings using the new inductive family indices to parameter promotion. Example: the following declaration using `{}`
```lean
inductive LE' (n : Nat) : Nat → Prop where
| refl {} : LE' n n -- Want `n` to be explicit
@@ -461,7 +1059,7 @@ v4.0.0-m4 (23 March 2022)
initialize my_ext : SimpExtension ← registerSimpAttr `my_simp "my own simp attribute"
```
If you don't neet to acces `my_ext`, you can also use the macro
If you don't need to access `my_ext`, you can also use the macro
```lean
import Lean
@@ -552,7 +1150,7 @@ For example, given `f : Nat → Nat` and `g : Nat → Nat`, `f.comp g` is now no
* Various improvements to go-to-definition & find-all-references accuracy.
* Auto generated congruence lemmas with support for casts on proofs and `Decidable` instances (see [whishlist](https://github.com/leanprover/lean4/issues/988)).
* Auto generated congruence lemmas with support for casts on proofs and `Decidable` instances (see [wishlist](https://github.com/leanprover/lean4/issues/988)).
@@ -11,6 +11,8 @@ There are two primary attributes for interoperating with other languages:
It can also be used with `def` to provide an internal definition, but ensuring consistency of both definitions is up to the user.
*`@[export sym] def leanSym : ...` exports `leanSym` under the unmangled symbol name `sym`.
For simple examples of how to call foreign code from Lean and vice versa, see <https://github.com/leanprover/lean4/blob/master/src/lake/examples/ffi> and <https://github.com/leanprover/lean4/blob/master/src/lake/examples/reverse-ffi>, respectively.
## The Lean ABI
The Lean Application Binary Interface (ABI) describes how the signature of a Lean declaration is encoded as a native calling convention.
@@ -21,7 +23,7 @@ If `n` is 0, the corresponding C declaration is
externssym;
```
where `s` is the C translation of `β` as specified in the next section.
In the case of an `@[extern]` definition, the symbol's value is guaranteed to be initialized only after calling the Lean module's initializer or that of an importing module; see [Initialization](.#init).
In the case of an `@[extern]` definition, the symbol's value is guaranteed to be initialized only after calling the Lean module's initializer or that of an importing module; see [Initialization](#initialization).
If `n` is greater than 0, the corresponding C declaration is
```c
@@ -32,7 +34,7 @@ In the case of `@[extern]` all *irrelevant* types are removed first; see next se
### Translating Types from Lean to C
* The integer types `UInt8`, ..., `UInt64`, `USize` are represented by the C types `uint8_t`, ..., `uint64_t`, `usize_t`, respectively
* The integer types `UInt8`, ..., `UInt64`, `USize` are represented by the C types `uint8_t`, ..., `uint64_t`, `size_t`, respectively
*`Char` is represented by `uint32_t`
*`Float` is represented by `double`
* An *enum* inductive type of at least 2 and at most 2^32 constructors, each of which with no parameters, is represented by the first type of `uint8_t`, `uint16_t`, `uint32_t` that is sufficient to represent all constructor indices.
@@ -43,8 +45,9 @@ In the case of `@[extern]` all *irrelevant* types are removed first; see next se
* it is none of the types described above
* it is not marked `unsafe`
* it has a single constructor with a single parameter of *relevant* type
is represented by the representation of that parameter's type.
For example, `{ x : α // p }`, the `Subtype` structure of a value of type `α` and an irrelevant proof, is represented by the representation of `α`.
* `Nat` is represented by `lean_object *`.
Its runtime value is either a pointer to an opaque bignum object or, if the lowest bit of the "pointer" is 1 (`lean_is_scalar`), an encoded unboxed natural number (`lean_box`/`lean_unbox`).
@@ -69,13 +72,13 @@ When including Lean code as part of a larger program, modules must be *initializ
Module initialization entails
* initialization of all "constants" (nullary functions), including closed terms lifted out of other functions
* execution of all `[init]` functions
* execution of all `[builtinInit]` functions, if the `builtin` parameter of the module initializer has been set
* execution of all `[builtin_init]` functions, if the `builtin` parameter of the module initializer has been set
The module initializer is automatically run with the `builtin` flag for executables compiled from Lean code and for "plugins" loaded with `lean --plugin`.
For all other modules imported by `lean`, the initializer is run without `builtin`.
Thus `[init]` functions are run iff their module is imported, regardless of whether they have native code available or not, while `[builtinInit]` functions are only run for native executable or plugins, regardless of whether their module is imported or not.
Thus `[init]` functions are run iff their module is imported, regardless of whether they have native code available or not, while `[builtin_init]` functions are only run for native executable or plugins, regardless of whether their module is imported or not.
`lean` uses built-in initializers for e.g. registering basic parsers that should be available even without importing their module (which is necessary for bootstrapping).
The initializer for module `A.B` is called `initialize_A_B` and will automatically initialize any imported modules.
Module initializers are idempotent (when run with the same `builtin` flag), but not thread-safe.
Together with initialization of the Lean runtime, you should execute code like the following exactly once before accessing any Lean declarations:
If you want to make changes to Lean itself, start by [building Lean](../make/index.html) from a clean checkout to make sure that everything is set up correctly.
If you want to make changes to Lean itself, start by [building Lean](../make/index.md) from a clean checkout to make sure that everything is set up correctly.
After that, read on below to find out how to set up your editor for changing the Lean source code, followed by further sections of the development manual where applicable such as on the [test suite](testing.md) and [commit convention](commit_convention.md).
If you are planning to make any changes that may affect the compilation of Lean itself, e.g. changes to the parser, elaborator, or compiler, you should first read about the [bootstrapping pipeline](bootstrap.md).
You can use `elantoolchain link` to give a specific stage build
directory a reference name, then use `elan override set` to associate
such a name to the current directory. We usually want to use `stage0`
for editing files in `src` and `stage1`for everything else (e.g.
tests).
The `lean-toolchain` files in the Lean 4 repository are set up to use the `lean4-stage0`
toolchain for editing files in `src` and the `lean4` toolchain for editing files in `tests`.
Run the following commands to make `lean4` point at `stage1` and `lean4-stage0`point at `stage0`:
```bash
# in the Lean rootdir
elan toolchain link lean4 build/release/stage1
elan toolchain link lean4-stage0 build/release/stage0
# make `lean` etc. point to stage1 in the rootdir and subdirs
elan override set lean4
cd src
# make `lean` etc. point to stage0 anywhere inside `src`
elan override set lean4-stage0
```
You can also use the `+toolchain` shorthand (e.g. `lean +lean4-debug`) to switch
@@ -57,3 +51,26 @@ You might find that debugging through elan, e.g. via `gdb lean`, disables some
things like symbol autocompletion because at first only the elan proxy binary
is loaded. You can instead pass the explicit path to `bin/lean` in your build
folder to gdb, or use `gdb $(elan which lean)`.
It is also possible to generate releases that others can use,
simply by pushing a tag to your fork of the Lean 4 github repository
(and waiting about an hour; check the `Actions` tab for completion).
If you push `my-tag` to a fork in your github account `my_name`,
you can then put `my_name/lean4:my-tag` in your `lean-toolchain` file in a project using `lake`.
(You must use a tag name that does not start with a numeral, or contain `_`).
### VS Code
There is a `lean.code-workspace` file that correctly sets up VS Code with workspace roots for the stage0/stage1 setup described above as well as with other settings.
You should always load it when working on Lean, such as by invoking
```
code lean.code-workspace
```
on the command line.
### `ccache`
Lean's build process uses [`ccache`](https://ccache.dev/) if it is
installed to speed up recompilation of the generated C code. Without
`ccache`, you'll likely spend more time than necessary waiting on
rebuilds - it's a good idea to make sure it's installed.
@@ -5,7 +5,7 @@ If the type of keys can be totally ordered -- that is, it supports a well-behave
then maps can be implemented with binary search trees (BSTs). Insert and lookup operations on BSTs take time
proportional to the height of the tree. If the tree is balanced, the operations therefore take logarithmic time.
This example is based on a similar example found in the ["Sofware Foundations"](https://softwarefoundations.cis.upenn.edu/vfa-current/SearchTree.html)
This example is based on a similar example found in the ["Software Foundations"](https://softwarefoundations.cis.upenn.edu/vfa-current/SearchTree.html)
book (volume 3).
-/
@@ -81,9 +81,9 @@ def Tree.toList (t : Tree β) : List (Nat × β) :=
|>.toList
/-!
The implemention of `Tree.toList` is inefficient because of how it uses the `++` operator.
The implementation of `Tree.toList` is inefficient because of how it uses the `++` operator.
On a balanced tree its running time is linearithmic, because it does a linear number of
concatentations at each level of the tree. On an unbalanced tree it's quadratic time.
concatenations at each level of the tree. On an unbalanced tree it's quadratic time.
Here's a tail-recursive implementation than runs in linear time, regardless of whether the tree is balanced:
-/
defTree.toListTR(t:Treeβ):List(Nat×β):=
@@ -92,7 +92,7 @@ where
go(t:Treeβ)(acc:List(Nat×β)):List(Nat×β):=
matchtwith
|leaf=>acc
|nodelkvr=>l.go((k,v)::r.goacc)
|nodelkvr=>gol((k,v)::goracc)
/-!
We now prove that `t.toList` and `t.toListTR` return the same list.
@@ -114,9 +114,9 @@ concatenating all goals produced by `tac'`. In this theorem, we use it to apply
The `simp` parameters `toListTR.go` and `toList` instruct the simplifier to try to reduce
and/or apply auto generated equation theorems for these two functions.
The parameter `*` intructs the simplifier to use any equation in a goal as rewriting rules.
The parameter `*` instructs the simplifier to use any equation in a goal as rewriting rules.
In this particular case, `simp` uses the induction hypotheses as rewriting rules.
Finally, the parameter `List.append_assoc` intructs the simplifier to use the
Finally, the parameter `List.append_assoc` instructs the simplifier to use the
`List.append_assoc` theorem as a rewriting rule.
-/
theoremTree.toList_eq_toListTR(t:Treeβ)
@@ -176,22 +176,23 @@ The modifier `local` specifies the scope of the macro.
/-- The `have_eq lhs rhs` tactic (tries to) prove that `lhs = rhs`,
@@ -222,7 +222,7 @@ def f2 (a b c : Bool) : Bool :=
def p : Nat × Bool := (1, false)
section
variables (a b c : Nat) (p : Nat × bool)
variable (a b c : Nat) (p : Nat × bool)
#check (1, 2)
#check p.1 * 2
@@ -232,8 +232,8 @@ end
/- lists -/
section
variables x y z : Nat
variables xs ys zs : list Nat
variable x y z : Nat
variable xs ys zs : list Nat
open list
#check (1 :: xs) ++ (y :: zs) ++ [1,2,3]
@@ -243,7 +243,7 @@ end
/- sets -/
section
variables s t u : set Nat
variable s t u : set Nat
#check ({1, 2, 3} ∩ s) ∪ ({x | x < 7} ∩ t)
end
@@ -276,7 +276,7 @@ Finally, for data types with one constructor, one destruct an element by pattern
.. code-block:: lean
universes u v
variables {α : Type u} {β : Type v}
variable {α : Type u} {β : Type v}
def p : Nat ×ℤ := ⟨1, 2⟩
#check p.fst
@@ -369,7 +369,7 @@ Here is an example:
.. code-block:: lean
variables (a b c d e : Nat)
variable (a b c d e : Nat)
variable h1 : a = b
variable h2 : b = c + 1
variable h3 : c = d
@@ -406,7 +406,7 @@ The reduction relation is transitive, which is to say, is ``s`` reduces to ``s'`
This last fact reflects the intuition that once we have proved a proposition ``p``, we only care that is has been proved; the proof does nothing more than witness the fact that ``p`` is true.
Definitional equality is a strong notion of equalty of values. Lean's logical foundations sanction treating definitionally equal terms as being the same when checking that a term is well-typed and/or that it has a given type.
Definitional equality is a strong notion of equality of values. Lean's logical foundations sanction treating definitionally equal terms as being the same when checking that a term is well-typed and/or that it has a given type.
The reduction relation is believed to be strongly normalizing, which is to say, every sequence of reductions applied to a term will eventually terminate. The property guarantees that Lean's type-checking algorithm terminates, at least in principle. The consistency of Lean and its soundness with respect to set-theoretic semantics do not depend on either of these properties.
@@ -7,15 +7,6 @@ Lean is a new open source theorem prover being developed at Microsoft Research.
It is a research project that aims to bridge the gap between interactive and automated theorem proving.
Lean can be also used as a programming language. Actually, some Lean features are implemented in Lean itself.
### Are pull requests welcome?
In the past, we accepted most pull requests. This practice produced hard to maintain code, performance problems, and bugs.
It takes time to review a pull request and make sure it is correct, useful and is not in conflict with our plans.
Small bug fixes (few lines of code) are always welcome. Any other kind of unrequested pull request is not.
Thus, before implementing a feature or modifying the system, please ask whether the change is welcome or not.
We have issues tagged with ["help wanted"](https://github.com/leanprover/lean4/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22), if you want to contribute to the project, please take a look at them.
If you are interested in one of them, post comments, ask questions, and engage with the core developers there.
### Should I use Lean?
Lean is under heavy development, and we are constantly trying new
@@ -36,7 +27,7 @@ It is a good place to interact with other Lean users.
### Should I use Lean to teach a course?
Lean has been used to teach courses on logic, type theory and programming languages at CMU and the University of Washington.
The lecture notes for the CMU course [Logic and Proof](https://leanprover.github.io/logic_and_proof) are available online,
The lecture notes for the CMU course [Logic and Proof](https://lean-lang.org/logic_and_proof) are available online,
but they are for Lean 3.
If you decide to teach a course using Lean, we suggest you prepare all material before the beginning of the course, and
make sure that Lean attends all your needs. You should not expect we will fix bugs and/or add features needed for your course.
@@ -56,7 +47,7 @@ We expect similar independent checkers will be built for Lean 4.
We use [GitHub](https://github.com/leanprover/lean4/issues) to track bugs and new features.
Bug reports are always welcome, but nitpicking issues are not (e.g., the error message is confusing).
See also our [contribution guidelines](../CONTRIBUTING.md).
See also our [contribution guidelines](https://github.com/leanprover/lean4/blob/master/CONTRIBUTING.md).
The goal of [this book](https://leanprover.github.io/functional_programming_in_lean/) is to be an accessible introduction to using Lean 4 as a programming language.
The goal of [this book](https://lean-lang.org/functional_programming_in_lean/) is to be an accessible introduction to using Lean 4 as a programming language.
It should be useful both to people who want to use Lean as a general-purpose programming language and to mathematicians who want to develop larger-scale proof automation but do not have a background in functional programming.
It does not assume any background with functional programming, though it's probably not a good first book on programming in general.
New content will be added once per month until it's done.
<pathd="M -807.881999182059,-412 L -847.12242702921,-475.387638592472"fill="none"stroke="#A0A0A0"stroke-width="1"/>
<pathd="M -851.859658804052,-483.04 L -849.997117457574,-472.431939869483 C -848.256110200696,-474.68582647768 -845.988743857725,-476.089450707263 -843.19501842866,-476.642812558231 z"fill="#A0A0A0"stroke="#A0A0A0"stroke-width="1"stroke-linejoin="round"/>
</g>
<gid="Applicative->Pure">
<pathd="M -796.388009621993,-412 L -779.775946795781,-474.343439288465"fill="none"stroke="#A0A0A0"stroke-width="1"/>
<pathd="M -777.458657044673,-483.04 L -783.898561528809,-474.407061321009 C -781.064326160453,-474.686741473815 -778.487567431109,-474.000137103116 -776.168285340778,-472.347248208913 z"fill="#A0A0A0"stroke="#A0A0A0"stroke-width="1"stroke-linejoin="round"/>
</g>
<gid="Applicative->Seq">
<pathd="M -785.682854982818,-412 L -714.799014210374,-476.959367842732"fill="none"stroke="#A0A0A0"stroke-width="1"/>
<pathd="M -708.163811683849,-483.04 L -718.238762116551,-479.232720948158 C -715.699848604043,-477.942360809625 -713.898179816704,-475.97637487584 -712.833755754535,-473.334763146803 z"fill="#A0A0A0"stroke="#A0A0A0"stroke-width="1"stroke-linejoin="round"/>
</g>
<gid="Applicative->SeqLeft">
<pathd="M -774.344312027491,-412 L -642.789872940275,-478.957606209781"fill="none"stroke="#A0A0A0"stroke-width="1"/>
<pathd="M -634.769021305842,-483.04 L -645.495475917531,-482.068829848393 C -643.394672020307,-480.145880525993 -642.185073860242,-477.769331893569 -641.866681437336,-474.93918395112 z"fill="#A0A0A0"stroke="#A0A0A0"stroke-width="1"stroke-linejoin="round"/>
</g>
<gid="Applicative->SeqRight">
<pathd="M -762.225406557428,-411.616331588423 L -552.255039618581,-481.91850535998"fill="none"stroke="#A0A0A0"stroke-width="1"/>
<pathd="M -543.720702607113,-484.775967831244 L -554.473282607084,-485.394048201604 C -552.678367392102,-483.182851583901 -551.831711845061,-480.654159136059 -551.93331596596,-477.807970858076 z"fill="#A0A0A0"stroke="#A0A0A0"stroke-width="1"stroke-linejoin="round"/>
</g>
<gid="Except->Monad">
<pathd="M -620.787981188119,-238 L -711.95378637201,-307.579654923495"fill="none"stroke="#A0A0A0"stroke-width="1"/>
<pathd="M -719.108129922992,-313.04 L -713.585679344792,-303.793241670113 C -712.762726383344,-306.519752175201 -711.144846360676,-308.639557671788 -708.732039276787,-310.152658159875 z"fill="#A0A0A0"stroke="#A0A0A0"stroke-width="1"stroke-linejoin="round"/>
</g>
<gid="List->Functor">
<pathd="M -892.034814302334,-412 L -868.075682352572,-474.634018472681"fill="none"stroke="#A0A0A0"stroke-width="1"/>
<pathd="M -864.86017701711,-483.04 L -872.168952513098,-475.129134007629 C -869.321012949211,-475.110389633491 -866.830351755932,-474.157647311872 -864.696968933259,-472.270907042774 z"fill="#A0A0A0"stroke="#A0A0A0"stroke-width="1"stroke-linejoin="round"/>
</g>
<gid="Monad->Applicative">
<pathd="M -747.447014155251,-339 L -782.595654197137,-379.260216894652"fill="none"stroke="#A0A0A0"stroke-width="1"/>
<pathd="M -788.514652511416,-386.04 L -784.951224653483,-375.876241743267 C -783.60006650904,-378.383328255499 -781.591241885233,-380.137105533804 -778.924750782062,-381.137573578181 z"fill="#A0A0A0"stroke="#A0A0A0"stroke-width="1"stroke-linejoin="round"/>
</g>
<gid="Monad->Bind">
<pathd="M -725.919943874952,-339 L -693.754264838054,-379.952252619104"fill="none"stroke="#A0A0A0"stroke-width="1"/>
<pathd="M -688.195056125048,-387.030048779297 L -697.517641877363,-381.63659025153 C -694.802827232157,-380.775839095105 -692.705702443952,-379.128666143103 -691.226267512747,-376.695071395525 z"fill="#A0A0A0"stroke="#A0A0A0"stroke-width="1"stroke-linejoin="round"/>
</g>
<gid="Option->Monad">
<pathd="M -856.761951485149,-238 L -761.177064707358,-307.735551794831"fill="none"stroke="#A0A0A0"stroke-width="1"/>
<pathd="M -753.906381848185,-313.04 L -764.342450894008,-310.377583265001 C -761.962908885902,-308.81268999619 -760.391220528815,-306.658413593472 -759.627385822747,-303.914754056846 z"fill="#A0A0A0"stroke="#A0A0A0"stroke-width="1"stroke-linejoin="round"/>
</g>
<gid="ReaderM->Monad">
<pathd="M -776.319514851485,-238 L -745.783102116211,-304.853562563497"fill="none"stroke="#A0A0A0"stroke-width="1"/>
<pathd="M -742.043818481848,-313.04 L -749.836994714031,-305.60586224138 C -746.99590766236,-305.407530509328 -744.570296570063,-304.299594617665 -742.560161437139,-302.28205456639 z"fill="#A0A0A0"stroke="#A0A0A0"stroke-width="1"stroke-linejoin="round"/>
</g>
<gid="StateM->Monad">
<pathd="M -695.681478217822,-238 L -726.395530552052,-304.861622913356"fill="none"stroke="#A0A0A0"stroke-width="1"/>
<pathd="M -730.152410671067,-313.04 L -729.612933688448,-302.283189850833 C -727.607141972296,-304.305048080909 -725.183919131808,-305.418197745802 -722.343265166986,-305.622638845513 z"fill="#A0A0A0"stroke="#A0A0A0"stroke-width="1"stroke-linejoin="round"/>
In Lean 3 stdlib, we find many [instances](https://github.com/leanprover/lean/blob/master/library/init/category/reader.lean#L39) of the dreadful `@`+`_` idiom.
It is often used when we the expected type is a function type with implicit arguments,
It is often used when the expected type is a function type with implicit arguments,
and we have a constant (`reader_t.pure` in the example) which also takes implicit arguments. In Lean 4, the elaborator automatically introduces lambdas
for consuming implicit arguments. We are still exploring this feature and analyzing its impact, but the experience so far has been very positive. As an example,
here is the example in the link above using Lean 4 implicit lambdas.
@@ -85,7 +85,7 @@ def id5 : {α : Type} → α → α :=
## Sugar for simple functions
In Lean 3, we can create simple functions from infix operators by using parentheses. For example, `(+1)` is sugar for `fun x, x + 1`. In Lean 4, we generalize this notation using `·`As a placeholder. Here are a few examples:
In Lean 3, we can create simple functions from infix operators by using parentheses. For example, `(+1)` is sugar for `fun x, x + 1`. In Lean 4, we generalize this notation using `·`as a placeholder. Here are a few examples:
```lean
#namespaceex3
@@ -196,6 +196,8 @@ example (f : Nat → Nat) (a b c : Nat) : f (a + b + c) = f (a + (b + c)) :=
congrArgf(Nat.add_assoc..)
```
In Lean 4, writing `f(x)` in place of `f x` is no longer allowed, you must use whitespace between the function and its arguments (e.g., `f (x)`).
## Dependent function types
Given `α : Type` and `β : α → Type`, `(x : α) → β x` denotes the type of functions `f` with the property that,
@@ -287,11 +289,11 @@ Lean execution runtime. For example, we cannot prove in Lean that arrays have a
the runtime used to execute Lean programs guarantees that an array cannot have more than 2^64 (2^32) elements
in a 64-bit (32-bit) machine. We can take advantage of this fact to provide a more efficient implementation for
array functions. However, the efficient version would not be very useful if it can only be used in
unsafe code. Thus, Lean 4 provides the attribute `@[implementedBy functionName]`. The idea is to provide
unsafe code. Thus, Lean 4 provides the attribute `@[implemented_by functionName]`. The idea is to provide
an unsafe (and potentially more efficient) version of a safe definition or constant. The function `f`
at the attribute `@[implementedBy f]` is very similar to an extern/foreign function,
at the attribute `@[implemented_by f]` is very similar to an extern/foreign function,
the key difference is that it is implemented in Lean itself. Again, the logical soundness of the system
cannot be compromised by using the attribute `implementedBy`, but if the implementation is incorrect your
cannot be compromised by using the attribute `implemented_by`, but if the implementation is incorrect your
program may crash at runtime. In the following example, we define `withPtrUnsafe a k h` which
executes `k` using the memory address where `a` is stored in memory. The argument `h` is proof
that `k` is a constant function. Then, we "seal" this unsafe implementation at `withPtr`. The proof `h`
@@ -340,8 +342,7 @@ partial def f (x : Nat) : IO Unit := do
These are changes to the library which may trip up Lean 3 users:
-`Option` and `List` are no longer monads. Instead there is `OptionM`. This was done to avoid some performance traps. For example `o₁ <|> o₂` where `o₁ o₂ : Option α` will evaluate both `o₁` and `o₂` even if `o₁` evaluates to `some x`. This can be a problem if `o₂` requires a lot of compute to evaluate. A zulip discussion on this design choice is [here](https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Option.20do.20notation.20regression.3F).
While [Nix](https://nixos.org/nix/) can be used to quickly open a shell with all dependencies for the [standard setup](index.md) installed, the user-facing [Nix Setup](../setup.md#nix-setup) can also be used to work *on* Lean.
## Setup
Follow the setup in the link above; to open the Lean shell inside a Lean checkout, you can also use
```bash
# in the Lean root directory
$ nix-shell -A nix
```
On top of the local and remote Nix cache, we do still rely on CCache as well to make C/C++ build steps incremental, which are atomic steps from Nix's point of view.
To enable CCache, add the following line to the config file mentioned in the setup:
```bash
extra-sandbox-paths = /nix/var/cache/ccache
```
Then set up that directory as follows:
```bash
sudo mkdir -m0770 -p /nix/var/cache/ccache
# macOS standard chown doesn't support --reference
From the Lean root directory inside the Lean shell:
```bash
nix build .#stage1 # build this stage's stdlib & executable
nix build .#stage1.test # run all tests
nix run .#stage1.update-stage0 # update ./stage0 from this stage
nix run .#stage1.update-stage0-commit # ...and commit the results
```
The `stage1.` part in each command is optional:
```bash
nix build .#test # run tests for stage 1
nix build . # build stage 1
nix build # ditto
```
## Build Process Description
The Nix build process conceptually works the same as described in [Lean Build Pipeline](index.md#lean-build-pipeline).
However, there are two important differences in practice apart from the standard Nix properties (hermeneutic, reproducible builds stored in a global hash-indexed store etc.):
* Only files tracked by git (using `git add` or at least `git add --intent-to-add`) are compiled.
This is actually a general property of Nix flakes, and has the benefit of making it basically impossible to forget to commit a file (at least in `src/`).
* Only files reachable from `src/Lean.lean` are compiled.
This is because modules are discovered not from a directory listing anymore but by recursively compiling all dependencies of that top module.
## Editor Integration
As in the standard Nix setup.
After adding `src/` as an LSP workspace, it should automatically fall back to using stage 0 in there.
Note that the UX of `{emacs,vscode}-dev` is quite different from the Make-based setup regarding the compilation of dependencies:
there is no mutable directory incrementally filled by the build that we could point the editor at for .olean files.
Instead, `emacs-dev` will gather the individual dependency outputs from the Nix store when checking a file -- and build them on the fly when necessary.
However, it will only ever load changes saved to disk, not ones opened in other buffers.
The absence of a mutable output directory also means that the Lean server will not automatically pick up `.ilean` metadata from newly compiled files.
Instead, you can run `nix run .#link-ilean` to symlink the `.ilean` tree of the stdlib state at that point in time to `src/build/lib`, where the server should automatically find them.
## Other Fun Stuff to Do with Nix
Open Emacs with Lean set up from an arbitrary commit (without even cloning Lean beforehand... if your Nix is new enough):
```bash
nix run github:leanprover/lean4/7e4edeb#emacs-package
```
Open a shell with `lean` and `LEAN_PATH` set up for compiling a specific module (this is exactly what `emacs-dev` is doing internally):
```bash
nix develop .#mods.\"Lean.Parser.Basic\"
# alternatively, directly pass a command to execute:
Here we changed the `user` in the `Environment` context to "new user" and then we passed that
modified context to `readerFunc2`.
So `withReader f m` executes monad `m` in the `ReaderM` context modified by `f`.
## Handy shortcut with (← e)
If you use the operator `←` in a let expression and the variable is only used once you can
eliminate the let expression and place the `←` operator in parentheses like this
call to loadEnv:
-/
defmain3:IOUnit:=do
letstr:=readerFunc3(←loadEnv)
IO.printlnstr
/-!
## Conclusion
It might not seem like much has been accomplished with this `ReaderM Environment` monad, but you will
find that in larger code bases, with many different types of monads all composed together this
greatly cleans up the code. Monads provide a beautiful functional way of managing cross-cutting
concerns that would otherwise make your code very messy.
Having this control over the inherited `ReaderM` context via `withReader` is actually very useful
and something that is quite messy if you try and do this sort of thing with global variables, saving
the old value, setting the new one, calling the function, then restoring the old value, making sure
you do that in a try/finally block and so on. The `ReaderM` design pattern avoids that mess
entirely.
Now it's time to move on to [StateM Monad](states.lean.md) which is like a `ReaderM` that is
also updatable.
-/
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.