Skip to content

Commit 63354ce

Browse files
authored
fix: spurious invariant instantiation in mspec by rfl (#10641)
This PR ensures that the `mspec` and `mvcgen` tactics no longer spuriously instantiate loop invariants by `rfl`.
1 parent 3095c9d commit 63354ce

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed

src/Lean/Elab/Tactic/Do/Spec.lean

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,16 @@ def mSpec (goal : MGoal) (elabSpecAtWP : Expr → n SpecTheorem) (goalTag : Name
159159
mTryFrame goal fun goal => do
160160

161161
-- Fully instantiate the specThm without instantiating its MVars to `wp` yet
162-
let (_, _, spec, specTy) ← specThm.proof.instantiate
162+
let (mvars, _, spec, specTy) ← specThm.proof.instantiate
163+
164+
-- Instantiation creates `.natural` MVars, which possibly get instantiated by the def eq checks
165+
-- below when they occur in `P` or `Q`.
166+
-- That's good for many such as MVars ("schematic variables"), but problematic for MVars
167+
-- corresponding to `Invariant`s, which should end up as user goals.
168+
-- To prevent accidental instantiation, we mark all `Invariant` MVars as synthetic opaque.
169+
for mvar in mvars do
170+
let ty ← mvar.mvarId!.getType
171+
if ty.isAppOf ``Invariant then mvar.mvarId!.setKind .syntheticOpaque
163172

164173
-- Apply the spec to the excess arguments of the `wp⟦e⟧ Q` application
165174
let T := goal.target.consumeMData
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import Std.Tactic.Do
2+
import Std.Do.WP.Basic
3+
4+
def tst (n : Nat) : Vector Bool n := Id.run do
5+
let mut res : Vector Bool n := .ofFn fun _ ↦ false
6+
for i in [:n] do
7+
for j in [:n] do
8+
if i = j ∧ i % 2 = 0 then
9+
res := res.set! i true
10+
return res
11+
12+
set_option warn.sorry false in
13+
open Std.Do in
14+
example (n i : Nat) (h : i < n) : (tst n)[i] = (i % 2 == 0) := by
15+
generalize h : tst n = bs
16+
apply Std.Do.Id.of_wp_run_eq h
17+
mvcgen
18+
-- We should see `inv1` and `inv2` here as separate goals.
19+
-- `inv2` should not have been spuriously instantiated in terms of `inv1`.
20+
-- Used to happen because `inv2` was born natural and got instantiated in a .rfl test.
21+
case inv1 => sorry
22+
case inv2 => sorry
23+
all_goals sorry

0 commit comments

Comments
 (0)