0

Consider the following development, an isolated part of Adam Chlipala's simplHyp:

(** Fail if H is in context *)
Ltac notInCtx H := assert H; [ assumption | fail 1 ] || idtac.

Ltac injectionInCtx :=
  match goal with
  (* Is matching on G strictly necessary? *)
  | [ H : ?F ?X = ?F ?Y |- ?G ] =>
    (* fail early if it wouldn't progress *)
    notInCtx (X = Y); 
    injection H;
    match goal with
      (* G is used here *)
      | [ |- X = Y -> G ] =>
        try clear H; intros; try subst
    end
  end.

Goal forall (x y : nat), S x = S y -> x = y.
  intros x y H.
  injectionInCtx.
  exact eq_refl.
Qed.

See the comments inline - G is matched at the outset, and eventually used to verify that the end goal remains the same. Is this to preclude the possibility that injection H might modify the goal or add extraneous assumptions?

Carl Patenaude Poulin
  • 6,238
  • 5
  • 24
  • 46
  • `injection` does [modify the goal](https://coq.inria.fr/refman/proof-engine/tactics.html#coq:tacn.injection): "the tactic derives the equality of all the subterms at positions where they differ and **adds them as antecedents to the conclusion of the current goal**." – Anton Trunov Oct 14 '18 at 16:16
  • Right, my wording is incorrect but I don't know how to do better. My point is, can the pattern `| [ |- X = Y -> G ] =>` ever fail to match? – Carl Patenaude Poulin Oct 14 '18 at 16:49
  • 1
    Sure, `Goal forall l n, cons n l = cons 0 nil -> n = 0. intros l n H. injection H. Undo. Fail injectionInCtx. Abort.` – Anton Trunov Oct 14 '18 at 17:08
  • For the versions of Coq I have tested, this last example fails at the first match, not at the second one. – eponier Oct 17 '18 at 12:16

1 Answers1

1

I do not think you can modify G, but you can craft an hypothesis from which injection will generate more than one equality.

We define injectionInCtx2 which is identical to injectionInCtx except that it does not use G.

Ltac injectionInCtx2 :=
  match goal with
  | [ H : ?F ?X = ?F ?Y |- _ ] =>
    (* fail early if it wouldn't progress *)
    notInCtx (X = Y);
    injection H;
    match goal with
    | [ |- X = Y -> _ ] =>
      try clear H; intros; try subst
    end
  end.

Definition make_pair {A} (n:A) := (n, n).

Goal forall (x y : nat), make_pair x = make_pair y -> x = y.
Proof.
  intros x y H.
  (* [injection H] gives [x = y -> x = y -> x = y] *)
  Fail injectionInCtx.
  injectionInCtx2.
  reflexivity.
Qed.
eponier
  • 3,062
  • 9
  • 20