End MSetLogicalFacts.
(** * Auxiliary Tactics Again, these lemmas and tactics are in a module so that they do not affect the namespace if you import the enclosing module [Decide].  *)
Module MSetDecideAuxiliary.
(** ** Generic Tactics We begin by defining a few generic, useful tactics. *)
(** remove logical hypothesis inter-dependencies (fix #2136). *)
Ltac no_logical_interdep :=
match goal with
| H : ?P |- _ =>
match type of P with
| Prop =>
match goal with H' : context [ H ] |- _ => clear dependent H' end
| _ => fail
end; no_logical_interdep
| _ => idtac
end.
Ltac abstract_term t :=
tryif (is_var t) then fail "no need to abstract a variable"
else (let x := fresh "x" in set (x := t) in *; try clearbody x).
Ltac abstract_elements :=
repeat
(match goal with
| |- context [ singleton ?t ] => abstract_term t
| _ : context [ singleton ?t ] |- _ => abstract_term t
| |- context [ add ?t _ ] => abstract_term t
| _ : context [ add ?t _ ] |- _ => abstract_term t
| |- context [ remove ?t _ ] => abstract_term t
| _ : context [ remove ?t _ ] |- _ => abstract_term t
| |- context [ In ?t _ ] => abstract_term t
| _ : context [ In ?t _ ] |- _ => abstract_term t
end).
(** [prop P holds by t] succeeds (but does not modify the goal or context) if the proposition [P] can be proved by [t] in the current context.  Otherwise, the tactic fails. *)
Tactic Notation "prop" constr(P) "holds" "by" tactic(t) :=
let H := fresh in
assert P as H by t;
clear H.
(** This tactic acts just like [assert ... by ...] but will fail if the context already contains the proposition. *)
Tactic Notation "assert" "new" constr(e) "by" tactic(t) :=
match goal with
| H: e |- _ => fail 1
| _ => assert e by t
end.
(** [subst++] is similar to [subst] except that - it never fails (as [subst] does on recursive equations), - it substitutes locally defined variable for their definitions, - it performs beta reductions everywhere, which may arise after substituting a locally defined function for its definition. *)
Tactic Notation "subst" "++" :=
repeat (
match goal with
| x : _ |- _ => subst x
end);
cbv zeta beta in *.
(** [decompose records] calls [decompose record H] on every relevant hypothesis [H]. *)
Tactic Notation "decompose" "records" :=
repeat (
match goal with
| H: _ |- _ => progress (decompose record H); clear H
end).
(** ** Discarding Irrelevant Hypotheses We will want to clear the context of any non-MSet-related hypotheses in order to increase the speed of the tactic.  To do this, we will need to be able to decide which are relevant.  We do this by making a simple inductive definition classifying the propositions of interest. *)
Inductive MSet_elt_Prop : Prop -> Prop :=
| eq_Prop : forall (S : Type) (x y : S),
MSet_elt_Prop (x = y)
| eq_elt_prop : forall x y,
MSet_elt_Prop (E.eq x y)
| In_elt_prop : forall x s,
MSet_elt_Prop (In x s)
| True_elt_prop :
MSet_elt_Prop True
| False_elt_prop :
MSet_elt_Prop False
| conj_elt_prop : forall P Q,
MSet_elt_Prop P ->
MSet_elt_Prop Q ->
MSet_elt_Prop (P /\ Q)
| disj_elt_prop : forall P Q,
MSet_elt_Prop P ->
MSet_elt_Prop Q ->
MSet_elt_Prop (P \/ Q)
| impl_elt_prop : forall P Q,
MSet_elt_Prop P ->
MSet_elt_Prop Q ->
MSet_elt_Prop (P -> Q)
| not_elt_prop : forall P,
MSet_elt_Prop P ->
MSet_elt_Prop (~ P).
Inductive MSet_Prop : Prop -> Prop :=
| elt_MSet_Prop : forall P,
MSet_elt_Prop P ->
MSet_Prop P
| Empty_MSet_Prop : forall s,
MSet_Prop (Empty s)
| Subset_MSet_Prop : forall s1 s2,
MSet_Prop (Subset s1 s2)
| Equal_MSet_Prop : forall s1 s2,
MSet_Prop (Equal s1 s2).
(** Here is the tactic that will throw away hypotheses that are not useful (for the intended scope of the [fsetdec] tactic). *)
#[global]
Hint Constructors MSet_elt_Prop MSet_Prop : MSet_Prop.
Ltac discard_nonMSet :=
repeat (
match goal with
| H : context [ @Logic.eq ?T ?x ?y ] |- _ =>
tryif (change T with E.t in H) then fail
else tryif (change T with t in H) then fail
else clear H
| H : ?P |- _ =>
tryif prop (MSet_Prop P) holds by
(auto 100 with MSet_Prop)
then fail
else clear H
end).
(** ** Turning Set Operators into Propositional Connectives The lemmas from [MSetFacts] will be used to break down set operations into propositional formulas built over the predicates [In] and [E.eq] applied only to variables.  We are going to use them with [autorewrite]. *)
Global Hint Rewrite
F.empty_iff F.singleton_iff F.add_iff F.remove_iff
F.union_iff F.inter_iff F.diff_iff
: set_simpl.

Lemma eq_refl_iff (x : E.t) : E.eq x x <-> True.
Global Hint Rewrite eq_refl_iff : set_eq_simpl.