(*************************************************************************)
(** * Substitution *)
(*************************************************************************)
(** Having proved weakening, we can now prove the usual substitution lemma, which we state both in the form we need and in the strengthened form needed to make the proof go through.  << typing_c_subst_simple : forall E e u S T z, typing_c ((z ~ S) ++ E) e T -> typing_c E u S -> typing_c E ([z ~> u] e) T  typing_c_subst : forall E F e u S T z, typing_c (F ++ (z ~ S) ++ E) e T -> typing_c E u S -> typing_c (F ++ E) ([z ~> u] e) T >>  The proof of the strengthened statement proceeds by induction on the given typing derivation for [e].  The most involved case is the one for variables; the others follow from the induction hypotheses. *)
(** *** Exercise  Below, we state what needs to be proved in the [typing_var_c] case of the substitution lemma.  Fill in the proof.  Proof sketch: The proof proceeds by a case analysis on [(x == z)], i.e., whether the two variables are the same or not.  - If [(x = z)], then we need to show [(typing (F ++ E) u T)]. This follows from the given typing derivation for [u] by weakening and the fact that [T] must equal [S].  - If [(x <> z)], then we need to show [(typing (F ++ E) x T)]. This follows by the typing rule for variables.  HINTS: Lemmas [binds_mid_eq], [uniq_remove_mid], and [binds_remove_mid] are useful.  *)

(* Specifications: *)
Lemma typing_subst_var_case : forall (E F : env) u S T (z x : atom),
binds x T (F ++ (z ~ S) ++ E) ->
uniq (F ++ (z ~ S) ++ E) ->
typing_c E u S ->
typing_c (F ++ E) ([z ~> u] x) T.
Lemma typing_subst_var_case : forall (E F : env) u S T (z x : atom),
binds x T (F ++ (z ~ S) ++ E) ->
uniq (F ++ (z ~ S) ++ E) ->
typing_c E u S ->
typing_c (F ++ E) ([z ~> u] x) T.