lean4-htt/tests/lean/run/simpHave.lean
jrr6 62f14514da
refactor: update built-in tactic error messages (#9633)
This PR updates various error messages produced by or associated with
built-in tactics and adapts their formatting to current conventions.
2025-07-31 14:16:57 +00:00

623 lines
13 KiB
Text

/-!
# Tests for `simp` of `have` expressions (and some `let` expressions)
Note: There are additional stress tests of deep `have`s in tests/lean/run/simpLetFunIssue.lean
-/
set_option linter.unusedSimpArgs false
-- Enable simp consistency checks, so that the elaborator type checker is run on generated proofs.
-- We want this so that we can verify that haves are "elaborator type correct",
-- since the kernel does not check `nonDep`.
set_option debug.simp.check.have true
-- To see the types of `have` binders for verification.
set_option pp.letVarTypes true
/-! Zeta reduction of lets -/
/--
trace: n : Nat
h : n = 5
⊢ 1 + 4 = n
-/
#guard_msgs in
example (n : Nat) (h : n = 5) :
let x := 1; let _y := 2; let _z := 3; let w := 4; x + w = n := by
simp +zeta only
trace_state
simp [h]
/-! Turning off zeta reduction of lets -/
/-- error: `simp` made no progress -/
#guard_msgs in
example (n : Nat) (h : n = 5) :
let x := 1; let _y := 2; let _z := 3; let w := 4; x + w = n := by
simp -zeta -zetaUnused -letToHave only
/-! Turning off zeta reduction of lets. Lets can only be dsimped. -/
/-- error: `simp` made no progress -/
#guard_msgs in
example (n : Nat) (h : n = 5) :
let x := 1; let _y := 2; let _z := 3; let w := 4; x + w = n := by
simp -zeta -zetaUnused -letToHave only [h]
/--
trace: n : Nat
h : n = 5
⊢ let x : Nat := 1;
let _y : Nat := 2;
let _z : Nat := 3;
let w : Nat := 4;
x + w = n
-/
#guard_msgs in
example (n : Nat) (h : n = 5) :
let x := 1; let _y := 2; let _z := 3; let w := 4 + 0; x + w = n + 0 := by
simp -zeta -zetaUnused -letToHave only [h, Nat.add_zero]
trace_state
simp [h]
/-! letToHave -/
/--
error: unsolved goals
n : Nat
h : n = 5
⊢ have x : Nat := 1;
have _y : Nat := 2;
have _z : Nat := 3;
have w : Nat := 4;
x + w = n
-/
#guard_msgs in
example (n : Nat) (h : n = 5) :
let x := 1; let _y := 2; let _z := 3; let w := 4; x + w = n := by
simp -zeta -zetaUnused +letToHave only
/-! Enabling zetaUnused for lets -/
/--
trace: n : Nat
h : n = 5
⊢ let x : Nat := 1;
let w : Nat := 4;
x + w = n
-/
#guard_msgs in
example (n : Nat) (h : n = 5) :
let x := 1; let _y := 2; let _z := 3; let w := 4; x + w = n := by
simp -zeta +zetaUnused -letToHave only
trace_state
simp [h]
/-! Zeta reduction of haves -/
/--
trace: n : Nat
h : n = 5
⊢ 1 + 4 = n
-/
#guard_msgs in
example (n : Nat) (h : n = 5) :
have x := 1; have _y := 2; have _z := 3; have w := 4; x + w = n := by
simp +zeta only
trace_state
simp [h]
/-! Turning off zeta reduction of haves, including with specific `zetaHave` option. -/
/-- error: `simp` made no progress -/
#guard_msgs in
example (n : Nat) (h : n = 5) :
have x := 1; have _y := 2; have _z := 3; have w := 4; x + w = n := by
simp -zeta -zetaUnused only
/-- error: `simp` made no progress -/
#guard_msgs in
example (n : Nat) (h : n = 5) :
have x := 1; have _y := 2; have _z := 3; have w := 4; x + w = n := by
simp -zetaHave -zetaUnused only
/-! Enabling zetaUnused for haves, and just haves -/
/--
trace: n : Nat
h : n = 5
⊢ have x : Nat := 1;
have w : Nat := 4;
x + w = n
-/
#guard_msgs in
example (n : Nat) (h : n = 5) :
have x := 1; have _y := 2; have _z := 3; have w := 4; x + w = n := by
simp -zeta +zetaUnused only
trace_state
simp [h]
/--
trace: n : Nat
h : n = 5
⊢ have x : Nat := 1;
have w : Nat := 4;
x + w = n
-/
#guard_msgs in
example (n : Nat) (h : n = 5) :
have x := 1; have _y := 2; have _z := 3; have w := 4; x + w = n := by
simp -zetaHave +zetaUnused only
trace_state
simp [h]
/-! Zeta reduction, but no zeta reduction of haves. -/
/--
trace: n : Nat
h : n = 5
⊢ have y : Nat := 2 + 1;
have _z : Nat := 3 + 1 + y;
1 + 4 = n
-/
#guard_msgs in
example (n : Nat) (h : n = 5) :
let x := 1; have y := 2 + x; have _z := 3 + x + y; let w := 4; x + w = n := by
simp +zeta -zetaHave -zetaUnused -letToHave only
trace_state
simp [h]
/--
trace: n : Nat
h : n = 5
⊢ have y : Nat := 3;
have _z : Nat := 4 + y;
5 = n
-/
#guard_msgs in
example (n : Nat) (h : n = 5) :
let x := 1; have y := 2 + x; have _z := 3 + x + y; let w := 4; x + w = n := by
simp +zeta -zetaHave -zetaUnused -letToHave [Nat.reduceAdd]
trace_state
simp [h]
def fix1 (n : Nat) : Fin (n + 1) := 0
/-!
Fixed because appears in type of body.
-/
/-- error: `simp` made no progress -/
#guard_msgs in
example (n : Nat) (h : n = 5) :
(have a := n + 1; fix1 a) = 0 := by
simp -zeta -zetaUnused [h]
/-!
Fixed, but can dsimp value.
-/
/--
trace: n : Nat
_h : n = 5
⊢ (have a : Nat := n + 1;
fix1 a) =
0
-/
#guard_msgs in
example (n : Nat) (_h : n = 5) :
(have a := n + 0 + 1; fix1 a) = 0 := by
simp -zeta -zetaUnused [_h]
trace_state
simp [fix1]
/-!
Check that zetaUnused doesn't affect this.
-/
/--
trace: n : Nat
_h : n = 5
⊢ (have a : Nat := n + 1;
fix1 a) =
0
-/
#guard_msgs in
example (n : Nat) (_h : n = 5) :
(have _u0 := 0; have a := n + 0 + 1; have _u1 := 1; fix1 a) = 0 := by
simp -zeta +zetaUnused [_h]
trace_state
simp [fix1]
/-!
Appears in the type of another `have` in telescope, but not fixed.
-/
/--
trace: n : Nat
h : n = 5
⊢ (have a : Nat := 6;
have b : Fin (a + 1) := fix1 a;
↑b) =
0
-/
#guard_msgs in
example (n : Nat) (h : n = 5) :
(have a := 0 + n + 1; have b := 0 + fix1 a + 0; (b : Nat)) = 0 := by
simp -zeta -zetaUnused [h]
trace_state
simp [fix1]
/-!
Check that zetaUnused doesn't affect this.
-/
/--
trace: n : Nat
h : n = 5
⊢ (have a : Nat := 6;
have b : Fin (a + 1) := fix1 a;
↑b) =
0
-/
#guard_msgs in
example (n : Nat) (h : n = 5) :
(have _u0 := 0; have a := 0 + n + 1; have _u1 := 1; have b := 0 + fix1 a + 0; have _u2 := 2; (b : Nat)) = 0 := by
simp -zeta +zetaUnused [h]
trace_state
simp [fix1]
/-!
Transitively unused `have`s.
-/
/--
trace: ⊢ have m : Nat := 1;
have n : Nat := 1;
n = m
-/
#guard_msgs in
example :
have m := 1; have u0 := 0; have u1 := u0; have n := 1; have u2 := u1; have u3 := u2; have _u4 := u3; n = m := by
simp -zeta
trace_state
simp
/-!
Unused, unfixed, fixed, all six permutations, with a changing body.
-/
/--
trace: n : Nat
⊢ (have a : Nat := n;
have b : Nat := 0 + n;
(a, fix1 b)) =
(n, 0)
-/
#guard_msgs in
example (n : Nat) :
(have _u1 := 1; have a := 0 + n; have b := 0 + n; (0 + a, fix1 b)) = (n, 0) := by
simp -zeta
trace_state
rfl
/--
trace: n : Nat
⊢ (have a : Nat := n;
have b : Nat := 0 + n;
(a, fix1 b)) =
(n, 0)
-/
#guard_msgs in
example (n : Nat) :
(have a := 0 + n; have _u1 := 1; have b := 0 + n; (0 + a, fix1 b)) = (n, 0) := by
simp -zeta
trace_state
rfl
/--
trace: n : Nat
⊢ (have a : Nat := n;
have b : Nat := 0 + n;
(a, fix1 b)) =
(n, 0)
-/
#guard_msgs in
example (n : Nat) :
(have a := 0 + n; have b := 0 + n; have _u1 := 1; (0 + a, fix1 b)) = (n, 0) := by
simp -zeta
trace_state
rfl
/--
trace: n : Nat
⊢ (have b : Nat := 0 + n;
have a : Nat := n;
(a, fix1 b)) =
(n, 0)
-/
#guard_msgs in
example (n : Nat) :
(have _u1 := 1; have b := 0 + n; have a := 0 + n; (0 + a, fix1 b)) = (n, 0) := by
simp -zeta
trace_state
rfl
/--
trace: n : Nat
⊢ (have b : Nat := 0 + n;
have a : Nat := n;
(a, fix1 b)) =
(n, 0)
-/
#guard_msgs in
example (n : Nat) :
(have b := 0 + n; have _u1 := 1; have a := 0 + n; (0 + a, fix1 b)) = (n, 0) := by
simp -zeta
trace_state
rfl
/--
trace: n : Nat
⊢ (have b : Nat := 0 + n;
have a : Nat := n;
(a, fix1 b)) =
(n, 0)
-/
#guard_msgs in
example (n : Nat) :
(have b := 0 + n; have a := 0 + n; have _u1 := 1; (0 + a, fix1 b)) = (n, 0) := by
simp -zeta
trace_state
rfl
/-!
Unused, unfixed, fixed, all six permutations, with an unchanging body.
-/
/--
trace: n : Nat
⊢ (have a : Nat := n;
have b : Nat := 0 + n;
(a, fix1 b)) =
(n, 0)
-/
#guard_msgs in
example (n : Nat) :
(have _u1 := 1; have a := 0 + n; have b := 0 + n; (a, fix1 b)) = (n, 0) := by
simp -zeta
trace_state
rfl
/--
trace: n : Nat
⊢ (have a : Nat := n;
have b : Nat := 0 + n;
(a, fix1 b)) =
(n, 0)
-/
#guard_msgs in
example (n : Nat) :
(have a := 0 + n; have _u1 := 1; have b := 0 + n; (a, fix1 b)) = (n, 0) := by
simp -zeta
trace_state
rfl
/--
trace: n : Nat
⊢ (have a : Nat := n;
have b : Nat := 0 + n;
(a, fix1 b)) =
(n, 0)
-/
#guard_msgs in
example (n : Nat) :
(have a := 0 + n; have b := 0 + n; have _u1 := 1; (a, fix1 b)) = (n, 0) := by
simp -zeta
trace_state
rfl
/--
trace: n : Nat
⊢ (have b : Nat := 0 + n;
have a : Nat := n;
(a, fix1 b)) =
(n, 0)
-/
#guard_msgs in
example (n : Nat) :
(have _u1 := 1; have b := 0 + n; have a := 0 + n; (a, fix1 b)) = (n, 0) := by
simp -zeta
trace_state
rfl
/--
trace: n : Nat
⊢ (have b : Nat := 0 + n;
have a : Nat := n;
(a, fix1 b)) =
(n, 0)
-/
#guard_msgs in
example (n : Nat) :
(have b := 0 + n; have _u1 := 1; have a := 0 + n; (a, fix1 b)) = (n, 0) := by
simp -zeta
trace_state
rfl
/--
trace: n : Nat
⊢ (have b : Nat := 0 + n;
have a : Nat := n;
(a, fix1 b)) =
(n, 0)
-/
#guard_msgs in
example (n : Nat) :
(have b := 0 + n; have a := 0 + n; have _u1 := 1; (a, fix1 b)) = (n, 0) := by
simp -zeta
trace_state
rfl
/-!
Unused tests: modifying and not modifying body.
-/
/--
trace: n : Nat
h : n = 1
⊢ n = 1
-/
#guard_msgs in
example (n : Nat) (h : n = 1) :
(have _u1 := n; 0 + n) = 1 := by
simp -zeta
trace_state
simp [h]
/--
trace: n : Nat
h : n = 1
⊢ n = 1
-/
#guard_msgs in
example (n : Nat) (h : n = 1) :
(have _u1 := n; n) = 1 := by
simp -zeta
trace_state
simp [h]
/-!
Non-fixed tests: modifying and not modifying value and body.
-/
/-- error: `simp` made no progress -/
#guard_msgs in
example (n : Nat) (h : n = 1) :
(have m := n; m) = 1 := by
simp -zeta -zetaUnused
/--
trace: n : Nat
h : n = 1
⊢ (have m : Nat := n;
m) =
1
-/
#guard_msgs in
example (n : Nat) (h : n = 1) :
(have m := n; 0 + m) = 1 := by
simp -zeta
trace_state
simp [h]
/--
trace: n : Nat
h : n = 1
⊢ (have m : Nat := n;
m) =
1
-/
#guard_msgs in
example (n : Nat) (h : n = 1) :
(have m := 0 + n; m) = 1 := by
simp -zeta
trace_state
simp [h]
/--
trace: n : Nat
h : n = 1
⊢ (have m : Nat := n;
m) =
1
-/
#guard_msgs in
example (n : Nat) (h : n = 1) :
(have m := 0 + n; 0 + m) = 1 := by
simp -zeta
trace_state
simp [h]
/-!
Fixed tests: modifying and not modifying body (with simp) and value (with dsimp)
-/
/-- error: `simp` made no progress -/
#guard_msgs in
example (n : Nat) (h : n = 1) :
(have m := n; fix1 m) = 1 := by
simp -zeta -zetaUnused
/--
trace: n : Nat
h : n = 0
⊢ (have m : Nat := n;
fix1 m) =
Fin.ofNat (n + 1) n
-/
#guard_msgs in
example (n : Nat) (h : n = 0) :
(have m := n; 0 + fix1 m) = Fin.ofNat (n + 1) n := by
simp -zeta
trace_state
simp [h, fix1]
/-- error: `simp` made no progress -/
#guard_msgs in
example (n : Nat) (h : n = 0) :
(have m := 0 + n; fix1 m) = n := by
simp -zeta
trace_state
simp [h, fix1]; rfl
/--
trace: n : Nat
h : n = 0
⊢ (have m : Nat := n;
fix1 m) =
Fin.ofNat (n + 1) n
-/
#guard_msgs in
example (n : Nat) (h : n = 0) :
(have m := n + 0; fix1 m) = Fin.ofNat (n + 1) n := by
simp -zeta
trace_state
simp [h, fix1]
/--
trace: n : Nat
h : n = 0
⊢ (have m : Nat := 0 + n;
fix1 m) =
Fin.ofNat (0 + n + 1) n
-/
#guard_msgs in
example (n : Nat) (h : n = 0) :
(have m := 0 + n; 0 + fix1 m) = Fin.ofNat (0 + n + 1) n := by
simp -zeta
trace_state
simp [h, fix1]
/--
trace: n : Nat
h : n = 0
⊢ (have m : Nat := n;
fix1 m) =
Fin.ofNat (n + 1) n
-/
#guard_msgs in
example (n : Nat) (h : n = 0) :
(have m := n + 0; 0 + fix1 m) = Fin.ofNat (n + 0 + 1) n := by
simp -zeta
trace_state
simp [h, fix1]
/-!
Stress test
-/
def lp (n : Nat) (acc : Nat) :=
match n with
| 0 => acc
| n' + 1 => have k := 0 + acc + n'; lp n' k
/--
trace: n : Nat
h : n = 190
⊢ (have k : Nat := 0 + 0 + 19;
have k : Nat := 0 + k + 18;
have k : Nat := 0 + k + 17;
have k : Nat := 0 + k + 16;
have k : Nat := 0 + k + 15;
have k : Nat := 0 + k + 14;
have k : Nat := 0 + k + 13;
have k : Nat := 0 + k + 12;
have k : Nat := 0 + k + 11;
have k : Nat := 0 + k + 10;
have k : Nat := 0 + k + 9;
have k : Nat := 0 + k + 8;
have k : Nat := 0 + k + 7;
have k : Nat := 0 + k + 6;
have k : Nat := 0 + k + 5;
have k : Nat := 0 + k + 4;
have k : Nat := 0 + k + 3;
have k : Nat := 0 + k + 2;
have k : Nat := 0 + k + 1;
have k : Nat := 0 + k + 0;
k) =
n
-/
#guard_msgs in
example (n : Nat) (h : n = 190) : lp 20 0 = n := by
simp -zeta only [lp]
trace_state
simp -zeta only [Nat.zero_add]
simp only
simp [h]
-- set_option Elab.async false
-- set_option profiler true
-- set_option profiler.threshold 2
-- #time
set_option debug.simp.check.have false in
example (n : Nat) (h : n = 4950) : lp 100 0 = n := by
simp -zeta -zetaUnused only [lp]
simp -zeta only [Nat.zero_add]
simp only
simp [h]