Commit fdfc790d authored by Robbert Krebbers's avatar Robbert Krebbers
Browse files

Make iDestruct smarter about when to copy a hypothesis.

It now copies the hypothesis when: 1.) it is persistent 2.) when destructing
it requires a universal quantifier to be instantiated. The new behavior is
implemented using a type class (called CopyDestruct) so that it can easily be
extended.
parent 1be17c0d
...@@ -958,7 +958,27 @@ Tactic Notation "iRevertIntros" "(" ident(x1) ident(x2) ident(x3) ident(x4) ...@@ -958,7 +958,27 @@ Tactic Notation "iRevertIntros" "(" ident(x1) ident(x2) ident(x3) ident(x4)
iRevertIntros (x1 x2 x3 x4 x5 x6 x7 x8) "" with tac. iRevertIntros (x1 x2 x3 x4 x5 x6 x7 x8) "" with tac.
(** * Destruct tactic *) (** * Destruct tactic *)
Class CopyDestruct {M} (P : uPred M).
Hint Mode CopyDestruct + ! : typeclass_instances.
Instance copy_destruct_forall {M A} (Φ : A uPred M) : CopyDestruct ( x, Φ x).
Instance copy_destruct_impl {M} (P Q : uPred M) :
CopyDestruct Q CopyDestruct (P Q).
Instance copy_destruct_wand {M} (P Q : uPred M) :
CopyDestruct Q CopyDestruct (P - Q).
Instance copy_destruct_always {M} (P : uPred M) :
CopyDestruct P CopyDestruct ( P).
Tactic Notation "iDestructCore" open_constr(lem) "as" constr(p) tactic(tac) := Tactic Notation "iDestructCore" open_constr(lem) "as" constr(p) tactic(tac) :=
let hyp_name :=
lazymatch type of lem with
| string => constr:(Some lem)
| iTrm =>
lazymatch lem with
| @iTrm string ?H _ _ => constr:(Some H) | _ => constr:(@None string)
end
| _ => constr:(@None string)
end in
let intro_destruct n := let intro_destruct n :=
let rec go n' := let rec go n' :=
lazymatch n' with lazymatch n' with
...@@ -972,14 +992,25 @@ Tactic Notation "iDestructCore" open_constr(lem) "as" constr(p) tactic(tac) := ...@@ -972,14 +992,25 @@ Tactic Notation "iDestructCore" open_constr(lem) "as" constr(p) tactic(tac) :=
| Z => (* to make it work in Z_scope. We should just be able to bind | Z => (* to make it work in Z_scope. We should just be able to bind
tactic notation arguments to notation scopes. *) tactic notation arguments to notation scopes. *)
let n := eval compute in (Z.to_nat lem) in intro_destruct n let n := eval compute in (Z.to_nat lem) in intro_destruct n
| string => tac lem | _ =>
| iTrm => (* Only copy the hypothesis in case there is a [CopyDestruct] instance.
(* only copy the hypothesis when universal quantifiers are instantiated *) Also, rule out cases in which it does not make sense to copy, namely when
lazymatch lem with destructing a lemma (instead of a hypothesis) or a spatial hyopthesis
| @iTrm string ?H _ hnil ?pat => iSpecializeCore lem as p; last tac (which cannot be kept). *)
| _ => iPoseProofCore lem as p false tac lazymatch hyp_name with
| None => iPoseProofCore lem as p false tac
| Some ?H => iTypeOf H (fun q P =>
lazymatch q with
| true =>
(* persistent hypothesis, check for a CopyDestruct instance *)
tryif (let dummy := constr:(_ : CopyDestruct P) in idtac)
then (iPoseProofCore lem as p false tac)
else (iSpecializeCore lem as p; last (tac H))
| false =>
(* spatial hypothesis, cannot copy *)
iSpecializeCore lem as p; last (tac H)
end)
end end
| _ => iPoseProofCore lem as p false tac
end. end.
Tactic Notation "iDestruct" open_constr(lem) "as" constr(pat) := Tactic Notation "iDestruct" open_constr(lem) "as" constr(pat) :=
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment