(* ********************************************************************* *)
  (** ** The [solve_uniq] tactic *)

  (** This tactic attempts to solve goals about [uniq].  Given its
      definition, it's likely to work only when the hypotheses in the
      goal already contain all the relevant [uniq] propositions.
      Thus, the tactic may not be generally useful.  It is useful,
      however, for proving facts about [uniq] such as the ones below.

      Implementation note: The second [simpl_asnlist] in the definition
      is because of [disjoint_one_{l,r}].  The "[|| fail]" at the end
      is so that in the case of failure, the error message reported to
      the user is not the one from [fsetdec]. *)

  Ltac solve_uniq :=
    try trivial;
    simpl_asnlist in *;
    autorewrite with rewr_uniq in *;
    simpl_asnlist in *;
    intuition (
      auto using uniq_nil, uniq_one_1 ||
      (rewrite -> disjoint_sym; auto) ||
      (unfold disjoint in *; fsetdec))
    || fail.

Lemma binds_app_uniq : uniq (E ++ F) -> (binds x a (E ++ F) <-> (binds x a E /\ x `notin` dom F) \/ (binds x a F /\ x `notin` dom E)).