|
| 1 | +/-! |
| 2 | +# Tests exercising basic behaviour of `rw`. |
| 3 | +
|
| 4 | +See also `tests/lean/rewrite.lean`. |
| 5 | +-/ |
| 6 | + |
| 7 | +-- Rewriting by `iff` |
| 8 | +example (h : P ↔ Q) (q : Q) : P := by |
| 9 | + rw [h] |
| 10 | + exact q |
| 11 | +example (h : P ↔ Q) (q : Q) : P := by |
| 12 | + rw [← h] at q |
| 13 | + exact q |
| 14 | + |
| 15 | +def f (_ : Nat) : Nat := 0 |
| 16 | +def g (n : Nat) : Nat := f n |
| 17 | + |
| 18 | +theorem t (n : Nat) : f n = f 0 := rfl |
| 19 | +theorem s (n m : Nat) : f n = f m := rfl |
| 20 | + |
| 21 | +example : f 1 = f 2 := by |
| 22 | + rw [s 1 2] -- closes the goal `f 2 = f 2` via `rfl` |
| 23 | +example : f 1 = f 2 := by |
| 24 | + rw [t] -- does not close the goal, because `rw` calls `rfl` under `withReducible` |
| 25 | + rfl |
| 26 | + |
| 27 | +example (h : f (f 1) = 0) : f (g 1) = 0 := by |
| 28 | + fail_if_success rw [h] -- Can not see through definition of `g` |
| 29 | + erw [h] -- "Expensive" rewrite can |
| 30 | + |
| 31 | +-- Check `(config := ...)` works: |
| 32 | +example (h : f (f 1) = 0) : f (g 1) = 0 := by |
| 33 | + rw (config := {transparency := .default}) [h] -- This is just `erw`. |
| 34 | + |
| 35 | +attribute [reducible] f in |
| 36 | +example : f 1 = f 2 := by |
| 37 | + rw [] -- Empty rewrite closes the goal via `rfl` |
| 38 | +example : f 1 = f 2 := by |
| 39 | + rw [t] -- Closes the goal via `rfl` |
| 40 | +example : f 1 = f 2 := by |
| 41 | + rw [s 1 3, s 3 4] -- Closes the goal via `rfl` |
| 42 | + |
| 43 | +-- For the remaining tests we prevent `rfl` from closing the goal. |
| 44 | +attribute [irreducible] f |
| 45 | + |
| 46 | +-- Multiple rewrites |
| 47 | +example : f 3 = f 7 := by |
| 48 | + rw [s 3 5, s 5 7] |
| 49 | + |
| 50 | +-- Rewrite only modifies the main goal. |
| 51 | +example (h : f 2 = f 3) : f 1 = f 2 := by |
| 52 | + rw [s 2 3, s 1 2] |
| 53 | + assumption |
| 54 | + |
| 55 | +-- Rewrite `at` |
| 56 | +example (h : f 2 = f 3) : f 1 = f 2 := by |
| 57 | + rw [s 2 1] at h |
| 58 | + rw [s 2 3] |
| 59 | + assumption |
| 60 | + |
| 61 | +-- Rewriting only affects the first occurrence. |
| 62 | +-- Providing an argument allows rewriting other occurrences. |
| 63 | +example : [f 1, f 2] = [f 0, f 0] := by |
| 64 | + rw [t] |
| 65 | + rw [t] |
| 66 | + rw [t 2] |
| 67 | + |
| 68 | +-- We can rewrite backwards. |
| 69 | +example : f 1 = f 0 := by |
| 70 | + rw [← t 2] |
| 71 | + rw [t] |
| 72 | + rw [t 2] |
| 73 | + |
| 74 | +-- Rewriting simultaneously replaces all occurrences of the first match. |
| 75 | +example : [f 1, f 2, f 1] = [f 0, f 0, f 0] := by |
| 76 | + rw [t] |
| 77 | + rw [t 2] |
| 78 | + |
| 79 | +-- Rewriting by lemmas with undetermined arguments creates additional goals. |
| 80 | +example : f 2 = f 3 := by |
| 81 | + rewrite [s] |
| 82 | + rfl |
| 83 | + |
| 84 | +-- These are often solved by the implicit `rfl` at the end of `rw`. |
| 85 | +example : f 2 = f 3 := by |
| 86 | + rw [s] |
| 87 | + |
| 88 | +-- We can rewrite at multiple locations, |
| 89 | +-- specializing the arguments differently at each location. |
| 90 | +-- This behaviour was accidentally broken by |
| 91 | +-- https://github.com/leanprover/lean4/pull/2317 |
| 92 | +-- and required a revert. |
| 93 | +example (w₁ : f 1 = 0) (w₂ : f 2 = 0) : f 3 = 0 ∧ f 0 = 0 := by |
| 94 | + rw [t] at w₁ w₂ ⊢ |
| 95 | + exact ⟨w₁, w₂⟩ |
| 96 | + |
| 97 | +class P (n : Nat) |
| 98 | + |
| 99 | +theorem t' (n : Nat) [P n] : f n = f 0 := t n |
| 100 | + |
| 101 | +-- Rewriting uses typeclass synthesis to fill arguments. |
| 102 | +example [∀ n, P n] : f 2 = f 0 := by |
| 103 | + rw [t'] |
| 104 | + |
| 105 | +example : f 2 = f 0 := by |
| 106 | + fail_if_success rw [t'] -- failed to synthesize P 2 |
| 107 | + fail_if_success rw [@t' 2 _] -- failed to synthesize P 2 |
| 108 | + -- By putting placeholders in a typeclass argument |
| 109 | + -- we can return the problem to the user. |
| 110 | + rw [@t' 2 ?_] |
| 111 | + constructor |
| 112 | + |
| 113 | + |
0 commit comments