785 lines
15 KiB
Text
785 lines
15 KiB
Text
/-!
|
||
# Tests of the `extract_lets` tactic
|
||
-/
|
||
|
||
set_option linter.tactic.unusedName true
|
||
set_option linter.unusedVariables false
|
||
axiom test_sorry {α : Sort _} : α
|
||
|
||
/-!
|
||
Extract a top-level let, no names given.
|
||
-/
|
||
/--
|
||
trace: x✝ : Nat := 2
|
||
⊢ x✝ = 2
|
||
-/
|
||
#guard_msgs in
|
||
example : let x := 2; x = 2 := by
|
||
extract_lets
|
||
trace_state
|
||
rfl
|
||
|
||
/-!
|
||
Extract a top-level let, name given.
|
||
-/
|
||
/--
|
||
trace: z : Nat := 2
|
||
⊢ z = 2
|
||
-/
|
||
#guard_msgs in
|
||
example : let x := 2; x = 2 := by
|
||
extract_lets z
|
||
trace_state
|
||
rfl
|
||
|
||
/-!
|
||
Extract a top-level let, placeholder name given.
|
||
-/
|
||
/--
|
||
trace: x✝ : Nat := 2
|
||
⊢ x✝ = 2
|
||
-/
|
||
#guard_msgs in
|
||
example : let x := 2; x = 2 := by
|
||
extract_lets _
|
||
trace_state
|
||
rfl
|
||
|
||
/-!
|
||
Extract an embedded let, name given.
|
||
-/
|
||
/--
|
||
trace: z : Nat := 2
|
||
⊢ z = 2
|
||
-/
|
||
#guard_msgs in
|
||
example : (let x := 2; x) = 2 := by
|
||
extract_lets z
|
||
trace_state
|
||
rfl
|
||
|
||
/-!
|
||
Extract multiple embedded lets, no names given.
|
||
-/
|
||
/--
|
||
trace: x✝ : Nat := 2
|
||
y✝ : Nat := 1 + 1
|
||
⊢ x✝ = y✝
|
||
-/
|
||
#guard_msgs in
|
||
example : (let x := 2; x) = (let y := 1 + 1; y) := by
|
||
extract_lets
|
||
trace_state
|
||
rfl
|
||
|
||
/-!
|
||
Names extracted lets in order, but keeps extracting even after list is exhausted.
|
||
-/
|
||
/--
|
||
trace: z : Nat := 2
|
||
y✝ : Nat := 1 + 1
|
||
⊢ z = y✝
|
||
-/
|
||
#guard_msgs in
|
||
example : (let x := 2; x) = (let y := 1 + 1; y) := by
|
||
extract_lets z
|
||
trace_state
|
||
rfl
|
||
|
||
/-!
|
||
Too many names, linter warning.
|
||
-/
|
||
/--
|
||
warning: unused name
|
||
note: this linter can be disabled with `set_option linter.tactic.unusedName false`
|
||
---
|
||
trace: z : Nat := 2
|
||
z' : Nat := 1 + 1
|
||
⊢ z = z'
|
||
-/
|
||
#guard_msgs in
|
||
example : (let x := 2; x) = (let y := 1 + 1; y) := by
|
||
extract_lets z z' z''
|
||
trace_state
|
||
rfl
|
||
|
||
/-!
|
||
Length of name list controls number of lets in `+onlyGivenNames` mode.
|
||
-/
|
||
/--
|
||
trace: z : Nat := 2
|
||
⊢ z =
|
||
let y := 1 + 1;
|
||
y
|
||
-/
|
||
#guard_msgs in
|
||
example : (let x := 2; x) = (let y := 1 + 1; y) := by
|
||
extract_lets +onlyGivenNames z
|
||
trace_state
|
||
rfl
|
||
/--
|
||
trace: z : Nat := 2
|
||
w : Nat := 1 + 1
|
||
⊢ z = w
|
||
-/
|
||
#guard_msgs in
|
||
example : (let x := 2; x) = (let y := 1 + 1; y) := by
|
||
extract_lets +onlyGivenNames z w
|
||
trace_state
|
||
rfl
|
||
|
||
/-!
|
||
Merging.
|
||
-/
|
||
/--
|
||
trace: x✝ : Nat := 2
|
||
⊢ x✝ = x✝
|
||
-/
|
||
#guard_msgs in
|
||
example : (let x := 2; x) = (let y := 2; y) := by
|
||
extract_lets
|
||
trace_state
|
||
rfl
|
||
|
||
/-!
|
||
Merging, even if we run out of names.
|
||
-/
|
||
/--
|
||
trace: z : Nat := 2
|
||
⊢ z = z
|
||
-/
|
||
#guard_msgs in
|
||
example : (let x := 2; x) = (let y := 2; y) := by
|
||
extract_lets z
|
||
trace_state
|
||
rfl
|
||
|
||
/-!
|
||
Merging reuses pre-existing declarations
|
||
-/
|
||
/--
|
||
trace: z : Nat := 2
|
||
⊢ z = z
|
||
-/
|
||
#guard_msgs in
|
||
example : (let x := 2; x) = (let y := 2; y) := by
|
||
let z := 2
|
||
extract_lets
|
||
trace_state
|
||
rfl
|
||
|
||
/-!
|
||
Merging doesn't reuse pre-existing declarations when `-useContext`.
|
||
-/
|
||
/--
|
||
trace: z : Nat := 2
|
||
x✝ : Nat := 2
|
||
⊢ x✝ = x✝
|
||
-/
|
||
#guard_msgs in
|
||
example : (let x := 2; x) = (let y := 2; y) := by
|
||
let z := 2
|
||
extract_lets -useContext
|
||
trace_state
|
||
rfl
|
||
|
||
/-!
|
||
Works with `have`
|
||
-/
|
||
/--
|
||
trace: a✝ : Nat := 2
|
||
x✝ : Nat := a✝
|
||
y✝ : Nat := a✝ + 0
|
||
⊢ x✝ = y✝
|
||
-/
|
||
#guard_msgs in
|
||
example : have a := 2; (have x := a; x) = (have y := a + 0; y) := by
|
||
extract_lets
|
||
trace_state
|
||
rfl
|
||
|
||
/-!
|
||
Extracts at both the type and the value of a local definition.
|
||
-/
|
||
/--
|
||
trace: α✝ : Type := Nat
|
||
y✝ : Nat := 2
|
||
x : α✝ := 2
|
||
⊢ x = x
|
||
-/
|
||
#guard_msgs in
|
||
example : let x : (let α := Nat; α) := (let y := 2; 2); x = x := by
|
||
intro x
|
||
extract_lets at x
|
||
trace_state
|
||
rfl
|
||
-- Essentially same state:
|
||
/--
|
||
trace: α✝ : Type := Nat
|
||
y✝ : Nat := 2
|
||
x✝ : α✝ := 2
|
||
⊢ x✝ = x✝
|
||
-/
|
||
#guard_msgs in
|
||
example : let x : (let α := Nat; α) := (let y := 2; 2); x = x := by
|
||
extract_lets
|
||
trace_state
|
||
rfl
|
||
|
||
/-!
|
||
Basic `descend := false` test.
|
||
-/
|
||
/--
|
||
trace: x✝ : Nat := 2
|
||
⊢ x✝ = 2
|
||
-/
|
||
#guard_msgs in
|
||
example : let x := 2; x = 2 := by
|
||
extract_lets -descend
|
||
trace_state
|
||
rfl
|
||
|
||
/-!
|
||
Make sure `descend := false` is not obstructed by metadata.
|
||
-/
|
||
/--
|
||
trace: this : True
|
||
x✝ : Nat := 2
|
||
⊢ x✝ = 2
|
||
-/
|
||
#guard_msgs in
|
||
example : let x := 2; x = 2 := by
|
||
have : True := trivial
|
||
extract_lets -descend
|
||
trace_state
|
||
rfl
|
||
|
||
/-
|
||
In `-descend` mode, does not extract embedded let.
|
||
-/
|
||
/--
|
||
error: tactic 'extract_lets' failed, made no progress
|
||
⊢ (let x := 2;
|
||
x) =
|
||
2
|
||
-/
|
||
#guard_msgs in
|
||
example : (let x := 2; x) = 2 := by
|
||
extract_lets -descend z
|
||
|
||
/-!
|
||
In `-descend` mode, merges using pre-existing declarations.
|
||
-/
|
||
/--
|
||
trace: w : Nat := 2
|
||
y✝ : Nat := 3
|
||
⊢ w = 2 + y✝ - y✝
|
||
-/
|
||
#guard_msgs in
|
||
example : let x := 2; let y := 3; let z := 3; x = 2 + y - z := by
|
||
let w := 2
|
||
extract_lets -descend
|
||
trace_state
|
||
rfl
|
||
|
||
/-!
|
||
`-descend` works with `have` (`have`)
|
||
-/
|
||
/--
|
||
trace: a✝ : Nat := 2
|
||
⊢ (have x := a✝;
|
||
x) =
|
||
have y := a✝ + 0;
|
||
y
|
||
-/
|
||
#guard_msgs in
|
||
example : have a := 2; (have x := a; x) = (have y := a + 0; y) := by
|
||
extract_lets -descend
|
||
trace_state
|
||
rfl
|
||
|
||
/-!
|
||
Extracting at a hypothesis
|
||
-/
|
||
/--
|
||
trace: x✝ : Nat := 1
|
||
h : x✝ = x✝
|
||
⊢ True
|
||
-/
|
||
#guard_msgs in
|
||
example (h : let x := 1; x = x) : True := by
|
||
extract_lets at h
|
||
fail_if_success extract_lets a at h
|
||
trace_state
|
||
trivial
|
||
|
||
/-!
|
||
Extracting at a hypothesis, with names
|
||
-/
|
||
/--
|
||
trace: y : Nat := 1
|
||
h : y = y
|
||
⊢ True
|
||
-/
|
||
#guard_msgs in
|
||
example (h : let x := 1; x = x) : True := by
|
||
extract_lets y at h
|
||
fail_if_success extract_lets a at h
|
||
trace_state
|
||
trivial
|
||
|
||
/-!
|
||
Extracting at a hypothesis, reorders hypotheses
|
||
-/
|
||
/--
|
||
trace: h' : Nat
|
||
y : Nat := 1
|
||
h : y = y
|
||
⊢ True
|
||
-/
|
||
#guard_msgs in
|
||
example (h : let x := 1; x = x) (h' : Nat) : True := by
|
||
extract_lets y at h
|
||
fail_if_success extract_lets a at h
|
||
trace_state
|
||
trivial
|
||
|
||
/-!
|
||
Extracting at a hypothesis, not all top level.
|
||
-/
|
||
/--
|
||
trace: x✝ : Nat := 1
|
||
y✝ : Nat := 2
|
||
h : x✝ + 1 = y✝
|
||
⊢ True
|
||
-/
|
||
#guard_msgs in
|
||
example (h : let x := 1; x + 1 = let y := 2; y) : True := by
|
||
extract_lets at h
|
||
trace_state
|
||
trivial
|
||
|
||
/-!
|
||
Extracting at a hypothesis, not all top level, in `-descend` mode.
|
||
-/
|
||
/--
|
||
trace: x✝ : Nat := 1
|
||
h :
|
||
x✝ + 1 =
|
||
let y := 2;
|
||
y
|
||
⊢ True
|
||
-/
|
||
#guard_msgs in
|
||
example (h : let x := 1; x + 1 = let y := 2; y) : True := by
|
||
extract_lets -descend at h
|
||
trace_state
|
||
trivial
|
||
|
||
/-!
|
||
At multiple locations with `merge := true`.
|
||
-/
|
||
/--
|
||
trace: _z✝ : Nat := 3
|
||
x✝ : Nat := 1
|
||
h : x✝ + 2 = _z✝
|
||
⊢ ∀ (x : Nat), True
|
||
-/
|
||
#guard_msgs in
|
||
example (h : let x := 1; let y := 3; x + 2 = y) : let _z := 3; ∀ (_ : Nat), True := by
|
||
extract_lets at *
|
||
trace_state
|
||
intro
|
||
trivial
|
||
|
||
/-!
|
||
At multiple locations with `merge := false`.
|
||
-/
|
||
/--
|
||
trace: _z✝ : Nat := 3
|
||
x✝ : Nat := 1
|
||
y✝ : Nat := 3
|
||
h : x✝ + 2 = y✝
|
||
⊢ ∀ (x : Nat), True
|
||
-/
|
||
#guard_msgs in
|
||
example (h : let x := 1; let y := 3; x + 2 = y) : let _z := 3; ∀ (_ : Nat), True := by
|
||
extract_lets -merge at *
|
||
trace_state
|
||
intro
|
||
trivial
|
||
|
||
/-!
|
||
Merging can chain. This tests how extracted let declarations are recalled and can handle dependence.
|
||
-/
|
||
/--
|
||
trace: x✝ : Nat := 2
|
||
y✝ : Nat := x✝
|
||
⊢ y✝ = y✝
|
||
-/
|
||
#guard_msgs in
|
||
example : (let x := 2; let y := x; y) = (let x' := 2; let y' := x'; y') := by
|
||
extract_lets
|
||
trace_state
|
||
rfl
|
||
|
||
/-!
|
||
Same merging example, but with `-merge`.
|
||
-/
|
||
/--
|
||
trace: x✝ : Nat := 2
|
||
y✝ : Nat := x✝
|
||
x'✝ : Nat := 2
|
||
y'✝ : Nat := x'✝
|
||
⊢ y✝ = y'✝
|
||
-/
|
||
#guard_msgs in
|
||
example : (let x := 2; let y := x; y) = (let x' := 2; let y' := x'; y') := by
|
||
extract_lets -merge
|
||
trace_state
|
||
rfl
|
||
|
||
/-!
|
||
This tests an issue reported about the mathlib version of `extract_lets`.
|
||
Reported at https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/.60extract_lets.60.20fails.20in.20a.20hypothesis.20if.20the.20name.20is.20unused/near/439675718
|
||
Unused lets are handled properly.
|
||
-/
|
||
/--
|
||
trace: ok✝ : Prop := True
|
||
h :
|
||
let _not_ok := False;
|
||
ok✝
|
||
⊢ let _also_ok := 3;
|
||
True
|
||
---
|
||
trace: ok✝ : Prop := True
|
||
h :
|
||
let _not_ok := False;
|
||
ok✝
|
||
_also_ok✝ : Nat := 3
|
||
⊢ True
|
||
---
|
||
trace: ok✝ : Prop := True
|
||
_also_ok✝ : Nat := 3
|
||
_not_ok✝ : Prop := False
|
||
h : ok✝
|
||
⊢ True
|
||
-/
|
||
#guard_msgs in
|
||
example (h : let ok := True; let _not_ok := False; ok) : let _also_ok := 3; True := by
|
||
extract_lets +onlyGivenNames _ at h
|
||
trace_state
|
||
extract_lets +onlyGivenNames _
|
||
trace_state
|
||
extract_lets +onlyGivenNames _ at h
|
||
trace_state
|
||
trivial
|
||
|
||
/-!
|
||
Testing `+usedOnly`
|
||
-/
|
||
/--
|
||
trace: ok✝ : Prop := True
|
||
h : ok✝
|
||
⊢ let _also_ok := 3;
|
||
True
|
||
---
|
||
trace: ok✝ : Prop := True
|
||
h : ok✝
|
||
⊢ True
|
||
-/
|
||
#guard_msgs in
|
||
example (h : let ok := True; let _not_ok := False; ok) : let _also_ok := 3; True := by
|
||
extract_lets +onlyGivenNames +usedOnly _ at h
|
||
trace_state
|
||
extract_lets +usedOnly
|
||
trace_state
|
||
trivial
|
||
|
||
/-!
|
||
Testing `+usedOnly` with `-descend`
|
||
-/
|
||
/--
|
||
trace: ok✝ : Prop := True
|
||
h : ok✝
|
||
⊢ let _also_ok := 3;
|
||
True
|
||
---
|
||
trace: ok✝ : Prop := True
|
||
h : ok✝
|
||
⊢ True
|
||
-/
|
||
#guard_msgs in
|
||
example (h : let ok := True; let _not_ok := False; ok) : let _also_ok := 3; True := by
|
||
extract_lets -descend +onlyGivenNames +usedOnly _ at h
|
||
trace_state
|
||
extract_lets -descend +usedOnly
|
||
trace_state
|
||
trivial
|
||
|
||
/-!
|
||
`+proofs`
|
||
-/
|
||
/--
|
||
trace: this✝ : (some true).isSome = true := of_eq_true (eq_self true)
|
||
⊢ (some true).get this✝ = true
|
||
-/
|
||
#guard_msgs in
|
||
example : Option.get (some true) (have := (by simp); this) = true := by
|
||
fail_if_success extract_lets -proofs
|
||
extract_lets +proofs
|
||
trace_state
|
||
rfl
|
||
|
||
/-!
|
||
`+implicits`
|
||
-/
|
||
/--
|
||
trace: α✝ : Type := Nat
|
||
⊢ id 2 = 2
|
||
-/
|
||
#guard_msgs in
|
||
example : @id (let α := Nat; α) 2 = 2 := by
|
||
fail_if_success extract_lets -implicits
|
||
extract_lets +implicits
|
||
trace_state
|
||
rfl
|
||
|
||
/-!
|
||
`-types`, works both to inhibit when the top level is a type and when the subterm is a type.
|
||
(This option isn't so useful outside of `conv` mode.)
|
||
-/
|
||
example : (let x := Nat; x) = Nat := by
|
||
fail_if_success extract_lets -types
|
||
extract_lets +types
|
||
rfl
|
||
example : (let x := 2; x) = 2 := by
|
||
fail_if_success extract_lets -types
|
||
extract_lets +types
|
||
rfl
|
||
|
||
/-!
|
||
Let value depends on binder, fails.
|
||
-/
|
||
example : ∀ n : Nat, let x := n; x = x := by
|
||
fail_if_success extract_lets
|
||
intros
|
||
rfl
|
||
|
||
/-!
|
||
Can extract from underneath another `let`.
|
||
-/
|
||
/--
|
||
trace: y✝ : Nat := 2
|
||
⊢ ∀ (n : Nat),
|
||
let x := n;
|
||
x + y✝ = x + y✝
|
||
-/
|
||
#guard_msgs in
|
||
example : ∀ n : Nat, let x := n; let y := 2; x + y = x + y := by
|
||
extract_lets
|
||
trace_state
|
||
intros
|
||
rfl
|
||
|
||
/-!
|
||
Can't extract from underneath another `let` when `underBinder := false`.
|
||
-/
|
||
/--
|
||
error: tactic 'extract_lets' failed, made no progress
|
||
⊢ ∀ (n : Nat),
|
||
let x := n;
|
||
let y := 2;
|
||
x + y = x + y
|
||
-/
|
||
#guard_msgs in
|
||
example : ∀ n : Nat, let x := n; let y := 2; x + y = x + y := by
|
||
extract_lets -underBinder
|
||
|
||
/-!
|
||
Testing lots of `let`s
|
||
-/
|
||
set_option maxHeartbeats 300 in
|
||
example :
|
||
let x := 2
|
||
let x := let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; x
|
||
let x := let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; x
|
||
let x := let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; x
|
||
let x := let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; x
|
||
let x := let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; x
|
||
let x := let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; x
|
||
let x := let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; x
|
||
let x := let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; x
|
||
let x := let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; x
|
||
let x := let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; x
|
||
let x := let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; x
|
||
let x := let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; x
|
||
let x := let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; x
|
||
let x := let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; x
|
||
let x := let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; x
|
||
let x := let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; x
|
||
let x := let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; x
|
||
let x := let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; x
|
||
let x := let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; x
|
||
let x := let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; let x := x; x
|
||
x = x := by
|
||
extract_lets
|
||
rename_i a
|
||
guard_target =ₛ a = a
|
||
rfl
|
||
|
||
/-!
|
||
### `+lift` mode
|
||
|
||
See also the `lift_lets.lean` test file.
|
||
-/
|
||
|
||
/-!
|
||
Lifts, does not make use of name generator.
|
||
-/
|
||
/--
|
||
trace: ⊢ ∀ (n : Nat),
|
||
let x := n;
|
||
n = x
|
||
-/
|
||
#guard_msgs in
|
||
example : ∀ n : Nat, n = (let x := n; x) := by
|
||
fail_if_success extract_lets
|
||
extract_lets +lift
|
||
trace_state
|
||
intros
|
||
rfl
|
||
|
||
/-!
|
||
Same example, but testing `letFun`.
|
||
-/
|
||
/--
|
||
trace: ⊢ ∀ (n : Nat),
|
||
have x := n;
|
||
n = x
|
||
-/
|
||
#guard_msgs in
|
||
example : ∀ n : Nat, n = (have x := n; x) := by
|
||
fail_if_success extract_lets
|
||
extract_lets +lift
|
||
trace_state
|
||
intros
|
||
rfl
|
||
|
||
/-!
|
||
Merging of merely-lifted lets. Four cases to this test, depending on whether a `have` or `let` is seen first,
|
||
and whether the second is a `have` or `let`.
|
||
-/
|
||
/--
|
||
trace: ⊢ ∀ (n : Nat),
|
||
have x := n;
|
||
x = x
|
||
-/
|
||
#guard_msgs in
|
||
example : ∀ n : Nat, (have x := n; x) = (have x' := n; x') := by
|
||
fail_if_success extract_lets
|
||
extract_lets +lift
|
||
trace_state
|
||
intros
|
||
rfl
|
||
/--
|
||
trace: ⊢ ∀ (n : Nat),
|
||
let x := n;
|
||
x = x
|
||
-/
|
||
#guard_msgs in
|
||
example : ∀ n : Nat, (let x := n; x) = (have x' := n; x') := by
|
||
fail_if_success extract_lets
|
||
extract_lets +lift
|
||
trace_state
|
||
intros
|
||
rfl
|
||
/--
|
||
trace: ⊢ ∀ (n : Nat),
|
||
let x := n;
|
||
x = x
|
||
-/
|
||
#guard_msgs in
|
||
example : ∀ n : Nat, (have x := n; x) = (let x' := n; x') := by
|
||
fail_if_success extract_lets
|
||
extract_lets +lift
|
||
trace_state
|
||
intros
|
||
rfl
|
||
/--
|
||
trace: ⊢ ∀ (n : Nat),
|
||
let x := n;
|
||
x = x
|
||
-/
|
||
#guard_msgs in
|
||
example : ∀ n : Nat, (let x := n; x) = (let x' := n; x') := by
|
||
fail_if_success extract_lets
|
||
extract_lets +lift
|
||
trace_state
|
||
intros
|
||
rfl
|
||
|
||
/-!
|
||
Without merging
|
||
-/
|
||
/--
|
||
trace: ⊢ ∀ (n : Nat),
|
||
have x := n;
|
||
have x' := n;
|
||
x = x'
|
||
-/
|
||
#guard_msgs in
|
||
example : ∀ n : Nat, (have x := n; x) = (have x' := n; x') := by
|
||
fail_if_success extract_lets
|
||
extract_lets +lift -merge
|
||
trace_state
|
||
intros
|
||
rfl
|
||
|
||
/-!
|
||
Make sure `+lift` doesn't lift things that transitively depend on a binder.
|
||
-/
|
||
example : ∀ n : Nat, let x := n; let y := x; y = n := by
|
||
fail_if_success extract_lets +lift
|
||
intros
|
||
rfl
|
||
|
||
/-!
|
||
Extracting `let`s in proofs in `+proof` mode.
|
||
-/
|
||
/--
|
||
trace: m : Nat
|
||
h : ∃ n, n + 1 = m
|
||
x : Fin m
|
||
y : Fin (h.choose + 1)
|
||
he : m = h.choose + 1 := Eq.symm (Exists.choose_spec h)
|
||
⊢ cast ⋯ x = y
|
||
-/
|
||
#guard_msgs in
|
||
example (m : Nat) (h : ∃ n, n + 1 = m) (x : Fin m) (y : Fin _) :
|
||
cast (let h' := h.choose_spec.symm; congrArg Fin h') x = y := by
|
||
fail_if_success extract_lets -proofs
|
||
extract_lets +proofs he
|
||
trace_state
|
||
exact test_sorry
|
||
|
||
/-!
|
||
### Conv mode
|
||
-/
|
||
|
||
/-!
|
||
Limitation: we can use `extract_lets` within `conv`, but the let bindings do not persist.
|
||
-/
|
||
/--
|
||
trace: y : Type := Nat
|
||
| y = Int
|
||
---
|
||
trace: ⊢ Nat = Int
|
||
-/
|
||
#guard_msgs in
|
||
example : let x := Nat; x = Int := by
|
||
conv =>
|
||
extract_lets y
|
||
trace_state
|
||
trace_state
|
||
exact test_sorry
|