(*************************************************************************)
(** * Renaming *)
(*************************************************************************)
(* Substitution and weakening together give us a property we call renaming: (see [typing_c_rename below] that we can change the name of the variable used to open an expression in a typing derivation. In practice, this means that if a variable is not "fresh enough" during a proof, we can use this lemma to rename it to one with additional freshness constraints.  Renaming is used below to show the correspondence between the exists-fresh version of the rules with the cofinite version, and also to show that typechecking is decidable. *)
(* However, before we prove renaming, we need an auxiliary lemma about typing judgments which says that terms are well-typed only in unique environments. *)

(* Specifications: *)
Lemma typing_c_uniq : forall E e T,
typing_c E e T -> uniq E.
(* Demo: the proof of renaming.  Note that this proof does not proceed by induction: even if we add new typing rules to the language, as long as the weakening and substution properties hold we can use this proof. *)
Lemma typing_c_rename : forall (x y : atom) E e T1 T2,
x `notin` fv e -> y `notin` (dom E `union` fv e) ->
typing_c ((x ~ T1) ++ E) (open e x) T2 ->
typing_c ((y ~ T1) ++ E) (open e y) T2.