Adds an alternative TOML configuration format to Lake.
* Uses TOML v1.0.0 and is fully specification compliant (tested via
[toml-test v1.4.0](https://github.com/toml-lang/toml-test/tree/v1.4.0)).
* Supports package configuration options, Lean libraries, Lean
executables, and dependencies.
* TOML configurations can be generated for new projects via `lake
new|init <pkg> <template>.toml`.
* Supported configurations can be converted to/from TOML via `lake
translate-config <lang>`.
This makes changes to the `GetElem` class so that it does not lead to
unnecessary overhead in container like `RBMap`.
The changes are to:
1. Make `getElem?` and `getElem!` part of the `GetElem` class so they
can be overridden in instances.
2. Introduce a `LawfulGetElem` class that contains correctness theorems
for `getElem?` and `getElem!` using the original definitions.
3. Reorganize definitions (e.g, by moving `GetElem` out of
`Init.Prelude`) so that the `GetElem` changes are feasible.
4. Provide `LawfulGetElem` instances to complement all existing
`GetElem` instances in Lean core.
To reduce the size of the PR, this doesn't do the work of providing new
`GetElem` instances for `RBMap`, `HashMap` etc. That will be done in a
separate PR (#3688) that depends on this.
---------
Co-authored-by: Mac Malone <tydeu@hatpress.net>
fixes#3657
These functions are mostly not used by lean itself, but it does affect
two occurrences of `ByteArray.toUInt64LE! <$> IO.getRandomBytes 8` which
I left as is instead of switching them to use `toUInt64BE!` to preserve
behavior; but they are random bytes anyway seeded by the OS so it's
unlikely any use of them depending on particular values was sound to
begin with.
Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
Previously:
If the `rfl` macro was going to fail, it would:
1. expand to `eq_refl`, which is implemented by
`Lean.Elab.Tactic.evalRefl`, and call `Lean.MVarId.refl` which would:
* either try kernel defeq (if in `.default` or `.all` transparency mode)
* otherwise try `IsDefEq`
* then fail.
2. Next expand to the `apply_rfl` tactic, which is implemented by
`Lean.Elab.Tactic.Rfl.evalApplyRfl`, and call `Lean.MVarId.applyRefl`
which would look for lemmas labelled `@[refl]`, and unfortunately in
Mathlib find `Eq.refl`, so try applying that (resulting in another
`IsDefEq`)
3. Because of an accidental duplication, if `Lean.Elab.Tactic.Rfl` was
imported, it would *again* expand to `apply_rfl`.
Now:
1. Same behaviour in `eq_refl`.
2. The `@[refl]` attribute will reject `Eq.refl`, and `MVarId.applyRefl`
will fail when applied to equality goals.
3. The duplication has been removed.
This makes several changes to rw? and lazy discrimination trees based on
test failures in rewrite search.
Changes include:
1. Reverting to Mathlib function for candidate lemma priority in rw?
2. Introducing additional filters for auto-generated named in lazy
discriminator tree.
3. Refactoring lazy discriminator values to clarify what is stored.
4. Including star keys in calculation of match closeness in
prioritization.
5. Using more fields in current core context when initializing lazy
discriminator tree and avoiding max heartbeat issues.
---------
Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
no need to enter `derive_functional_induction` anymore.
(Will remove the support for `derive_functional_induction` after the
next stage0 update, since we are already using it in Init.)
fixes#3770
Also start `rfl` with a `fail` message that is hopefully more helpful
than what we get now (see updated test output). This would be a cheaper
way to address #3302 without changing the implementation of rfl (as
tried in #3714).
This extends `derive_functional_induction` to work with structural
recursion as well.
It produces the less general, more concrete induction rule where the
induction hypothesis is
specialized for every argument of the recursive call, not just the the
one that the function
is recursing on.
Care is taken so that the induction principle and it's motive take the
arguments in the same
order as the original function.
While I was it, also makes sure that the order of the cases in the
induction principle matches
the order of recursive calls in the function better.
---------
Co-authored-by: David Thrane Christiansen <david@davidchristiansen.dk>
Co-authored-by: Leonardo de Moura <leomoura@amazon.com>
System.FilePath.parent did not return the correct parent path in the
case of absolute file paths
Example of previous behavior
```
(FilePath.mk "/foo").parent -> some (FilePath.mk "")
(System.FilePath.mk "/").parent -> some (FilePath.mk "")
```
The new behavior is based on rust's std::path::Path::parent function (as
previously described in comment in System.FilePath)
Example of updated behavior
```
(System.FilePath.mk "/foo").parent -> some (FilePath.mk "/")
(System.FilePath.mk "/").parent -> none
```
Behavior for relative file paths is unchanged
Closes#3618
Given a definition `foo`, they were previously called `foo._unfold`
until 4.7.0. We tried to rename them to `foo.def`, but it created too
many issues in the Mathlib repo. We decided to rename it again to
`foo.eq_def`. The new name is also consistent with the `eq_<idx>`
theorems generated for different "cases". That is, `foo.eq_def` is the
equality theorem for the whole definition, and `foo.eq_<idx>` is the
equality theorem for case `<idx>`.
cc @semorrison
Given
```lean
structure A where
x : Nat
structure B extends A where
y : Nat
```
rather than pretty printing `{ x := 1, y := 2 : B }` as `{ toA := { x :=
1 }, y := 2 }`, it now pretty prints as `{ x := 1, y := 2 }`.
The option `pp.structureInstances.flatten` controls whether to flatten
structure instances like this.
This updates the rw? tactic from Mathlib to use lazy discriminator trees
and upstreams it.
---------
Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
Sets the default value to `pp.fieldNotation.generalized` to `true`.
Updates tests, and fixes some minor flaws in the implementation of the
generalized field notation pretty printer.
Now generalized field notation won't be used for any function that has a
`motive` argument. This is intended to prevent recursors from pretty
printing using it as (1) recursors are more like control flow structures
than actual functions and (2) generalized field notation tends to cause
elaboration problems for recursors.
Note: be sure functions that have an `@[app_unexpander]` use
`@[pp_nodot]` if applicable. For example, `List.toArray` needs
`@[pp_nodot]` to ensure the unexpander prints it using `#[...]`
notation.
Refactors app delaborator, merging in the projection delaborator, to
support pretty printing with generalized field notation.
Renames option `pp.structureProjections` to `pp.fieldNotation` and adds
sub-option `pp.fieldNotation.generalized` to enable/disable generalized
field notation. Adds `@[pp_nodot]` attribute to permanently disable
using field notation for a given declaration.
For now, the default value of `pp.fieldNotation.generalized` is false
since we need a stage0 update to add `@[pp_nodot]` to some core
definitions (such as `List.toArray`) before updating the tests.
[Zulip
discussion](https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/.60pp.2EgeneralizedFieldNotation.60/near/425856054)
This attribute, which was implemented in #3640, is applied to the
following structures: `Sigma`, `PSigma`, `PProd`, `And`, `Subtype`, and
`Fin`. These were given this attribute in Lean 3.
This coercion caused difficult-to-diagnose bugs sometimes. Because there
are some situations where converting a string to a name should be done
by parsing the string, and others where it should not, an explicit
choice seems better here.
---------
Co-authored-by: Mac Malone <tydeu@hatpress.net>
This is a rewrite of the `UnusedVariables` lint to inline and simplify
many of the dependent functions to try to improve the performance of
this lint, which quite often shows up in perf reports.
* The mvar assignment scanning is one of the most expensive parts of the
process, so we do two things to improve this:
* Lazily perform the scan only if we need it
* Use an object-pointer hashmap to ensure that we don't have quadratic
behavior when there are many mvar assignments with slight differences.
* The dependency on `Lean.Server` is removed, meaning we don't need to
do the LSP conversion stuff anymore. The main logic of reference finding
is inlined.
* We take `fvarAliases` into account, and union together fvars which are
aliases of a base fvar. (It would be great if we had `UnionFind` here.)
More docs will be added once we confirm an actual perf improvement.
---------
Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
Closes#3706
This derive handler's implementation is very similar to `BEq`'s, which
already ignores unused alternative so as to work correctly on indexed
inductive types. This PR simply implements the same solution as the one
present in
[`BEq.lean`](2c15cdda04/src/Lean/Elab/Deriving/BEq.lean (L94)).
After some tests, it doesn't seem like any other derive handler present
in Core suffers from the same issue (though some handlers don't work on
indexed inductives for other reasons).
using the `substVars` tactic on the goal can remove too much
information, as it does not take into account that the `motive` may
depend on the fixed parameters.
This is fixed by etracting `substVar` from `subst` which expects the
`x`, not the `h : x = rhs`, and then using this tactic on the local
declarations _after_ the `motive` exclusively.
a common pattern for recursive functions is
```
def countUp (n i acc : Nat) : Nat :=
if i < n then
countUp n (i+1) (acc + i)
else
acc
```
where we increase a value `i` until it hits an upper bound. This is
particularly common with array processing functions:
```
$ git grep 'termination_by.*size.*-' src/|wc -l
26
```
GuessLex now recognizes this pattern. The general approach is:
For every recursive call, check if the context contains hypotheses of
the form `e₁ < e₂` (or similar comparisions), and then consider `e₂ -
e₁` as a termination argument.
Currently, this only fires when `e₁` and `e₂` only depend on the
functions parameters, but not local let-bindings or variables bound in
local pattern matches.
Duplicates are removed.
In the table showing the termination argument failures, long termination
arguments are now given a number and abbreviated as e.g. `#4` in the
table headers.
More examples in the test file, here as some highlights:
```
def distinct (xs : Array Nat) : Bool :=
let rec loop (i j : Nat) : Bool :=
if _ : i < xs.size then
if _ : j < i then
if xs[j] = xs[i] then
false
else
loop i (j+1)
else
loop (i+1) 0
else
true
loop 0 0
```
infers
```
termination_by (Array.size xs - i, i - j)
```
and the weird functions where `i` goes up or down
```
def weird (xs : Array Nat) (i : Nat) : Bool :=
if _ : i < xs.size then
if _ : 0 < i then
if xs[i] = 42 then
weird xs.pop (i - 1)
else
weird xs (i+1)
else
weird xs (i+1)
else
true
decreasing_by all_goals simp_wf; omega
```
infers
```
termination_by (Array.size xs - i, i)
```
but unfortunately needs `decreasing_by` pending the “big
decreasing_tactic refactor” that
I expect we’ll want to do at some point.
this refactor prepares GuessLex to be able to infer more complex
termination arguments.
As a side-effect it fixes an (obscure) bug where `sizeOf` would be
applied to a term of the wrong type and thus a wrong `SizeOf` instance
could be inferred.
On Windows, we now compile all core `.o`s twice, once with and without
`dllexport`, for use in the shipped dynamic and static libraries,
respectively. On other platforms, we export always as before to avoid
the duplicate work.
---------
Co-authored-by: tydeu <tydeu@hatpress.net>
- Add support for reserved declaration names. We use them for theorems
generated on demand.
- Equation theorems are not private declarations anymore.
- Generate equation theorems on demand when resolving symbols.
- Prevent users from creating declarations using reserved names. Users
can bypass it using meta-programming.
See next test for examples.
Before, the termination argument as inferred by `GuessLex` was passed
further
on as `Syntax`, to be elaborated later in `WF.Rel`.
This didn’t feel quite right anymore. In particular if we want to teach
`GuessLex` about guessing more complex termination arguments like
`xs.size -
i`, using `Expr` here is more natural.
So this introduces `TerminationArgument` based on an `Expr` to be used
here.
A side-effect of how the termination arguments are elaborated is that
the unused
variables linter will now look at `termination_by` variables, and that
parameters
past the colon are not even invisibly in scope, so `‹_›` will not find
them
See https://github.com/leanprover-community/mathlib4/pull/11370/files
for examples
of fixing these changes.
Fixes#1170.
This PR adds the module name to `RefIdent` in order to distinguish
conflicting names from different files. This also fixes related issues
in find-references or the call hierarchy feature.
It also adds some docstrings and stylistically refactors a bunch of
code.
This introduces the `ArgsPacker` module and abstraction, to replace the
exising `PackDomain`/`PackMutual` code. The motivation was that we now
have more uses besides `Fix.lean` (`GuessLex` and `FunInd`), and the
code was spread in various places.
The goals are
* consistent function naming withing the the `PSigma` handling, the
`PSum` handling, and the combined interface
* avoid taking a type apart just based on the `PSigma`/`PSum` nesting,
to be robust in case the user happens to be using `PSigma`/`PSum`
somewhere. Therefore, always pass an `arity` or `numFuncs` or `varNames`
around.
* keep all the `PSigma`/`PSum` encoding logic contained within one
module (`ArgsPacker`), and keep that module independent of its users (so
no `EqnInfos` visible here).
* pick good variable names when matching on a packed argument
* the unary function now is either called `fun1._unary` or
`fun1._mutual`, never `fun1._unary._mutual`.
This file has less heavy dependencies than `PackMutual` had, so build
parallelism is improved as well.
This makes trailing whitespace visible and protectes them against
trimming by the editor, by appending the symbol ⏎ to such a line (and
also to any line that ends with such a symbol, to avoid ambiguities in
the case the message already had that symbol).
(Only the code action output / docstring parsing is affected; the error
message as sent
to the InfoView is unaffected.)
Fixes#3571
this makes `termination_by?` even slicker.
The heuristics is agressive in the non-mutual case (will omit `sizeOf`
if the argument is non-dependent and the `WellFoundedRelation` relation
is via `sizeOfWFRel`.
In the mutual case we'd also have to check the arguments, as they line
up in the termination argument, have the same types. I did not bother at
this point; in the mutual case we omit `sizeOf` only if the argument
type is `Nat`.
As a drive-by fix, `termination_by?` now also works on functions that
have only one plausible measure.
Replaces `@[eliminator]` with two attributes `@[induction_eliminator]`
and `@[cases_eliminator]` for defining custom eliminators for the
`induction` and `cases` tactics, respectively.
Adds `Nat.recAux` and `Nat.casesAuxOn`, which are eliminators that are
defeq to `Nat.rec` and `Nat.casesOn`, but these use `0` and `n + 1`
rather than `Nat.zero` and `Nat.succ n`.
For example, using `induction` to prove that the factorial function is
positive now has the following goal states (thanks also to #3616 for the
goal state after unfolding).
```lean
example : 0 < fact x := by
induction x with
| zero => decide
| succ x ih =>
/-
x : Nat
ih : 0 < fact x
⊢ 0 < fact (x + 1)
-/
unfold fact
/-
...
⊢ 0 < (x + 1) * fact x
-/
simpa using ih
```
Thanks to @adamtopaz for initial work on splitting the `@[eliminator]`
attribute.