(* --------------------------------------------------------------------- *)
(* This is the place for "smart constructors" and "smart inversion" lemmas. They are especialy useful for constructing derivations from a particular variable and avoiding the co-finite quantification stuff.  *)
(* In a locally nameless development, these should be stated and immediately proven after substitution. *)

Lemma An_CAbsCong_exists :
forall c1 c2 (G : context) (D : available_props) (g1 g3 g4 : co)
(phi1 : constraint) (a1 : tm) (phi2 : constraint) (a3 a2 B1 B2 B : tm),
AnnIso G D g1 phi1 phi2
-> c1 `notin` D \u fv_co_co_tm a2 \u fv_co_co_tm a1 \u fv_co_co_co g3
-> c2 `notin` fv_co_co_co g1 \u fv_co_co_tm a2 \u fv_co_co_tm a3
→ (AnnDefEq ([(c1, Co phi1)] ++ G) D (open_co_wrt_co g3 (g_Var_f c1))
(open_tm_wrt_co a1 (g_Var_f c1)) (open_tm_wrt_co a2 (g_Var_f c1)))
→ (open_tm_wrt_co a3 (g_Var_f c2) =
open_tm_wrt_co a2 (g_Cast (g_Var_f c2) (g_Sym g1)))
→ AnnTyping G (a_CAbs phi1 a1) (a_CPi phi1 B1)
→ AnnTyping G (a_CAbs phi2 a3) (a_CPi phi2 B2)
→ AnnDefEq G (dom G) g4 (a_CPi phi1 B1) (a_CPi phi2 B2)
-> AnnTyping G (a_CAbs phi1 a2) B
→ AnnDefEq G D (g_CAbsCong g1 g3 g4) (a_CAbs phi1 a1) (a_CAbs phi2 a3).