(* -------------------------------
   Find a better place for these tactics
*)
Ltac expand sub_tm tm :=
  match tm with
  | (a_Abs ?rho (_ ?A1) (_ ?b)) =>
    replace (a_Abs rho (sub_tm A1) (sub_tm b)) with (sub_tm (a_Abs rho A1 b)); auto
  | (a_Pi ?rho (_ ?A1) (_ ?B1)) =>
    replace (a_Pi rho (sub_tm A1) (sub_tm B1)) with (sub_tm (a_Pi rho A1 B1)); auto
  | (a_CAbs (?sc ?phi) (_ ?B)) =>
    replace (a_CAbs (sc phi) (sub_tm B)) with (sub_tm (a_CAbs phi B)); auto
  | (a_CPi (?sc ?phi) (_ ?B)) =>
    replace (a_CPi (sc phi) (sub_tm B)) with (sub_tm (a_CPi phi B)); auto

  | a_Star => replace a_Star with (sub_tm a_Star); auto

  | _ => idtac
  end.Ltac expand_constraint sub_tm sub_constraint constraint :=
  match constraint with
  | (Eq (_ _ _ ?a) (_ _ _  ?b) (_ _ _ ?A)) =>
    replace (Eq (sub_tm a) (sub_tm b) (sub_tm A)) with
    (sub_constraint (Eq a b A)); auto
  | _ => idtac
  end.Ltac un_subst_tm :=
   match goal with
   | [ |- context [tm_subst_tm_tm ?g ?c _] ] =>
     match goal with
     | [ |- Typing _ ?a ?A ] => expand (tm_subst_tm_tm g c) a; expand (tm_subst_tm_tm g c) A
     | [ |- DefEq _ _ ?a ?b ] => expand (tm_subst_tm_tm g c) a; expand (tm_subst_tm_tm g c) b
     | [ |- PropWff ?phi ] => expand_constraint (tm_subst_tm_tm g c) (tm_subst_tm_constraint g c) phi
     end
   | [ |- context [co_subst_co_tm ?g ?c _] ] =>
     match goal with
     | [ |- Typing _ ?a ?A ] => expand (co_subst_co_tm g c) a; expand (co_subst_co_tm g c) A
     | [ |- DefEq _ _ ?a ?b ] => expand (co_subst_co_tm g c) a; expand (co_subst_co_tm g c) b
     | [ |- PropWff ?phi ] => expand_constraint (co_subst_co_tm g c) (co_subst_co_constraint g c) phi
     end
   end.

Lemma invert_a_App_Rel : forall G a b C, Typing G (a_App a Rel b) C -> exists A B, Typing G a (a_Pi Rel A B) /\ Typing G b A /\ DefEq G (dom G) C (open_tm_wrt_tm B b) a_Star.