Module fc_subst (wf : fc_wf_sig) (weak : fc_weak_sig) <: fc_subst_sig.
Export wf.
Export weak.
Set Bullet Behavior "Strict Subproofs".
Set Implicit Arguments.
(* --------------------------------------- *)
induction G0; auto; try done.
destruct a as [x s].
intros a b A c H H0.
destruct s; auto; try done.
case H0; try done.
+ move => h0;
simpl_env;
eapply AnnPropWff_weakening with (F:=nil); eauto; simpl_env;
inversion H; subst;
apply (IHG0 _ _ _ c); eauto.
+ destruct H0; subst.
inversion H0; subst.
inversion H; subst.
rewrite_env (nil ++ [(c, Co (Eq a b A))] ++ G0).
eapply AnnPropWff_weakening; eauto.
rewrite_env (nil ++ [(x, Co phi)] ++ G0).
eapply AnnPropWff_weakening; eauto.
simpl.
inversion H; subst.
apply (IHG0 _ _ _ c); auto.
Qed.
(* --------------------------------------- *)
(* Lemma co_subst_fresh : forall G phi a0 x s, AnnPropWff G phi -> AnnCtx ((x ~ s) ++ G) -> tm_subst_tm_constraint a0 x phi = phi. *)
(* --------------------------------------- *)
(* ------------------------------------------- *)
(* In the case of a binding term, prepare the environment in the goal for a use of the induction hypothesis *)
Ltac prepare_env :=
match goal with
[ |- context[ (?x' ~ (?S (?sub ?a1 ?x ?A))) ++ map (?tm_subst_tm_sort ?a1 ?x) ?F ++ ?G ] ] =>
rewrite -app_assoc;
replace (x' ~ (S (sub a1 x A)) ++  map (tm_subst_tm_sort a1 x) F) with
(map (tm_subst_tm_sort a1 x) (x' ~ S A ++ F)); eauto using map_app
end.
(* Find a binding for a prop in a well-formed context and invert it. *)
Ltac binds_PropWff_inversion :=
let wff := fresh in
match goal with
[ bind_c : binds ?c (Co (Eq ?a ?b ?A)) ?G0 |- _ ] =>
move: (@binds_to_AnnPropWff G0 _ _ _ _ ltac:(eauto with ctx_wff) bind_c) => wff;
inversion wff; subst
end.
(* --------------------------------------- *)
(* Convenience lemmas for working with substitution. *)

Lemma AnnTyping_tm_subst_nondep : forall L G a A b B,
AnnTyping G a A ->
(forall x, x `notin` L -> AnnTyping ([(x,Tm A)] ++ G) (open_tm_wrt_tm b (a_Var_f x)) B) ->
AnnTyping G (open_tm_wrt_tm b a) B.