A pending tactic mvar managed to escape into an unexpected context in
specific circumstances.
```lean
example : True := by
· rw [show 0 = 0 by rfl]
```
* Term elaboration of the `show` creates a pending mvar for the `by rfl`
proof
* `rw` fails with an exception because the pattern does not occur in the
target
* `cdot` catches the exception and admits the goal
* `Term.runTactic` [synthesizes all pending mvars from the tactic's
execution](5f9dedfe5e/src/Lean/Elab/SyntheticMVars.lean (L350)),
including the `by rfl` proof. But this would not have happened without
`cdot` as the exception would have skipped that invocation!
* Now incrementality is confused because the nested `by rfl` proof is
unexpectedly run in the same context as the top-level proof, writing to
the wrong promise, and the error message is lost
Solution: disable incrementality for these pending mvars
76 lines
2.4 KiB
Text
76 lines
2.4 KiB
Text
b 0
|
|
b 1
|
|
b 2
|
|
b 2.5
|
|
t 0
|
|
t 1
|
|
t 2
|
|
t 2
|
|
{"version": 3,
|
|
"uri": "file:///incrementalTactic.lean",
|
|
"diagnostics":
|
|
[{"source": "Lean 4",
|
|
"severity": 1,
|
|
"range":
|
|
{"start": {"line": 4, "character": 4}, "end": {"line": 4, "character": 13}},
|
|
"message":
|
|
"tactic 'introN' failed, insufficient number of binders\na n : Nat\n⊢ True",
|
|
"fullRange":
|
|
{"start": {"line": 4, "character": 4}, "end": {"line": 4, "character": 13}}},
|
|
{"source": "Lean 4",
|
|
"severity": 1,
|
|
"range":
|
|
{"start": {"line": 2, "character": 22}, "end": {"line": 3, "character": 0}},
|
|
"message": "unsolved goals\nthis : Nat → Nat → True\n⊢ True",
|
|
"fullRange":
|
|
{"start": {"line": 2, "character": 22},
|
|
"end": {"line": 10, "character": 11}}}]}
|
|
{"version": 1,
|
|
"uri": "file:///incrementalTactic.lean",
|
|
"diagnostics":
|
|
[{"source": "Lean 4",
|
|
"severity": 1,
|
|
"range":
|
|
{"start": {"line": 1, "character": 38}, "end": {"line": 4, "character": 3}},
|
|
"message": "unexpected token '/-!'; expected ')', '_', identifier or term",
|
|
"fullRange":
|
|
{"start": {"line": 1, "character": 38},
|
|
"end": {"line": 4, "character": 3}}}]}
|
|
{"version": 1,
|
|
"uri": "file:///incrementalTactic.lean",
|
|
"diagnostics":
|
|
[{"source": "Lean 4",
|
|
"severity": 1,
|
|
"range":
|
|
{"start": {"line": 2, "character": 9}, "end": {"line": 2, "character": 11}},
|
|
"message": "unknown identifier 'no'",
|
|
"fullRange":
|
|
{"start": {"line": 2, "character": 9}, "end": {"line": 2, "character": 11}}},
|
|
{"source": "Lean 4",
|
|
"severity": 1,
|
|
"range":
|
|
{"start": {"line": 3, "character": 9}, "end": {"line": 3, "character": 16}},
|
|
"message": "unsolved goals\n⊢ Nat",
|
|
"fullRange":
|
|
{"start": {"line": 3, "character": 9},
|
|
"end": {"line": 3, "character": 16}}}]}
|
|
s
|
|
{ goals := #[{ type := Lean.Widget.TaggedText.tag
|
|
{ subexprPos := "/", diffStatus? := none }
|
|
(Lean.Widget.TaggedText.text "True"),
|
|
isInserted? := some false,
|
|
isRemoved? := none,
|
|
hyps := #[] }] }
|
|
|
|
{"version": 1,
|
|
"uri": "file:///incrementalTactic.lean",
|
|
"diagnostics":
|
|
[{"source": "Lean 4",
|
|
"severity": 1,
|
|
"range":
|
|
{"start": {"line": 2, "character": 8}, "end": {"line": 2, "character": 25}},
|
|
"message":
|
|
"tactic 'rewrite' failed, did not find instance of the pattern in the target expression\n 0\n⊢ True",
|
|
"fullRange":
|
|
{"start": {"line": 2, "character": 8},
|
|
"end": {"line": 2, "character": 25}}}]}
|