Commit graph

7857 commits

Author SHA1 Message Date
Leonardo de Moura
84b0919a11 feat: type of theorems must be propositions 2024-03-13 12:37:58 -07:00
Leonardo de Moura
600412838c
fix: auxiliary definition nested in theorem should be def if its type is not a proposition (#3662) 2024-03-13 09:38:37 +00:00
Joachim Breitner
a81205c290
feat: conv => calc (#3659)
`calc` is great for explicit rewriting, `conv` is great to say where to
rewrite, so it's natural to want `calc` as a `conv` tactic.

Zulip disucssion at
https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/idiom.20for.20using.20calc.20to.20rewrite.20the.20goal/near/424269608

Fixes #3557.
2024-03-13 09:03:39 +00:00
Leonardo de Moura
2003814085
chore: rename automatically generated equational theorems (#3661)
cc @nomeata
2024-03-13 07:56:27 +00:00
Scott Morrison
317adf42e9
chore: add @[simp] to Nat.succ_eq_add_one, and cleanup downstream (#3579) 2024-03-13 05:35:52 +00:00
Leonardo de Moura
5aca09abca
fix: add Canonicalizer.lean and use it to canonicalize terms in omega (#3639) 2024-03-12 23:18:56 +00:00
Joachim Breitner
07dac67847
feat: guard_msgs to escapes trailing newlines (#3617)
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
2024-03-12 16:35:14 +00:00
Joachim Breitner
32dcc6eb89
feat: GuessLex: avoid writing sizeOf in termination argument when not needed (#3630)
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.
2024-03-10 22:57:10 +00:00
Kyle Miller
45fccc5906
feat: custom eliminators for induction and cases tactics, and beautiful eliminators for Nat (#3629)
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.
2024-03-09 15:31:51 +00:00
Kyle Miller
3acd77a154
fix: make elabTermEnsuringType respect errToSorry when there is a type mismatch (#3633)
Floris van Doorn [reported on
Zulip](https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/have.20tactic.20error.20recovery/near/425283053)
that it is confusing that the `have : T := e` tactic completely fails if
the body `e` is not of type `T`. This is in contrast to `have : T := by
exact e`, which does not completely fail when `e` is not of type `T`.

This ends up being caused by `elabTermEnsuringType` throwing an error
when it fails to insert a coercion. Now, it detects this case, and it
checks the `errToSorry` flag to decide whether to throw the error or to
log the error and insert a `sorry`.

This is justified by `elabTermEnsuringType` being a frontend to
`elabTerm`, which inserts `sorry` on error.

An alternative would be to make `ensureType` respect `errToSorry`, but
there exists code that expects being able to catch when `ensureType`
fails. Making such code manipulate `errToSorry` seems error prone, and
this function is not a main entry point to the term elaborator, unlike
`elabTermEnsuringType`.
2024-03-09 15:30:47 +00:00
Leonardo de Moura
b39042b32c
fix: eta-expanded instances at SynthInstance.lean (#3638)
Remark: this commit removes the `jason1.lean` test. Motivation: It
breaks all the time due to changes we make, and it is not clear anymore
what it is testing.

---------

Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>
2024-03-08 20:37:38 +00:00
Kyle Miller
f336525f31
fix: make delabConstWithSignature avoid using inaccessible names (#3625)
The `delabConstWithSignature` delaborator is responsible for pretty
printing constants with a declaration-like signature, with binders, a
colon, and a type. This is used by the `#check` command when it is given
just an identifier.

It used to accumulate binders from pi types indiscriminately, but this
led to unfriendly behavior. For example, `#check String.append` would
give
```
String.append (a✝ : String) (a✝¹ : String) : String
```
with inaccessible names. These appear because `String.append` is defined
using patterns, so it never names these parameters.

Now the delaborator stops accumulating binders once it reaches an
inaccessible name, and for example `#check String.append` now gives
```
String.append : String → String → String
```
We do not synthesize names for the sake of enabling binder syntax
because the binder names are part of the API of a function — one can use
`(arg := ...)` syntax to pass arguments by name. The delaborator also
now stops accumulating binders once it reaches a parameter with a name
already seen before — we then rely on the main delaborator to provide
that parameter with a fresh name when pretty printing the pi type.

As a special case, instance parameters with inaccessible names are
included as binders, pretty printing like `[LT α]`, rather than
relegating them (and all the remaining parameters) to after the colon.
It would be more accurate to pretty print this as `[inst✝ : LT α]`, but
we make the simplifying assumption that such instance parameters are
generally used via typeclass inference. Likely `inst✝` would not
directly appear in pretty printer output, and even if it appears in a
hover, users can likely figure out what is going on. (We may consider
making such `inst✝` variables pretty print as `‹LT α›` or
`infer_instance` in the future, to make this more consistent.)

Something we note here is that we do not do anything to make sure
parameters that can be used as named arguments actually appear named
after the colon (nor do we assure that the names are the correct names).
For example, one sees `foo : String → String → String` rather than `foo
: String → (baz : String) → String`. We can investigate this later if it
is wanted.

We also give `delabConstWithSignature` a `universes` flag to enable
turning off pretty printing universe levels parameters.

Closes #2846
2024-03-07 18:14:06 +00:00
Leonardo de Moura
611b174689
fix: ofScientific at simp (#3628)
closes #2159
2024-03-07 00:11:31 +00:00
Leonardo de Moura
ef33882e2f test: issue #2835
closes #2835
2024-03-06 15:29:04 -08:00
Leonardo de Moura
5302b7889a
fix: fold raw Nat literals at dsimp (#3624)
closes #2916

Remark: this PR also renames `Expr.natLit?` ==> `Expr.rawNatLit?`.
Motivation: consistent naming convention: `Expr.isRawNatLit`.
2024-03-06 18:29:20 +00:00
Joachim Breitner
0072d13bd4
feat: MatcherApp.transform: Try to preserve alt’s variable name (#3620)
this makes the ugly `fst`/`snd` variable names in the functional
induction principles go away.

Ironically I thought in order to fix these name, I should touch the
mutual/n-ary argument packing code used for well-founded recursion, and
embarked on a big refactor/rewrite of that code, only to find that at
least this particular instance of the issue was somewhere else. Hence
breaking this into its own PR; the refactoring will follow (and will
also improve some other variable names.)
2024-03-06 15:56:17 +00:00
Leonardo de Moura
09bc477016
feat: better support for reducing Nat.rec (#3616)
closes #3022

With this commit, given the declaration
```
def foo : Nat → Nat
  | 0 => 2
  | n + 1 => foo n
```
when we unfold `foo (n+1)`, we now obtain `foo n` instead of `foo
(Nat.add n 0)`.
2024-03-06 13:28:07 +00:00
Leonardo de Moura
794228a982
refactor: Offset.lean and related files (#3614)
Motivation: avoid the unfold and check idiom.
This commit also minimize dependencies at `Offset.lean`.

closes #2615
2024-03-05 19:40:15 -08:00
Leonardo de Moura
acdb0054d5 feat: use dsimprocs at dsimp 2024-03-05 14:42:05 -08:00
Leonardo de Moura
436d7befa5
fix: dsimp should reduce kernel projections (#3607)
closes #3395
2024-03-05 14:56:27 +00:00
Joachim Breitner
8038604d3e
feat: functional induction (#3432)
This adds the concept of **functional induction** to lean.

Derived from the definition of a (possibly mutually) recursive function,
a **functional
induction principle** is tailored to proofs about that function. For
example from:

```
def ackermann : Nat → Nat → Nat
  | 0, m => m + 1
  | n+1, 0 => ackermann n 1
  | n+1, m+1 => ackermann n (ackermann (n + 1) m)
derive_functional_induction ackermann
```
we get
```
ackermann.induct (motive : Nat → Nat → Prop) (case1 : ∀ (m : Nat), motive 0 m)
  (case2 : ∀ (n : Nat), motive n 1 → motive (Nat.succ n) 0)
  (case3 : ∀ (n m : Nat), motive (n + 1) m → motive n (ackermann (n + 1) m) → motive (Nat.succ n) (Nat.succ m))
  (x x : Nat) : motive x x
```

At the moment, the user has to ask for the functional induction
principle explicitly using
```
derive_functional_induction ackermann
```

The module docstring of `Lean/Meta/Tactic/FunInd.lean` contains more
details on the
design and implementation of this command.

More convenience around this (e.g. a `functional induction` tactic) will
follow eventually.


This PR includes a bunch of `PSum`/`PSigma` related functions in the
`Lean.Tactic.FunInd`
namespace. I plan to move these to `PackArgs`/`PackMutual` afterwards,
and do some cleaning
up as I do that.

---------

Co-authored-by: David Thrane Christiansen <david@davidchristiansen.dk>
Co-authored-by: Leonardo de Moura <leomoura@amazon.com>
2024-03-05 13:02:05 +00:00
Joe Hendrix
01104cc81e
chore: bool and prop lemmas for Mathlib compatibility and improved confluence (#3508)
This adds a number of lemmas for simplification of `Bool` and `Prop`
terms. It pulls lemmas from Mathlib and adds additional lemmas where
confluence or consistency suggested they are needed.

It has been tested against Mathlib using some automated test
infrastructure.

That testing module is not yet included in this PR, but will be included
as part of this.

Note. There are currently some comments saying the origin of the simp
rule. These will be removed prior to merging, but are added to clarify
where the rule came from during review.

---------

Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
2024-03-04 23:56:30 +00:00
Leonardo de Moura
37450d47e2
fix: bug at elimOptParam (#3595)
`let_expr` uses `cleanupAnnotations` which consumes `optParam` type
annotations.

cc @nomeata
2024-03-04 23:56:00 +00:00
Leonardo de Moura
bba4ef3728
feat: simprocs for folding numeric literals (#3586)
This PR folds exposed `BitVec` (`Fin`, `UInt??`, and `Int`) ground
literals.
cc @shigoel
2024-03-04 02:51:04 +00:00
Leonardo de Moura
8689a56a5d
feat: #print equations <decl-name> command (#3584) 2024-03-04 02:32:20 +00:00
Kyle Miller
acb1b09fbf
fix: expression tree elaborator for relations now localizes error messages to the LHS or RHS (#3442)
Added `withRef` when processing the LHS or RHS. Without this, in an
expression such as `true = ()` the entire expression would be
highlighted with "type mismatch, `()` has type `Unit` but is expected to
have type `Bool`". Now the error is localized to `()`.

This behavior was pointed out [on
Zulip](https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/error.20location.20bug/near/422665805).
2024-03-04 00:53:32 +00:00
Leonardo de Moura
9f305fb31f
fix: rename_i in macro (#3581)
closes #3553

Co-authored-by: Sebastian Ullrich <sebasti@nullri.ch>
2024-03-03 19:05:37 +00:00
Leonardo de Moura
a4d41beab1
perf: match_expr join points (#3580)
We use `let_delayed` to elaborate `match_expr` join points, which
elaborate the body of the `let` before its value. Thus, there is a
difference between:
- `let_delayed f (x : Expr) := <val>; <body>`
- `let_delayed f := fun (x : Expr) => <val>; <body>`

In the latter, when `<body>` is elaborated, the elaborator does not know
that `f` takes an argument of type `Expr`, and that `f` is a function.
Before this commit ensures the former representation is used.
2024-03-03 18:15:49 +00:00
Leonardo de Moura
95f28be088
fix: generalize excessive resource usage (#3575)
closes #3524
2024-03-03 17:58:11 +00:00
Leonardo de Moura
c66c5bb45b
fix: simp? suggests generated equations lemma names (#3573)
closes #3547

---------

Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>
2024-03-02 23:59:35 +00:00
Leonardo de Moura
870de4322c
fix: missing atomic at match_expr parser (#3572) 2024-03-02 21:55:07 +00:00
Leonardo de Moura
826f0580a6 fix: propagate expected type at do-match_expr 2024-03-02 10:07:15 -08:00
Leonardo de Moura
17e498c11f feat: expand let_expr macros 2024-03-02 08:16:18 -08:00
Leonardo de Moura
ecfaf8f3e7 feat: add let_expr notation 2024-03-02 08:16:18 -08:00
Leonardo de Moura
7a27b04d50 feat: monadic match_expr 2024-03-01 22:33:14 -08:00
Sebastian Ullrich
61fba365f2
fix: revert shared library split on non-Windows platforms (#3529)
Avoids the performance hit and fixes #3528.
2024-02-29 19:15:01 +00:00
Joe Hendrix
b9f9ce874d
chore: have library search drop star only symbols (#3534)
Co-authored-by: David Thrane Christiansen <david@davidchristiansen.dk>
2024-02-29 07:09:02 +00:00
Scott Morrison
819a32a9eb chore: upstream show_term
add missing prelude
2024-02-29 17:34:15 +11:00
Scott Morrison
755de48ff3
chore: upstream orphaned tests from Std (#3539) 2024-02-29 04:12:52 +00:00
Leonardo de Moura
37cd4cc996
fix: match-expression when patterns cover all cases of a BitVec finite type (#3538) 2024-02-29 02:24:47 +00:00
Joe Hendrix
9afca1c3a9
feat: port check_tactic commands from Std and add test cases (#3532)
This also adds several Array lemmas from std after cleaning up proofs
2024-02-28 23:32:54 +00:00
Leonardo de Moura
e1acdcd339
fix: get_elem_tactic_trivial regression (#3531) 2024-02-28 23:14:15 +00:00
Scott Morrison
dc4c2b14d3 chore: begin moving orphaned tests from Std 2024-02-29 10:54:19 +11:00
Joe Hendrix
2312c15ac6
chore: port librarySearch tests from std (#3530)
Needed List.partitionMap for test to complete, so ported it too.
2024-02-28 17:24:17 +00:00
Joachim Breitner
fa058ed228
fix: include let bindings when determining altParamNums for eliminators (#3505)
Else the `case` will now allow introducing all necessary variables.

Induction principles with `let` in the types of the cases will be more
common with #3432.

This implementation no longer reduces the type as it goes, but really
only counts
manifest foralls and lets. I find this more sensible and predictable: If
you have
```
theorem induction₂_symm {P : EReal → EReal → Prop} (symm : Symmetric P) …
```
then previously, writing
```
case symm => 
```
would actually bring a fresh `x` and `y` and variable `h : P x y` into
scope and produce a
goal of `P y x`, because `Symmetric P` happens to be
```
def Symmetric := ∀ ⦃x y⦄, x ≺ y → y ≺ x
```

After this change, after `case symm =>` will leave `Symmetric P` as the
goal.

This gives more control to the author of the induction hypothesis about
the actual
goal of the cases. This shows up in mathlib in two places; fixes in
https://github.com/leanprover-community/mathlib4/pull/11023.
I consider these improvements.
2024-02-28 13:14:34 +00:00
Joachim Breitner
b9c4a7e51d
feat: termination_by? (#3514)
the user can now write `termination_by?` to see the termination argument
inferred by GuessLex, and turn it into `termination_by …` using the “Try
this” widget or a code action.

To be done later, maybe: Avoid writing `sizeOf` if it's not necessary.
2024-02-28 10:53:17 +00:00
Kyle Miller
08e149de15 fix: make omission syntax be a builtin syntax (part 2)
Re-enables `⋯` processing that was disabled during the move to a builtin.
Adds tests.
2024-02-28 09:23:17 +01:00
Leonardo de Moura
a23292f049
feat: add option tactic.skipAssignedInstances := true for backward compatibilty (#3526)
When using `set_option tactic.skipAssignedInstances false`, `simp` and
`rw` will synthesize instance implicit arguments even if they have
assigned by unification. If the synthesized argument does not match the
assigned one the rewrite is not performed. This option has been added
for backward compatibility.
2024-02-28 05:52:29 +00:00
Scott Morrison
7cce64ee70
feat: omega doesn't check for defeq atoms (#3525)
```
example (a : Nat) :
    (((a + (2 ^ 64 - 1)) % 2 ^ 64 + 1) * 8 - 1 - (a + (2 ^ 64 - 1)) % 2 ^ 64 * 8 + 1) = 8 := by
  omega
```
used to time out, and now is fast.

(We will probably make separate changes later so the defeq checks would
be fast in any case here.)
2024-02-28 05:41:29 +00:00
Leonardo de Moura
86ca8e32c6
feat: improve simp discharge trace messages (#3523) 2024-02-28 04:39:57 +00:00