This PR is a followup to #8449 to refine the syntax of `clear_value`. The syntax for adding equality hypotheses before clearing values is now `clear_value (h : x = _)`. Any expression definitionally equal to `x` can be used in place of the underscore. This syntax was developed in a [Zulip discussion](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/.60clear_value.60.20syntax.20request.20for.20comments/near/520704290).
349 lines
6.3 KiB
Text
349 lines
6.3 KiB
Text
/-!
|
||
# Tests for `clear_value` tactic
|
||
-/
|
||
|
||
/-!
|
||
Check that `clear_value` clears the value.
|
||
-/
|
||
/--
|
||
trace: x : Nat
|
||
⊢ 0 ≤ x
|
||
-/
|
||
#guard_msgs in
|
||
example : let x := 22; 0 ≤ x := by
|
||
intro x
|
||
clear_value x
|
||
trace_state
|
||
exact Nat.zero_le _
|
||
|
||
/-!
|
||
Test `*` mode.
|
||
-/
|
||
/--
|
||
trace: x : Nat
|
||
⊢ 0 ≤ x
|
||
-/
|
||
#guard_msgs in
|
||
example : let x := 22; 0 ≤ x := by
|
||
intro x
|
||
clear_value *
|
||
trace_state
|
||
exact Nat.zero_le _
|
||
|
||
/-!
|
||
Double `*` is not allowd.
|
||
-/
|
||
/-- error: Multiple `*` arguments provided. -/
|
||
#guard_msgs in
|
||
example : let x := 22; 0 ≤ x := by
|
||
intro x
|
||
clear_value * *
|
||
|
||
/-!
|
||
Check that `clear_value` fails if there is no value to clear.
|
||
-/
|
||
/-- error: Hypothesis `x` is not a local definition. -/
|
||
#guard_msgs in
|
||
example (x : Nat) : 0 ≤ x := by
|
||
clear_value x
|
||
|
||
/-!
|
||
Check that `clear_value *` fails if it does nothing.
|
||
-/
|
||
/--
|
||
error: Tactic `clear_value` failed to clear any values.
|
||
x : Nat
|
||
⊢ 0 ≤ x
|
||
-/
|
||
#guard_msgs in
|
||
example (x : Nat) : 0 ≤ x := by
|
||
clear_value *
|
||
|
||
/-!
|
||
Check for validation that hypotheses aren't mentioned multiple times.
|
||
-/
|
||
/-- error: Hypothesis `x` appears multiple times. -/
|
||
#guard_msgs in
|
||
example : let x := 22; 0 ≤ x := by
|
||
intro x
|
||
clear_value x x
|
||
|
||
/-!
|
||
Check that `clear_value (h : x = _)` creates an equality hypothesis.
|
||
-/
|
||
/--
|
||
trace: x : Nat
|
||
h : x = 22
|
||
⊢ 0 ≤ x
|
||
-/
|
||
#guard_msgs in
|
||
example : let x := 22; 0 ≤ x := by
|
||
intro x
|
||
clear_value (h : x = _)
|
||
trace_state
|
||
rw [h]
|
||
exact Nat.zero_le _
|
||
|
||
/-!
|
||
Can use any term that is definitionally equal to the term.
|
||
-/
|
||
/--
|
||
trace: x : Nat
|
||
h : x = 12 + 10
|
||
⊢ 0 ≤ x
|
||
-/
|
||
#guard_msgs in
|
||
example : let x := 22; 0 ≤ x := by
|
||
intro x
|
||
clear_value (h : x = 12 + 10)
|
||
trace_state
|
||
rw [h]
|
||
exact Nat.zero_le _
|
||
|
||
/-!
|
||
There is no restriction on the value, except that it can't depend on the values being cleared.
|
||
-/
|
||
/--
|
||
trace: x : Nat
|
||
h : x = x
|
||
⊢ 0 ≤ x
|
||
-/
|
||
#guard_msgs in
|
||
example : let x := 22; 0 ≤ x := by
|
||
intro x
|
||
clear_value (h : x = x)
|
||
trace_state
|
||
rw [h]
|
||
exact Nat.zero_le _
|
||
|
||
/-!
|
||
Failure because it depends on the value.
|
||
-/
|
||
/--
|
||
error: Tactic `clear_value` failed, the value of `x` cannot be cleared.
|
||
x : Nat := 22
|
||
h : x = 22 + ↑0
|
||
⊢ 0 ≤ x
|
||
-/
|
||
#guard_msgs in
|
||
example : let x := 22; 0 ≤ x := by
|
||
intro x
|
||
clear_value (h : x = 22 + (0 : Fin x))
|
||
trace_state
|
||
rw [h]
|
||
exact Nat.zero_le _
|
||
|
||
/-!
|
||
Unifies the term.
|
||
-/
|
||
/--
|
||
trace: x : Nat
|
||
h : x = id 22
|
||
⊢ 0 ≤ x
|
||
-/
|
||
#guard_msgs in
|
||
example : let x := 22; 0 ≤ x := by
|
||
intro x
|
||
clear_value (h : x = id _)
|
||
trace_state
|
||
rw [h]
|
||
exact Nat.zero_le _
|
||
|
||
/-!
|
||
Error if provided term is not defeq.
|
||
-/
|
||
/--
|
||
error: Provided term
|
||
23
|
||
is not definitionally equal to
|
||
x := 22
|
||
-/
|
||
#guard_msgs in
|
||
example : let x := 22; 0 ≤ x := by
|
||
intro x
|
||
clear_value (h : x = 23)
|
||
|
||
/-!
|
||
Error if unification does not solve all metavariables.
|
||
-/
|
||
/--
|
||
error: don't know how to synthesize placeholder for argument 'e'
|
||
context:
|
||
x : Nat := ⋯
|
||
⊢ Nat
|
||
---
|
||
error: unsolved goals
|
||
x : Nat := 22
|
||
⊢ 0 ≤ x
|
||
-/
|
||
#guard_msgs in
|
||
example : let x := 22; 0 ≤ x := by
|
||
intro x
|
||
clear_value (h : x = if True then _ else _)
|
||
|
||
/-!
|
||
Check `clear_value` with `_` for binder for equality hypothesis.
|
||
-/
|
||
/--
|
||
trace: x : Nat
|
||
h✝ : x = 22
|
||
⊢ 0 ≤ 22
|
||
-/
|
||
#guard_msgs in
|
||
example : let x := 22; 0 ≤ x := by
|
||
intro x
|
||
clear_value (_ : x = _)
|
||
rw [‹x = 22›]
|
||
trace_state
|
||
exact Nat.zero_le _
|
||
|
||
/-!
|
||
Check that `clear_value` checks for type correctness.
|
||
-/
|
||
/--
|
||
error: Tactic `clear_value` failed, the value of `x` cannot be cleared.
|
||
x : Nat := 22
|
||
y : Fin x := 0
|
||
⊢ ↑y < x
|
||
-/
|
||
#guard_msgs in
|
||
example : let x := 22; let y : Fin x := 0; y.1 < x := by
|
||
intro x y
|
||
clear_value x
|
||
|
||
/-!
|
||
Even though we cannot clear `x` on its own, we can clear it if we clear `y` first.
|
||
-/
|
||
/--
|
||
trace: x : Nat
|
||
y : Fin x
|
||
⊢ ↑y < x
|
||
-/
|
||
#guard_msgs in
|
||
example : let x := 22; let y : Fin x := 0; y.1 < x := by
|
||
intro x y
|
||
clear_value y
|
||
clear_value x
|
||
trace_state
|
||
exact y.2
|
||
|
||
/-!
|
||
We can clear the values `x` and `y` in any order.
|
||
-/
|
||
/--
|
||
trace: x : Nat
|
||
y : Fin x
|
||
⊢ ↑y < x
|
||
-/
|
||
#guard_msgs in
|
||
example : let x := 22; let y : Fin x := 0; y.1 < x := by
|
||
intro x y
|
||
clear_value y x
|
||
trace_state
|
||
exact y.2
|
||
/--
|
||
trace: x : Nat
|
||
y : Fin x
|
||
⊢ ↑y < x
|
||
-/
|
||
#guard_msgs in
|
||
example : let x := 22; let y : Fin x := 0; y.1 < x := by
|
||
intro x y
|
||
clear_value x y
|
||
trace_state
|
||
exact y.2
|
||
|
||
/-!
|
||
Clearing `x` on its own and `y` on its own are OK because `y + 1` is nonzero.
|
||
-/
|
||
/--
|
||
trace: x y : Nat
|
||
z : Fin (y + 1) := 0
|
||
⊢ ↑z < y + 1
|
||
-/
|
||
#guard_msgs in
|
||
example : let x := 22; let y : Nat := x; let z : Fin (y + 1) := 0; z.1 < y + 1 := by
|
||
intro x y z
|
||
clear_value x
|
||
clear_value y
|
||
trace_state
|
||
exact z.2
|
||
|
||
/-!
|
||
Dependence, `clear_value` fails.
|
||
-/
|
||
/--
|
||
error: Tactic `clear_value` failed, the value of `α` cannot be cleared.
|
||
α : Type := Nat
|
||
x : α := 1
|
||
⊢ x = x
|
||
-/
|
||
#guard_msgs in
|
||
example : let α := Nat; let x : α := 1; @Eq α x x := by
|
||
intro α x
|
||
clear_value α
|
||
|
||
/-!
|
||
`clear_value *` manages to clear `x` but not `α`
|
||
-/
|
||
/--
|
||
trace: α : Type := Nat
|
||
x : α
|
||
⊢ x = 1
|
||
---
|
||
warning: declaration uses 'sorry'
|
||
-/
|
||
#guard_msgs in
|
||
example : let α := Nat; let x : α := 1; @Eq α x 1 := by
|
||
intro α x
|
||
clear_value *
|
||
trace_state
|
||
sorry
|
||
|
||
/-!
|
||
`clear_value *` fails if `x` is already cleared
|
||
-/
|
||
/--
|
||
error: Tactic `clear_value` failed to clear any values.
|
||
α : Type := Nat
|
||
x : α
|
||
⊢ x = 1
|
||
-/
|
||
#guard_msgs in
|
||
example : let α := Nat; let x : α := 1; @Eq α x 1 := by
|
||
intro α x
|
||
clear_value x
|
||
clear_value *
|
||
|
||
/-!
|
||
Can use `*` along with `(h : x = _)`.
|
||
-/
|
||
#guard_msgs in
|
||
example : let α := Nat; let x : α := 1; @Eq α x 1 := by
|
||
intro α x
|
||
clear_value (h : x = _) *
|
||
exact h
|
||
|
||
/-!
|
||
Minimized from https://github.com/leanprover-community/mathlib4/issues/25053
|
||
The issue is that `by exact k` under the binder creates a delayed assigned metavariable
|
||
```
|
||
?m : ℕ →
|
||
let val := 22;
|
||
val = 22 → ℕ → ℕ
|
||
```
|
||
that is applied to `val` and `val_def`. Note that this first `ℕ` corresponds to `val`,
|
||
so, despite the fact that the local context of the metavariable delayed assigned to `?m`
|
||
has `val` as a let binding, the value is still being passed in (the types are *not* ensuring
|
||
that `val` is defeq to the expected `val`!)
|
||
|
||
In this case, we can fix the issue by making sure to instantiate metavariables before running
|
||
`isTypeCorrect`.
|
||
-/
|
||
example : True := by
|
||
let val := 22
|
||
have val_def : val = 22 := rfl
|
||
have : Nat.zero = (fun k => by exact k) Nat.zero := by
|
||
clear_value val -- used to fail
|
||
rfl
|
||
trivial
|