(** ** Discarding Irrelevant Hypotheses
        We will want to clear the context of any
        non-FSet-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 FSet_elt_Prop : Prop -> Prop :=
    | eq_Prop : forall (S : Type) (x y : S),
        FSet_elt_Prop (x = y)
    | eq_elt_prop : forall x y,
        FSet_elt_Prop (E.eq x y)
    | In_elt_prop : forall x s,
        FSet_elt_Prop (In x s)
    | True_elt_prop :
        FSet_elt_Prop True
    | False_elt_prop :
        FSet_elt_Prop False
    | conj_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P /\ Q)
    | disj_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P \/ Q)
    | impl_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P -> Q)
    | not_elt_prop : forall P,
        FSet_elt_Prop P ->
        FSet_elt_Prop (~ P).(** ** Discarding Irrelevant Hypotheses
        We will want to clear the context of any
        non-FSet-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 FSet_elt_Prop : Prop -> Prop :=
    | eq_Prop : forall (S : Type) (x y : S),
        FSet_elt_Prop (x = y)
    | eq_elt_prop : forall x y,
        FSet_elt_Prop (E.eq x y)
    | In_elt_prop : forall x s,
        FSet_elt_Prop (In x s)
    | True_elt_prop :
        FSet_elt_Prop True
    | False_elt_prop :
        FSet_elt_Prop False
    | conj_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P /\ Q)
    | disj_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P \/ Q)
    | impl_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P -> Q)
    | not_elt_prop : forall P,
        FSet_elt_Prop P ->
        FSet_elt_Prop (~ P).(** ** Discarding Irrelevant Hypotheses
        We will want to clear the context of any
        non-FSet-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 FSet_elt_Prop : Prop -> Prop :=
    | eq_Prop : forall (S : Type) (x y : S),
        FSet_elt_Prop (x = y)
    | eq_elt_prop : forall x y,
        FSet_elt_Prop (E.eq x y)
    | In_elt_prop : forall x s,
        FSet_elt_Prop (In x s)
    | True_elt_prop :
        FSet_elt_Prop True
    | False_elt_prop :
        FSet_elt_Prop False
    | conj_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P /\ Q)
    | disj_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P \/ Q)
    | impl_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P -> Q)
    | not_elt_prop : forall P,
        FSet_elt_Prop P ->
        FSet_elt_Prop (~ P).(** ** Discarding Irrelevant Hypotheses
        We will want to clear the context of any
        non-FSet-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 FSet_elt_Prop : Prop -> Prop :=
    | eq_Prop : forall (S : Type) (x y : S),
        FSet_elt_Prop (x = y)
    | eq_elt_prop : forall x y,
        FSet_elt_Prop (E.eq x y)
    | In_elt_prop : forall x s,
        FSet_elt_Prop (In x s)
    | True_elt_prop :
        FSet_elt_Prop True
    | False_elt_prop :
        FSet_elt_Prop False
    | conj_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P /\ Q)
    | disj_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P \/ Q)
    | impl_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P -> Q)
    | not_elt_prop : forall P,
        FSet_elt_Prop P ->
        FSet_elt_Prop (~ P).(** ** Discarding Irrelevant Hypotheses
        We will want to clear the context of any
        non-FSet-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 FSet_elt_Prop : Prop -> Prop :=
    | eq_Prop : forall (S : Type) (x y : S),
        FSet_elt_Prop (x = y)
    | eq_elt_prop : forall x y,
        FSet_elt_Prop (E.eq x y)
    | In_elt_prop : forall x s,
        FSet_elt_Prop (In x s)
    | True_elt_prop :
        FSet_elt_Prop True
    | False_elt_prop :
        FSet_elt_Prop False
    | conj_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P /\ Q)
    | disj_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P \/ Q)
    | impl_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P -> Q)
    | not_elt_prop : forall P,
        FSet_elt_Prop P ->
        FSet_elt_Prop (~ P).(** ** Discarding Irrelevant Hypotheses
        We will want to clear the context of any
        non-FSet-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 FSet_elt_Prop : Prop -> Prop :=
    | eq_Prop : forall (S : Type) (x y : S),
        FSet_elt_Prop (x = y)
    | eq_elt_prop : forall x y,
        FSet_elt_Prop (E.eq x y)
    | In_elt_prop : forall x s,
        FSet_elt_Prop (In x s)
    | True_elt_prop :
        FSet_elt_Prop True
    | False_elt_prop :
        FSet_elt_Prop False
    | conj_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P /\ Q)
    | disj_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P \/ Q)
    | impl_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P -> Q)
    | not_elt_prop : forall P,
        FSet_elt_Prop P ->
        FSet_elt_Prop (~ P).(** ** Discarding Irrelevant Hypotheses
        We will want to clear the context of any
        non-FSet-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 FSet_elt_Prop : Prop -> Prop :=
    | eq_Prop : forall (S : Type) (x y : S),
        FSet_elt_Prop (x = y)
    | eq_elt_prop : forall x y,
        FSet_elt_Prop (E.eq x y)
    | In_elt_prop : forall x s,
        FSet_elt_Prop (In x s)
    | True_elt_prop :
        FSet_elt_Prop True
    | False_elt_prop :
        FSet_elt_Prop False
    | conj_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P /\ Q)
    | disj_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P \/ Q)
    | impl_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P -> Q)
    | not_elt_prop : forall P,
        FSet_elt_Prop P ->
        FSet_elt_Prop (~ P).(** ** Discarding Irrelevant Hypotheses
        We will want to clear the context of any
        non-FSet-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 FSet_elt_Prop : Prop -> Prop :=
    | eq_Prop : forall (S : Type) (x y : S),
        FSet_elt_Prop (x = y)
    | eq_elt_prop : forall x y,
        FSet_elt_Prop (E.eq x y)
    | In_elt_prop : forall x s,
        FSet_elt_Prop (In x s)
    | True_elt_prop :
        FSet_elt_Prop True
    | False_elt_prop :
        FSet_elt_Prop False
    | conj_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P /\ Q)
    | disj_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P \/ Q)
    | impl_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P -> Q)
    | not_elt_prop : forall P,
        FSet_elt_Prop P ->
        FSet_elt_Prop (~ P).(** ** Discarding Irrelevant Hypotheses
        We will want to clear the context of any
        non-FSet-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 FSet_elt_Prop : Prop -> Prop :=
    | eq_Prop : forall (S : Type) (x y : S),
        FSet_elt_Prop (x = y)
    | eq_elt_prop : forall x y,
        FSet_elt_Prop (E.eq x y)
    | In_elt_prop : forall x s,
        FSet_elt_Prop (In x s)
    | True_elt_prop :
        FSet_elt_Prop True
    | False_elt_prop :
        FSet_elt_Prop False
    | conj_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P /\ Q)
    | disj_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P \/ Q)
    | impl_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P -> Q)
    | not_elt_prop : forall P,
        FSet_elt_Prop P ->
        FSet_elt_Prop (~ P).(** ** Discarding Irrelevant Hypotheses
        We will want to clear the context of any
        non-FSet-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 FSet_elt_Prop : Prop -> Prop :=
    | eq_Prop : forall (S : Type) (x y : S),
        FSet_elt_Prop (x = y)
    | eq_elt_prop : forall x y,
        FSet_elt_Prop (E.eq x y)
    | In_elt_prop : forall x s,
        FSet_elt_Prop (In x s)
    | True_elt_prop :
        FSet_elt_Prop True
    | False_elt_prop :
        FSet_elt_Prop False
    | conj_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P /\ Q)
    | disj_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P \/ Q)
    | impl_elt_prop : forall P Q,
        FSet_elt_Prop P ->
        FSet_elt_Prop Q ->
        FSet_elt_Prop (P -> Q)
    | not_elt_prop : forall P,
        FSet_elt_Prop P ->
        FSet_elt_Prop (~ P).Inductive FSet_Prop : Prop -> Prop :=
    | elt_FSet_Prop : forall P,
        FSet_elt_Prop P ->
        FSet_Prop P
    | Empty_FSet_Prop : forall s,
        FSet_Prop (Empty s)
    | Subset_FSet_Prop : forall s1 s2,
        FSet_Prop (Subset s1 s2)
    | Equal_FSet_Prop : forall s1 s2,
        FSet_Prop (Equal s1 s2).Inductive FSet_Prop : Prop -> Prop :=
    | elt_FSet_Prop : forall P,
        FSet_elt_Prop P ->
        FSet_Prop P
    | Empty_FSet_Prop : forall s,
        FSet_Prop (Empty s)
    | Subset_FSet_Prop : forall s1 s2,
        FSet_Prop (Subset s1 s2)
    | Equal_FSet_Prop : forall s1 s2,
        FSet_Prop (Equal s1 s2).Inductive FSet_Prop : Prop -> Prop :=
    | elt_FSet_Prop : forall P,
        FSet_elt_Prop P ->
        FSet_Prop P
    | Empty_FSet_Prop : forall s,
        FSet_Prop (Empty s)
    | Subset_FSet_Prop : forall s1 s2,
        FSet_Prop (Subset s1 s2)
    | Equal_FSet_Prop : forall s1 s2,
        FSet_Prop (Equal s1 s2).Inductive FSet_Prop : Prop -> Prop :=
    | elt_FSet_Prop : forall P,
        FSet_elt_Prop P ->
        FSet_Prop P
    | Empty_FSet_Prop : forall s,
        FSet_Prop (Empty s)
    | Subset_FSet_Prop : forall s1 s2,
        FSet_Prop (Subset s1 s2)
    | Equal_FSet_Prop : forall s1 s2,
        FSet_Prop (Equal s1 s2).Inductive FSet_Prop : Prop -> Prop :=
    | elt_FSet_Prop : forall P,
        FSet_elt_Prop P ->
        FSet_Prop P
    | Empty_FSet_Prop : forall s,
        FSet_Prop (Empty s)
    | Subset_FSet_Prop : forall s1 s2,
        FSet_Prop (Subset s1 s2)
    | Equal_FSet_Prop : forall s1 s2,
        FSet_Prop (Equal s1 s2).Ltac discard_nonFSet :=
      repeat (
        match goal with
        | H : ?P |- _ =>
          if prop (FSet_Prop P) holds by
            (auto 100 with FSet_Prop)
          then fail
          else clear H
        end).

Lemma dec_eq : forall (x y : E.t), decidable (E.eq x y).