(* --------------------------------------------------------------------- *)
(* 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_CPiCong_exists :  ∀ c1 c2 (G : context) D (g1 g3 : co) (phi1 : constraint)
(B1 : tm) (phi2 : constraint) (B3 B2 : tm),
AnnIso G D g1 phi1 phi2
-> c1 `notin` D \u fv_co_co_tm B2 \u fv_co_co_tm B1 \u fv_co_co_co g3
-> c2 `notin` fv_co_co_co g1 \u fv_co_co_tm B2 \u fv_co_co_tm B3
→ (AnnDefEq ([(c1, Co phi1)] ++ G) D (open_co_wrt_co g3 (g_Var_f c1))
(open_tm_wrt_co B1 (g_Var_f c1)) (open_tm_wrt_co B2 (g_Var_f c1)))
→ (open_tm_wrt_co B3 (g_Var_f c2) =
open_tm_wrt_co B2 (g_Cast (g_Var_f c2) (g_Sym g1)))
→ AnnTyping G (a_CPi phi1 B1) a_Star
→ AnnTyping G (a_CPi phi2 B3) a_Star
-> AnnTyping G (a_CPi phi1 B2) a_Star
→ AnnDefEq G D (g_CPiCong g1 g3) (a_CPi phi1 B1)
(a_CPi phi2 B3).