Fixpoint subst_te (Z : atom) (U : typ) (e : exp) {struct e} : exp :=
  match e with
  | exp_bvar i => exp_bvar i
  | exp_fvar x => exp_fvar x
  | exp_abs V e1 => exp_abs  (subst_tt Z U V)  (subst_te Z U e1)
  | exp_app e1 e2 => exp_app  (subst_te Z U e1) (subst_te Z U e2)
  | exp_tabs V e1 => exp_tabs (subst_tt Z U V)  (subst_te Z U e1)
  | exp_tapp e1 V => exp_tapp (subst_te Z U e1) (subst_tt Z U V)
  | exp_let e1 e2 => exp_let (subst_te Z U e1) (subst_te Z U e2)
  | exp_inl e1 => exp_inl (subst_te Z U e1)
  | exp_inr e1 => exp_inr (subst_te Z U e1)
  | exp_case e1 e2 e3 => exp_case (subst_te Z U e1)
                                  (subst_te Z U e2) (subst_te Z U e3)
  end.Definition subst_tb (Z : atom) (P : typ) (b : binding) : binding :=
  match b with
  | bind_sub T => bind_sub (subst_tt Z P T)
  | bind_typ T => bind_typ (subst_tt Z P T)
  end.

(* Specifications: *)
Lemma open_tt_rec_type_aux : forall T j V i U, i <> j -> open_tt_rec j V T = open_tt_rec i U (open_tt_rec j V T) -> T = open_tt_rec i U T.
Lemma open_tt_rec_type : forall T U k, type T -> T = open_tt_rec k U T.
Lemma subst_tt_open_tt_rec : forall T1 T2 X P k, type P -> subst_tt X P (open_tt_rec k T2 T1) = open_tt_rec k (subst_tt X P T2) (subst_tt X P T1).
Lemma subst_tt_open_tt : forall T1 T2 (X:atom) P, type P -> subst_tt X P (open_tt T1 T2) = open_tt (subst_tt X P T1) (subst_tt X P T2).
Lemma subst_tt_open_tt_var : forall (X Y:atom) P T, Y <> X -> type P -> open_tt (subst_tt X P T) Y = subst_tt X P (open_tt T Y).
Lemma open_te_rec_expr_aux : forall e j u i P , open_ee_rec j u e = open_te_rec i P (open_ee_rec j u e) -> e = open_te_rec i P e.
Lemma open_te_rec_type_aux : forall e j Q i P, i <> j -> open_te_rec j Q e = open_te_rec i P (open_te_rec j Q e) -> e = open_te_rec i P e.
Lemma open_te_rec_expr : forall e U k, expr e -> e = open_te_rec k U e.
Lemma subst_te_open_te_rec : forall e T X U k, type U -> subst_te X U (open_te_rec k T e) = open_te_rec k (subst_tt X U T) (subst_te X U e).
Lemma subst_te_open_te : forall e T X U, type U -> subst_te X U (open_te e T) = open_te (subst_te X U e) (subst_tt X U T).
Lemma subst_te_open_te_var : forall (X Y:atom) U e, Y <> X -> type U -> open_te (subst_te X U e) Y = subst_te X U (open_te e Y).
Lemma open_ee_rec_expr_aux : forall e j v u i, i <> j -> open_ee_rec j v e = open_ee_rec i u (open_ee_rec j v e) -> e = open_ee_rec i u e.
Lemma open_ee_rec_type_aux : forall e j V u i, open_te_rec j V e = open_ee_rec i u (open_te_rec j V e) -> e = open_ee_rec i u e.
Lemma open_ee_rec_expr : forall u e k, expr e -> e = open_ee_rec k u e.
Lemma subst_ee_open_ee_rec : forall e1 e2 x u k, expr u -> subst_ee x u (open_ee_rec k e2 e1) = open_ee_rec k (subst_ee x u e2) (subst_ee x u e1).
Lemma subst_ee_open_ee : forall e1 e2 x u, expr u -> subst_ee x u (open_ee e1 e2) = open_ee (subst_ee x u e1) (subst_ee x u e2).
Lemma subst_ee_open_ee_var : forall (x y:atom) u e, y <> x -> expr u -> open_ee (subst_ee x u e) y = subst_ee x u (open_ee e y).
Lemma subst_te_open_ee_rec : forall e1 e2 Z P k, subst_te Z P (open_ee_rec k e2 e1) = open_ee_rec k (subst_te Z P e2) (subst_te Z P e1).
Lemma subst_te_open_ee : forall e1 e2 Z P, subst_te Z P (open_ee e1 e2) = open_ee (subst_te Z P e1) (subst_te Z P e2).
Lemma subst_te_open_ee_var : forall Z (x:atom) P e, open_ee (subst_te Z P e) x = subst_te Z P (open_ee e x).
Lemma subst_ee_open_te_rec : forall e P z u k, expr u -> subst_ee z u (open_te_rec k P e) = open_te_rec k P (subst_ee z u e).
Lemma subst_ee_open_te : forall e P z u, expr u -> subst_ee z u (open_te e P) = open_te (subst_ee z u e) P.
Lemma subst_ee_open_te_var : forall z (X:atom) u e, expr u -> open_te (subst_ee z u e) X = subst_ee z u (open_te e X).
Lemma subst_tt_type : forall Z P T, type T -> type P -> type (subst_tt Z P T).
Lemma subst_te_expr : forall Z P e, expr e -> type P -> expr (subst_te Z P e).
Lemma subst_ee_expr : forall z e1 e2, expr e1 -> expr e2 -> expr (subst_ee z e2 e1).
Lemma expr_let_from_body : forall e1 e2, expr e1 -> body_e e2 -> expr (exp_let e1 e2).
Lemma body_from_expr_let : forall e1 e2, expr (exp_let e1 e2) -> body_e e2.
Lemma expr_case_from_body : forall e1 e2 e3, expr e1 -> body_e e2 -> body_e e3 -> expr (exp_case e1 e2 e3).
Lemma body_inl_from_expr_case : forall e1 e2 e3, expr (exp_case e1 e2 e3) -> body_e e2.
Lemma body_inr_from_expr_case : forall e1 e2 e3, expr (exp_case e1 e2 e3) -> body_e e3.
Lemma open_ee_body_e : forall e1 e2, body_e e1 -> expr e2 -> expr (open_ee e1 e2).