diff --git a/tests/tactics.v b/tests/tactics.v index 715e747db6d7b30ac1bbe2d91ac8c18709fcd2c7..b91a47339b2dab2a042a985aae239ad53ed6629e 100644 --- a/tests/tactics.v +++ b/tests/tactics.v @@ -55,6 +55,11 @@ Proof. intros ?. rename select nat into m. exists m. done. Qed. Goal ∀ (P : nat → Prop), P 3 → P 4 → P 4. Proof. intros P **. rename select (P _) into HP4. apply HP4. Qed. +(** Regression tests for [naive_solver]. *) +Lemma naive_solver_issue_115 (P : nat → Prop) (x : nat) : + (∀ x', P x' → x' = 10) → P x → x + 1 = 11. +Proof. naive_solver. Qed. + (** [mk_evar] works on things that coerce to types. *) (** This is a feature when we have packed structures, for example Iris's [ofe] (fields other than the carrier omitted). *) @@ -63,7 +68,6 @@ Goal ∀ A : ofe, True. intros A. let x := mk_evar A in idtac. Abort. - (** More surprisingly, it also works for other coercions into a universe, like [Is_true : bool → Prop]. *) Goal True. diff --git a/theories/tactics.v b/theories/tactics.v index d3910a89c7e524253793f239617aa8d8015b64d7..6ec949e0612abbc35a2c2ca994a7c028c850617f 100644 --- a/theories/tactics.v +++ b/theories/tactics.v @@ -222,8 +222,21 @@ current context. This is usually a more useful behavior than Coq's [evar], which is a side-effecting tactic (not returning anything) that introduces a local -definition into the context that holds the evar. *) -Ltac mk_evar T := open_constr:(_ : T). +definition into the context that holds the evar. +Note that the obvious alternative [open_constr (_:T)] has subtly different +behavior, see std++ issue 115. + +Usually, Ltacs cannot return a value and have a side-effect, but we use the +trick described at +<https://stackoverflow.com/questions/45949064/check-for-evars-in-a-tactic-that-returns-a-value/46178884#46178884> +to work around that: wrap the side-effect in a [match goal]. *) +Ltac mk_evar T := + let T := constr:(T : Type) in + let e := fresh in + let _ := match goal with _ => evar (e:T) end in + let e' := eval unfold e in e in + let _ := match goal with _ => clear e end in + e'. (** The tactic [eunify x y] succeeds if [x] and [y] can be unified, and fails otherwise. If it succeeds, it will instantiate necessary evars in [x] and [y].