(`!n tm env tyin.
        welltyped tm /\ (sizeof tm = n) /\
        (!s s'. 
 (s,s') env
                ==> ?x ty. (s = Var x ty) /\
                           (s' = Var x (
 tyin ty)))
        ==> (?x ty. (
 tyin ty))
                                 env (Var x ty) = Var x ty)) \/
            (!x ty. 
 tyin ty))
                                 env (Var x ty) = Var x ty)) /\
            (?tm'. (
 tyin (typeof tm)) /\
                   (!u uty. 
 (Var u uty) tm' <=>
                                ?oty. 
 tau sigma
                       ==> (semantics sigma tau tm' =
                            semantics
                               (\(x,ty). sigma(x,
 tyin ty))
                               (\s. typeset tau (
  MATCH_MP_TAC 
num_WF THEN GEN_TAC THEN DISCH_TAC THEN
  MATCH_MP_TAC term_INDUCT THEN
  ONCE_REWRITE_TAC[
INST_CORE] THEN REWRITE_TAC[semantics] THEN
  REPEAT CONJ_TAC THENL
   [POP_ASSUM(K ALL_TAC) THEN
    REWRITE_TAC[
REV_ASSOCD; 
LET_DEF; 
LET_END_DEF] THEN
    REPEAT GEN_TAC THEN COND_CASES_TAC THEN
    ASM_REWRITE_TAC[result_DISTINCT; result_INJ; 
UNWIND_THM1] THEN
    REWRITE_TAC[typeof; 
has_type_RULES] THEN
    CONV_TAC(ONCE_DEPTH_CONV GEN_BETA_CONV) THEN
    REWRITE_TAC[
RESULT; semantics; 
VFREE_IN; term_INJ] THEN ASM_MESON_TAC[];
    POP_ASSUM(K ALL_TAC) THEN
    REWRITE_TAC[
TYPE_SUBST; 
RESULT; 
VFREE_IN; term_DISTINCT] THEN
    ASM_REWRITE_TAC[result_DISTINCT; result_INJ; 
UNWIND_THM1] THEN
    REWRITE_TAC[typeof; 
has_type_RULES; 
TYPE_SUBST; 
VFREE_IN] THEN
    REWRITE_TAC[semantics; typeset; 
TYPESET_LEMMA; 
TYPE_SUBST; term_DISTINCT];
    POP_ASSUM(K ALL_TAC) THEN
    REWRITE_TAC[
TYPE_SUBST; 
RESULT; 
VFREE_IN; term_DISTINCT] THEN
    ASM_REWRITE_TAC[result_DISTINCT; result_INJ; 
UNWIND_THM1] THEN
    REWRITE_TAC[typeof; 
has_type_RULES; 
TYPE_SUBST; 
VFREE_IN] THEN
    REWRITE_TAC[semantics; typeset; 
TYPESET_LEMMA; 
TYPE_SUBST; term_DISTINCT];
    MAP_EVERY X_GEN_TAC [`s:term`; `t:term`] THEN DISCH_THEN(K ALL_TAC) THEN
    POP_ASSUM MP_TAC THEN ASM_CASES_TAC `n = sizeof(Comb s t)` THEN
    ASM_REWRITE_TAC[] THEN
    DISCH_THEN(fun th -> MP_TAC(SPEC `sizeof t` th) THEN
                         MP_TAC(SPEC `sizeof s` th)) THEN
    REWRITE_TAC[sizeof; ARITH_RULE `s < 1 + s + t /\ t < 1 + s + t`] THEN
    DISCH_THEN(fun th -> DISCH_THEN(MP_TAC o SPEC `t:term`) THEN
                         MP_TAC(SPEC `s:term` th)) THEN
    REWRITE_TAC[IMP_IMP; 
AND_FORALL_THM; 
WELLTYPED_CLAUSES] THEN
    REPEAT(MATCH_MP_TAC 
MONO_FORALL THEN GEN_TAC) THEN
    DISCH_THEN(fun th -> STRIP_TAC THEN MP_TAC th) THEN ASM_REWRITE_TAC[] THEN
    GEN_REWRITE_TAC I [
IMP_CONJ] THEN
    DISCH_THEN(DISJ_CASES_THEN MP_TAC) THENL
     [DISCH_THEN(fun th -> DISCH_THEN(K ALL_TAC) THEN MP_TAC th) THEN
      DISCH_THEN(fun th -> DISJ1_TAC THEN MP_TAC th) THEN
      REPEAT(MATCH_MP_TAC 
MONO_EXISTS THEN GEN_TAC) THEN
      STRIP_TAC THEN ASM_REWRITE_TAC[
LET_DEF; 
LET_END_DEF; 
IS_CLASH; 
VFREE_IN];
      ALL_TAC] THEN
    REWRITE_TAC[
TYPE_SUBST] THEN
    DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
    DISCH_THEN(X_CHOOSE_THEN `s':term` STRIP_ASSUME_TAC) THEN
    DISCH_THEN(DISJ_CASES_THEN MP_TAC) THENL
     [DISCH_THEN(fun th -> DISJ1_TAC THEN MP_TAC th) THEN
      REPEAT(MATCH_MP_TAC 
MONO_EXISTS THEN GEN_TAC) THEN
      STRIP_TAC THEN ASM_REWRITE_TAC[
LET_DEF; 
LET_END_DEF; 
IS_CLASH; 
VFREE_IN];
      ALL_TAC] THEN
    DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
    DISCH_THEN(X_CHOOSE_THEN `t':term` STRIP_ASSUME_TAC) THEN
    DISJ2_TAC THEN CONJ_TAC THENL
     [REWRITE_TAC[
VFREE_IN] THEN ASM_MESON_TAC[]; ALL_TAC] THEN
    EXISTS_TAC `Comb s' t'` THEN
    ASM_SIMP_TAC[
LET_DEF; 
LET_END_DEF; 
IS_CLASH; semantics; 
RESULT] THEN
    ASM_REWRITE_TAC[
VFREE_IN] THEN
    ASM_REWRITE_TAC[typeof] THEN ONCE_REWRITE_TAC[
has_type_CASES] THEN
    REWRITE_TAC[term_DISTINCT; term_INJ; codomain] THEN ASM_MESON_TAC[];
    ALL_TAC] THEN
  MAP_EVERY X_GEN_TAC [`x:string`; `ty:type`; `t:term`] THEN
  DISCH_THEN(K ALL_TAC) THEN POP_ASSUM MP_TAC THEN
  ASM_CASES_TAC `n = sizeof (Abs x ty t)` THEN ASM_REWRITE_TAC[] THEN
  POP_ASSUM(K ALL_TAC) THEN DISCH_TAC THEN REPEAT GEN_TAC THEN
  REWRITE_TAC[
WELLTYPED_CLAUSES] THEN STRIP_TAC THEN REPEAT LET_TAC THEN
  FIRST_ASSUM(MP_TAC o SPEC `sizeof t`) THEN
  REWRITE_TAC[sizeof; ARITH_RULE `t < 2 + t`] THEN
  DISCH_THEN(MP_TAC o SPECL
   [`t:term`; `env':(term#term)list`; `tyin:(type#type)list`]) THEN
  ASM_REWRITE_TAC[] THEN
  ANTS_TAC THENL
   [EXPAND_TAC "env'" THEN REWRITE_TAC[
MEM; 
PAIR_EQ] THEN ASM_MESON_TAC[];
    ALL_TAC] THEN
  DISCH_THEN(DISJ_CASES_THEN MP_TAC) THENL
   [ALL_TAC;
    FIRST_X_ASSUM(K ALL_TAC o SPEC `0`) THEN
    DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
    DISCH_THEN(X_CHOOSE_THEN `t':term` STRIP_ASSUME_TAC) THEN
    DISJ2_TAC THEN ASM_REWRITE_TAC[
IS_RESULT] THEN CONJ_TAC THENL
     [FIRST_X_ASSUM(fun th ->
       MP_TAC th THEN MATCH_MP_TAC 
MONO_FORALL THEN
       GEN_TAC THEN MATCH_MP_TAC 
MONO_FORALL THEN GEN_TAC THEN
       DISCH_THEN(MP_TAC o check (is_imp o concl))) THEN
       EXPAND_TAC "env'" THEN
      REWRITE_TAC[
VFREE_IN; 
REV_ASSOCD; term_INJ] THEN
      COND_CASES_TAC THEN ASM_REWRITE_TAC[term_INJ] THEN MESON_TAC[];
      ALL_TAC] THEN
    REWRITE_TAC[result_INJ; 
UNWIND_THM1; 
RESULT] THEN
    MATCH_MP_TAC(TAUT `a /\ b /\ (b ==> c) ==> b /\ a /\ c`) THEN
    CONJ_TAC THENL
     [ASM_REWRITE_TAC[
VFREE_IN; term_INJ] THEN
      MAP_EVERY X_GEN_TAC [`u:string`; `uty:type`] THEN
      ASM_CASES_TAC `u:string = x` THEN ASM_REWRITE_TAC[] THEN
      UNDISCH_THEN `u:string = x` SUBST_ALL_TAC THEN
      REWRITE_TAC[
RIGHT_AND_EXISTS_THM] THEN
      AP_TERM_TAC THEN GEN_REWRITE_TAC I [
FUN_EQ_THM] THEN
      X_GEN_TAC `oty:type` THEN REWRITE_TAC[] THEN
      ASM_CASES_TAC `uty = 
TYPE_SUBST tyin oty` THEN ASM_REWRITE_TAC[] THEN
      ASM_CASES_TAC `
VFREE_IN (Var x oty) t` THEN ASM_REWRITE_TAC[] THEN
      EQ_TAC THENL [ASM_MESON_TAC[]; ALL_TAC] THEN
      REWRITE_TAC[CONTRAPOS_THM] THEN DISCH_THEN(ASSUME_TAC o SYM) THEN
      FIRST_X_ASSUM(fun th ->
       MP_TAC(SPECL [`x:string`; `oty:type`] th) THEN
       ANTS_TAC THENL [ASM_REWRITE_TAC[] THEN NO_TAC; ALL_TAC]) THEN
      EXPAND_TAC "env'" THEN REWRITE_TAC[
REV_ASSOCD] THEN
      ASM_MESON_TAC[term_INJ];
      ALL_TAC] THEN
    CONJ_TAC THENL
     [REWRITE_TAC[typeof; 
TYPE_SUBST] THEN ASM_REWRITE_TAC[] THEN
      ASM_MESON_TAC[
has_type_RULES];
      ALL_TAC] THEN
    DISCH_TAC THEN REPEAT GEN_TAC THEN STRIP_TAC THEN
    REWRITE_TAC[semantics] THEN
    ASM_REWRITE_TAC[
TYPE_SUBST; 
TYPESET_LEMMA] THEN
    MATCH_MP_TAC 
ABSTRACT_EQ THEN
    CONJ_TAC THENL [ASM_SIMP_TAC[
TYPESET_INHABITED]; ALL_TAC] THEN
    X_GEN_TAC `a:V` THEN REWRITE_TAC[] THEN DISCH_TAC THEN CONJ_TAC THENL
     [MATCH_MP_TAC 
SEMANTICS_TYPESET THEN
      ASM_SIMP_TAC[
TERM_VALUATION_VALMOD] THEN
      ASM_MESON_TAC[welltyped; 
WELLTYPED];
      ALL_TAC] THEN
    MATCH_MP_TAC(TAUT `(b ==> a) /\ b ==> a /\ b`) THEN CONJ_TAC THENL
     [DISCH_THEN(SUBST1_TAC o SYM) THEN
      MATCH_MP_TAC 
SEMANTICS_TYPESET THEN
      ASM_SIMP_TAC[
TERM_VALUATION_VALMOD];
      ALL_TAC] THEN
    FIRST_X_ASSUM(MP_TAC o SPECL
     [`(x,ty' |-> a) (sigma:(string#type)->V)`; `tau:string->V`]) THEN
    ASM_SIMP_TAC[
TERM_VALUATION_VALMOD] THEN DISCH_TAC THEN
    REWRITE_TAC[GSYM(CONJUNCT1 
TYPE_SUBST)] THEN
    MATCH_MP_TAC 
TERM_VALUATION_VFREE_IN THEN CONJ_TAC THENL
     [REWRITE_TAC[
type_valuation] THEN ASM_SIMP_TAC[
TYPESET_INHABITED];
      ALL_TAC] THEN
    CONJ_TAC THENL
     [REWRITE_TAC[
term_valuation] THEN
      MAP_EVERY X_GEN_TAC [`y:string`; `yty:type`] THEN
      CONV_TAC(ONCE_DEPTH_CONV GEN_BETA_CONV) THEN
      REWRITE_TAC[
VALMOD; 
PAIR_EQ] THEN
      COND_CASES_TAC THEN ASM_REWRITE_TAC[
TYPE_SUBST; 
TYPESET_LEMMA] THEN
      ASM_MESON_TAC[
term_valuation];
      ALL_TAC] THEN
    CONJ_TAC THENL
     [REWRITE_TAC[
term_valuation] THEN
      MAP_EVERY X_GEN_TAC [`y:string`; `yty:type`] THEN
      REWRITE_TAC[
VALMOD] THEN
      CONV_TAC(ONCE_DEPTH_CONV GEN_BETA_CONV) THEN
      REWRITE_TAC[
VALMOD; 
PAIR_EQ] THEN
      COND_CASES_TAC THEN ASM_REWRITE_TAC[
TYPE_SUBST; 
TYPESET_LEMMA] THEN
      ASM_MESON_TAC[
term_valuation];
      ALL_TAC] THEN
    UNDISCH_THEN
     `!u uty.
         
VFREE_IN (Var u uty) t' <=>
         (?oty. 
VFREE_IN (Var u oty) t /\ (uty = 
TYPE_SUBST tyin oty))`
     (K ALL_TAC) THEN
    ASM_REWRITE_TAC[] THEN MAP_EVERY X_GEN_TAC [`y:string`; `yty:type`] THEN
    CONV_TAC(ONCE_DEPTH_CONV GEN_BETA_CONV) THEN
    REWRITE_TAC[
VALMOD] THEN
    CONV_TAC(ONCE_DEPTH_CONV GEN_BETA_CONV) THEN
    ASM_CASES_TAC `y:string = x` THEN ASM_REWRITE_TAC[
PAIR_EQ] THEN
    ASM_CASES_TAC `yty:type = ty` THEN ASM_REWRITE_TAC[] THEN
    UNDISCH_THEN `y:string = x` SUBST_ALL_TAC THEN COND_CASES_TAC THEN
    ASM_REWRITE_TAC[] THEN DISCH_TAC THEN
    FIRST_X_ASSUM(MP_TAC o SPECL [`x:string`; `yty:type`]) THEN
    ASM_REWRITE_TAC[] THEN EXPAND_TAC "env'" THEN
    ASM_REWRITE_TAC[
REV_ASSOCD; term_INJ]] THEN
  DISCH_THEN(X_CHOOSE_THEN `z:string` (X_CHOOSE_THEN `zty:type`
   (CONJUNCTS_THEN2 SUBST_ALL_TAC MP_TAC))) THEN
  EXPAND_TAC "w" THEN REWRITE_TAC[
CLASH; 
IS_RESULT; term_INJ] THEN
  COND_CASES_TAC THEN ASM_REWRITE_TAC[] THENL
   [FIRST_X_ASSUM(K ALL_TAC o SPEC `0`) THEN
    DISCH_THEN(fun th ->
      DISJ1_TAC THEN REWRITE_TAC[result_INJ] THEN
      MAP_EVERY EXISTS_TAC [`z:string`; `zty:type`] THEN
      MP_TAC th) THEN
    ASM_REWRITE_TAC[
VFREE_IN; term_INJ] THEN
    EXPAND_TAC "env'" THEN ASM_REWRITE_TAC[
REV_ASSOCD; term_INJ] THEN
    ASM_MESON_TAC[];
    ALL_TAC] THEN
  FIRST_X_ASSUM(CONJUNCTS_THEN2 SUBST_ALL_TAC ASSUME_TAC) THEN STRIP_TAC THEN
  ONCE_REWRITE_TAC[
INST_CORE] THEN ASM_REWRITE_TAC[] THEN
  ONCE_REWRITE_TAC[letlemma] THEN
  ABBREV_TAC `env'' = CONS (Var x' ty,Var x' ty') env` THEN
  ONCE_REWRITE_TAC[letlemma] THEN
  ABBREV_TAC
   `ures = 
INST_CORE env'' tyin (
VSUBST[Var x' ty,Var x ty] t)` THEN
  ONCE_REWRITE_TAC[letlemma] THEN
  FIRST_X_ASSUM(MP_TAC o SPEC `sizeof t`) THEN
  REWRITE_TAC[sizeof; ARITH_RULE `t < 2 + t`] THEN
  DISCH_THEN(fun th ->
    MP_TAC(SPECL [`
VSUBST [Var x' ty,Var x ty] t`;
                  `env'':(term#term)list`; `tyin:(type#type)list`] th) THEN
    MP_TAC(SPECL [`t:term`; `[]:(term#term)list`; `tyin:(type#type)list`]
       th)) THEN
  REWRITE_TAC[
MEM; 
REV_ASSOCD] THEN ASM_REWRITE_TAC[] THEN
  DISCH_THEN(X_CHOOSE_THEN `t':term` MP_TAC) THEN STRIP_TAC THEN
  UNDISCH_TAC `
VARIANT (
RESULT (
INST_CORE [] tyin t)) x ty' = x'` THEN
  ASM_REWRITE_TAC[
RESULT] THEN DISCH_TAC THEN
  MP_TAC(SPECL [`t':term`; `x:string`; `ty':type`] 
VARIANT) THEN
  ASM_REWRITE_TAC[] THEN
  GEN_REWRITE_TAC (LAND_CONV o TOP_DEPTH_CONV)
   [
NOT_EXISTS_THM; TAUT `~(a /\ b) <=> a ==> ~b`] THEN DISCH_TAC THEN
  ANTS_TAC THENL
   [ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
     [MATCH_MP_TAC 
VSUBST_WELLTYPED THEN ASM_REWRITE_TAC[
MEM; 
PAIR_EQ] THEN
      ASM_MESON_TAC[
has_type_RULES];
      ALL_TAC] THEN
    CONJ_TAC THENL
     [MATCH_MP_TAC 
SIZEOF_VSUBST THEN
      ASM_REWRITE_TAC[
MEM; 
PAIR_EQ] THEN ASM_MESON_TAC[
has_type_RULES];
      ALL_TAC] THEN
    EXPAND_TAC "env''" THEN REWRITE_TAC[
MEM; 
PAIR_EQ] THEN
    ASM_MESON_TAC[];
    ALL_TAC] THEN
  DISCH_THEN(DISJ_CASES_THEN MP_TAC) THENL
   [DISCH_THEN(fun th -> DISJ1_TAC THEN MP_TAC th) THEN
    MATCH_MP_TAC 
MONO_EXISTS THEN X_GEN_TAC `v:string` THEN
    MATCH_MP_TAC 
MONO_EXISTS THEN X_GEN_TAC `vty:type` THEN
    ASM_REWRITE_TAC[] THEN
    DISCH_THEN(CONJUNCTS_THEN2 SUBST_ALL_TAC MP_TAC) THEN
    ASM_REWRITE_TAC[
IS_RESULT; 
CLASH] THEN
    ONCE_REWRITE_TAC[letlemma] THEN
    COND_CASES_TAC THEN ASM_REWRITE_TAC[] THENL
     [REWRITE_TAC[
VFREE_IN_VSUBST] THEN EXPAND_TAC "env''" THEN
      REWRITE_TAC[
REV_ASSOCD] THEN ASM_REWRITE_TAC[] THEN
      DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
      ASM_REWRITE_TAC[] THEN REWRITE_TAC[term_INJ] THEN
      DISCH_THEN(REPEAT_TCL CHOOSE_THEN MP_TAC) THEN
      COND_CASES_TAC THEN ASM_REWRITE_TAC[
VFREE_IN; term_INJ] THEN
      ASM_MESON_TAC[];
      ALL_TAC] THEN
    FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [term_INJ]) THEN
    DISCH_THEN(CONJUNCTS_THEN2 SUBST_ALL_TAC ASSUME_TAC) THEN
    MATCH_MP_TAC(TAUT `~p ==> p ==> q`) THEN
    EXPAND_TAC "env''" THEN REWRITE_TAC[
REV_ASSOCD] THEN
    ASM_CASES_TAC `vty:type = ty` THEN ASM_REWRITE_TAC[] THEN
    DISCH_THEN(MP_TAC o CONJUNCT1) THEN
    REWRITE_TAC[
VFREE_IN_VSUBST; 
NOT_EXISTS_THM; 
REV_ASSOCD] THEN
    ONCE_REWRITE_TAC[
COND_RAND] THEN REWRITE_TAC[
VFREE_IN; term_INJ] THEN
    MAP_EVERY X_GEN_TAC [`k:string`; `kty:type`] THEN
    MP_TAC(SPECL [`t':term`; `x:string`; `ty':type`] 
VARIANT) THEN
    ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[];
    ALL_TAC] THEN
  ASM_REWRITE_TAC[] THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
  DISCH_THEN(X_CHOOSE_THEN `t'':term` STRIP_ASSUME_TAC) THEN
  ASM_REWRITE_TAC[
IS_RESULT; result_INJ; 
UNWIND_THM1; result_DISTINCT] THEN
  REWRITE_TAC[
RESULT] THEN
  MATCH_MP_TAC(TAUT `b /\ (b ==> c /\ a /\ d) ==> a /\ b /\ c /\ d`) THEN
  CONJ_TAC THENL
   [ASM_REWRITE_TAC[typeof; 
TYPE_SUBST] THEN
    MATCH_MP_TAC(last(CONJUNCTS 
has_type_RULES)) THEN
    SUBGOAL_THEN `(
VSUBST [Var x' ty,Var x ty] t) 
has_type (typeof t)`
      (fun th -> ASM_MESON_TAC[th; 
WELLTYPED_LEMMA]) THEN
    MATCH_MP_TAC 
VSUBST_HAS_TYPE THEN ASM_REWRITE_TAC[GSYM 
WELLTYPED] THEN
    REWRITE_TAC[
MEM; 
PAIR_EQ] THEN MESON_TAC[
has_type_RULES];
    ALL_TAC] THEN
  DISCH_TAC THEN MATCH_MP_TAC(TAUT `a /\ (a ==> b) ==> a /\ b`) THEN
  CONJ_TAC THENL
   [ASM_REWRITE_TAC[
VFREE_IN] THEN
    MAP_EVERY X_GEN_TAC [`k:string`; `kty:type`]  THEN
    ASM_REWRITE_TAC[
VFREE_IN_VSUBST; 
REV_ASSOCD] THEN
    ONCE_REWRITE_TAC[
COND_RAND] THEN REWRITE_TAC[
VFREE_IN; term_INJ] THEN
    SIMP_TAC[] THEN
    REWRITE_TAC[TAUT `x /\ (if p then a /\ b else c /\ b) <=>
                      b /\ x /\ (if p then a else c)`] THEN
    REWRITE_TAC[
UNWIND_THM2] THEN
    REWRITE_TAC[TAUT `x /\ (if p /\ q then a else b) <=>
                      p /\ q /\ a /\ x \/ b /\ ~(p /\ q) /\ x`] THEN
    REWRITE_TAC[
EXISTS_OR_THM; 
UNWIND_THM1; 
UNWIND_THM2] THEN
    ASM_MESON_TAC[];
    ALL_TAC] THEN
  DISCH_TAC THEN CONJ_TAC THENL
   [MAP_EVERY X_GEN_TAC [`k:string`; `kty:type`] THEN
    REWRITE_TAC[
VFREE_IN] THEN STRIP_TAC THEN
    UNDISCH_TAC `!x'' ty'.
           
VFREE_IN (Var x'' ty') (
VSUBST [Var x' ty,Var x ty] t)
           ==> (
REV_ASSOCD (Var x'' (
TYPE_SUBST tyin ty')) env''
                           (Var x'' ty') = Var x'' ty')` THEN
    DISCH_THEN(MP_TAC o SPECL [`k:string`; `kty:type`]) THEN
    REWRITE_TAC[
VFREE_IN_VSUBST; 
REV_ASSOCD] THEN
    ONCE_REWRITE_TAC[
COND_RAND] THEN REWRITE_TAC[
VFREE_IN] THEN
    REWRITE_TAC[
VFREE_IN; term_INJ] THEN
    SIMP_TAC[] THEN
    REWRITE_TAC[TAUT `x /\ (if p then a /\ b else c /\ b) <=>
                      b /\ x /\ (if p then a else c)`] THEN
    REWRITE_TAC[
UNWIND_THM2] THEN
    REWRITE_TAC[TAUT `x /\ (if p /\ q then a else b) <=>
                      p /\ q /\ a /\ x \/ b /\ ~(p /\ q) /\ x`] THEN
    REWRITE_TAC[
EXISTS_OR_THM; 
UNWIND_THM1; 
UNWIND_THM2] THEN
    UNDISCH_TAC `~(Var x ty = Var k kty)` THEN
    REWRITE_TAC[term_INJ] THEN DISCH_TAC THEN ASM_REWRITE_TAC[] THEN
    EXPAND_TAC "env''" THEN REWRITE_TAC[
REV_ASSOCD] THEN ASM_MESON_TAC[];
    ALL_TAC] THEN
  REPEAT STRIP_TAC THEN REWRITE_TAC[semantics] THEN
  REWRITE_TAC[
TYPE_SUBST; 
TYPESET_LEMMA] THEN ASM_REWRITE_TAC[] THEN
  MATCH_MP_TAC 
ABSTRACT_EQ THEN
  CONJ_TAC THENL [ASM_SIMP_TAC[
TYPESET_INHABITED]; ALL_TAC] THEN
  X_GEN_TAC `a:V` THEN REWRITE_TAC[] THEN DISCH_TAC THEN CONJ_TAC THENL
   [MATCH_MP_TAC 
SEMANTICS_TYPESET THEN
    ASM_SIMP_TAC[
TERM_VALUATION_VALMOD] THEN
    ASM_MESON_TAC[welltyped; 
WELLTYPED];
    ALL_TAC] THEN
  MATCH_MP_TAC(TAUT `(b ==> a) /\ b ==> a /\ b`) THEN CONJ_TAC THENL
   [DISCH_THEN(SUBST1_TAC o SYM) THEN
    MATCH_MP_TAC 
SEMANTICS_TYPESET THEN
    ASM_SIMP_TAC[
TERM_VALUATION_VALMOD] THEN
    SUBGOAL_THEN `(
VSUBST [Var x' ty,Var x ty] t) 
has_type (typeof t)`
      (fun th -> ASM_MESON_TAC[th; 
WELLTYPED_LEMMA]) THEN
    MATCH_MP_TAC 
VSUBST_HAS_TYPE THEN ASM_REWRITE_TAC[GSYM 
WELLTYPED] THEN
    REWRITE_TAC[
MEM; 
PAIR_EQ] THEN MESON_TAC[
has_type_RULES];
    ALL_TAC] THEN
  W(fun (asl,w) -> FIRST_X_ASSUM(fun th ->
        MP_TAC(PART_MATCH (lhand o rand) th (lhand w)))) THEN
  ASM_SIMP_TAC[
TERM_VALUATION_VALMOD] THEN DISCH_TAC THEN
  REWRITE_TAC[GSYM(CONJUNCT1 
TYPE_SUBST)] THEN
  MP_TAC 
SEMANTICS_VSUBST THEN
  REWRITE_TAC[
RIGHT_IMP_FORALL_THM; IMP_IMP] THEN
  DISCH_THEN(fun th ->
   W(fun (asl,w) -> MP_TAC(PART_MATCH (lhand o rand) th (lhand w)))) THEN
  ANTS_TAC THENL
   [ASM_REWRITE_TAC[
MEM; 
PAIR_EQ] THEN CONJ_TAC THENL
     [MESON_TAC[
has_type_RULES]; ALL_TAC] THEN
    CONJ_TAC THENL
     [REWRITE_TAC[
type_valuation] THEN ASM_SIMP_TAC[
TYPESET_INHABITED];
      ALL_TAC] THEN
    REWRITE_TAC[
term_valuation] THEN
    MAP_EVERY X_GEN_TAC [`y:string`; `yty:type`] THEN
    REWRITE_TAC[
VALMOD] THEN
    CONV_TAC(ONCE_DEPTH_CONV GEN_BETA_CONV) THEN
    REWRITE_TAC[
VALMOD; 
PAIR_EQ] THEN
    COND_CASES_TAC THEN ASM_REWRITE_TAC[
TYPE_SUBST; 
TYPESET_LEMMA] THEN
    ASM_MESON_TAC[
term_valuation];
    ALL_TAC] THEN
  DISCH_THEN SUBST1_TAC THEN
  REWRITE_TAC[GSYM(CONJUNCT1 
TYPE_SUBST)] THEN
  MATCH_MP_TAC 
TERM_VALUATION_VFREE_IN THEN CONJ_TAC THENL
   [REWRITE_TAC[
type_valuation] THEN ASM_SIMP_TAC[
TYPESET_INHABITED];
    ALL_TAC] THEN
  REWRITE_TAC[
ITLIST] THEN
  CONV_TAC(ONCE_DEPTH_CONV GEN_BETA_CONV) THEN
  REWRITE_TAC[
DEST_VAR] THEN REWRITE_TAC[
CONJ_ASSOC] THEN CONJ_TAC THENL
   [ASM_REWRITE_TAC[] THEN CONJ_TAC THEN
    REWRITE_TAC[
term_valuation; semantics] THEN
    MAP_EVERY X_GEN_TAC [`k:string`; `kty:type`] THEN
    REWRITE_TAC[
VALMOD] THEN CONV_TAC(ONCE_DEPTH_CONV GEN_BETA_CONV) THEN
    REWRITE_TAC[
TYPESET_LEMMA; 
TYPE_SUBST] THEN
    SIMP_TAC[
PAIR_EQ] THEN ASM_REWRITE_TAC[] THEN
    COND_CASES_TAC THEN ASM_REWRITE_TAC[] THEN
    ASM_MESON_TAC[
term_valuation];
    ALL_TAC] THEN
  MAP_EVERY X_GEN_TAC [`k:string`; `kty:type`] THEN DISCH_TAC THEN
  REWRITE_TAC[
VALMOD; semantics] THEN
  CONV_TAC(ONCE_DEPTH_CONV GEN_BETA_CONV) THEN
  SIMP_TAC[
PAIR_EQ] THEN ASM_REWRITE_TAC[] THEN ASM_MESON_TAC[]);;