theory SubstTPX
  imports SubstDropEnv
begin

lemma wt_sexp_no_npv_use: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx; is_sexp e; req_type tau = Prim \<rbrakk> \<Longrightarrow> x \<notin> non_prim_vars env e"
  apply (induct e arbitrary: env r_s1 tau r_s2 rx)
       apply (auto)
    (* const + op case *)
      apply (simp add: non_prim_vars_def)
     apply (simp add: non_prim_vars_def)
    (* var case *)
     apply (case_tac xa)
      apply (auto)
    (* pair case *)
    apply (case_tac r)
      apply (auto)
    apply (case_tac "max_aff (req_type t1) (req_type t2)")
      apply (auto)
    apply (cut_tac ?a1.0="req_type t1" and ?a2.0="req_type t2" in max_aff_prim)
     apply (simp)
    apply (case_tac "x \<notin> res_vars (PairExp e1 e2)")
     apply (simp add: non_prim_vars_def)
    apply (auto)
     apply (case_tac "x \<notin> non_prim_vars env e1")
      apply (simp add: non_prim_vars_def)
     apply (cut_tac e="e1" in value_is_sexp)
      apply (auto)
    apply (case_tac "x \<notin> non_prim_vars env e2")
     apply (simp add: non_prim_vars_def)
    apply (cut_tac e="e2" in value_is_sexp)
     apply (auto)
    (* lam case *)
   apply (simp add: non_prim_vars_def)
   apply (simp add: aff_use_env_def)
   apply (simp add: null_use_env_def)
   apply (erule_tac x="x" in allE)
   apply (auto)
   apply (cut_tac env="add_env env (Var x1a) t1" and ?r_s1.0="add_use_env rxa (Var x1a) r" and e="e" and x="x" in well_typed_no_npv_use)
     apply (auto)
    apply (simp add: add_use_env_def)
   apply (simp add: non_prim_vars_def)
   apply (simp add: non_prim_entry_def)
   apply (simp add: add_env_def)
   apply (auto)
    (* app case *)
  apply (simp add: non_prim_vars_def)
  apply (case_tac e1)
       apply (auto)
  apply (case_tac x1)
               apply (auto)
       apply (simp_all add: pure_fun_def)
  apply (auto)
  apply (case_tac e2)
       apply (auto)
  apply (simp add: aff_use_env_def)
  apply (simp add: null_use_env_def)
  apply (cut_tac env="add_env env (Var x61) t" and ?r_s1.0="add_use_env rxa (Var x61) UsePerm" and e="x62" and x="x" in well_typed_no_npv_use)
    apply (auto)
   apply (simp add: add_use_env_def)
  apply (simp add: non_prim_vars_def)
  apply (simp add: non_prim_entry_def)
  apply (simp add: add_env_def)
  apply (auto)
  done

lemma subst_type_preserve_prim_fv: "\<lbrakk> well_typed (add_env env (Var x) t) r_s1 e tau r_se r_xe;
  well_typed env rx2 e' t rx2 rx2; is_sexp e'; req_type t = Prim; lam_vars e \<inter> free_vars e' = {} \<rbrakk> \<Longrightarrow>
  well_typed env r_s1 (subst_exp e x e') tau r_se r_xe"
  apply (induct e arbitrary: env tau r_s1 r_se r_xe)
        apply (auto)
    (* var case *)
       apply (case_tac "\<not> t = tau_x")
        apply (simp add: add_env_def)
        apply (case_tac xa)
         apply (auto)
       apply (case_tac xa)
        apply (auto)
         apply (rule_tac rx="empty_use_env" in well_typed_incr_req)
           apply (rule_tac ?r_s1.0="r_se" in well_typed_incr_start_perm)
            apply (rule_tac r_s="empty_use_env" in well_typed_incr_simul_perm)
             apply (rule_tac leq_empty_use_env)
            apply (rule_tac ?r_s1.0="rx2" and ?r_s2.0="rx2" and rx="rx2" in wt_sexp_no_all)
              apply (auto)
          apply (rule_tac r_sb="diff_use_env r_s1 (comp_use_env (ereq_use_env (Var x) t) r_ex)" in trans_leq_use_env)
           apply (rule_tac self_diff_leq_use_env)
          apply (simp)
         apply (rule_tac leq_empty_use_env)
        apply (simp add: add_env_def)
       apply (simp add: add_env_def)
       apply (auto)
    (* pair case *)
      apply (rule_tac x="r_s2" in exI)
       apply (rule_tac x="r_s3" in exI)
       apply (rule_tac x="rx1" in exI)
       apply (auto)
        apply (case_tac "\<not> lam_vars e1 \<inter> free_vars e' = {}")
         apply (auto)
       apply (rule_tac x="rx2a" in exI)
       apply (auto)
       apply (case_tac "\<not> lam_vars e2 \<inter> free_vars e' = {}")
        apply (auto)
    (* if case *)
      apply (rule_tac x="rx'" in exI)
      apply (rule_tac x="r_s2" in exI)
      apply (auto)
       apply (case_tac "\<not> lam_vars e1 \<inter> free_vars e' = {}")
        apply (auto)
      apply (rule_tac x="rx1" in exI)
      apply (auto)
       apply (case_tac "\<not> lam_vars e2 \<inter> free_vars e' = {}")
        apply (auto)
      apply (rule_tac x="rx2a" in exI)
      apply (auto)
      apply (case_tac "\<not> lam_vars e3 \<inter> free_vars e' = {}")
       apply (auto)
    (* lam case p1. *)
     apply (rule_tac x="rx" in exI)
     apply (auto)
     apply (rule_tac x="r_end" in exI)
     apply (rule_tac x="r_s'" in exI)
     apply (cut_tac env="env" and x="Var x" and t="t" and t'="t1" in double_add_env)
     apply (auto)
    (* lam case p2. *)
   apply (rule_tac x="rx" in exI)
   apply (auto)
   apply (rule_tac x="r_end" in exI)
   apply (rule_tac x="r_s'" in exI)
   apply (cut_tac env="env" and x="x1a" and t="t1" and ?r_s1.0="rx2" and e="e'" and tau="t" and ?r_s2.0="rx2" and rx="rx2" in well_typed_add_vars)
     apply (auto)
   apply (cut_tac env="env" and x="Var x1a" and y="Var x" and t="t" and t'="t1" in almost_comm_add_env)
    apply (auto)
    (* app case *)
  apply (rule_tac x="t1" in exI)
  apply (rule_tac x="r" in exI)
  apply (rule_tac x="a" in exI)
  apply (rule_tac x="r_s2" in exI)
  apply (rule_tac x="rx1" in exI)
  apply (auto)
   apply (case_tac "\<not> lam_vars e1 \<inter> free_vars e' = {}")
    apply (auto)
  apply (rule_tac x="rx2a" in exI)
  apply (rule_tac x="r_s3" in exI)
  apply (auto)
   apply (case_tac "\<not> lam_vars e2 \<inter> free_vars e' = {}")
    apply (auto)
  done

lemma subst_type_preserve_no_npv: "\<lbrakk> well_typed (add_env env (Var x) t) r_s1 e tau r_se r_xe;
  well_typed env rx2 e' t rx2 rx2; is_sexp e'; (Var x) \<notin> non_prim_vars (add_env env (Var x) t) e;
  lam_vars e \<inter> free_vars e' = {} \<rbrakk> \<Longrightarrow>
  well_typed env r_s1 (subst_exp e x e') tau r_se r_xe"
  apply (simp add: non_prim_vars_def)
  apply (auto)
   apply (simp add: non_prim_entry_def)
   apply (simp add: add_env_def)
   apply (rule_tac subst_type_preserve_prim_fv)
       apply (simp add: add_env_def)
      apply (auto)
  apply (rule_tac subst_type_preserve_no_fv)
   apply (auto)
   apply (rule_tac well_typed_add_vars_rev)
    apply (auto)
   apply (cut_tac x="x" and e="e" in free_res_vars_rev)
    apply (auto)
  apply (cut_tac x="x" and e="e" in free_res_vars_rev)
   apply (auto)
  done

    (*
      ####################################
        P1. specialized definitions for the statement of stp
      ####################################
    *)

    (* - requirement negation (removes r_x only if it was already removed from r_se) *)

definition end_neg_use_env where
  "end_neg_use_env r_se x r_x r = (if r_se x = NoPerm then lift_use_env r_x r else empty_use_env)"

lemma end_neg_leq_use_env: "\<lbrakk> leq_use_env (lift_use_env r_x r) r_s \<rbrakk> \<Longrightarrow> leq_use_env (end_neg_use_env r_se x r_x r) r_s"
  apply (simp add: end_neg_use_env_def)
  apply (auto)
  apply (rule_tac leq_empty_use_env)
  done

lemma dist_end_neg_leq_use_env: "\<lbrakk> leq_use_env r_sb r_sa \<rbrakk> \<Longrightarrow> leq_use_env (end_neg_use_env r_sa x r_x r) (end_neg_use_env r_sb x r_x r)"
  apply (simp add: end_neg_use_env_def)
  apply (auto)
     apply (rule_tac id_leq_use_env)
    apply (simp add: leq_use_env_def)
    apply (auto)
    apply (erule_tac x="x" in allE)
    apply (auto)
    apply (case_tac "r_sb x")
      apply (auto)
   apply (rule_tac leq_empty_use_env)
  apply (rule_tac leq_empty_use_env)
  done

    (* - stpx requirements (defines the requirements taken from rx2 based on the requirements originally used) *)

definition stpx_req where
  "stpx_req rx1 rx2 r = (if r = NoPerm then rx1 else if r = UsePerm then comp_use_env rx1 (drop_use_env rx2) else comp_use_env rx1 rx2)"

definition stpx_ex where
  "stpx_ex rx r = (if r = UsePerm then drop_use_env rx else if r = NoPerm then empty_use_env else rx)"

definition stpx_compact where
  "stpx_compact rx1 rx2 r = (if r = NoPerm then rx1 else comp_use_env rx1 (stpx_ex rx2 r))"

lemma stpx_compact_conv: "stpx_req rx1 rx2 r = stpx_compact rx1 rx2 r"
  apply (case_tac "\<forall> x. stpx_req rx1 rx2 r x = stpx_compact rx1 rx2 r x")
   apply (auto)
  apply (simp add: stpx_req_def)
  apply (simp add: stpx_compact_def)
  apply (simp add: stpx_ex_def)
  done

lemma stpx_req_leq_use_env: "\<lbrakk> leq_use_env (comp_use_env r_xa r_xb) r_s \<rbrakk>\<Longrightarrow> leq_use_env (stpx_req r_xa r_xb x) r_s"
  apply (rule_tac r_sb="comp_use_env r_xa r_xb" in trans_leq_use_env)
   apply (simp)
  apply (simp add: stpx_req_def)
  apply (auto)
    apply (rule_tac dist_comp_leq_use_env)
     apply (rule_tac self_comp_leq_use_env1)
    apply (rule_tac comp_leq_use_env2)
    apply (rule_tac self_drop_leq_use_env)
   apply (rule_tac self_comp_leq_use_env1)
  apply (rule_tac id_leq_use_env)
  done

lemma stpx_req_leq_use_env2: "\<lbrakk> leq_use_env r_x r_sa \<rbrakk>\<Longrightarrow> leq_use_env r_x (stpx_req r_sa r_sb x)"
  apply (simp add: stpx_req_def)
  apply (auto)
  apply (rule_tac r_sb="r_sa" in trans_leq_use_env)
    apply (rule_tac self_comp_leq_use_env1)
   apply (simp)
  apply (rule_tac comp_leq_use_env1)
  apply (simp)
  done

lemma stpx_req_leq_use_env3: "\<lbrakk> leq_use_env (comp_use_env r_xa (stpx_ex r_xb r)) r_s \<rbrakk> \<Longrightarrow> leq_use_env (stpx_req r_xa r_xb r) r_s"
  apply (simp add: stpx_req_def)
  apply (auto)
    apply (simp add: stpx_ex_def)
   apply (rule_tac r_sb="comp_use_env r_xa (stpx_ex r_xb NoPerm)" in trans_leq_use_env)
    apply (simp)
   apply (rule_tac self_comp_leq_use_env1)
  apply (rule_tac r_sb="comp_use_env r_xa (stpx_ex r_xb r)" in trans_leq_use_env)
   apply (simp)
  apply (rule_tac dist_comp_leq_use_env)
   apply (rule_tac self_comp_leq_use_env1)
  apply (simp add: stpx_ex_def)
  apply (rule_tac self_comp_leq_use_env2)
  done

lemma stpx_ex_leq_use_env: "\<lbrakk> leq_use_env r_x r_s \<rbrakk> \<Longrightarrow> leq_use_env (stpx_ex r_x r) r_s"
  apply (simp add: stpx_ex_def)
  apply (auto)
   apply (rule_tac leq_empty_use_env)
  apply (rule_tac drop_leq_use_env)
  apply (simp)
  done

lemma stpx_req_leq_use_env4: "\<lbrakk> leq_use_env r_x (comp_use_env r_sa (stpx_ex r_sb r)) \<rbrakk> \<Longrightarrow> leq_use_env r_x (stpx_req r_sa r_sb r)"
  apply (simp add: stpx_req_def)
  apply (auto)
    apply (simp add: stpx_ex_def)
   apply (simp add: stpx_ex_def)
   apply (rule_tac r_sb="comp_use_env r_sa empty_use_env" in trans_leq_use_env)
    apply (rule_tac dist_comp_leq_use_env)
     apply (rule_tac id_leq_use_env)
    apply (rule_tac leq_empty_use_env)
   apply (simp)
  apply (rule_tac r_sb="comp_use_env r_sa (stpx_ex r_sb r)" in trans_leq_use_env)
   apply (rule_tac dist_comp_leq_use_env)
    apply (rule_tac self_comp_leq_use_env1)
   apply (rule_tac stpx_ex_leq_use_env)
   apply (rule_tac self_comp_leq_use_env2)
  apply (simp)
  done

lemma dist_end_neg_leq_use_env_gen: "\<lbrakk> leq_use_env r_xb r_xa \<rbrakk> \<Longrightarrow>
  leq_use_env (end_neg_use_env r_s x r_xb r) (end_neg_use_env r_s x r_xa r)"
  apply (simp add: end_neg_use_env_def)
  apply (auto)
   apply (rule_tac dist_lift_leq_use_env)
   apply (simp)
  apply (rule_tac leq_empty_use_env)
  done

lemma dist_stpx_ex_leq_use_env_gen: "\<lbrakk> leq_perm q r; leq_use_env r_x r_s \<rbrakk> \<Longrightarrow> leq_use_env (stpx_ex r_x q) (stpx_ex r_s r)"
  apply (case_tac q)
    apply (auto)
    apply (case_tac "stpx_ex r_x NoPerm \<noteq> empty_use_env")
     apply (simp add: stpx_ex_def)
    apply (auto)
    apply (rule_tac leq_empty_use_env)
   apply (simp add: stpx_ex_def)
   apply (auto)
    apply (rule_tac dist_drop_leq_use_env)
    apply (simp)
   apply (rule_tac drop_leq_use_env)
   apply (simp)
  apply (simp add: stpx_ex_def)
  apply (auto)
  done

lemma dist_stpx_req_leq_use_env: "\<lbrakk> leq_perm q r; leq_use_env r_x r_s; leq_use_env r_exb r_exa \<rbrakk> \<Longrightarrow>
  leq_use_env (stpx_req r_x r_exb q) (stpx_req r_s r_exa r)"
  apply (rule_tac stpx_req_leq_use_env3)
  apply (rule_tac stpx_req_leq_use_env4)
  apply (rule_tac dist_comp_leq_use_env)
   apply (rule_tac comp_leq_use_env1)
   apply (simp)
  apply (rule_tac comp_leq_use_env2)
  apply (rule_tac dist_stpx_ex_leq_use_env_gen)
   apply (simp_all)
  done

lemma disj_stpx_end_neg_use_env: "\<lbrakk> leq_perm q (r_x x); leq_perm (r_x x) r; disj_use_env r_ex (lift_use_env r_s r) \<rbrakk> \<Longrightarrow>
  disj_use_env (stpx_req r_ex (lift_use_env r_s q) q) (end_neg_use_env r_x x r_s r)"
  apply (rule_tac r_s="comp_use_env r_ex (stpx_ex (lift_use_env r_s r) q)" in disj_leq_use_env1)
   apply (rule_tac disj_comp_use_env1)
    apply (rule_tac r_s="lift_use_env r_s r" in disj_leq_use_env2)
     apply (simp)
    apply (rule_tac end_neg_leq_use_env)
    apply (rule_tac id_leq_use_env)
   apply (simp add: end_neg_use_env_def)
   apply (auto)
    apply (case_tac q)
      apply (auto)
    apply (simp add: stpx_ex_def)
    apply (rule_tac disj_empty_use_env2)
   apply (rule_tac disj_empty_use_env1)
  apply (rule_tac stpx_req_leq_use_env3)
  apply (rule_tac dist_comp_leq_use_env)
   apply (rule_tac self_comp_leq_use_env1)
  apply (rule_tac comp_leq_use_env2)
  apply (rule_tac dist_stpx_ex_leq_use_env_gen)
   apply (case_tac q)
     apply (auto)
  apply (rule_tac dist_lift_leq_use_env_gen)
  apply (case_tac "q")
    apply (auto)
   apply (case_tac "r_x x")
     apply (auto)
   apply (case_tac r)
     apply (auto)
  apply (case_tac "r_x x")
    apply (auto)
  done

lemma dist_stpx_ex_leq_use_env: "\<lbrakk> leq_perm q r \<rbrakk> \<Longrightarrow> leq_use_env (stpx_ex (lift_use_env r_s q) q) (stpx_ex (lift_use_env r_s r) r)"
  apply (rule_tac dist_stpx_ex_leq_use_env_gen)
   apply (simp)
  apply (rule_tac dist_lift_leq_use_env_gen)
  apply (simp)
  done

lemma dist_stpx_ex_leq_use_env2: "\<lbrakk> leq_use_env r_x r_s \<rbrakk> \<Longrightarrow> leq_use_env (stpx_ex r_x r) (stpx_ex r_s r)"
  apply (simp add: stpx_ex_def)
  apply (auto)
   apply (rule_tac leq_empty_use_env)
  apply (rule_tac dist_drop_leq_use_env)
  apply (simp)
  done

lemma stpx_ex_disj_use_env: "\<lbrakk> disj_use_env r_xa r_xb \<rbrakk> \<Longrightarrow> disj_use_env (stpx_ex r_x (r_xa x)) (stpx_ex r_s (r_xb x))"
  apply (case_tac "r_xa x = OwnPerm")
   apply (case_tac "r_xb x \<noteq> NoPerm")
    apply (simp add: disj_use_env_def)
    apply (simp add: mini_disj_use_env_def)
   apply (simp add: stpx_ex_def)
   apply (rule_tac disj_empty_use_env1)
  apply (case_tac "r_xb x = OwnPerm")
   apply (case_tac "r_xa x \<noteq> NoPerm")
    apply (simp add: disj_use_env_def)
    apply (simp add: mini_disj_use_env_def)
   apply (simp add: stpx_ex_def)
   apply (rule_tac disj_empty_use_env2)
  apply (case_tac "\<not> weak_use_env empty_use_env")
   apply (simp add: weak_use_env_def)
   apply (simp add: empty_use_env_def)
  apply (rule_tac double_weak_disj_use_env)
   apply (simp add: stpx_ex_def)
   apply (auto)
    apply (rule_tac drop_weak_use_env)
   apply (case_tac "r_xa x")
     apply (auto)
  apply (simp add: stpx_ex_def)
  apply (auto)
   apply (rule_tac drop_weak_use_env)
  apply (case_tac "r_xb x")
    apply (auto)
  done

lemma stpx_ex_lift_leq_use_env: "leq_use_env (stpx_ex (lift_use_env r_s r) x) (lift_use_env (stpx_ex r_s x) r)"
  apply (simp add: stpx_ex_def)
  apply (auto)
    apply (rule_tac leq_empty_use_env)
   apply (rule_tac drop_lift_leq_use_env)
  apply (rule_tac id_leq_use_env)
  done

lemma stpx_req_drop_use_env: "\<lbrakk> r \<noteq> NoPerm \<rbrakk> \<Longrightarrow>
  stpx_req r_x (lift_use_env r_s r) r = comp_use_env r_x (lift_use_env (drop_use_env_ex r_s r) r)"
  apply (simp add: stpx_req_def)
  apply (auto)
  apply (case_tac r)
     apply (auto)
  done

lemma stpx_req_leq_use_env5: "\<lbrakk> leq_use_env (comp_use_env r_x (lift_use_env (drop_use_env_ex r_s r) r)) r_ex \<rbrakk> \<Longrightarrow>
  leq_use_env (stpx_req r_x (lift_use_env r_s r) r) r_ex"
  apply (rule_tac r_sb="comp_use_env r_x (lift_use_env (drop_use_env_ex r_s r) r)" in trans_leq_use_env)
   apply (simp)
  apply (case_tac "r = NoPerm")
   apply (auto)
   apply (simp add: stpx_req_def)
   apply (rule_tac self_comp_leq_use_env1)
  apply (cut_tac r_x="r_x" and r_s="r_s" and r="r" in stpx_req_drop_use_env)
   apply (auto)
  apply (rule_tac id_leq_use_env)
  done

lemma self_stpx_req_drop_leq_use_env: "\<lbrakk> q \<noteq> NoPerm; leq_perm q r \<rbrakk> \<Longrightarrow>
  leq_use_env (comp_use_env r_x (lift_use_env (drop_use_env_ex r_s q) q)) (stpx_req r_x (lift_use_env r_s r) q)"
  apply (rule_tac r_sb="stpx_req r_x (lift_use_env r_s q) q" in trans_leq_use_env)
   apply (rule_tac dist_stpx_req_leq_use_env)
     apply (case_tac q)
       apply (auto)
    apply (rule_tac id_leq_use_env)
   apply (rule_tac dist_lift_leq_use_env_gen)
   apply (simp)
  apply (cut_tac r="q" and r_x="r_x" and r_s="r_s" in stpx_req_drop_use_env)
   apply (auto)
  apply (rule_tac id_leq_use_env)
  done

lemma stpx_req_drop_leq_use_env: "\<lbrakk> q \<noteq> NoPerm; leq_perm q r; leq_use_env r_d (comp_use_env r_x (lift_use_env (drop_use_env_ex r_s q) q)) \<rbrakk> \<Longrightarrow>
  leq_use_env r_d (stpx_req r_x (lift_use_env r_s r) q)"
  apply (rule_tac r_sb="(comp_use_env r_x (lift_use_env (drop_use_env_ex r_s q) q))" in trans_leq_use_env)
   apply (rule_tac self_stpx_req_drop_leq_use_env)
    apply (simp_all)
  done

lemma safe_lift_stpx_ex_use_env: "\<lbrakk> ra \<noteq> NoPerm; leq_perm (r_x x) ra \<rbrakk> \<Longrightarrow> safe_use_lift (stpx_ex r_s (r_x x)) ra"
  apply (case_tac ra)
    apply (auto)
  apply (simp add: stpx_ex_def)
  apply (case_tac "r_x x")
    apply (auto)
   apply (simp add: empty_use_env_def)
  apply (simp add: drop_use_env_def)
  apply (case_tac "r_s xa")
    apply (auto)
  done

lemma aff_stpx_ex_use_env: "\<lbrakk> aff_use_env r_x a; r_x x = r \<rbrakk> \<Longrightarrow> aff_use_env (stpx_ex r_s r) a"
  apply (simp add: aff_use_env_def)
  apply (case_tac a)
    apply (auto)
   apply (simp add: stpx_ex_def)
   apply (auto)
     apply (simp add: weak_use_env_def)
     apply (simp add: empty_use_env_def)
    apply (rule_tac drop_weak_use_env)
   apply (simp add: weak_use_env_def)
   apply (case_tac "r_x x")
     apply (auto)
  apply (simp add: null_use_env_def)
  apply (simp add: stpx_ex_def)
  apply (simp add: empty_use_env_def)
  done

lemma well_typed_stpx_req:
  "\<lbrakk> well_typed env r_s1 e tau (comp_use_env (rem_use_env r_se x) rx2) (rem_use_env r_xe x); leq_use_env rx2_c rx2 \<rbrakk> \<Longrightarrow>
  well_typed env r_s1 e tau (comp_use_env (rem_use_env r_se x) rx2) (stpx_req (rem_use_env r_xe x) rx2_c r)"
  apply (simp add: stpx_req_def)
  apply (auto)
  apply (rule_tac well_typed_comp_req2)
    apply (auto)
   apply (rule_tac drop_leq_use_env)
   apply (rule_tac comp_leq_use_env2)
   apply (simp)
  apply (rule_tac well_typed_comp_req2)
   apply (simp)
  apply (rule_tac comp_leq_use_env2)
  apply (simp)
  done

lemma well_typed_stpx_req2:
  "\<lbrakk> well_typed env r_s1 e tau r_se r_xe; leq_perm q r; leq_use_env rx2_c rx2; disj_use_env r_s1 rx2 \<rbrakk> \<Longrightarrow>
  well_typed env (stpx_req r_s1 rx2 r) e tau (stpx_req r_se rx2 r) (stpx_req r_xe rx2_c q)"
  apply (rule_tac rx="r_xe" in well_typed_incr_req)
    apply (case_tac r)
      apply (auto)
      apply (simp add: stpx_req_def)
     apply (simp add: stpx_req_def)
    apply (rule_tac well_typed_comp_perms)
      apply (auto)
     apply (rule_tac r_s="rx2" in disj_leq_use_env2)
      apply (simp)
     apply (rule_tac self_drop_leq_use_env)
    apply (simp add: stpx_req_def)
    apply (rule_tac well_typed_comp_perms)
     apply (auto)
   apply (rule_tac stpx_req_leq_use_env2)
   apply (rule_tac id_leq_use_env)
  apply (rule_tac dist_stpx_req_leq_use_env)
    apply (simp)
   apply (rule_tac well_typed_perm_leqx)
   apply (auto)
  done

lemma well_typed_diff_decr_end_neg_perm: "\<lbrakk>
  well_typed env (diff_use_env r_s1 (end_neg_use_env r_s x r_ex r)) e tau (diff_use_env r_s2 (end_neg_use_env r_s x r_ex r))
    (diff_use_env rx (end_neg_use_env r_s x r_ex r)); leq_use_env r_x r_s; leq_use_env (lift_use_env r_ex r) r_s1 \<rbrakk> \<Longrightarrow>
  well_typed env (diff_use_env r_s1 (end_neg_use_env r_s x r_ex r)) e tau (diff_use_env r_s2 (end_neg_use_env r_x x r_ex r))
    (diff_use_env rx (end_neg_use_env r_x x r_ex r))"
  apply (case_tac "r_s x = NoPerm")
   apply (simp add: end_neg_use_env_def)
   apply (auto)
   apply (cut_tac r_x="r_x" and r_s="r_s" and x="x" in leq_use_none)
     apply (auto)
  apply (simp add: end_neg_use_env_def)
  apply (auto)
  apply (rule_tac r_exb="empty_use_env" in well_typed_diff_decr_end_perm_gen)
    apply (auto)
   apply (rule_tac leq_empty_use_env)
  apply (rule_tac rhs_weak_leq_use_env)
   apply (simp add: weak_use_env_def)
   apply (simp add: empty_use_env_def)
  apply (simp)
  done

    (*
      ####################################
        P2. var case
      ####################################
    *)

    (*
      the intuition behind this lemma is that - if x is owned by r_xe, these are trivially the same.
      - if x is not in r_xe, x is not in rx - r_ex either. since x was in rx, it must be getting subtracted out.
      this means it would be subtracted out of r_s as well, which means it cant be in r_se either. this means (lift rx2)
      will get subtracted out. since r_ex has the ability to subtract x, we know r = own. case analysis of both sides
      of the equation show that they're all the same, since rx2 will be totally annihilated under these conditions.
      - the hardest case is if x is used by r_xe.
    *)
lemma stpx_diff_req_use_env: "\<lbrakk> leq_use_env r_ex (add_use_env rx1 x r); rx x \<noteq> NoPerm; safe_use_lift rx2 r; leq_perm q r; r_xe x \<noteq> UsePerm;
  leq_use_env r_se (diff_use_env r_s r_ex); leq_use_env (diff_use_env rx r_ex) r_xe; disj_use_env (rem_use_env r_xe x) (lift_use_env rx2 r) \<rbrakk> \<Longrightarrow>
  diff_use_env (stpx_req (rem_use_env r_xe x) (lift_use_env rx2 q) (r_xe x)) (end_neg_use_env r_se x rx2 r) =
  diff_use_env (comp_use_env (rem_use_env r_xe x) (lift_use_env rx2 q)) (end_neg_use_env r_se x rx2 r)"
    (* we are assuming r_xe x = None, and therefore rx2 is not included on the lhs *)
  apply (case_tac "r_xe x \<noteq> NoPerm")
   apply (simp add: stpx_req_def)
  apply (simp add: stpx_req_def)
    (* we want to show that r = Own, which is true since r_ex x \<le> r, and r_ex x = Own since it must be subtracted out of rx somehow *)
  apply (cut_tac r_ex="r_ex" and r_s="r_xe" and r_x="rx" and x="x" in diff_use_own)
     apply (auto)
  apply (case_tac "\<not> is_own r")
   apply (simp add: leq_use_env_def)
   apply (erule_tac x="x" in allE)
   apply (simp add: add_use_env_def)
   apply (simp add: is_own_def)
   apply (case_tac r)
     apply (auto)
    (* we can also use this to infer that r_se x = None *)
  apply (cut_tac r_s="r_s" and r_x="rx" and r_ex="r_ex" and x="x" in diff_use_none)
    apply (auto)
   apply (rule_tac r_s="r_xe" in leq_use_none)
    apply (auto)
  apply (cut_tac r_s="diff_use_env r_s r_ex" and r_x="r_se" in leq_use_none)
    apply (auto)
  apply (simp add: end_neg_use_env_def)
    (* the intuition is that lift rx2 q - lift rx2 r = empty_use_env *)
  apply (rule_tac t="diff_use_env (comp_use_env (rem_use_env r_xe x) (lift_use_env rx2 q)) (lift_use_env rx2 r)" and
      s="comp_use_env (diff_use_env (rem_use_env r_xe x) (lift_use_env rx2 r)) (diff_use_env (lift_use_env rx2 q) (lift_use_env rx2 r))" in subst)
   apply (rule_tac dist_diff_comp_use_env)
  apply (cut_tac r_x="rx2" and q="q" and r="r" in cancel_diff_lift_use_env)
   apply (auto)
  apply (simp add: comp_empty_use_env2)
  done

lemma stpx_var_case: "\<lbrakk>well_typed env rx2 e' t rx2 rx2; rx1 (Var xa) = NoPerm; xa \<in> (case x of VarType x \<Rightarrow> {x} | LocType list1 list2 \<Rightarrow> {}); is_sexp e';
        leq_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_s1; disj_use_env rx1 (lift_use_env rx2 r); add_env env (Var xa) t (res_name x) = Some tau;
        add_env env (Var xa) t (owner_name x) = Some tau_x; value_req x tau tau_x; leq_use_env (ereq_use_env (owner_name x) tau_x) (add_use_env rx1 (Var xa) r);
        leq_use_env r_se (diff_use_env (add_use_env rx1 (Var xa) r) (comp_use_env (ereq_use_env (owner_name x) tau_x) r_ex)); leq_use_env r_xe r_se;
        leq_use_env r_ex (add_use_env rx1 (Var xa) r);
        leq_use_env (diff_use_env (ereq_use_env (owner_name x) tau_x) (comp_use_env (ereq_use_env (owner_name x) tau_x) r_ex)) r_xe\<rbrakk>
       \<Longrightarrow> well_typed env r_s1 (subst_exp (VarExp x) xa e') tau
            (diff_use_env (comp_use_env (rem_use_env r_se (Var xa)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var xa) rx2 r))
            (diff_use_env (stpx_req (rem_use_env r_xe (Var xa)) (lift_use_env rx2 (r_xe (Var xa))) (r_xe (Var xa))) (end_neg_use_env r_se (Var xa) rx2 r))"
    (* - tau = tau_x. *)
  apply (case_tac "\<not> tau_x = tau")
   apply (case_tac x)
    apply (auto)
    (* - x is a var *)
  apply (case_tac x)
   apply (auto)
    (* - r_xe x1a \<le> r *)
  apply (case_tac "\<not> leq_perm (r_xe (Var xa)) r")
   apply (case_tac "\<not> (\<forall> x'. leq_perm (r_xe x') (add_use_env rx1 (Var xa) r x'))")
    apply (cut_tac r_sc="r_xe" and r_sb="diff_use_env (add_use_env rx1 (Var xa) r) (comp_use_env (ereq_use_env (Var xa) tau) r_ex)" and r_sa="add_use_env rx1 (Var xa) r" in trans_leq_use_env)
      apply (rule_tac self_diff_leq_use_env)
     apply (rule_tac r_sb="r_se" in trans_leq_use_env)
      apply (simp_all)
    apply (simp add: leq_use_env_def)
   apply (erule_tac x="Var xa" in allE)
   apply (simp add: add_use_env_def)
    (* - simplify the requirements followed by manipulation *)
  apply (rule_tac rx="diff_use_env (comp_use_env (rem_use_env r_xe (Var xa)) (stpx_ex rx2 (end_req_perm tau))) (end_neg_use_env r_se (Var xa) rx2 r)" in well_typed_incr_req)
    apply (rule_tac well_typed_diff_end_perm)
     apply (rule_tac ?r_s1.0="comp_use_env (rem_use_env r_se (Var xa)) (lift_use_env rx2 r)" in well_typed_incr_start_perm)
      apply (rule_tac well_typed_comp_req1)
       apply (rule_tac well_typed_comp_perms2)
        apply (rule_tac well_typed_lift_perms)
        apply (simp add: add_env_def)
    (* - minor case analysis to get rid of the extra *)
        apply (simp add: stpx_ex_def)
        apply (case_tac "req_type tau_x")
          apply (simp add: end_req_perm_def)
         apply (simp add: end_req_perm_def)
         apply (rule_tac wt_sexp_drop_req)
           apply (simp_all)
        apply (simp add: end_req_perm_def)
        apply (rule_tac rx="rx2" in wt_sexp_no_req)
          apply (simp_all)
    (* - proving disjointness of r_se - x / rx2 (required to remove rse from end perms) [comp_perms2] *)
       apply (rule_tac comm_disj_use_env)
       apply (rule_tac r_s="rx1" in disj_leq_use_env1)
        apply (simp)
       apply (rule_tac r="r" in rem_add_leq_use_env)
       apply (rule_tac r_sb="diff_use_env (add_use_env rx1 (Var xa) r) (comp_use_env (ereq_use_env (Var xa) tau) r_ex)" in trans_leq_use_env)
        apply (rule_tac self_diff_leq_use_env)
       apply (simp)
    (* - proving that removing r_xe - x from the reqs was valid [comp_req1] *)
      apply (rule_tac comp_leq_use_env1)
      apply (rule_tac dist_rem_leq_use_env)
      apply (simp)
    (* - proving that downgrading the start perms was valid (rse - x) + rx2 \<le> r_s1 [incr_start_perm] *)
     apply (rule_tac dist_comp_leq_use_env)
      apply (rule_tac r_sb="rx1" in trans_leq_use_env)
       apply (rule_tac r_sb="comp_use_env rx1 (lift_use_env rx2 r)" in trans_leq_use_env)
        apply (simp)
       apply (rule_tac self_comp_leq_use_env1)
      apply (rule_tac r="r" in rem_add_leq_use_env)
      apply (rule_tac r_sb="diff_use_env (add_use_env rx1 (Var xa) r) (comp_use_env (ereq_use_env (Var xa) tau) r_ex)" in trans_leq_use_env)
       apply (rule_tac self_diff_leq_use_env)
      apply (simp)
     apply (rule_tac r_sb="comp_use_env rx1 (lift_use_env rx2 r)" in trans_leq_use_env)
      apply (simp)
     apply (rule_tac self_comp_leq_use_env2)
    (* - proving that the very first removal of rx2 was okay *)
    apply (rule_tac end_neg_leq_use_env)
    apply (rule_tac r_sb="comp_use_env rx1 (lift_use_env rx2 r)" in trans_leq_use_env)
     apply (simp)
    apply (rule_tac self_comp_leq_use_env2)
    (* - prove that the initial change in requirements was valid. to prove the end perm bound (the harder one), we split based on r_xe x1a.
          we start with the ownership case to make the manipulation easier. *)
   apply (case_tac "is_own (r_xe (Var xa))")
    apply (rule_tac dist_diff_leq_use_env)
    apply (case_tac "stpx_req (rem_use_env r_xe (Var xa)) (lift_use_env rx2 (r_xe (Var xa))) (r_xe (Var xa)) \<noteq>
      comp_use_env (rem_use_env r_xe (Var xa)) (lift_use_env rx2 (r_xe (Var xa)))")
     apply (simp add: is_own_def)
     apply (simp add: stpx_req_def)
    apply (auto)
    apply (rule_tac dist_comp_leq_use_env)
     apply (rule_tac self_comp_leq_use_env1)
    apply (rule_tac comp_leq_use_env2)
    apply (rule_tac stpx_ex_leq_use_env)
    apply (rule_tac self_lift_leq_use_env)
   apply (case_tac "r_xe (Var xa)")
     apply (auto)
    (* - in the None case, our main goal is to get rid of rx2 *)
     apply (simp add: stpx_req_def)
     apply (rule_tac lhs_dist_dcl_use_env)
     apply (rule_tac dist_comp_leq_use_env)
      apply (rule_tac id_leq_use_env)
    (* - if req_type tau = Prim, then rx2 will give nothing *)
     apply (case_tac "req_type tau = Prim")
      apply (simp add: stpx_ex_def)
      apply (simp add: end_req_perm_def)
      apply (rule_tac diff_leq_use_env)
      apply (rule_tac leq_empty_use_env)
    (* - otherwise, ereq_use_env x1a tau x1a \<noteq> None *)
     apply (case_tac "ereq_use_env (Var xa) tau (Var xa) = NoPerm")
      apply (simp add: ereq_use_env_def)
      apply (simp add: one_use_env_def)
      apply (simp add: end_req_perm_def)
      apply (case_tac "req_type tau")
        apply (auto)
    (* - knowing this, (ereq x1a tau + r_ex) x1a = Own, since r_xe = None *)
     apply (cut_tac r_x="ereq_use_env (Var xa) tau" and r_ex="comp_use_env (ereq_use_env (Var xa) tau) r_ex" and r_s="r_xe" and x="(Var xa)" in diff_use_own)
        apply (auto)
    (* - this means r = OwnPerm, since (ereq x1a tau + r_ex) \<le> rx1 + (x: r) *)
     apply (case_tac "\<not> is_own r")
      apply (cut_tac r_x="comp_use_env (ereq_use_env (Var xa) tau) r_ex" and r_s="add_use_env rx1 (Var xa) r" and x="Var xa" in leq_use_own)
        apply (simp)
       apply (rule_tac dist_comp_leq_use_env)
        apply (auto)
      apply (simp add: add_use_env_def)
      apply (simp add: is_own_def)
    (* - we also have r_se x = None *)
     apply (cut_tac r_x="r_se" and r_s="diff_use_env (add_use_env rx1 (Var xa) r) (comp_use_env (ereq_use_env (Var xa) tau) r_ex)" and x="Var xa" in leq_use_none)
       apply (simp)
      apply (rule_tac diff_use_none_ex)
      apply (auto)
    (* - with that we can resolve the inequality *)
     apply (simp add: end_neg_use_env_def)
     apply (rule_tac r_sb="diff_use_env (lift_use_env rx2 r) (lift_use_env rx2 r)" in trans_leq_use_env)
      apply (rule_tac cancel_lift_leq_use_env)
      apply (simp)
     apply (rule_tac dist_diff_leq_use_env)
     apply (rule_tac stpx_ex_leq_use_env)
     apply (rule_tac self_lift_leq_use_env)
    (* - in the Use case, we know req_type tau \<noteq> Aff, since otherwise it would be subtracted out *)
    apply (simp add: stpx_req_def)
    apply (rule_tac dist_diff_leq_use_env)
    apply (case_tac "req_type tau = Aff")
     apply (cut_tac r_x="r_xe" and r_s="diff_use_env (add_use_env rx1 (Var xa) r) (comp_use_env (ereq_use_env (Var xa) tau) r_ex)" and x="Var xa" in leq_use_none)
       apply (rule_tac r_sb="r_se" in trans_leq_use_env)
        apply (auto)
     apply (rule_tac diff_use_none_ex)
     apply (case_tac "comp_use_env (ereq_use_env (Var xa) tau) r_ex (Var xa) \<noteq> OwnPerm")
      apply (cut_tac r_sa="ereq_use_env (Var xa) tau" and r_sb="r_ex" and x="Var xa" in comp_use_no_own_both)
       apply (auto)
     apply (simp add: ereq_use_env_def)
     apply (simp add: one_use_env_def)
     apply (simp add: end_req_perm_def)
    (* - the rest of the inequality follows simply from this *)
    apply (rule_tac dist_comp_leq_use_env)
     apply (rule_tac self_comp_leq_use_env1)
    apply (rule_tac comp_leq_use_env2)
    apply (simp add: stpx_ex_def)
    apply (simp add: end_req_perm_def)
    apply (auto)
      apply (rule_tac leq_empty_use_env)
     apply (rule_tac id_leq_use_env)
    apply (case_tac "req_type tau")
      apply (auto)
    (* - the Own case was already solved at the start *)
   apply (simp add: is_own_def)
    (* - lastly, the other half of the inequality *)
  apply (rule_tac dist_diff_leq_use_env)
  apply (rule_tac stpx_req_leq_use_env)
  apply (rule_tac dist_comp_leq_use_env)
   apply (rule_tac comp_leq_use_env1)
   apply (rule_tac dist_rem_leq_use_env)
   apply (simp)
  apply (rule_tac comp_leq_use_env2)
  apply (rule_tac dist_lift_leq_use_env_gen)
  apply (simp)
  done

    (*
      ####################################
        P2b. pair case
      ####################################
    *)

    (* our approach to the pair case goes roughly like this:
        - in order to avoid repeating the end solutions, we want to specify the reqs in a way that is dependent on whether or not
            x actually appears in the perms. because we have an affinity constraint, the implication is that we'll have to do it
            using stpx_req.
        - with that in mind, for the non-npv case, we can remove the diff since the subtractant is disjoint in the reqs. the rest of the
            manipulations are straightforward.
        - for the npv case,
    *)

    (*

lemma stpxpc_coerce: "\<lbrakk> \<And>env x tau t rx1 r_se r_xe r_s1 rx2 r.
           \<lbrakk>well_typed (add_env env x t) (add_use_env rx1 x r) e1 tau r_se r_xe; well_typed env rx2 e' t rx2 rx2; rx1 x = NoPerm; x \<in> free_vars e1;
            lam_vars e1 \<inter> free_vars e' = {}; leq_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_s1; (*safe_use_lift rx2 r;*)
            disj_use_env rx1 (lift_use_env rx2 r)\<rbrakk>
           \<Longrightarrow> well_typed env r_s1 (subst_exp e1 x e') tau (diff_use_env (comp_use_env (rem_use_env r_se x) (lift_use_env rx2 r)) (end_neg_use_env r_se x rx2 r))
                (diff_use_env (stpx_req (rem_use_env r_xe x) (lift_use_env rx2 (r_xe x)) (r_xe x)) (end_neg_use_env r_se x rx2 r));
  well_typed (add_env env x t) (add_use_env rx1 x r) e1 tau r_se r_xe; well_typed env rx2 e' t rx2 rx2; rx1 x = NoPerm; x \<in> free_vars e1;
            lam_vars e1 \<inter> free_vars e' = {}; leq_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_s1; (*safe_use_lift rx2 r;*)
            disj_use_env rx1 (lift_use_env rx2 r)
   \<rbrakk> \<Longrightarrow>
  well_typed env r_s1 (subst_exp e1 x e') tau (diff_use_env (comp_use_env (rem_use_env r_se x) (lift_use_env rx2 r)) (end_neg_use_env r_se x rx2 r))
                (diff_use_env (stpx_req (rem_use_env r_xe x) (lift_use_env rx2 (r_xe x)) (r_xe x)) (end_neg_use_env r_se x rx2 r))"
  apply (auto)
  done

lemma stpxpc_well_typed: "\<lbrakk>\<And>env x tau t rx1 r_se r_xe r_s1 rx2 r.
        \<lbrakk>well_typed (add_env env x t) (add_use_env rx1 x r) e1 tau r_se r_xe; well_typed env rx2 e' t rx2 rx2; rx1 x = NoPerm; x \<in> free_vars e1;
         lam_vars e1 \<inter> free_vars e' = {}; leq_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_s1; (*safe_use_lift rx2 r;*) disj_use_env rx1 (lift_use_env rx2 r)\<rbrakk>
        \<Longrightarrow> well_typed env r_s1 (subst_exp e1 x e') tau (diff_use_env (comp_use_env (rem_use_env r_se x) (lift_use_env rx2 r)) (end_neg_use_env r_se x rx2 r))
             (diff_use_env (stpx_req (rem_use_env r_xe x) (lift_use_env rx2 (r_xe x)) (r_xe x)) (end_neg_use_env r_se x rx2 r));
     well_typed env rx2 e' t rx2 rx2; rx1 x = NoPerm; is_sexp e'; lam_vars e1 \<inter> (free_vars e' \<union> ref_vars e') = {}; x \<notin> ref_vars e1;
     leq_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_s1; (*safe_use_lift rx2 r;*) disj_use_env rx1 (lift_use_env rx2 r);
     well_typed (add_env env x t) rx1a e1 t1 r_sa r_xa;
     leq_use_env rx (add_use_env rx1 x r); leq_use_env rx1a rx;
     leq_perm (rx1a x) r; leq_use_env r_xa rx1a; leq_perm (r_xa x) r \<rbrakk>
    \<Longrightarrow> \<exists>r_xa r_sa. well_typed env (stpx_req (rem_use_env rx1a x) (lift_use_env rx2 (rx1a x)) (rx1a x)) (subst_exp e1 x e') t1 r_sa r_xa"
  apply (rule_tac x="diff_use_env (stpx_req (rem_use_env r_xa x) (lift_use_env rx2 (r_xa x)) (r_xa x))
    (end_neg_use_env r_sa x (drop_use_env_ex rx2 (rx1a x)) (rx1a x))" in exI)
  apply (rule_tac x="diff_use_env (stpx_req (rem_use_env r_sa x) (lift_use_env rx2 (rx1a x)) (rx1a x))
  (end_neg_use_env r_sa x (drop_use_env_ex rx2 (rx1a x)) (rx1a x))" in exI)
    (* x \<notin> fv e1. *)
  apply (case_tac "x \<notin> non_prim_vars (add_env env x t) e1")
   apply (rule_tac t="t" in subst_type_preserve_no_npv)
        apply (auto)
   apply (rule_tac rx="stpx_req (rem_use_env r_xa x) (lift_use_env rx2 (r_xa x)) (r_xa x)" and
        ?r_s2.0="stpx_req (rem_use_env r_sa x) (lift_use_env rx2 (rx1a x)) (rx1a x)" in well_typed_simul_end_perm)
      apply (rule_tac well_typed_stpx_req2)
         apply (rule_tac well_typed_rem_perms)
          apply (auto)
        apply (rule_tac r_x="r_xa" and r_s="rx1a" in spec_leq_perm)
        apply (simp)
       apply (rule_tac dist_lift_leq_use_env_gen)
       apply (rule_tac r_x="r_xa" and r_s="rx1a" in spec_leq_perm)
       apply (simp)
      apply (rule_tac r_s="rx1" in disj_leq_use_env1)
       apply (rule_tac r_s="lift_use_env rx2 r" in disj_leq_use_env2)
        apply (simp)
       apply (rule_tac dist_lift_leq_use_env_gen)
       apply (simp)
      apply (rule_tac r="r" in rem_add_leq_use_env)(*
      apply (rule_tac r_sb="lift_use_env rx1a ra" in trans_leq_use_env)*)
       apply (rule_tac r_sb="rx" in trans_leq_use_env)
        apply (simp_all)
      (*apply (rule_tac self_lift_leq_use_env)*)
     apply (rule_tac diff_leq_use_env)
     apply (rule_tac id_leq_use_env)
    apply (rule_tac dist_diff_leq_use_env)
    apply (rule_tac dist_stpx_req_leq_use_env)
      apply (rule_tac r_x="r_xa" and r_s="rx1a" in spec_leq_perm)
      apply (simp)
     apply (rule_tac dist_rem_leq_use_env)
     apply (rule_tac well_typed_perm_leqx)
     apply (auto)
    apply (rule_tac dist_lift_leq_use_env_gen)
    apply (rule_tac r_x="r_xa" and r_s="rx1a" in spec_leq_perm)
    apply (simp)
   apply (rule_tac disj_diff_leq_use_env)
    apply (rule_tac comm_disj_use_env)
    apply (rule_tac r_s="end_neg_use_env r_sa x rx2 (rx1a x)" in disj_leq_use_env2)
     apply (rule_tac disj_stpx_end_neg_use_env)
       apply (rule_tac r_x="r_xa" and r_s="r_sa" in spec_leq_perm)
       apply (rule_tac well_typed_perm_leqx)
       apply (auto)
      apply (cut_tac r_x="r_sa" and r_s="rx1a" and x="x" in spec_leq_perm)
       apply (rule_tac well_typed_perm_leq)
       apply (auto)
     apply (rule_tac r_s="rx1" in disj_leq_use_env1)
      apply (rule_tac r_s="lift_use_env rx2 r" in disj_leq_use_env2)
       apply (simp)
      apply (rule_tac dist_lift_leq_use_env_gen)
      apply (simp)
     apply (rule_tac r="r" in rem_add_leq_use_env)
     (*apply (rule_tac r_sb="lift_use_env rx1a ra" in trans_leq_use_env)*)
     apply (rule_tac r_sb="rx1a" in trans_leq_use_env)
      apply (rule_tac r_sb="rx" in trans_leq_use_env)
       apply (auto)(*
     apply (rule_tac lift_leq_use_env)
     apply (simp)*)
    apply (rule_tac dist_end_neg_leq_use_env_gen)
    apply (case_tac "rx1a x")
      apply (auto)
      apply (rule_tac self_drop_leq_use_env)
     apply (rule_tac self_drop_leq_use_env)
    apply (rule_tac id_leq_use_env)
   apply (rule_tac id_leq_use_env)
    (* x \<in> fv e1. rx1 = rem_use_env rx1a x, r = rx1a x, r_se = r_sa, r_xe = r_xa, rx2 = drop_use_env_ex rx2 (rx1a x),
        r_s1 = stpx_req (rem_use_env rx1a x) (lift_use_env rx2 r) (rx1a x) *)
  apply (case_tac "rx1a x = NoPerm")
   apply (cut_tac env="add_env env x t" and e="e1" and ?r_s1.0="rx1a" and x="x" in well_typed_no_npv_use)
     apply (auto)
  apply (cut_tac r_x="rem_use_env r_sa x" and r_s="rx2" and r="rx1a x" in stpx_req_drop_use_env)
   apply (simp)
  apply (cut_tac r_x="rem_use_env rx1a x" and r_s="rx2" and r="rx1a x" in stpx_req_drop_use_env)
   apply (auto)
  apply (rule_tac rx="diff_use_env (stpx_req (rem_use_env r_xa x) (lift_use_env (drop_use_env_ex rx2 (rx1a x)) (r_xa x)) (r_xa x))
      (end_neg_use_env r_sa x (drop_use_env_ex rx2 (rx1a x)) (rx1a x))" in well_typed_incr_req)
    apply (rule_tac ?rx1.0="rem_use_env rx1a x" and t="t" in stpxpc_coerce)
            apply (auto)
          apply (cut_tac r_s="rx1a" and x="x" and r="rx1a x" in cancel_add_rem_use_env)
           apply (simp_all)
         apply (rule_tac wt_sexp_drop_all_ex)
           apply (simp)
          apply (simp add: tau_drop_req_def)
          apply (case_tac "rx1a x")
            apply (auto)
         apply (cut_tac env="add_env env x t" and ?r_s1.0="rx1a" and e="e1" and x="x" and t="t" in well_typed_aff_fv_own)
             apply (auto)
          apply (simp add: non_prim_vars_def)
         apply (simp add: add_env_def)
        apply (simp add: rem_use_env_def)
       apply (simp add: non_prim_vars_def)
      apply (rule_tac id_leq_use_env)(*
     apply (rule_tac safe_lift_drop_use_env)
     apply (simp)*)
    apply (rule_tac r_s="rx1" in disj_leq_use_env1)
     apply (rule_tac r_s="lift_use_env rx2 r" in disj_leq_use_env2)
      apply (simp)
     apply (rule_tac r_sb="lift_use_env rx2 (rx1a x)" in trans_leq_use_env)
      apply (rule_tac dist_lift_leq_use_env_gen)
      apply (simp)
     apply (rule_tac dist_lift_leq_use_env)
     apply (case_tac "rx1a x")
       apply (auto)
      apply (rule_tac self_drop_leq_use_env)
     apply (rule_tac id_leq_use_env)
    apply (rule_tac r="r" in rem_add_leq_use_env)
    (*apply (rule_tac r_sb="lift_use_env rx1a ra" in trans_leq_use_env)*)
     apply (rule_tac r_sb="rx" in trans_leq_use_env)
      apply (auto)
    (*apply (rule_tac self_lift_leq_use_env)*)
   apply (rule_tac dist_diff_leq_use_env)
   apply (rule_tac dist_stpx_req_leq_use_env)
     apply (case_tac "r_xa x")
       apply (auto)
    apply (rule_tac id_leq_use_env)
   apply (rule_tac dist_lift_leq_use_env)
   apply (case_tac "rx1a x")
     apply (auto)
    apply (rule_tac self_drop_leq_use_env)
   apply (rule_tac id_leq_use_env)
  apply (rule_tac dist_diff_leq_use_env)
  apply (rule_tac stpx_req_leq_use_env5)
  apply (rule_tac dist_comp_leq_use_env)
   apply (rule_tac comp_leq_use_env1)
   apply (rule_tac dist_rem_leq_use_env)
   apply (rule_tac well_typed_perm_leqx)
   apply (auto)
  apply (rule_tac comp_leq_use_env2)
  apply (rule_tac r_sb="lift_use_env (drop_use_env_ex rx2 (rx1a x)) (r_xa x)" in trans_leq_use_env)
   apply (rule_tac dist_lift_leq_use_env_gen)
   apply (rule_tac r_x="r_xa" and r_s="rx1a" in spec_leq_perm)
   apply (simp)
  apply (rule_tac dist_lift_leq_use_env)
  apply (rule_tac dist_drop_leq_use_env_ex)
  apply (rule_tac r_x="r_xa" and r_s="rx1a" in spec_leq_perm)
  apply (simp)
  done*)

lemma stpxpc_leq_use_env1: "\<lbrakk>leq_use_env (lift_use_env rx1a ra) rx; (*ra \<noteq> NoPerm;*) leq_perm (rx1a x) (rx x)\<rbrakk>
    \<Longrightarrow> leq_use_env (lift_use_env (stpx_ex (lift_use_env rx2 (rx1a x)) (rx1a x)) ra) (stpx_ex (lift_use_env rx2 (rx x)) (rx x))"
  apply (case_tac "\<not> is_own ra")
   apply (simp add: is_own_def)
   apply (case_tac "lift_use_env rx1a ra \<noteq> rx1a")
    apply (case_tac ra)
      apply (auto)
   apply (case_tac "lift_use_env (stpx_ex (lift_use_env rx2 (rx1a x)) (rx1a x)) ra \<noteq> stpx_ex (lift_use_env rx2 (rx1a x)) (rx1a x)")
    apply (case_tac ra)
      apply (auto)
   apply (rule_tac dist_stpx_ex_leq_use_env)
   apply (auto)
  apply (case_tac "rx1a x = NoPerm")
   apply (case_tac "stpx_ex (lift_use_env rx2 (rx1a x)) (rx1a x) \<noteq> empty_use_env")
    apply (simp add: stpx_ex_def)
   apply (auto)
   apply (simp add: lift_empty_use_env)
   apply (rule_tac leq_empty_use_env)
  apply (case_tac "\<not> is_own (rx x)")
   apply (cut_tac r_x="lift_use_env rx1a ra" and r_s="rx" and x="x" in leq_use_own)
     apply (simp add: is_own_def)
    apply (simp)
   apply (simp add: is_own_def)
  apply (rule_tac r_sb="lift_use_env rx2 (rx x)" in trans_leq_use_env)
   apply (simp add: is_own_def)
   apply (simp add: stpx_ex_def)
   apply (rule_tac id_leq_use_env)
  apply (rule_tac lhs_lift_leq_use_env_gen)
   apply (rule_tac stpx_ex_leq_use_env)
   apply (rule_tac dist_lift_leq_use_env_gen)
   apply (simp)
  apply (simp add: is_own_def)
  done
    (*
lemma stpxpc_leq_use_env2: "\<lbrakk> leq_use_env (lift_use_env rx1a ra) rx; ra \<noteq> NoPerm; leq_perm (rx1a x) (rx x) \<rbrakk> \<Longrightarrow>
  leq_use_env (lift_use_env (stpx_req (rem_use_env rx1a x) (lift_use_env rx2 (rx1a x)) (rx1a x)) ra)
         (stpx_req (rem_use_env rx x) (lift_use_env rx2 (rx x)) (rx x))"
  apply (rule_tac stpx_req_leq_use_env4)
  apply (rule_tac r_sb="comp_use_env (lift_use_env (rem_use_env rx1a x) ra) (lift_use_env (stpx_ex (lift_use_env rx2 (rx1a x)) (rx1a x)) ra)" in trans_leq_use_env)
   apply (rule_tac dist_comp_leq_use_env)
    apply (rule_tac comp_leq_use_env1)
    apply (cut_tac r_s="rx1a" and x="x" and r="ra" in lift_rem_use_env)
    apply (simp)
    apply (rule_tac dist_rem_leq_use_env)
    apply (simp)
   apply (rule_tac comp_leq_use_env2)
   apply (rule_tac rx1a="rx1a" in stpxpc_leq_use_env1)
     apply (auto)
  apply (rule_tac t="comp_use_env (lift_use_env (rem_use_env rx1a x) ra) (lift_use_env (stpx_ex (lift_use_env rx2 (rx1a x)) (rx1a x)) ra)"
      and s="lift_use_env (comp_use_env (rem_use_env rx1a x) (stpx_ex (lift_use_env rx2 (rx1a x)) (rx1a x))) ra" in subst)
   apply (rule_tac lift_comp_use_env)
  apply (rule_tac dist_lift_leq_use_env)
  apply (rule_tac stpx_req_leq_use_env3)
  apply (rule_tac id_leq_use_env)
  done*)

lemma stpxpc_disj_use_env1: "\<lbrakk> disj_use_env (lift_use_env rx1a ra) (lift_use_env rx2a ra); disj_use_env rx1 (lift_use_env rx2 r);
  leq_perm (rx2a x) r; (*ra \<noteq> NoPerm;*) (*safe_use_lift rx2 r; r \<noteq> NoPerm;*) leq_use_env (lift_use_env rx1a ra) rx;
  leq_use_env (lift_use_env rx2a ra) rx; leq_use_env rx (add_use_env rx1 x r) \<rbrakk> \<Longrightarrow>
  disj_use_env (lift_use_env (rem_use_env rx1a x) ra) (lift_use_env (stpx_ex (lift_use_env rx2 (rx2a x)) (rx2a x)) ra)"
  apply (rule_tac r_s="rx1" in disj_leq_use_env1)
   apply (rule_tac r_s="lift_use_env rx2 r" in disj_leq_use_env2)
    apply (simp)
   apply (rule_tac r_sb="stpx_ex (lift_use_env rx2 (rx x)) (rx x)" in trans_leq_use_env)
    apply (rule_tac stpx_ex_leq_use_env)
    apply (rule_tac dist_lift_leq_use_env_gen)
    apply (cut_tac r_x="rx" and r_s="add_use_env rx1 x r" and x="x" in spec_leq_perm)
     apply (simp)
    apply (simp add: add_use_env_def)
   apply (rule_tac rx1a="rx2a" in stpxpc_leq_use_env1)
     apply (auto)
   apply (rule_tac r_x="rx2a" and r_s="rx" in spec_leq_perm)
   apply (rule_tac r_sb="lift_use_env rx2a ra" in trans_leq_use_env)
    apply (simp)
   apply (rule_tac self_lift_leq_use_env)
  apply (cut_tac r_s="rx1a" and x="x" and r="ra" in lift_rem_use_env)
  apply (simp)
  apply (rule_tac r="r" in rem_add_leq_use_env)
  apply (rule_tac r_sb="rx" in trans_leq_use_env)
   apply (auto)
  done

lemma stpxic_valid_diff: "\<lbrakk> xa \<in> non_prim_vars env (subst_exp e2 x e'); xa \<in> own_env_vars (end_neg_use_env r_s2 (Var x) rx2 r);
  x \<in> free_vars e2; well_typed env rx2 e' t rx2 rx2; is_sexp e'; disj_use_env rx1 (lift_use_env rx2 r);
  well_typed (add_env env (Var x) t) (add_use_env rx1 (Var x) r) e1 tau' r_s2 rx'; well_typed (add_env env (Var x) t) r_s2 e2 tau r_se rx \<rbrakk> \<Longrightarrow> False"
    (* if r_s2 x \<noteq> None, end_neg contains no vars. so then r_s2 x = None. since we have x \<in> free_vars e2, t must be Prim *)
  apply (case_tac "r_s2 (Var x) \<noteq> NoPerm")
   apply (simp add: own_env_vars_def)
   apply (simp add: end_neg_use_env_def)
   apply (simp add: empty_use_env_def)
  apply (case_tac "req_type t \<noteq> Prim")
   apply (cut_tac env="add_env env (Var x) t" and ?r_s1.0="r_s2" and e="e2" and x="Var x" in well_typed_no_npv_use)
     apply (auto)
   apply (simp add: non_prim_vars_def)
   apply (simp add: non_prim_entry_def)
   apply (simp add: add_env_def)
   apply (auto)
   apply (cut_tac x="x" and e="e2" in free_res_vars_rev)
    apply (auto)
    (* with that in mind, xa cannot be in a non-prim-var of e2, since it would appear in both rx1 and rx2 *)
    thm subst_np_vars
  apply (cut_tac e="e2" and e'="e'" and x="xa" and y="x" in subst_np_vars)
   apply (auto)
   apply (case_tac "r_s2 xa = NoPerm")
    apply (cut_tac env="add_env env (Var x) t" and ?r_s1.0="r_s2" and e="e2" and x="xa" in well_typed_no_npv_use)
      apply (auto)
    apply (simp add: non_prim_vars_def)
    apply (simp add: non_prim_entry_def)
    apply (simp add: add_env_def)
    apply (auto)
   apply (case_tac "rx1 xa = NoPerm")
    apply (case_tac "add_use_env rx1 (Var x) r xa = NoPerm")
     apply (cut_tac r_x="r_s2" and r_s="add_use_env rx1 (Var x) r" and x="xa" in leq_use_none)
       apply (rule_tac well_typed_perm_leq)
       apply (auto)
    apply (simp add: add_use_env_def)
   apply (case_tac "lift_use_env rx2 r xa \<noteq> OwnPerm")
    apply (simp add: own_env_vars_def)
    apply (simp add: end_neg_use_env_def)
   apply (simp add: disj_use_env_def)
   apply (simp add: mini_disj_use_env_def)
    (* then it must be in e', however none of the np_vars of e' can be non-primitive, which shows that removing xa is safe *)
  apply (cut_tac x="xa" and env="env" and ?r_s1.0="rx2" and e="e'" in wt_sexp_no_npv_use)
     apply (auto)
  done

lemma stpxpc_coercex: "\<lbrakk>\<And>env x tau t rx1 r_se r_xe r_s1 rx2 r.
           \<lbrakk>well_typed (add_env env (Var x) t) (add_use_env rx1 (Var x) r) e1 tau r_se r_xe; well_typed env rx2 e' t rx2 rx2; rx1 (Var x) = NoPerm;
            x \<in> free_vars e1; lam_vars e1 \<inter> free_vars e' = {}; leq_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_s1; disj_use_env rx1 (lift_use_env rx2 r)\<rbrakk>
           \<Longrightarrow> well_typed env r_s1 (subst_exp e1 x e') tau
                (diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r))
                (diff_use_env (stpx_req (rem_use_env r_xe (Var x)) (lift_use_env rx2 (r_xe (Var x))) (r_xe (Var x))) (end_neg_use_env r_se (Var x) rx2 r));
  well_typed (add_env env (Var x) t) (add_use_env rx1 (Var x) r) e1 tau r_se r_xe; well_typed env rx2 e' t rx2 rx2; rx1 (Var x) = NoPerm;
            x \<in> free_vars e1; lam_vars e1 \<inter> free_vars e' = {}; leq_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_s1; disj_use_env rx1 (lift_use_env rx2 r)
  \<rbrakk> \<Longrightarrow> well_typed env r_s1 (subst_exp e1 x e') tau
                (diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r))
                (diff_use_env (stpx_req (rem_use_env r_xe (Var x)) (lift_use_env rx2 (r_xe (Var x))) (r_xe (Var x))) (end_neg_use_env r_se (Var x) rx2 r))"
  apply (auto)
  done

lemma stpx_pair_case: "\<lbrakk>\<And>env x tau t rx1 r_se r_xe r_s1 rx2 r.
           \<lbrakk>well_typed (add_env env (Var x) t) (add_use_env rx1 (Var x) r) e1 tau r_se r_xe; well_typed env rx2 e' t rx2 rx2; rx1 (Var x) = NoPerm;
            x \<in> free_vars e1; lam_vars e1 \<inter> free_vars e' = {}; leq_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_s1; disj_use_env rx1 (lift_use_env rx2 r)\<rbrakk>
           \<Longrightarrow> well_typed env r_s1 (subst_exp e1 x e') tau
                (diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r))
                (diff_use_env (stpx_req (rem_use_env r_xe (Var x)) (lift_use_env rx2 (r_xe (Var x))) (r_xe (Var x))) (end_neg_use_env r_se (Var x) rx2 r));
        \<And>env x tau t rx1 r_se r_xe r_s1 rx2 r.
           \<lbrakk>well_typed (add_env env (Var x) t) (add_use_env rx1 (Var x) r) e2 tau r_se r_xe; well_typed env rx2 e' t rx2 rx2; rx1 (Var x) = NoPerm;
            x \<in> free_vars e2; lam_vars e2 \<inter> free_vars e' = {}; leq_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_s1; disj_use_env rx1 (lift_use_env rx2 r)\<rbrakk>
           \<Longrightarrow> well_typed env r_s1 (subst_exp e2 x e') tau
                (diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r))
                (diff_use_env (stpx_req (rem_use_env r_xe (Var x)) (lift_use_env rx2 (r_xe (Var x))) (r_xe (Var x))) (end_neg_use_env r_se (Var x) rx2 r));
        well_typed env rx2 e' t rx2 rx2; rx1 (Var x) = NoPerm; is_sexp e'; (lam_vars e1 \<union> lam_vars e2) \<inter> free_vars e' = {};
        leq_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_s1; disj_use_env rx1 (lift_use_env rx2 r);
        well_typed (add_env env (Var x) t) (add_use_env rx1 (Var x) r) e1 t1 r_s2 rx1a; well_typed (add_env env (Var x) t) r_s2 e2 t2 r_s3 rx2a;
        leq_use_env (lift_use_env rx1a ra) r_s3; leq_use_env (lift_use_env rx2a ra) r_s3; aff_leq (max_aff (req_type t1) (req_type t2)) ra;
        disj_use_env (lift_use_env rx1a ra) (lift_use_env rx2a ra); leq_use_env r_se (diff_use_env r_s3 r_ex); leq_use_env r_xe r_se;
        leq_use_env r_ex (add_use_env rx1 (Var x) r);
        leq_use_env (pair_req (comp_use_env (lift_use_env rx1a ra) (lift_use_env rx2a ra)) r_ex (PairTy t1 t2 ra)) r_xe\<rbrakk>
       \<Longrightarrow> \<exists>r_s2 r_s3 rx1.
              well_typed env r_s1 (subst_exp e1 x e') t1 r_s2 rx1 \<and>
              (\<exists>rx2a. well_typed env r_s2 (subst_exp e2 x e') t2 r_s3 rx2a \<and>
                      leq_use_env (lift_use_env rx1 ra) r_s3 \<and>
                      leq_use_env (lift_use_env rx2a ra) r_s3 \<and>
                      disj_use_env (lift_use_env rx1 ra) (lift_use_env rx2a ra) \<and>
                      (\<exists>r_ex. leq_use_env (diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r))
                               (diff_use_env r_s3 r_ex) \<and>
                              leq_use_env
                               (diff_use_env (stpx_req (rem_use_env r_xe (Var x)) (lift_use_env rx2 (r_xe (Var x))) (r_xe (Var x)))
                                 (end_neg_use_env r_se (Var x) rx2 r))
                               (diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r)) \<and>
                              leq_use_env r_ex r_s1 \<and>
                              leq_use_env (pair_req (comp_use_env (lift_use_env rx1 ra) (lift_use_env rx2a ra)) r_ex (PairTy t1 t2 ra))
                               (diff_use_env (stpx_req (rem_use_env r_xe (Var x)) (lift_use_env rx2 (r_xe (Var x))) (r_xe (Var x)))
                                 (end_neg_use_env r_se (Var x) rx2 r))))"
    (* prelim: r_s3 \<le> rx1 + x *)
  apply (cut_tac r_sc="r_s3" and r_sb="r_s2" and r_sa="add_use_env rx1 (Var x) r" in trans_leq_use_env)
    apply (rule_tac well_typed_perm_leq)
    apply (auto)
   apply (rule_tac well_typed_perm_leq)
   apply (auto)
    (* prelim: lift rx1a ra x \<le> r *)
  apply (case_tac "\<not> leq_perm (lift_use_env rx1a ra (Var x)) r")
   apply (cut_tac r_x="lift_use_env rx1a ra" and r_s="add_use_env rx1 (Var x) r" and x="Var x" in spec_leq_perm)
    apply (rule_tac r_sb="r_s3" in trans_leq_use_env)
     apply (auto)
   apply (simp add: add_use_env_def)
    (* prelim: lift rx2a ra x \<le> r *)
  apply (case_tac "\<not> leq_perm (lift_use_env rx2a ra (Var x)) r")
   apply (cut_tac r_x="lift_use_env rx2a ra" and r_s="add_use_env rx1 (Var x) r" and x="Var x" in spec_leq_perm)
    apply (rule_tac r_sb="r_s3" in trans_leq_use_env)
     apply (auto)
   apply (simp add: add_use_env_def)
    (* prelim: rx1a x \<le> r *)
  apply (case_tac "\<not> leq_perm (rx1a (Var x)) r")
   apply (cut_tac r_x="rx1a" and r_s="add_use_env rx1 (Var x) r" and x="Var x" in spec_leq_perm)
    apply (rule_tac r_sb="r_s2" in trans_leq_use_env)
     apply (rule_tac well_typed_perm_leq)
     apply (auto)
    apply (rule_tac well_typed_perm_leqx)
    apply (auto)
   apply (simp add: add_use_env_def)
    (* prelim: rx2a x \<le> r *)
  apply (case_tac "\<not> leq_perm (rx2a (Var x)) r")
   apply (cut_tac r_x="rx2a" and r_s="add_use_env rx1 (Var x) r" and x="Var x" in spec_leq_perm)
    apply (rule_tac r_sb="r_s3" in trans_leq_use_env)
     apply (auto)
    apply (rule_tac well_typed_perm_leqx)
    apply (auto)
   apply (simp add: add_use_env_def)
  apply (rule_tac x="diff_use_env (comp_use_env (rem_use_env r_s2 (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_s2 (Var x) rx2 r)" in exI)
  apply (rule_tac x="diff_use_env (comp_use_env (rem_use_env r_s3 (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_s3 (Var x) rx2 r)" in exI)
  apply (rule_tac x="diff_use_env (stpx_req (rem_use_env rx1a (Var x)) (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x))) (end_neg_use_env r_s2 (Var x) rx2 r)" in exI)
  apply (auto)
    (* x \<notin> fv e1 *)
   apply (case_tac "x \<notin> free_vars e1")
    apply (rule_tac well_typed_diff_end_perm)
     apply (rule_tac ?r_s1.0="comp_use_env rx1 (lift_use_env rx2 r)" in well_typed_incr_start_perm)
      apply (rule_tac rx="rem_use_env rx1a (Var x)" in well_typed_incr_req)
        apply (rule_tac well_typed_comp_perms)
         apply (rule_tac subst_type_preserve_no_fv)
          apply (rule_tac r="r" in well_typed_add_perms_rev2)
           apply (rule_tac x="x" and t="t" in well_typed_add_vars_rev)
            apply (auto)
       apply (cut_tac x="x" and e="e1" in free_res_vars)
        apply (auto)
      apply (rule_tac stpx_req_leq_use_env2)
      apply (rule_tac id_leq_use_env)
     apply (rule_tac stpx_req_leq_use_env)
     apply (rule_tac dist_comp_leq_use_env)
      apply (rule_tac comp_leq_use_env1)
      apply (rule_tac dist_rem_leq_use_env)
      apply (rule_tac well_typed_perm_leqx)
      apply (auto)
     apply (rule_tac comp_leq_use_env2)
     apply (rule_tac dist_lift_leq_use_env_gen)
     apply (simp)
    apply (rule_tac end_neg_leq_use_env)
    apply (rule_tac r_sb="comp_use_env rx1 (lift_use_env rx2 r)" in trans_leq_use_env)
     apply (simp)
    apply (rule_tac self_comp_leq_use_env2)
    (* x \<in> fv e1 *)
   apply (rule_tac env="env" and ?rx1.0="rem_use_env rx1 (Var x)" and ?e1.0="e1" and ?r_s1.0="r_s1" and x="x" in stpxpc_coercex)
           apply (auto)
      apply (rule_tac t="add_use_env (rem_use_env rx1 (Var x)) (Var x) r" and s="add_use_env rx1 (Var x) r" in subst)
       apply (rule_tac partial_add_rem_use_env)
      apply (simp)
     apply (simp add: rem_use_env_def)
    apply (rule_tac r_sb="comp_use_env rx1 (lift_use_env rx2 r)" in trans_leq_use_env)
     apply (simp)
    apply (rule_tac dist_comp_leq_use_env)
     apply (rule_tac comp_leq_use_env1)
     apply (rule_tac self_rem_leq_use_env)
    apply (rule_tac self_comp_leq_use_env2)
   apply (rule_tac r_s="rx1" in disj_leq_use_env1)
    apply (simp)
   apply (rule_tac self_rem_leq_use_env)
    (* x \<notin> fv e2 *)
  apply (rule_tac x="diff_use_env (stpx_req (rem_use_env rx2a (Var x)) (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) (end_neg_use_env r_s3 (Var x) rx2 r)" in exI)
  apply (auto)
      apply (case_tac "\<not> well_typed (add_env env (Var x) t) (add_use_env (rem_use_env r_s2 (Var x)) (Var x) (r_s2 (Var x))) e2 t2 r_s3 rx2a")
       apply (cut_tac r_s="r_s2" and x="Var x" and r="r_s2 (Var x)" in cancel_add_rem_use_env)
        apply (auto)
      apply (case_tac "x \<notin> free_vars e2")
       apply (rule_tac r_s="r_s2" in well_typed_diff_decr_end_neg_perm)
         apply (rule_tac rx="diff_use_env (rem_use_env rx2a (Var x)) (end_neg_use_env r_s2 (Var x) rx2 r)" in well_typed_incr_req)
           apply (rule_tac t="diff_use_env (comp_use_env (rem_use_env r_s2 (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_s2 (Var x) rx2 r)" and
      s="comp_use_env (diff_use_env (rem_use_env r_s2 (Var x)) (end_neg_use_env r_s2 (Var x) rx2 r)) (diff_use_env (lift_use_env rx2 r) (end_neg_use_env r_s2 (Var x) rx2 r))" in subst)
          apply (rule_tac dist_diff_comp_use_env)
           apply (rule_tac t="diff_use_env (comp_use_env (rem_use_env r_s3 (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_s2 (Var x) rx2 r)" and
      s="comp_use_env (diff_use_env (rem_use_env r_s3 (Var x)) (end_neg_use_env r_s2 (Var x) rx2 r)) (diff_use_env (lift_use_env rx2 r) (end_neg_use_env r_s2 (Var x) rx2 r))" in subst)
            apply (rule_tac dist_diff_comp_use_env)
           apply (rule_tac well_typed_comp_perms)
            apply (rule_tac well_typed_disj_diff_perms)
             apply (rule_tac subst_type_preserve_no_fv)
              apply (rule_tac well_typed_rem_perms)
               apply (rule_tac x="x" and t="t" in well_typed_add_vars_rev)
                apply (auto)
             apply (simp add: non_prim_vars_def)
             apply (cut_tac x="x" and e="e2" in free_res_vars)
              apply (auto)
            apply (rule_tac gen_mini_disj_use_env2)
            apply (rule_tac r_s="rx1" in disj_leq_use_env1)
             apply (rule_tac r_s="lift_use_env rx2 r" in disj_leq_use_env2)
              apply (simp)
             apply (rule_tac end_neg_leq_use_env)
             apply (rule_tac id_leq_use_env)
            apply (rule_tac r="r" in rem_add_leq_use_env)
            apply (rule_tac well_typed_perm_leq)
            apply (auto)
           apply (rule_tac r_s="rx1" in disj_leq_use_env1)
            apply (rule_tac r_s="lift_use_env rx2 r" in disj_leq_use_env2)
             apply (simp)
            apply (rule_tac self_diff_leq_use_env)
           apply (rule_tac diff_leq_use_env)
           apply (rule_tac r="r" in rem_add_leq_use_env)
           apply (rule_tac well_typed_perm_leq)
           apply (auto)
          apply (rule_tac dist_diff_leq_use_env)
          apply (rule_tac stpx_req_leq_use_env2)
          apply (rule_tac id_leq_use_env)
         apply (rule_tac dist_diff_leq_use_env)
         apply (rule_tac stpx_req_leq_use_env)
         apply (rule_tac dist_comp_leq_use_env)
          apply (rule_tac comp_leq_use_env1)
          apply (rule_tac dist_rem_leq_use_env)
          apply (rule_tac well_typed_perm_leqx)
          apply (auto)
         apply (rule_tac comp_leq_use_env2)
         apply (rule_tac dist_lift_leq_use_env_gen)
         apply (simp)
        apply (rule_tac well_typed_perm_leq)
        apply (auto)
       apply (case_tac "r_s3 (Var x) = NoPerm")
        apply (simp add: end_neg_use_env_def)
        apply (rule_tac self_comp_leq_use_env2)
       apply (rule_tac self_comp_leq_use_env2)
    (* x \<in> fv e2. we start by removing end_neg r_s2 x  *)
      apply (case_tac "\<not> (non_prim_vars env (subst_exp e2 x e') \<inter> own_env_vars (end_neg_use_env r_s2 (Var x) rx2 r) = {})")
       apply (auto)
       apply (rule_tac xa="xa" and env="env" and ?e1.0="e1" and ?e2.0="e2" and e'="e'" in stpxic_valid_diff)
              apply (auto)
      apply (rule_tac t="diff_use_env (comp_use_env (rem_use_env r_s3 (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_s3 (Var x) rx2 r)" and
        s="diff_use_env (diff_use_env (comp_use_env (rem_use_env r_s3 (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_s3 (Var x) rx2 r))
          (end_neg_use_env r_s2 (Var x) rx2 r)" in subst)
       apply (cut_tac r_s="comp_use_env (rem_use_env r_s3 (Var x)) (lift_use_env rx2 r)" and r_x="end_neg_use_env r_s2 (Var x) rx2 r" and
          r_c="end_neg_use_env r_s3 (Var x) rx2 r" in cancel_diff_use_env2)
        apply (rule_tac dist_end_neg_leq_use_env)
        apply (rule_tac well_typed_perm_leq)
        apply (auto)
      apply (rule_tac t="diff_use_env (stpx_req (rem_use_env rx2a (Var x)) (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) (end_neg_use_env r_s3 (Var x) rx2 r)" and
        s="diff_use_env (diff_use_env (stpx_req (rem_use_env rx2a (Var x)) (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) (end_neg_use_env r_s3 (Var x) rx2 r))
          (end_neg_use_env r_s2 (Var x) rx2 r)" in subst)
       apply (cut_tac r_s="stpx_req (rem_use_env rx2a (Var x)) (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))" and r_x="end_neg_use_env r_s2 (Var x) rx2 r" and
        r_c="end_neg_use_env r_s3 (Var x) rx2 r" in cancel_diff_use_env2)
        apply (rule_tac dist_end_neg_leq_use_env)
        apply (rule_tac well_typed_perm_leq)
        apply (auto)
      apply (rule_tac well_typed_diff_perms)
       apply (auto)
    (* - with that, it's safe to activate the coercion lemma *)
      apply (rule_tac env="env" and ?rx1.0="rem_use_env r_s2 (Var x)" and ?e1.0="e2" and x="x" and r="r" in stpxpc_coercex)
              apply (auto)
         apply (rule_tac ?r_s1.0="add_use_env (rem_use_env r_s2 (Var x)) (Var x) (r_s2 (Var x))" in well_typed_incr_start_perm)
          apply (rule_tac t="add_use_env (rem_use_env r_s2 (Var x)) (Var x) (r_s2 (Var x))" and s="r_s2" in subst)
           apply (rule_tac cancel_add_rem_use_env)
           apply (auto)
         apply (rule_tac dist_add_leq_use_env_gen)
          apply (rule_tac id_leq_use_env)
         apply (cut_tac r_x="r_s2" and r_s="add_use_env rx1 (Var x) r" and x="Var x" in spec_leq_perm)
          apply (rule_tac well_typed_perm_leq)
          apply (auto)
         apply (simp add: add_use_env_def)
        apply (simp add: rem_use_env_def)
       apply (rule_tac id_leq_use_env)
      apply (rule_tac r_s="rx1" in disj_leq_use_env1)
       apply (simp)
      apply (rule_tac r="r" in rem_add_leq_use_env)
      apply (rule_tac well_typed_perm_leq)
      apply (auto)
     apply (rule_tac t="lift_use_env (diff_use_env (stpx_req (rem_use_env rx1a (Var x)) (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x))) (end_neg_use_env r_s2 (Var x) rx2 r)) ra"
      and s="diff_use_env (lift_use_env (stpx_req (rem_use_env rx1a (Var x)) (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x))) ra) (end_neg_use_env r_s2 (Var x) rx2 r)" in subst)
      apply (rule_tac lift_diff_use_env)
    (* - the issue here is that if r_s2 \<noteq> None, r_s3 = None, the lhs wont subtract but the rhs will. this only matters if rx1a has a value, in which
        case r_s3 \<noteq> None. *)
     apply (case_tac "rx1a (Var x) \<noteq> NoPerm")
      apply (case_tac "r_s3 (Var x) = NoPerm")
       apply (cut_tac r_x="rx1a" and r_s="r_s3" and x="Var x" in leq_use_none)
         apply (rule_tac r_sb="lift_use_env rx1a ra" in trans_leq_use_env)
          apply (simp)
         apply (rule_tac self_lift_leq_use_env)
        apply (auto)
      apply (case_tac "r_s2 (Var x) = NoPerm")
       apply (cut_tac r_x="r_s3" and r_s="r_s2" and x="Var x" in leq_use_none)
         apply (rule_tac well_typed_perm_leq)
         apply (auto)
      apply (simp add: end_neg_use_env_def)
      apply (rule_tac dist_diff_leq_use_env)
    (* - since rx1a x \<noteq> None, and lift rx1a ra x \<le> r, we have ra \<le> r *)
      apply (rule_tac r_sb="lift_use_env (comp_use_env (rem_use_env rx1a (Var x)) (lift_use_env rx2 (rx1a (Var x)))) ra" in trans_leq_use_env)
       apply (simp add: lift_comp_use_env)
       apply (rule_tac dist_comp_leq_use_env)
        apply (rule_tac comp_leq_use_env1)
        apply (simp add: lift_rem_use_env)
        apply (rule_tac dist_rem_leq_use_env)
        apply (simp)
       apply (rule_tac comp_leq_use_env2)
       apply (rule_tac lhs_lift_leq_use_env_gen)
        apply (rule_tac dist_lift_leq_use_env_gen)
        apply (simp)
       apply (case_tac r)
         apply (auto)
        apply (case_tac "rx1a (Var x)")
          apply (auto)
       apply (case_tac ra)
         apply (auto)
      apply (rule_tac dist_lift_leq_use_env)
      apply (rule_tac stpx_req_leq_use_env)
      apply (rule_tac id_leq_use_env)
    (* otherwise, stpx_req = None, meaning end_neg is disjoint *)
     apply (simp add: stpx_req_def)
     apply (rule_tac disj_diff_leq_use_env)
      apply (rule_tac r_s="lift_use_env rx2 r" in disj_leq_use_env1)
       apply (rule_tac r_s="rx1" in disj_leq_use_env2)
        apply (rule_tac comm_disj_use_env)
        apply (simp)
       apply (rule_tac diff_leq_use_env)
       apply (rule_tac r_sb="rem_use_env r_s3 (Var x)" in trans_leq_use_env)
        apply (rule_tac r="r" in rem_add_leq_use_env)
        apply (simp)
       apply (simp add: lift_rem_use_env)
       apply (rule_tac dist_rem_leq_use_env)
       apply (simp)
      apply (rule_tac end_neg_leq_use_env)
      apply (rule_tac id_leq_use_env)
     apply (rule_tac diff_leq_use_env)
     apply (rule_tac comp_leq_use_env1)
     apply (simp add: lift_rem_use_env)
     apply (rule_tac dist_rem_leq_use_env)
     apply (simp)
    (* similar transformation from before, but we dont need to split over end_neg *)
    apply (rule_tac t="lift_use_env (diff_use_env (stpx_req (rem_use_env rx2a (Var x)) (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) (end_neg_use_env r_s3 (Var x) rx2 r)) ra"
      and s="diff_use_env (lift_use_env (stpx_req (rem_use_env rx2a (Var x)) (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) ra) (end_neg_use_env r_s3 (Var x) rx2 r)" in subst)
     apply (rule_tac lift_diff_use_env)
    apply (rule_tac dist_diff_leq_use_env)
    apply (case_tac "rx2a (Var x) \<noteq> NoPerm")
     apply (rule_tac r_sb="lift_use_env (comp_use_env (rem_use_env rx2a (Var x)) (lift_use_env rx2 (rx2a (Var x)))) ra" in trans_leq_use_env)
      apply (simp add: lift_comp_use_env)
      apply (rule_tac dist_comp_leq_use_env)
       apply (rule_tac comp_leq_use_env1)
       apply (simp add: lift_rem_use_env)
       apply (rule_tac dist_rem_leq_use_env)
       apply (simp)
      apply (rule_tac comp_leq_use_env2)
      apply (rule_tac lhs_lift_leq_use_env_gen)
       apply (rule_tac dist_lift_leq_use_env_gen)
       apply (simp)
      apply (case_tac r)
        apply (auto)
       apply (case_tac "rx2a (Var x)")
         apply (auto)
      apply (case_tac ra)
        apply (auto)
     apply (rule_tac dist_lift_leq_use_env)
     apply (rule_tac stpx_req_leq_use_env)
     apply (rule_tac id_leq_use_env)
    apply (simp add: stpx_req_def)
    apply (rule_tac comp_leq_use_env1)
    apply (simp add: lift_rem_use_env)
    apply (rule_tac dist_rem_leq_use_env)
      apply (simp)
   apply (rule_tac r_s="comp_use_env (lift_use_env (rem_use_env rx1a (Var x)) ra) (lift_use_env (stpx_ex (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x))) ra)" in disj_leq_use_env1)
    apply (rule_tac r_s="comp_use_env (lift_use_env (rem_use_env rx2a (Var x)) ra) (lift_use_env (stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) ra)" in disj_leq_use_env2)
     apply (rule_tac disj_comp_use_env1)
      apply (rule_tac disj_comp_use_env2)
       apply (rule_tac r_s="lift_use_env rx1a ra" in disj_leq_use_env1)
        apply (rule_tac r_s="lift_use_env rx2a ra" in disj_leq_use_env2)
         apply (simp)
        apply (rule_tac dist_lift_leq_use_env)
        apply (rule_tac self_rem_leq_use_env)
       apply (rule_tac dist_lift_leq_use_env)
       apply (rule_tac self_rem_leq_use_env)
      apply (rule_tac rx="r_s3" in stpxpc_disj_use_env1)
             apply (auto)
     apply (rule_tac disj_comp_use_env2)
      apply (rule_tac comm_disj_use_env)
      apply (rule_tac rx="r_s3" in stpxpc_disj_use_env1)
             apply (auto)
      apply (rule_tac comm_disj_use_env)
      apply (simp)
    (* disjointness case analysis *)
     apply (case_tac "is_own ra")
      apply (case_tac "rx1a (Var x) \<noteq> NoPerm")
       apply (case_tac "rx2a (Var x) \<noteq> NoPerm")
        apply (case_tac "\<not> (\<forall>x. lift_use_env rx1a ra (Var x) = OwnPerm \<longrightarrow> lift_use_env rx2a ra (Var x) = NoPerm)")
         apply (simp add: disj_use_env_def)
         apply (simp add: mini_disj_use_env_def)
         apply (auto)
        apply (erule_tac x="x" in allE)
        apply (simp add: is_own_def)
       apply (simp add: stpx_ex_def)
       apply (simp add: lift_empty_use_env)
       apply (simp add: disj_empty_use_env1)
      apply (simp add: stpx_ex_def)
      apply (simp add: lift_empty_use_env)
      apply (simp add: disj_empty_use_env2)
     apply (simp add: is_own_def)
     apply (case_tac ra)
       apply (auto)
    (* - ra = None*)
      apply (rule_tac r_xa="rx1a" and r_xb="rx2a" and x="Var x" in stpx_ex_disj_use_env)
      apply (rule_tac r_s="lift_use_env rx1a ra" in disj_leq_use_env1)
       apply (rule_tac r_s="lift_use_env rx2a ra" in disj_leq_use_env2)
        apply (simp)
       apply (rule_tac self_lift_leq_use_env)
      apply (rule_tac self_lift_leq_use_env)
    (* - ra = Use *)
     apply (rule_tac r_xa="rx1a" and r_xb="rx2a" and x="Var x" in stpx_ex_disj_use_env)
     apply (rule_tac r_s="lift_use_env rx1a ra" in disj_leq_use_env1)
      apply (rule_tac r_s="lift_use_env rx2a ra" in disj_leq_use_env2)
       apply (simp)
      apply (rule_tac self_lift_leq_use_env)
     apply (rule_tac self_lift_leq_use_env)
    (* - ra = Own *)
    apply (rule_tac t="comp_use_env (lift_use_env (rem_use_env rx2a (Var x)) ra) (lift_use_env (stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) ra)"
      and s="lift_use_env (comp_use_env (rem_use_env rx2a (Var x)) (stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x)))) ra" in subst)
     apply (rule_tac lift_comp_use_env)
    apply (rule_tac dist_lift_leq_use_env)
    apply (rule_tac diff_leq_use_env)
    apply (rule_tac stpx_req_leq_use_env3)
    apply (rule_tac id_leq_use_env)
   apply (rule_tac t="comp_use_env (lift_use_env (rem_use_env rx1a (Var x)) ra) (lift_use_env (stpx_ex (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x))) ra)"
      and s="lift_use_env (comp_use_env (rem_use_env rx1a (Var x)) (stpx_ex (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x)))) ra" in subst)
    apply (rule_tac lift_comp_use_env)
   apply (rule_tac dist_lift_leq_use_env)
   apply (rule_tac diff_leq_use_env)
   apply (rule_tac stpx_req_leq_use_env3)
   apply (rule_tac id_leq_use_env)
    (* final existentials *)
  apply (rule_tac x="comp_use_env (rem_use_env r_ex (Var x)) (end_neg_use_env r_se (Var x) rx2 r)" in exI)
  apply (auto)
     apply (rule_tac rhs_unroll_dcl_use_env)
     apply (rule_tac rhs_diff_leq_use_env)
     apply (rule_tac rhs_fold_dcl_use_env)
     apply (rule_tac lhs_dist_dcl_use_env)
     apply (rule_tac rhs_dist_dcl_use_env)
     apply (rule_tac dist_comp_leq_use_env)
      apply (rule_tac diff_leq_use_env)
      apply (rule_tac comp_leq_use_env1)
      apply (rule_tac rhs_flip_use_env)
      apply (rule_tac rhs_unroll_dcl_use_env)
      apply (rule_tac disj_diff_leq_use_env)
       apply (rule_tac comm_disj_use_env)
       apply (rule_tac r_s="rx1" in disj_leq_use_env1)
        apply (rule_tac r_s="lift_use_env rx2 r" in disj_leq_use_env2)
         apply (simp)
        apply (rule_tac end_neg_leq_use_env)
        apply (rule_tac id_leq_use_env)
       apply (rule_tac r="r" in rem_add_leq_use_env)
       apply (rule_tac r_sb="diff_use_env r_s3 r_ex" in trans_leq_use_env)
        apply (rule_tac diff_leq_use_env)
        apply (auto)
      apply (rule_tac t="diff_use_env (rem_use_env r_s3 (Var x)) (rem_use_env r_ex (Var x))" and
        s="rem_use_env (diff_use_env r_s3 r_ex) (Var x)" in subst)
       apply (rule_tac dist_diff_rem_use_env)
      apply (rule_tac dist_rem_leq_use_env)
      apply (simp)
     apply (rule_tac comp_leq_use_env2)
     apply (rule_tac rhs_unroll_dcl_use_env)
     apply (rule_tac disj_diff_leq_use_env)
      apply (rule_tac r_s="rx1" in disj_leq_use_env1)
       apply (rule_tac r_s="lift_use_env rx2 r" in disj_leq_use_env2)
        apply (simp)
       apply (rule_tac self_diff_leq_use_env)
      apply (rule_tac r="r" in rem_add_leq_use_env)
      apply (simp)
     apply (rule_tac dist_diff_leq_use_env_gen)
      apply (rule_tac id_leq_use_env)
     apply (rule_tac dist_end_neg_leq_use_env)
     apply (rule_tac r_sb="diff_use_env r_s3 r_ex" in trans_leq_use_env)
      apply (rule_tac self_diff_leq_use_env)
     apply (simp)
    apply (rule_tac dist_diff_leq_use_env)
    apply (rule_tac stpx_req_leq_use_env)
    apply (rule_tac dist_comp_leq_use_env)
     apply (rule_tac comp_leq_use_env1)
     apply (rule_tac dist_rem_leq_use_env)
     apply (simp)
    apply (rule_tac comp_leq_use_env2)
    apply (rule_tac dist_lift_leq_use_env_gen)
    apply (cut_tac r_x="r_xe" and r_s="add_use_env rx1 (Var x) r" and x="Var x" in spec_leq_perm)
     apply (rule_tac r_sb="diff_use_env r_s3 r_ex" in trans_leq_use_env)
      apply (rule_tac diff_leq_use_env)
      apply (simp)
     apply (rule_tac r_sb="r_se" in trans_leq_use_env)
      apply (auto)
    apply (simp add: add_use_env_def)
   apply (rule_tac r_sb="comp_use_env rx1 (lift_use_env rx2 r)" in trans_leq_use_env)
    apply (simp)
   apply (rule_tac dist_comp_leq_use_env)
    apply (rule_tac comp_leq_use_env1)
    apply (rule_tac r="r" in rem_add_leq_use_env)
    apply (simp)
   apply (rule_tac end_neg_leq_use_env)
   apply (rule_tac self_comp_leq_use_env2)
    (* - requirements bound haaa *)
  apply (case_tac "req_type (PairTy t1 t2 ra) = Prim")
   apply (simp add: pair_req_def)
   apply (rule_tac leq_empty_use_env)
  apply (simp add: pair_req_def)
  apply (rule_tac r_sb="diff_use_env (comp_use_env (rem_use_env r_xe (Var x)) (stpx_ex (lift_use_env rx2 (r_xe (Var x))) (r_xe (Var x)))) (end_neg_use_env r_se (Var x) rx2 r)" in trans_leq_use_env)
   apply (rule_tac dist_diff_leq_use_env)
   apply (rule_tac stpx_req_leq_use_env4)
   apply (rule_tac id_leq_use_env)
  apply (rule_tac r_sb="diff_use_env
           (comp_use_env (lift_use_env (diff_use_env (comp_use_env (rem_use_env rx1a (Var x)) (stpx_ex (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x)))) (end_neg_use_env r_s2 (Var x) rx2 r)) ra)
             (lift_use_env (diff_use_env (comp_use_env (rem_use_env rx2a (Var x)) (stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x)))) (end_neg_use_env r_s3 (Var x) rx2 r)) ra))
           (comp_use_env (rem_use_env r_ex (Var x)) (end_neg_use_env r_se (Var x) rx2 r))" in trans_leq_use_env)
   apply (rule_tac lhs_dist_dcl_use_env)
   apply (rule_tac dist_comp_leq_use_env)
    apply (rule_tac t="lift_use_env (diff_use_env (comp_use_env (rem_use_env rx1a (Var x)) (stpx_ex (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x)))) (end_neg_use_env r_s2 (Var x) rx2 r)) ra"
      and s="diff_use_env (lift_use_env (comp_use_env (rem_use_env rx1a (Var x)) (stpx_ex (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x)))) ra) (end_neg_use_env r_s2 (Var x) rx2 r)" in subst)
     apply (cut_tac r_s="comp_use_env (rem_use_env rx1a (Var x)) (stpx_ex (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x)))" and r="ra"
      and r_x="(end_neg_use_env r_s2 (Var x) rx2 r)" in lift_diff_use_env)
     apply (auto)
    apply (simp add: lift_comp_use_env)
    apply (rule_tac lhs_fold_dcl_use_env)
    apply (rule_tac lhs_dist_dcl_use_env)
    apply (rule_tac dist_comp_leq_use_env)
     apply (rule_tac lhs_unroll_dcl_use_env)
     apply (rule_tac lhs_unroll_dcl_use_env)
     apply (rule_tac dist_diff_leq_use_env)
     apply (rule_tac comp_leq_use_env1)
     apply (rule_tac r_sb="rem_use_env (diff_use_env (comp_use_env (lift_use_env rx1a ra) (lift_use_env rx2a ra)) r_ex) (Var x)" in trans_leq_use_env)
      apply (rule_tac dist_rem_leq_use_env)
      apply (simp)
     apply (simp add: dist_diff_rem_use_env)
     apply (rule_tac dist_diff_leq_use_env)
     apply (simp add: dist_rem_comp_use_env)
     apply (rule_tac comp_leq_use_env1)
     apply (simp add: lift_rem_use_env)
     apply (rule_tac self_diff_leq_use_env)
    apply (rule_tac rhs_dist_dcl_use_env)
    apply (rule_tac comp_leq_use_env2)
    apply (rule_tac r_sb="diff_use_env (lift_use_env (stpx_ex (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x))) ra) (end_neg_use_env r_se (Var x) rx2 r)" in trans_leq_use_env)
    (* - rx1a x \<noteq> None *)
     apply (case_tac "rx1a (Var x) = NoPerm")
      apply (rule_tac diff_leq_use_env)
      apply (simp add: stpx_ex_def)
      apply (simp add: lift_empty_use_env)
      apply (simp add: leq_empty_use_env)
    (* - if r_ex = Own, r = Own and r_se x = None *)
     apply (case_tac "r_ex (Var x) = OwnPerm")
      apply (case_tac "\<not> is_own r")
       apply (cut_tac r_x="r_ex" and r_s="add_use_env rx1 (Var x) r" and x="Var x" in leq_use_own)
         apply (simp_all)
       apply (simp add: add_use_env_def)
       apply (simp add: is_own_def)
      apply (cut_tac r_x="r_se" and r_s="diff_use_env r_s3 r_ex" and x="Var x" in leq_use_none)
        apply (simp)
       apply (rule_tac diff_use_none_ex)
       apply (auto)
    (* this proves that the lhs cancels itself *)
      apply (rule_tac r_sb="diff_use_env (lift_use_env rx2 r) (lift_use_env rx2 r)" in trans_leq_use_env)
       apply (rule_tac cancel_lift_leq_use_env)
       apply (simp)
      apply (simp add: end_neg_use_env_def)
      apply (rule_tac dist_diff_leq_use_env)
      apply (rule_tac lhs_lift_leq_use_env_gen)
       apply (rule_tac stpx_ex_leq_use_env)
       apply (rule_tac dist_lift_leq_use_env_gen)
       apply (simp add: is_own_def)
      apply (simp add: is_own_def)
    (* - if r_xe x = Own, trivial *)
     apply (case_tac "is_own (r_xe (Var x))")
      apply (case_tac "stpx_ex (lift_use_env rx2 (r_xe (Var x))) (r_xe (Var x)) \<noteq> lift_use_env rx2 (r_xe (Var x))")
       apply (simp add: is_own_def)
       apply (simp add: stpx_ex_def)
      apply (auto)
      apply (rule_tac dist_diff_leq_use_env)
      apply (rule_tac lhs_lift_leq_use_env_gen)
       apply (rule_tac stpx_ex_leq_use_env)
       apply (rule_tac dist_lift_leq_use_env_gen)
       apply (simp add: is_own_def)
      apply (simp add: is_own_def)
    (* - if ra = Own, then r_ex = Own, since (lift rx1a ra) - r_ex \<le> r_xe *)
     apply (case_tac "is_own ra")
      apply (cut_tac r_x="diff_use_env (lift_use_env rx1a ra) r_ex" and r_s="r_xe" and x="Var x" in leq_use_own)
        apply (cut_tac r_x="lift_use_env rx1a ra" and r_s="r_xe" and r_ex="r_ex" and x="Var x" in diff_use_leq)
          apply (simp)
         apply (rule_tac r_sb="diff_use_env (comp_use_env (lift_use_env rx1a ra) (lift_use_env rx2a ra)) r_ex" in trans_leq_use_env)
          apply (simp)
         apply (rule_tac dist_diff_leq_use_env)
         apply (rule_tac self_comp_leq_use_env1)
        apply (simp add: is_own_def)
        apply (case_tac "r_xe (Var x)")
          apply (auto)
       apply (rule_tac r_sb="diff_use_env (comp_use_env (lift_use_env rx1a ra) (lift_use_env rx2a ra)) r_ex" in trans_leq_use_env)
        apply (simp)
       apply (rule_tac dist_diff_leq_use_env)
       apply (rule_tac self_comp_leq_use_env1)
      apply (simp add: is_own_def)
    (* if ra \<noteq> Own, we can ignore it. now we should have rx1a \<le> r_xe *)
     apply (case_tac "ra \<noteq> UsePerm")
      apply (simp add: is_own_def)
      apply (case_tac ra)
        apply (auto)
     apply (cut_tac r_x="rx1a" and r_s="r_xe" and r_ex="r_ex" and x="Var x" in diff_use_leq)
       apply (auto)
      apply (rule_tac r_sb="diff_use_env (comp_use_env rx1a rx2a) r_ex" in trans_leq_use_env)
       apply (simp)
      apply (rule_tac dist_diff_leq_use_env)
      apply (rule_tac self_comp_leq_use_env1)
     apply (rule_tac dist_diff_leq_use_env)
     apply (rule_tac dist_stpx_ex_leq_use_env)
     apply (simp)
    (* back to the normal cases *)
    apply (rule_tac lhs_unroll_dcl_use_env)
    apply (rule_tac lhs_unroll_dcl_use_env)
    apply (rule_tac dist_diff_leq_use_env)
    apply (rule_tac diff_leq_use_env)
    apply (rule_tac self_diff_leq_use_env)
    (* we have to do essentially the same manipulations a second time *)
   apply (rule_tac t="lift_use_env (diff_use_env (comp_use_env (rem_use_env rx2a (Var x)) (stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x)))) (end_neg_use_env r_s3 (Var x) rx2 r)) ra"
      and s="diff_use_env (lift_use_env (comp_use_env (rem_use_env rx2a (Var x)) (stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x)))) ra) (end_neg_use_env r_s3 (Var x) rx2 r)" in subst)
    apply (cut_tac r_s="comp_use_env (rem_use_env rx2a (Var x)) (stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x)))" and r="ra"
      and r_x="(end_neg_use_env r_s3 (Var x) rx2 r)" in lift_diff_use_env)
    apply (auto)
   apply (simp add: lift_comp_use_env)
   apply (rule_tac lhs_fold_dcl_use_env)
   apply (rule_tac lhs_dist_dcl_use_env)
   apply (rule_tac dist_comp_leq_use_env)
    apply (rule_tac lhs_unroll_dcl_use_env)
    apply (rule_tac lhs_unroll_dcl_use_env)
    apply (rule_tac dist_diff_leq_use_env)
    apply (rule_tac comp_leq_use_env1)
    apply (rule_tac r_sb="rem_use_env (diff_use_env (comp_use_env (lift_use_env rx1a ra) (lift_use_env rx2a ra)) r_ex) (Var x)" in trans_leq_use_env)
     apply (rule_tac dist_rem_leq_use_env)
     apply (simp)
    apply (simp add: dist_diff_rem_use_env)
    apply (rule_tac dist_diff_leq_use_env)
    apply (simp add: dist_rem_comp_use_env)
    apply (rule_tac comp_leq_use_env2)
    apply (simp add: lift_rem_use_env)
    apply (rule_tac self_diff_leq_use_env)
   apply (rule_tac rhs_dist_dcl_use_env)
   apply (rule_tac comp_leq_use_env2)
   apply (rule_tac r_sb="diff_use_env (lift_use_env (stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) ra) (end_neg_use_env r_se (Var x) rx2 r)" in trans_leq_use_env)
    (* - rx2a x \<noteq> None *)
    apply (case_tac "rx2a (Var x) = NoPerm")
     apply (rule_tac diff_leq_use_env)
     apply (simp add: stpx_ex_def)
     apply (simp add: lift_empty_use_env)
     apply (simp add: leq_empty_use_env)
    (* - if r_ex = Own, r = Own and r_se x = None *)
    apply (case_tac "r_ex (Var x) = OwnPerm")
     apply (case_tac "\<not> is_own r")
      apply (cut_tac r_x="r_ex" and r_s="add_use_env rx1 (Var x) r" and x="Var x" in leq_use_own)
        apply (simp_all)
      apply (simp add: add_use_env_def)
      apply (simp add: is_own_def)
     apply (cut_tac r_x="r_se" and r_s="diff_use_env r_s3 r_ex" and x="Var x" in leq_use_none)
       apply (simp)
      apply (rule_tac diff_use_none_ex)
      apply (auto)
    (* this proves that the lhs cancels itself *)
     apply (rule_tac r_sb="diff_use_env (lift_use_env rx2 r) (lift_use_env rx2 r)" in trans_leq_use_env)
      apply (rule_tac cancel_lift_leq_use_env)
      apply (simp)
     apply (simp add: end_neg_use_env_def)
     apply (rule_tac dist_diff_leq_use_env)
     apply (rule_tac lhs_lift_leq_use_env_gen)
      apply (rule_tac stpx_ex_leq_use_env)
      apply (rule_tac dist_lift_leq_use_env_gen)
      apply (simp add: is_own_def)
     apply (simp add: is_own_def)
    (* - if r_xe x = Own, trivial *)
    apply (case_tac "is_own (r_xe (Var x))")
     apply (case_tac "stpx_ex (lift_use_env rx2 (r_xe (Var x))) (r_xe (Var x)) \<noteq> lift_use_env rx2 (r_xe (Var x))")
      apply (simp add: is_own_def)
      apply (simp add: stpx_ex_def)
     apply (auto)
     apply (rule_tac dist_diff_leq_use_env)
     apply (rule_tac lhs_lift_leq_use_env_gen)
      apply (rule_tac stpx_ex_leq_use_env)
      apply (rule_tac dist_lift_leq_use_env_gen)
      apply (simp add: is_own_def)
     apply (simp add: is_own_def)
    (* - if ra = Own, then r_ex = Own, since (lift rx2a ra) - r_ex \<le> r_xe *)
    apply (case_tac "is_own ra")
     apply (cut_tac r_x="diff_use_env (lift_use_env rx2a ra) r_ex" and r_s="r_xe" and x="Var x" in leq_use_own)
       apply (cut_tac r_x="lift_use_env rx2a ra" and r_s="r_xe" and r_ex="r_ex" and x="Var x" in diff_use_leq)
         apply (simp)
        apply (rule_tac r_sb="diff_use_env (comp_use_env (lift_use_env rx1a ra) (lift_use_env rx2a ra)) r_ex" in trans_leq_use_env)
         apply (simp)
        apply (rule_tac dist_diff_leq_use_env)
        apply (rule_tac self_comp_leq_use_env2)
       apply (simp add: is_own_def)
       apply (case_tac "r_xe (Var x)")
         apply (auto)
      apply (rule_tac r_sb="diff_use_env (comp_use_env (lift_use_env rx1a ra) (lift_use_env rx2a ra)) r_ex" in trans_leq_use_env)
       apply (simp)
      apply (rule_tac dist_diff_leq_use_env)
      apply (rule_tac self_comp_leq_use_env2)
     apply (simp add: is_own_def)
    (* if ra \<noteq> Own, we can ignore it. now we should have rx2a \<le> r_xe *)
    apply (case_tac "ra \<noteq> UsePerm")
     apply (simp add: is_own_def)
     apply (case_tac ra)
       apply (auto)
    apply (cut_tac r_x="rx2a" and r_s="r_xe" and r_ex="r_ex" and x="Var x" in diff_use_leq)
      apply (auto)
     apply (rule_tac r_sb="diff_use_env (comp_use_env rx1a rx2a) r_ex" in trans_leq_use_env)
      apply (simp)
     apply (rule_tac dist_diff_leq_use_env)
     apply (rule_tac self_comp_leq_use_env2)
    apply (rule_tac dist_diff_leq_use_env)
    apply (rule_tac dist_stpx_ex_leq_use_env)
    apply (simp)
    (* resolve the initial changes *)
   apply (rule_tac lhs_unroll_dcl_use_env)
   apply (rule_tac lhs_unroll_dcl_use_env)
   apply (rule_tac dist_diff_leq_use_env)
   apply (rule_tac diff_leq_use_env)
   apply (rule_tac self_diff_leq_use_env)
  apply (rule_tac dist_diff_leq_use_env)
  apply (rule_tac dist_comp_leq_use_env)
   apply (rule_tac comp_leq_use_env1)
   apply (rule_tac dist_lift_leq_use_env)
   apply (rule_tac dist_diff_leq_use_env)
   apply (rule_tac stpx_req_leq_use_env3)
   apply (rule_tac id_leq_use_env)
  apply (rule_tac comp_leq_use_env2)
  apply (rule_tac dist_lift_leq_use_env)
  apply (rule_tac dist_diff_leq_use_env)
  apply (rule_tac stpx_req_leq_use_env3)
  apply (rule_tac id_leq_use_env)
  done

    (*
      ####################################
        P3. if case
      ####################################
    *)

lemma stpxic_finish: "\<lbrakk> rx1a x \<noteq> NoPerm; rx2a x \<noteq> NoPerm \<rbrakk> \<Longrightarrow>
  stpx_ex (comp_use_env (lift_use_env rx2 (rx1a x)) (lift_use_env rx2 (rx2a x))) (comp_use_env rx1a rx2a x) =
  comp_use_env (stpx_ex (lift_use_env rx2 (rx1a x)) (rx1a x)) (stpx_ex (lift_use_env rx2 (rx2a x)) (rx2a x))"
    (* we take care of the combined use case first *)
  apply (case_tac "comp_use_env rx1a rx2a x = UsePerm")
   apply (case_tac "\<not> rx1a x = UsePerm")
    apply (simp add: comp_use_env_def)
    apply (case_tac "rx1a x")
      apply (auto)
   apply (case_tac "\<not> rx2a x = UsePerm")
    apply (simp add: comp_use_env_def)
    apply (case_tac "rx2a x")
      apply (auto)
   apply (simp add: stpx_ex_def)
   apply (rule_tac dist_drop_comp_use_env)
    (* otherwise, we demonstrate comp_use_env rx1a rx2a x = Own *)
  apply (case_tac "comp_use_env rx1a rx2a x \<noteq> OwnPerm")
   apply (simp add: comp_use_env_def)
   apply (case_tac "rx1a x")
     apply (auto)
   apply (case_tac "rx2a x")
     apply (auto)
    (* with that, we do the final case analysis *)
  apply (simp add: stpx_ex_def)
  apply (auto)
    apply (simp add: comp_use_env_def)
    apply (case_tac "rx1a x")
      apply (auto)
    apply (case_tac "rx2a x")
      apply (auto)
   apply (cut_tac r_s="lift_use_env rx2 (rx1a x)" and r="rx2a x" in dom_lift_comp_use_env)
    apply (auto)
   apply (case_tac "rx1a x")
     apply (auto)
  apply (simp add: comm_comp_use_env)
  apply (cut_tac r_s="lift_use_env rx2 (rx2a x)" and r="rx1a x" in dom_lift_comp_use_env)
   apply (auto)
  done

lemma stpx_if_no_fv: "\<lbrakk>
     leq_use_env (rem_use_env r_s1 (Var x)) rx1; disj_use_env rx1 (lift_use_env rx2 r);
     well_typed (add_env env (Var x) t) r_s1 e tau r_s2 rx'; leq_perm (rx' (Var x)) r; x \<notin> free_vars e \<rbrakk>
    \<Longrightarrow> well_typed env (diff_use_env (comp_use_env (rem_use_env r_s1 (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_s2 (Var x) rx2 r)) (subst_exp e x e') tau
         (diff_use_env (comp_use_env (rem_use_env r_s2 (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_s2 (Var x) rx2 r))
         (diff_use_env (stpx_req (rem_use_env rx' (Var x)) (lift_use_env rx2 (rx' (Var x))) (rx' (Var x))) (end_neg_use_env r_s2 (Var x) rx2 r))"
    (* no fv case *)
  apply (rule_tac subst_type_preserve_no_fv)
   apply (rule_tac well_typed_diff_perms)
    apply (rule_tac well_typed_stpx_req)
     apply (rule_tac well_typed_comp_perms)
      apply (rule_tac well_typed_rem_perms)
       apply (rule_tac x="x" and t="t" in well_typed_add_vars_rev)
        apply (simp_all)
     apply (simp add: non_prim_vars_def)
     apply (auto)
     apply (cut_tac x="x" and e="e" in free_res_vars)
      apply (auto)
    apply (rule_tac r_s="rx1" in disj_leq_use_env1)
     apply (simp_all)
   apply (rule_tac dist_lift_leq_use_env_gen)
   apply (simp)
    (* prove rx2 is disjoint from free vars in e *)
  apply (simp add: own_env_vars_def)
  apply (simp add: end_neg_use_env_def)
  apply (case_tac "r_s2 (Var x) \<noteq> NoPerm")
   apply (auto)
   apply (simp add: empty_use_env_def)
    (* - say that x = xa. this is impossible, since x \<notin> free vars e *)
  apply (case_tac "Var x = xa")
   apply (simp add: non_prim_vars_def)
   apply (cut_tac x="x" and e="e" in free_res_vars)
    apply (auto)
    (* - say that (r_s1 - x) xa = None. then r_s1 xa = None, which is impossible since xa is in e  *)
  apply (case_tac "(rem_use_env r_s1 (Var x)) xa = NoPerm")
   apply (cut_tac env="add_env env (Var x) t" and ?r_s1.0="r_s1" and e="e" and x="xa" in well_typed_no_npv_use)
     apply (auto)
    apply (simp add: rem_use_env_def)
   apply (simp add: non_prim_vars_def)
   apply (simp add: non_prim_entry_def)
   apply (simp add: add_env_def)
   apply (auto)
    (* - this means xa is in rx1 *)
  apply (case_tac "rx1 xa = NoPerm")
   apply (cut_tac r_x="rem_use_env r_s1 (Var x)" and r_s="rx1" and x="xa" in leq_use_none)
     apply (auto)
    (* - this means xa is present in rx1 + rx2, a contradiction *)
  apply (simp add: disj_use_env_def)
  apply (simp add: mini_disj_use_env_def)
  done

lemma stpx_if_case: "\<lbrakk>\<And>env x tau t rx1 r_se r_xe r_s1 rx2 r.
           \<lbrakk>well_typed (add_env env (Var x) t) (add_use_env rx1 (Var x) r) e1 tau r_se r_xe; well_typed env rx2 e' t rx2 rx2; rx1 (Var x) = NoPerm;
            x \<in> free_vars e1; lam_vars e1 \<inter> free_vars e' = {}; leq_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_s1; disj_use_env rx1 (lift_use_env rx2 r)\<rbrakk>
           \<Longrightarrow> well_typed env r_s1 (subst_exp e1 x e') tau
                (diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r))
                (diff_use_env (stpx_req (rem_use_env r_xe (Var x)) (lift_use_env rx2 (r_xe (Var x))) (r_xe (Var x))) (end_neg_use_env r_se (Var x) rx2 r));
        \<And>env x tau t rx1 r_se r_xe r_s1 rx2 r.
           \<lbrakk>well_typed (add_env env (Var x) t) (add_use_env rx1 (Var x) r) e2 tau r_se r_xe; well_typed env rx2 e' t rx2 rx2; rx1 (Var x) = NoPerm;
            x \<in> free_vars e2; lam_vars e2 \<inter> free_vars e' = {}; leq_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_s1; disj_use_env rx1 (lift_use_env rx2 r)\<rbrakk>
           \<Longrightarrow> well_typed env r_s1 (subst_exp e2 x e') tau
                (diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r))
                (diff_use_env (stpx_req (rem_use_env r_xe (Var x)) (lift_use_env rx2 (r_xe (Var x))) (r_xe (Var x))) (end_neg_use_env r_se (Var x) rx2 r));
        \<And>env x tau t rx1 r_se r_xe r_s1 rx2 r.
           \<lbrakk>well_typed (add_env env (Var x) t) (add_use_env rx1 (Var x) r) e3 tau r_se r_xe; well_typed env rx2 e' t rx2 rx2; rx1 (Var x) = NoPerm;
            x \<in> free_vars e3; lam_vars e3 \<inter> free_vars e' = {}; leq_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_s1; disj_use_env rx1 (lift_use_env rx2 r)\<rbrakk>
           \<Longrightarrow> well_typed env r_s1 (subst_exp e3 x e') tau
                (diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r))
                (diff_use_env (stpx_req (rem_use_env r_xe (Var x)) (lift_use_env rx2 (r_xe (Var x))) (r_xe (Var x))) (end_neg_use_env r_se (Var x) rx2 r));
        well_typed env rx2 e' t rx2 rx2; rx1 (Var x) = NoPerm; is_sexp e'; (lam_vars e1 \<union> lam_vars e2 \<union> lam_vars e3) \<inter> free_vars e' = {};
        leq_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_s1; disj_use_env rx1 (lift_use_env rx2 r);
        well_typed (add_env env (Var x) t) (add_use_env rx1 (Var x) r) e1 BoolTy r_s2 rx'; well_typed (add_env env (Var x) t) r_s2 e2 tau r_se rx1a;
        well_typed (add_env env (Var x) t) r_s2 e3 tau r_se rx2a\<rbrakk>
       \<Longrightarrow> \<exists>rx' r_s2. well_typed env r_s1 (subst_exp e1 x e') BoolTy r_s2 rx' \<and>
                      (\<exists>rx1. well_typed env r_s2 (subst_exp e2 x e') tau
                              (diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r)) rx1 \<and>
                             (\<exists>rx2b. well_typed env r_s2 (subst_exp e3 x e') tau
                                      (diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r)) rx2b \<and>
                                     diff_use_env
                                      (stpx_req (rem_use_env (comp_use_env rx1a rx2a) (Var x)) (lift_use_env rx2 (comp_use_env rx1a rx2a (Var x)))
                                        (comp_use_env rx1a rx2a (Var x)))
                                      (end_neg_use_env r_se (Var x) rx2 r) =
                                     comp_use_env rx1 rx2b))"
    (* - prelim: rx' x \<le> r *)
  apply (case_tac "\<not> leq_perm (rx' (Var x)) r")
   apply (cut_tac r_x="rx'" and r_s="add_use_env rx1 (Var x) r" and x="Var x" in spec_leq_perm)
    apply (rule_tac r_sb="r_s2" in trans_leq_use_env)
     apply (rule_tac well_typed_perm_leq)
      apply (auto)
    apply (rule_tac well_typed_perm_leqx)
    apply (auto)
   apply (simp add: add_use_env_def)
    (* - prelim: rx1a x, rx2a x \<le> r *)
  apply (cut_tac r_sc="r_se" and r_sb="r_s2" and r_sa="add_use_env rx1 (Var x) r" in trans_leq_use_env)
    apply (rule_tac well_typed_perm_leq)
    apply (auto)
   apply (rule_tac well_typed_perm_leq)
   apply (auto)
  apply (case_tac "\<not> leq_perm (rx1a (Var x)) r")
   apply (cut_tac r_x="rx1a" and r_s="add_use_env rx1 (Var x) r" and x="Var x" in spec_leq_perm)
    apply (rule_tac r_sb="r_se" in trans_leq_use_env)
     apply (simp)
    apply (rule_tac well_typed_perm_leqx)
    apply (auto)
   apply (simp add: add_use_env_def)
  apply (case_tac "\<not> leq_perm (rx2a (Var x)) r")
   apply (cut_tac r_x="rx2a" and r_s="add_use_env rx1 (Var x) r" and x="Var x" in spec_leq_perm)
    apply (rule_tac r_sb="r_se" in trans_leq_use_env)
     apply (simp)
    apply (rule_tac well_typed_perm_leqx)
    apply (auto)
   apply (simp add: add_use_env_def)
    (* x \<notin> fv e1 *)
  apply (rule_tac x="diff_use_env (stpx_req (rem_use_env rx' (Var x)) (lift_use_env rx2 (rx' (Var x))) (rx' (Var x))) (end_neg_use_env r_s2 (Var x) rx2 r)" in exI)
  apply (rule_tac x="diff_use_env (comp_use_env (rem_use_env r_s2 (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_s2 (Var x) rx2 r)" in exI)
  apply (auto)
   apply (case_tac "x \<notin> free_vars e1")
    apply (rule_tac ?r_s1.0="diff_use_env (comp_use_env (rem_use_env rx1 (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_s2 (Var x) rx2 r)" in well_typed_incr_start_perm)
     apply (cut_tac r_s="rx1" and x="Var x" in self_rem_leq_use_env)
     apply (cut_tac r_s="rx1" and x="Var x" and r="r" in partial_rem_add_use_env)
     apply (simp)
     apply (rule_tac t="t" in stpx_if_no_fv)
           apply (auto)
    apply (rule_tac diff_leq_use_env)
    apply (rule_tac r_sb="comp_use_env rx1 (lift_use_env rx2 r)" in trans_leq_use_env)
     apply (simp)
    apply (rule_tac dist_comp_leq_use_env)
     apply (rule_tac comp_leq_use_env1)
     apply (rule_tac self_rem_leq_use_env)
    apply (rule_tac self_comp_leq_use_env2)
    (* x \<in> fv e1, induct *)
   apply (case_tac "\<not> lam_vars e1 \<inter> free_vars e' = {}")
    apply (auto)
    (* minor lemma *)
  apply (case_tac "\<not> leq_use_env (end_neg_use_env r_s2 (Var x) rx2 r) (end_neg_use_env r_se (Var x) rx2 r)")
   apply (simp add: end_neg_use_env_def)
   apply (auto)
      apply (cut_tac r="lift_use_env rx2 r" in id_leq_use_env)
      apply (simp)
     apply (cut_tac r_x="r_se" and r_s="r_s2" and x="Var x" in leq_use_none)
       apply (rule_tac well_typed_perm_leq)
       apply (auto)
    apply (cut_tac r="lift_use_env rx2 r" in leq_empty_use_env)
    apply (simp)
   apply (cut_tac r="empty_use_env" in id_leq_use_env)
   apply (auto)
    (* e2 case, x \<notin> fv e2  *)
  apply (rule_tac x="diff_use_env (stpx_req (rem_use_env rx1a (Var x)) (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x))) (end_neg_use_env r_se (Var x) rx2 r)" in exI)
  apply (auto)
   apply (case_tac "x \<notin> free_vars e2")
    apply (rule_tac ?r_s1.0="diff_use_env (comp_use_env (rem_use_env r_s2 (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r)" in well_typed_incr_start_perm)
     apply (rule_tac stpx_if_no_fv)
          apply (auto)
     apply (rule_tac r="r" in rem_add_leq_use_env)
     apply (rule_tac well_typed_perm_leq)
     apply (simp)
    apply (rule_tac dist_diff_leq_use_env_gen)
     apply (rule_tac id_leq_use_env)
    apply (simp)
    (* x \<in> fv e2, well-typedness manipulation *)
   apply (case_tac "\<not> well_typed (add_env env (Var x) t) (add_use_env (rem_use_env r_s2 (Var x)) (Var x) r) e2 tau r_se rx1a")
    apply (cut_tac env="add_env env (Var x) t" and ?r_s1.0="r_s2" and r_c="add_use_env (rem_use_env r_s2 (Var x)) (Var x) r" and e="e2" and
      tau="tau" and ?r_s2.0="r_se" and rx="rx1a" in well_typed_incr_start_perm)
      apply (simp)
     apply (rule_tac r_sb="add_use_env (rem_use_env r_s2 (Var x)) (Var x) (r_s2 (Var x))" in trans_leq_use_env)
      apply (rule_tac dist_add_leq_use_env_gen)
       apply (rule_tac id_leq_use_env)
      apply (cut_tac env="add_env env (Var x) t" and ?r_s1.0="add_use_env rx1 (Var x) r" and ?r_s2.0="r_s2" and x="Var x" in well_typed_spec_perm_leq)
       apply (auto)
     apply (simp add: add_use_env_def)
    apply (cut_tac r_s="r_s2" and x="Var x" and r="r_s2 (Var x)" in cancel_add_rem_use_env)
     apply (auto)
    apply (rule_tac id_leq_use_env)
    (* we have to remove the rx2 subtraction from the start perms *)
   apply (rule_tac t="diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r)" and
      s="diff_use_env (diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r))
      (end_neg_use_env r_s2 (Var x) rx2 r)" in subst)
    apply (cut_tac r_s="comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)" and r_c="end_neg_use_env r_se (Var x) rx2 r" and
      r_x="end_neg_use_env r_s2 (Var x) rx2 r" in cancel_diff_use_env2)
     apply (auto)
   apply (rule_tac t="diff_use_env (stpx_req (rem_use_env rx1a (Var x)) (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x))) (end_neg_use_env r_se (Var x) rx2 r)" and
      s="diff_use_env (diff_use_env (stpx_req (rem_use_env rx1a (Var x)) (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x))) (end_neg_use_env r_se (Var x) rx2 r))
      (end_neg_use_env r_s2 (Var x) rx2 r)" in subst)
    apply (cut_tac r_s="stpx_req (rem_use_env rx1a (Var x)) (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x))" and r_c="end_neg_use_env r_se (Var x) rx2 r" and
      r_x="end_neg_use_env r_s2 (Var x) rx2 r" in cancel_diff_use_env2)
     apply (auto)
   apply (rule_tac well_typed_diff_perms)
    (* induction requirements *)
    apply (case_tac "\<not> rem_use_env r_s2 (Var x) (Var x) = NoPerm")
     apply (simp add: rem_use_env_def)
    apply (cut_tac r="comp_use_env (rem_use_env r_s2 (Var x)) (lift_use_env rx2 r)" in id_leq_use_env)
    apply (case_tac "lam_vars e2 \<inter> free_vars e' = {}")
     apply (auto)
    apply (cut_tac r_x="rem_use_env r_s2 (Var x)" and r_s="rx1" and r_ex="lift_use_env rx2 r" in disj_leq_use_env1)
      apply (simp)
     apply (rule_tac r="r" in rem_add_leq_use_env)
     apply (rule_tac well_typed_perm_leq)
     apply (auto)
    (* proving the subtraction was valid. *)
   apply (rule_tac xa="xa" and ?e1.0="e1" and ?e2.0="e2" and env="env" in stpxic_valid_diff)
          apply (auto)
    (* e3 case, x \<notin> fv e3  *)
  apply (rule_tac x="diff_use_env (stpx_req (rem_use_env rx2a (Var x)) (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) (end_neg_use_env r_se (Var x) rx2 r)" in exI)
  apply (auto)
   apply (case_tac "x \<notin> free_vars e3")
    apply (rule_tac ?r_s1.0="diff_use_env (comp_use_env (rem_use_env r_s2 (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r)" in well_typed_incr_start_perm)
     apply (rule_tac stpx_if_no_fv)
          apply (auto)
     apply (rule_tac r="r" in rem_add_leq_use_env)
     apply (rule_tac well_typed_perm_leq)
     apply (simp)
    apply (rule_tac dist_diff_leq_use_env_gen)
     apply (rule_tac id_leq_use_env)
    apply (simp)
    (* x \<in> fv e3, well-typedness manipulation *)
   apply (case_tac "\<not> well_typed (add_env env (Var x) t) (add_use_env (rem_use_env r_s2 (Var x)) (Var x) r) e3 tau r_se rx2a")
    apply (cut_tac env="add_env env (Var x) t" and ?r_s1.0="r_s2" and r_c="add_use_env (rem_use_env r_s2 (Var x)) (Var x) r" and e="e3" and
      tau="tau" and ?r_s2.0="r_se" and rx="rx2a" in well_typed_incr_start_perm)
      apply (simp)
     apply (rule_tac r_sb="add_use_env (rem_use_env r_s2 (Var x)) (Var x) (r_s2 (Var x))" in trans_leq_use_env)
      apply (rule_tac dist_add_leq_use_env_gen)
       apply (rule_tac id_leq_use_env)
      apply (cut_tac env="add_env env (Var x) t" and ?r_s1.0="add_use_env rx1 (Var x) r" and ?r_s2.0="r_s2" and x="Var x" in well_typed_spec_perm_leq)
       apply (auto)
     apply (simp add: add_use_env_def)
    apply (cut_tac r_s="r_s2" and x="Var x" and r="r_s2 (Var x)" in cancel_add_rem_use_env)
     apply (auto)
    apply (rule_tac id_leq_use_env)
    (* we have to remove the rx2 subtraction from the start perms *)
   apply (rule_tac t="diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r)" and
      s="diff_use_env (diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r))
      (end_neg_use_env r_s2 (Var x) rx2 r)" in subst)
    apply (cut_tac r_s="comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)" and r_c="end_neg_use_env r_se (Var x) rx2 r" and
      r_x="end_neg_use_env r_s2 (Var x) rx2 r" in cancel_diff_use_env2)
     apply (auto)
   apply (rule_tac t="diff_use_env (stpx_req (rem_use_env rx2a (Var x)) (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) (end_neg_use_env r_se (Var x) rx2 r)" and
      s="diff_use_env (diff_use_env (stpx_req (rem_use_env rx2a (Var x)) (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) (end_neg_use_env r_se (Var x) rx2 r))
      (end_neg_use_env r_s2 (Var x) rx2 r)" in subst)
    apply (cut_tac r_s="stpx_req (rem_use_env rx2a (Var x)) (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))" and r_c="end_neg_use_env r_se (Var x) rx2 r" and
      r_x="end_neg_use_env r_s2 (Var x) rx2 r" in cancel_diff_use_env2)
     apply (auto)
   apply (rule_tac well_typed_diff_perms)
    (* induction requirements *)
    apply (case_tac "\<not> rem_use_env r_s2 (Var x) (Var x) = NoPerm")
     apply (simp add: rem_use_env_def)
    apply (cut_tac r="comp_use_env (rem_use_env r_s2 (Var x)) (lift_use_env rx2 r)" in id_leq_use_env)
    apply (case_tac "lam_vars e3 \<inter> free_vars e' = {}")
     apply (auto)
    apply (cut_tac r_x="rem_use_env r_s2 (Var x)" and r_s="rx1" and r_ex="lift_use_env rx2 r" in disj_leq_use_env1)
      apply (simp)
     apply (rule_tac r="r" in rem_add_leq_use_env)
     apply (rule_tac well_typed_perm_leq)
     apply (auto)
    (* proving the subtraction was valid. *)
   apply (rule_tac xa="xa" and ?e1.0="e1" and ?e2.0="e3" and env="env" in stpxic_valid_diff)
          apply (auto)
    (* final structural manipulation *)
  apply (cut_tac r_s="stpx_req (rem_use_env rx1a (Var x)) (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x))" and
      r_x="stpx_req (rem_use_env rx2a (Var x)) (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))"
     and r_ex="end_neg_use_env r_se (Var x) rx2 r" in dist_diff_comp_use_env)
  apply (simp)
  apply (rule_tac t="comp_use_env (stpx_req (rem_use_env rx1a (Var x)) (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x)))
      (stpx_req (rem_use_env rx2a (Var x)) (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x)))"
      and s="stpx_req (rem_use_env (comp_use_env rx1a rx2a) (Var x)) (lift_use_env rx2 (comp_use_env rx1a rx2a (Var x))) (comp_use_env rx1a rx2a (Var x))" in subst)
    (* - we prep by noting that rx1a + rx2a has a value at x *)
   apply (case_tac "comp_use_env rx1a rx2a (Var x) = NoPerm")
    apply (cut_tac r_sa="rx1a" and r_sb="rx2a" and x="Var x" in comp_use_none_both)
     apply (simp)
    apply (simp add: stpx_req_def)
    apply (auto)
   apply (rule_tac dist_rem_comp_use_env)
  apply (simp add: stpx_compact_conv)
  apply (simp add: stpx_compact_def)
  apply (auto)
    (* - both none case, impossible *)
     apply (cut_tac r_sa="rx1a" and r_sb="rx2a" and x="Var x" in comp_use_none)
       apply (simp_all)
    (* - rx2a has a value, rx1a does not *)
    apply (case_tac "\<not> comp_use_env rx1a rx2a (Var x) = rx2a (Var x)")
     apply (simp add: comp_use_env_def)
     apply (case_tac "rx2a (Var x)")
       apply (auto)
    apply (cut_tac r_ex="rem_use_env rx1a (Var x)" and r_s="rem_use_env rx2a (Var x)" and r_x="stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))" in assoc_comp_use_env)
    apply (simp)
    apply (cut_tac r_s="rx1a" and r_x="rx2a" and x="Var x" in dist_rem_comp_use_env)
    apply (simp)
     (* - rx1a has a value, rx2a does not *)
   apply (case_tac "\<not> comp_use_env rx1a rx2a (Var x) = rx1a (Var x)")
    apply (simp add: comp_use_env_def)
    apply (case_tac "rx1a (Var x)")
      apply (auto)
   apply (cut_tac r_s="rem_use_env rx1a (Var x)" and r_ex="rem_use_env rx2a (Var x)" and r_x="stpx_ex (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x))" in shuffle_comp_use_env)
   apply (simp)
   apply (cut_tac r_s="rx1a" and r_x="rx2a" and x="Var x" in dist_rem_comp_use_env)
   apply (simp)
    (* - rx1a and rx2a have values *)
  apply (cut_tac r_s="rx1a" and r_x="rx2a" and x="Var x" in dist_rem_comp_use_env)
  apply (auto)
  apply (cut_tac r_xa="rem_use_env rx1a (Var x)" and r_xb="stpx_ex (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x))" and
      r_sa="rem_use_env rx2a (Var x)" and r_sb="stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))" in dist_foil_comp_use_env)
  apply (simp)
  apply (cut_tac r_s="rx2" and r_xa="rx1a" and r_xb="rx2a" and x="Var x" in foil_comp_lift_use_env)
  apply (simp)
  apply (cut_tac ?rx2.0="rx2" and rx1a="rx1a" and rx2a="rx2a" and x="Var x" in stpxic_finish)
    apply (simp_all)
  done

    (*
      ####################################
        P4. lam case
      ####################################
    *)

lemma stpalc_drl_use_env: "\<lbrakk> leq_use_env (rem_use_env r_x x) (diff_use_env r_s r_ex) \<rbrakk> \<Longrightarrow>
  leq_use_env (rem_use_env r_x x) (diff_use_env r_s (rem_use_env r_ex x))"
  apply (simp add: leq_use_env_def)
  apply (simp add: rem_use_env_def)
  apply (simp add: diff_use_env_def)
  apply (auto)
  apply (erule_tac x="xa" in allE)
  apply (auto)
  done

lemma stpalc_nal_use_env: "\<lbrakk> r_s x = NoPerm; leq_use_env r_x (add_use_env r_s x r) \<rbrakk> \<Longrightarrow> leq_use_env (norm_use_env r_x r_s) r_s"
  apply (simp add: leq_use_env_def)
  apply (auto)
  apply (erule_tac x="xa" in allE)
  apply (simp add: add_use_env_def)
  apply (simp add: norm_use_env_def)
  apply (case_tac "x = xa")
   apply (auto)
  done

lemma stpx_lam_case: "\<lbrakk>\<And>env x tau t rx1 r_se r_xe r_s1 rx2 r.
           \<lbrakk>well_typed (add_env env (Var x) t) (add_use_env rx1 (Var x) r) e tau r_se r_xe; well_typed env rx2 e' t rx2 rx2; rx1 (Var x) = NoPerm;
            x \<in> free_vars e; leq_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_s1; disj_use_env rx1 (lift_use_env rx2 r)\<rbrakk>
           \<Longrightarrow> well_typed env r_s1 (subst_exp e x e') tau
                (diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r))
                (diff_use_env (stpx_req (rem_use_env r_xe (Var x)) (lift_use_env rx2 (r_xe (Var x))) (r_xe (Var x))) (end_neg_use_env r_se (Var x) rx2 r));
        well_typed env rx2 e' t rx2 rx2; rx1 (Var x) = NoPerm; is_sexp e'; leq_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_s1;
        disj_use_env rx1 (lift_use_env rx2 r); x \<in> free_vars e; x \<noteq> x1a; x1a \<notin> free_vars e'; lam_vars e \<inter> free_vars e' = {};
        well_typed (add_env (add_env env (Var x) t) (Var x1a) t1) (add_use_env rx (Var x1a) ra) e t2 r_s' r_end; aff_use_env rx a;
        leq_use_env rx (add_use_env rx1 (Var x) r); leq_use_env r_se (diff_use_env (add_use_env rx1 (Var x) r) r_ex); leq_use_env r_xe r_se;
        leq_use_env r_ex (add_use_env rx1 (Var x) r); leq_use_env (diff_use_env rx r_ex) r_xe\<rbrakk>
       \<Longrightarrow> \<exists>rx. (\<exists>r_end r_s'. well_typed (add_env env (Var x1a) t1) (add_use_env rx (Var x1a) ra) (subst_exp e x e') t2 r_s' r_end) \<and>
                aff_use_env rx a \<and>
                leq_use_env rx r_s1 \<and>
                (\<exists>r_ex. leq_use_env (diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r))
                         (diff_use_env r_s1 r_ex) \<and>
                        leq_use_env
                         (diff_use_env (stpx_req (rem_use_env r_xe (Var x)) (lift_use_env rx2 (r_xe (Var x))) (r_xe (Var x)))
                           (end_neg_use_env r_se (Var x) rx2 r))
                         (diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r)) \<and>
                        leq_use_env r_ex r_s1 \<and>
                        leq_use_env (diff_use_env rx r_ex)
                         (diff_use_env (stpx_req (rem_use_env r_xe (Var x)) (lift_use_env rx2 (r_xe (Var x))) (r_xe (Var x)))
                           (end_neg_use_env r_se (Var x) rx2 r)))"
    (* prelim: rx x \<le> r *)
  apply (case_tac "\<not> leq_perm (rx (Var x)) r")
   apply (cut_tac r_x="rx" and r_s="add_use_env rx1 (Var x) r" and x="Var x" in spec_leq_perm)
    apply (simp)
   apply (simp add: add_use_env_def)
    (* prelim: r_xe x \<le> r *)
  apply (case_tac "\<not> leq_perm (r_xe (Var x)) r")
   apply (cut_tac r_x="r_xe" and r_s="add_use_env rx1 (Var x) r" and x="Var x" in spec_leq_perm)
    apply (rule_tac r_sb="diff_use_env (add_use_env rx1 (Var x) r) r_ex" in trans_leq_use_env)
     apply (rule_tac self_diff_leq_use_env)
    apply (rule_tac r_sb="r_se" in trans_leq_use_env)
    apply (simp_all)
   apply (simp add: add_use_env_def)
    (* prelim: rx x \<noteq> None. if rx x = None, then x1a is a non-prim var *)
  apply (case_tac "rx (Var x) = NoPerm")
   apply (cut_tac env="add_env (add_env env (Var x) t) (Var x1a) t1" and ?r_s1.0="add_use_env rx (Var x1a) ra" and x="Var x" and e="e" in well_typed_no_npv_use)
     apply (auto)
    apply (simp add: add_use_env_def)
   apply (case_tac "\<not> req_type t = Prim")
    apply (simp add: non_prim_vars_def)
    apply (simp add: non_prim_entry_def)
    apply (cut_tac x="x" and e="e" in free_res_vars_rev)
     apply (auto)
    apply (erule_tac x="t" in allE)
    apply (simp add: add_env_def)
   apply (rule_tac x="rx" in exI)
   apply (auto)
     apply (rule_tac x="r_end" in exI)
     apply (rule_tac x="r_s'" in exI)
     apply (rule_tac t="t" and ?rx2.0="rx2" in subst_type_preserve_prim_fv)
           apply (auto)
      apply (cut_tac env="env" and x="Var x" and y="Var x1a" and t="t1" and t'="t" in almost_comm_add_env)
       apply (auto)
     apply (rule_tac well_typed_add_vars)
       apply (auto)
    apply (rule_tac r_sb="comp_use_env rx1 (lift_use_env rx2 r)" in trans_leq_use_env)
     apply (simp)
    apply (rule_tac comp_leq_use_env1)
    apply (rule_tac r_sb="rem_use_env rx (Var x)" in trans_leq_use_env)
     apply (rule_tac r="r" in rem_add_leq_use_env)
     apply (simp)
    apply (cut_tac r_s="rx" and x="Var x" in ignore_rem_use_env)
     apply (auto)
    apply (rule_tac id_leq_use_env)
    (* - inequalities to finish this section *)
   apply (rule_tac x="comp_use_env (rem_use_env r_ex (Var x)) (end_neg_use_env r_se (Var x) rx2 r)" in exI)
   apply (auto)
      apply (rule_tac rhs_unroll_dcl_use_env)
      apply (rule_tac dist_diff_leq_use_env)
      apply (rule_tac dist_comp_leq_use_env)
       apply (rule_tac stpalc_drl_use_env)
       apply (rule_tac r_sb="diff_use_env rx1 r_ex" in trans_leq_use_env)
        apply (rule_tac dist_diff_leq_use_env)
        apply (rule_tac r_sb="comp_use_env rx1 (lift_use_env rx2 r)" in trans_leq_use_env)
         apply (simp)
        apply (rule_tac self_comp_leq_use_env1)
       apply (rule_tac r="r" in rem_add_leq_use_env)
       apply (rule_tac r_sb="diff_use_env (add_use_env rx1 (Var x) r) r_ex" in trans_leq_use_env)
        apply (rule_tac add_diff_leq_use_env)
       apply (simp)
      apply (rule_tac mini_disj_diff_leq_use_env2)
       apply (rule_tac r_sb="comp_use_env rx1 (lift_use_env rx2 r)" in trans_leq_use_env)
        apply (simp)
       apply (rule_tac self_comp_leq_use_env2)
      apply (rule_tac r_s="rx1" in mini_disj_leq_use_env1)
       apply (simp add: disj_use_env_def)
      apply (rule_tac r="r" in rem_add_leq_use_env)
      apply (simp)
     apply (rule_tac dist_diff_leq_use_env)
     apply (rule_tac stpx_req_leq_use_env)
     apply (rule_tac dist_comp_leq_use_env)
      apply (rule_tac comp_leq_use_env1)
      apply (rule_tac dist_rem_leq_use_env)
      apply (simp)
     apply (rule_tac comp_leq_use_env2)
     apply (rule_tac dist_lift_leq_use_env_gen)
     apply (simp)
    apply (rule_tac r_sb="comp_use_env rx1 (lift_use_env rx2 r)" in trans_leq_use_env)
     apply (simp)
    apply (rule_tac dist_comp_leq_use_env)
     apply (rule_tac comp_leq_use_env1)
     apply (rule_tac rem_add_leq_use_env)
     apply (simp)
    apply (rule_tac end_neg_leq_use_env)
    apply (rule_tac self_comp_leq_use_env2)
   apply (rule_tac lhs_unroll_dcl_use_env)
   apply (rule_tac dist_diff_leq_use_env)
   apply (rule_tac stpx_req_leq_use_env2)
   apply (cut_tac r_s="rx" and x="Var x" in ignore_rem_use_env)
    apply (auto)
   apply (rule_tac t="diff_use_env rx (rem_use_env r_ex (Var x))" and s="rem_use_env (diff_use_env rx r_ex) (Var x)" in subst)
    apply (cut_tac r_s="rx" and x="Var x" and r_x="r_ex" in dist_diff_rem_use_env)
    apply (auto)
   apply (rule_tac dist_rem_leq_use_env)
    apply (simp)
    (* new requirements passed in: (rx - x) + (lift rx2) *)
  apply (rule_tac x="comp_use_env (rem_use_env rx (Var x)) (lift_use_env (drop_use_env_ex rx2 (rx (Var x))) (rx (Var x)))" in exI)
  apply (auto)
     apply (rule_tac x="diff_use_env (stpx_req (rem_use_env r_end (Var x)) (lift_use_env (rem_use_env (drop_use_env_ex rx2 (rx (Var x))) (Var x1a)) (r_end (Var x))) (r_end (Var x)))
        (end_neg_use_env r_s' (Var x) (rem_use_env (drop_use_env_ex rx2 (rx (Var x))) (Var x1a)) (rx (Var x)))" in exI)
     apply (rule_tac x="diff_use_env (comp_use_env (rem_use_env r_s' (Var x)) (lift_use_env (rem_use_env (drop_use_env_ex rx2 (rx (Var x))) (Var x1a)) (rx (Var x))))
        (end_neg_use_env r_s' (Var x) (rem_use_env (drop_use_env_ex rx2 (rx (Var x))) (Var x1a)) (rx (Var x)))" in exI)
    (* - manipulating well-typedness statement to use for induction.
        env has both x and x1a added to it. so we put x on the outside.
    *)
     apply (cut_tac env="env" and x="Var x1a" and t="t" and y="Var x" and t'="t1" in almost_comm_add_env)
      apply (auto)
    (* chosen rx1: (rx + x1a ra) - x *)
    (* - we're allowed to add x to rx (after removing some original value of x to further facilitate induction) *)
     apply (case_tac "\<not> well_typed (add_env (add_env env (Var x1a) t1) (Var x) t) (add_use_env (rem_use_env (add_use_env rx (Var x1a) ra) (Var x)) (Var x) (rx (Var x))) e t2 r_s' r_end")
      apply (cut_tac env="add_env (add_env env (Var x1a) t1) (Var x) t" and ?r_s1.0="add_use_env rx (Var x1a) ra" and r_c="add_use_env (add_use_env rx (Var x1a) ra) (Var x) (rx (Var x))" and
        e="e" and tau="t2" and ?r_s2.0="r_s'" and rx="r_end" in well_typed_incr_start_perm)
        apply (auto)
       apply (cut_tac r_s="add_use_env rx (Var x1a) ra" and x="Var x" and r="rx (Var x)" in cancel_add_rem_use_env)
        apply (simp add: add_use_env_def)
       apply (auto)
      apply (cut_tac r_s="add_use_env rx (Var x1a) ra" and x="Var x" and r="rx (Var x)" in cancel_add_rem_use_env)
       apply (simp add: add_use_env_def)
      apply (auto)
    (* chosen rx2: (drop rx2) - x *)
    (* - manipulation of the rx2 well-typedness constraint, so that we can remove x1a from it. *)
     apply (case_tac "\<not> well_typed (add_env env (Var x1a) t1) (rem_use_env (drop_use_env_ex rx2 (rx (Var x))) (Var x1a)) e' t
        (rem_use_env (drop_use_env_ex rx2 (rx (Var x))) (Var x1a)) (rem_use_env (drop_use_env_ex rx2 (rx (Var x))) (Var x1a))")
      apply (cut_tac env="env" and ?r_s1.0="rx2" and ?r_s2.0="rx2" and rx="rx2" and x="x1a" and e="e'" and tau="t" and t="t1" in well_typed_add_vars)
        apply (auto)
      apply (cut_tac env="add_env env (Var x1a) t1" and rx="rx2" and e="e'" and r="rx (Var x)" in wt_sexp_drop_all_ex)
         apply (auto)
    (* - case analysis to prove rx x = None is impossible, rx x = Use implies unlim t *)
       apply (simp add: tau_drop_req_def)
       apply (case_tac "rx (Var x)")
         apply (auto)
       apply (cut_tac env="add_env (add_env env (Var x) t) (Var x1a) t1" and ?r_s1.0="add_use_env rx (Var x1a) ra" and e="e" and x="Var x" and t="t" in well_typed_aff_fv_own)
           apply (auto)
         apply (cut_tac x="x" and e="e" in free_res_vars_rev)
          apply (auto)
        apply (simp add: add_env_def)
       apply (simp add: add_use_env_def)
    (* - finish with the removal *)
      apply (cut_tac env="add_env env (Var x1a) t1" and ?r_s1.0="drop_use_env_ex rx2 (rx (Var x))" and ?r_s2.0="drop_use_env_ex rx2 (rx (Var x))" and
        rx="drop_use_env_ex rx2 (rx (Var x))" and x="Var x1a" and e="e'" and tau="t" in well_typed_rem_perms)
        apply (auto)
      apply (simp add: non_prim_vars_def)
      apply (cut_tac x="x1a" and e="e'" in free_res_vars)
       apply (auto)
    (* - manual proofs of the other induction constraints *)(*
     apply (case_tac "\<not> add_env env x1a t1 x = None")
      apply (simp add: add_env_def)*)
     apply (case_tac "\<not> rem_use_env (add_use_env rx (Var x1a) ra) (Var x) (Var x) = NoPerm")
      apply (simp add: rem_use_env_def)
     apply (auto)
    (* - rx1 is removable *)
     apply (case_tac "\<not> leq_use_env (rem_use_env (add_use_env rx (Var x1a) ra) (Var x))
      (add_use_env (comp_use_env (rem_use_env rx (Var x)) (lift_use_env (drop_use_env_ex rx2 (rx (Var x))) (rx (Var x)))) (Var x1a) ra)")
      apply (cut_tac r_x="rem_use_env rx (Var x)" and r_s="comp_use_env (rem_use_env rx (Var x)) (lift_use_env (drop_use_env_ex rx2 (rx (Var x))) (rx (Var x)))" and x="Var x1a" and r="ra" in dist_add_leq_use_env)
       apply (rule_tac self_comp_leq_use_env1)
      apply (cut_tac r_s="rx" and x="Var x1a" and r="ra" and y="Var x" in almost_comm_rem_add_use_env)
       apply (auto)
    (* - disjoint-ness *)
     apply (case_tac "\<not> disj_use_env (rem_use_env (add_use_env rx (Var x1a) ra) (Var x)) (lift_use_env (rem_use_env (drop_use_env_ex rx2 (rx (Var x))) (Var x1a)) (rx (Var x)))")
      apply (cut_tac r_s="rem_use_env rx (Var x)" and r_x="lift_use_env (rem_use_env (drop_use_env_ex rx2 (rx (Var x))) (Var x1a)) (rx (Var x))" and x="Var x1a" and r="ra" in disj_add_use_env)
        apply (simp add: rem_use_env_def)
        apply (case_tac "rx (Var x)")
          apply (auto)
       apply (rule_tac r_s="rx1" in disj_leq_use_env1)
        apply (rule_tac r_s="lift_use_env rx2 r" in disj_leq_use_env2)
         apply (simp)
        apply (rule_tac r_sb="lift_use_env rx2 (rx (Var x))" in trans_leq_use_env)
         apply (rule_tac dist_lift_leq_use_env_gen)
         apply (simp)
        apply (rule_tac dist_lift_leq_use_env)
        apply (rule_tac rem_leq_use_env)
        apply (case_tac "rx (Var x)")
          apply (auto)
         apply (rule_tac self_drop_leq_use_env)
        apply (rule_tac id_leq_use_env)
       apply (rule_tac r="r" in rem_add_leq_use_env)
       apply (simp)
      apply (cut_tac r_s="rx" and x="Var x1a" and r="ra" and y="Var x" in almost_comm_rem_add_use_env)
       apply (auto)
    (* - rx2 is removable *)
     apply (case_tac "\<not> leq_use_env (lift_use_env (rem_use_env (drop_use_env_ex rx2 (rx (Var x))) (Var x1a)) (rx (Var x)))
      (add_use_env (comp_use_env (rem_use_env rx (Var x)) (lift_use_env (drop_use_env_ex rx2 (rx (Var x))) (rx (Var x)))) (Var x1a) ra)")
      apply (cut_tac r_x="lift_use_env (drop_use_env_ex rx2 (rx (Var x))) (rx (Var x))" and
        r_s="comp_use_env (rem_use_env rx (Var x)) (lift_use_env (drop_use_env_ex rx2 (rx (Var x))) (rx (Var x)))" and x="Var x1a" and r="ra" in cancel_rem_add_leq_use_env)
       apply (rule_tac self_comp_leq_use_env2)
      apply (cut_tac r_s="drop_use_env_ex rx2 (rx (Var x))" and x="Var x1a" and r="rx (Var x)" in lift_rem_use_env)
      apply (auto)
    (* - rx1 + rx2 removable *)
     apply (cut_tac r_xa="rem_use_env (add_use_env rx (Var x1a) ra) (Var x)" and r_xb="lift_use_env (rem_use_env (drop_use_env_ex rx2 (rx (Var x))) (Var x1a)) (rx (Var x))" and
        r_s="add_use_env (comp_use_env (rem_use_env rx (Var x)) (lift_use_env (drop_use_env_ex rx2 (rx (Var x))) (rx (Var x)))) (Var x1a) ra" in dist_comp_leq_use_env)
       apply (auto)
    (* - safety *)
     apply (case_tac "\<not> safe_use_lift (rem_use_env (drop_use_env_ex rx2 (rx (Var x))) (Var x1a)) (rx (Var x))")
      apply (cut_tac r_s="drop_use_env_ex rx2 (rx (Var x))" and x="Var x1a" and r="rx (Var x)" in safe_lift_rem_use_env)
       apply (case_tac "rx (Var x)")
         apply (auto)
     apply (simp add: drop_use_env_def)
     apply (case_tac "rx2 xaa = OwnPerm")
      apply (auto)
    (* post-induction rx2 affinity requirement.
      - if rx x = Use then rx2 affine by construction, non-prim a
      - if rx x = Own then affine a
      ** the main issue is, what if e' is a lambda that does actually require some ownerships?
    *)
    apply (rule_tac aff_comp_use_env)
     apply (rule_tac aff_rem_use_env)
     apply (simp)
    apply (case_tac "rx (Var x)")
      apply (auto)
     apply (simp add: aff_use_env_def)
     apply (case_tac a)
       apply (auto)
      apply (rule_tac drop_weak_use_env)
     apply (simp add: null_use_env_def)
    apply (case_tac a)
      apply (simp add: aff_use_env_def)
     apply (simp add: aff_use_env_def)
     apply (simp add: weak_use_env_def)
    apply (simp add: aff_use_env_def)
    apply (simp add: null_use_env_def)
    (* the conclusion that we're being forced to draw is that an unlim lambda cannot take ownership,
      because the ownership by itself has the potential to force resource re-usage.
      - the intuition for why the substitution should work is that, if x is passed into rx, which gets
        used for the lambda, then it should drop to use permissions. now the problem is that if x
        initially had ownership permissions, then when the actual substitution is performed, it will
        inherit the full permissions. and even though it uses those permissions safely, our type system
        will balk at allowing ownership permissions to be passed into an unlim lambda.
      - the absolutely sneaky intuition for why it should still work is that we ought to vary the
        induction based on whether rx x = UsePerm or not, since we are actually allowed to vary the
        induction based on a different r.

        if rx x = UsePerm, then rx2 will not be lifted. if t is unlim, then by unlim_aff, rx2 is also non-aff
        if t is non-unlim, then we must have ownership to use it.
        and if rx x = OwnPerm, then simply a is affine.
    *)
    (* - requirements existential bound *)
   apply (rule_tac r_sb="comp_use_env rx1 (lift_use_env rx2 r)" in trans_leq_use_env)
    apply (simp)
   apply (rule_tac dist_comp_leq_use_env)
    apply (rule_tac comp_leq_use_env1)
    apply (rule_tac r="r" in rem_add_leq_use_env)
    apply (simp)
   apply (rule_tac comp_leq_use_env2)
   apply (rule_tac r_sb="lift_use_env rx2 (rx (Var x))" in trans_leq_use_env)
    apply (rule_tac dist_lift_leq_use_env_gen)
    apply (simp)
   apply (rule_tac dist_lift_leq_use_env)
   apply (case_tac "rx (Var x)")
     apply (auto)
    apply (rule_tac self_drop_leq_use_env)
   apply (rule_tac id_leq_use_env)
    (* chosen subtracter: (r_ex \ rx2) + (lift rx2) *)
  apply (rule_tac x="comp_use_env (norm_use_env (rem_use_env r_ex (Var x)) rx1) (end_neg_use_env r_se (Var x) rx2 r)" in exI)
  apply (auto)
    (* - upper bound on end permissions *)
     apply (rule_tac rhs_unroll_dcl_use_env)
     apply (rule_tac dist_diff_leq_use_env)
     apply (rule_tac dist_comp_leq_use_env)
      apply (rule_tac r_sb="diff_use_env rx1 r_ex" in trans_leq_use_env)
       apply (rule_tac dist_diff_leq_use_env_gen)
        apply (rule_tac r_sb="comp_use_env rx1 (lift_use_env rx2 r)" in trans_leq_use_env)
         apply (simp)
        apply (rule_tac self_comp_leq_use_env1)
       apply (rule_tac norm_leq_use_env)
       apply (rule_tac self_rem_leq_use_env)
      apply (rule_tac r="r" in rem_add_leq_use_env)
      apply (rule_tac r_sb="diff_use_env (add_use_env rx1 (Var x) r) r_ex" in trans_leq_use_env)
       apply (rule_tac add_diff_leq_use_env)
      apply (simp)
     apply (rule_tac disj_diff_leq_use_env)
      apply (rule_tac disj_norm_use_env1)
       apply (rule_tac gen_mini_disj_use_env1)
       apply (rule_tac r_s="rx1" in disj_leq_use_env1)
        apply (simp)
       apply (rule_tac r="r" in rem_add_leq_use_env)
       apply (simp_all)
     apply (rule_tac r_sb="comp_use_env rx1 (lift_use_env rx2 r)" in trans_leq_use_env)
      apply (simp)
     apply (rule_tac self_comp_leq_use_env2)
    (* - relative bound *)
    apply (rule_tac dist_diff_leq_use_env)
    apply (rule_tac stpx_req_leq_use_env)
    apply (rule_tac dist_comp_leq_use_env)
     apply (rule_tac comp_leq_use_env1)
     apply (rule_tac dist_rem_leq_use_env)
     apply (simp)
    apply (rule_tac comp_leq_use_env2)
    apply (rule_tac dist_lift_leq_use_env_gen)
    apply (simp)
    (* - subtracter validity *)
   apply (rule_tac r_sb="comp_use_env rx1 (lift_use_env rx2 r)" in trans_leq_use_env)
    apply (simp)
   apply (rule_tac dist_comp_leq_use_env)
    apply (rule_tac comp_leq_use_env1)
    apply (rule_tac x="Var x" and r="r" in stpalc_nal_use_env)
     apply (auto)
    apply (rule_tac rem_leq_use_env)
    apply (simp)
   apply (rule_tac end_neg_leq_use_env)
   apply (rule_tac self_comp_leq_use_env2)
    (* - lower bound on requirements *)
  apply (rule_tac lhs_dist_dcl_use_env)
  apply (rule_tac dist_comp_leq_use_env)
   apply (rule_tac lhs_unroll_dcl_use_env)
   apply (rule_tac dist_diff_leq_use_env)
   apply (rule_tac r_sb="diff_use_env (rem_use_env rx (Var x)) (rem_use_env r_ex (Var x))" in trans_leq_use_env)
    apply (rule_tac t="diff_use_env (rem_use_env rx (Var x)) (rem_use_env r_ex (Var x))" and s="rem_use_env (diff_use_env rx r_ex) (Var x)" in subst)
     apply (rule_tac dist_diff_rem_use_env)
    apply (rule_tac stpx_req_leq_use_env2)
    apply (rule_tac dist_rem_leq_use_env)
    apply (simp)
   apply (rule_tac diff_norm_leq_use_env_ex)
   apply (rule_tac r="r" in rem_add_leq_use_env)
   apply (simp)
  apply (rule_tac lhs_flip_use_env)
  apply (rule_tac lhs_unroll_dcl_use_env)
  apply (rule_tac diff_leq_use_env)
    (* - the hardest part of the inequality, depends on r_xe x. say that r_xe x \<noteq> none *)
  apply (case_tac "r_xe (Var x) \<noteq> NoPerm")
    (* - say that r_se x \<noteq> None. then r_ex x \<noteq> Own, and we have rx x \<le> r_xe x, which allows us to dissolve the inequalities *)
   apply (case_tac "r_se (Var x) \<noteq> NoPerm")
    apply (case_tac "r_ex (Var x) = OwnPerm")
     apply (cut_tac r_x="r_se" and r_s="diff_use_env (add_use_env rx1 (Var x) r) r_ex" and x="Var x" in leq_use_none)
       apply (simp)
      apply (rule_tac diff_use_none_ex)
      apply (simp_all)
    apply (cut_tac r_x="rx" and r_ex="r_ex" and r_s="r_xe" and x="Var x" in diff_use_leq)
      apply (simp_all)
    apply (rule_tac dist_diff_leq_use_env)
    apply (case_tac "rx (Var x)")
      apply (auto)
     apply (simp add: stpx_req_def)
     apply (auto)
      apply (rule_tac self_comp_leq_use_env2)
     apply (rule_tac comp_leq_use_env2)
     apply (rule_tac drop_leq_use_env)
     apply (rule_tac self_lift_leq_use_env)
    apply (simp add: stpx_req_def)
    apply (auto)
    apply (rule_tac comp_leq_use_env2)
    apply (case_tac "r_xe (Var x)")
      apply (auto)
    apply (rule_tac id_leq_use_env)
    (* - r_se x \<noteq> None since r_xe \<le> r_se *)
   apply (cut_tac r_x="r_xe" and r_s="r_se" and x="Var x" in spec_leq_perm)
    apply (simp)
   apply (case_tac "r_xe (Var x)")
     apply (auto)
    (* - otherwise r_xe x = None. in this case r_ex x = Own, which means that r_se = None + r = Own. which means rx2 annihilates *)
  apply (rule_tac r_sb="diff_use_env (lift_use_env rx2 (rx (Var x))) (end_neg_use_env r_se (Var x) rx2 r)" in trans_leq_use_env)
   apply (case_tac "r_ex (Var x) \<noteq> OwnPerm")
    apply (case_tac "diff_use_env rx r_ex (Var x) = NoPerm")
     apply (simp add: diff_use_env_def)
     apply (case_tac "r_ex (Var x)")
       apply (auto)
    apply (cut_tac r_x="diff_use_env rx r_ex" and r_s="r_xe" and x="Var x" in leq_use_none)
      apply (simp_all)
   apply (cut_tac r_s="add_use_env rx1 (Var x) r" and r_ex="r_ex" and x="Var x" in diff_use_none_ex)
    apply (simp)
   apply (cut_tac r_x="r_se" and r_s="diff_use_env (add_use_env rx1 (Var x) r) r_ex" and x="Var x" in leq_use_none)
     apply (simp_all)
   apply (case_tac "\<not> is_own r")
    apply (cut_tac r_x="r_ex" and r_s="add_use_env rx1 (Var x) r" and x="Var x" in spec_leq_perm)
     apply (simp)
    apply (simp add: add_use_env_def)
    apply (simp add: is_own_def)
    apply (case_tac r)
      apply (simp_all)
   apply (simp add: end_neg_use_env_def)
   apply (cut_tac r_s="rx2" and q="rx (Var x)" and r="r" in ann_lift_use_env)
    apply (simp add: is_own_def)
   apply (simp)
   apply (rule_tac leq_empty_use_env)
  apply (rule_tac dist_diff_leq_use_env)
  apply (rule_tac dist_lift_leq_use_env)
  apply (case_tac "rx (Var x)")
    apply (auto)
   apply (rule_tac self_drop_leq_use_env)
  apply (rule_tac id_leq_use_env)
  done

    (*
      ####################################
        P5. app case
      ####################################
    *)

    (*
      the end-permissions will be r_s3 + rx2 that has already had
       x & (lift rx2) removed from it.

      from here we have to further subtract
        (rx1a + rx2) - x - (lift rx2)
        & lift [(rx2a + rx2) - x - (lift rx2)]

      in theory we can easily consolidate this to
       ((r_s3 + rx2) - rx1a - rx2a) - x - (lift rx2)

      which allows us to satisfy the upper bound quite summarily

      the requirements (assuming that they arent squashed) will be
       (rx1a + rx2) - x - (lift rx2)
       + (rx2a + rx2) - x - (lift rx2)
       - ((rx1a + rx2) - x - (lift rx2))
       - lift ((rx2a + rx2) - x - (lift rx2))
      *)

lemma stpa_incr_ind_perm: "\<lbrakk> well_typed env (add_use_env r_s1 x r) e tau r_s2 rx; leq_perm r p \<rbrakk> \<Longrightarrow> well_typed env (add_use_env r_s1 x p) e tau r_s2 rx"
  apply (rule_tac well_typed_incr_start_perm)
   apply (auto)
    apply (simp add: leq_use_env_def)
  apply (simp add: add_use_env_def)
  apply (auto)
  apply (case_tac "r_s1 xa")
    apply (auto)
  done

(*
  say that r = Use, but ra = Own. this means that r_s1 x is a use, which means rx2a x is a use.
  however, (lift rx2a ra) x = Own. since (lift rx2a ra) is subtractable from r_s1 x, we have a
  contradiction
*)

definition stpxac_lift_res where
  "stpxac_lift_res p q r = (p = NoPerm \<or> leq_perm q r)"

lemma stpxac_lift_order: "\<lbrakk> leq_use_env (lift_use_env rx2a ra) (add_use_env rx1 x r) \<rbrakk> \<Longrightarrow> stpxac_lift_res (rx2a x) ra r"
  apply (simp add: stpxac_lift_res_def)
  apply (auto)
  apply (case_tac "rx2a x \<noteq> NoPerm")
   apply (auto)
  apply (cut_tac r_x="lift_use_env rx2a ra" and r_s="add_use_env rx1 x r" and x="x" in spec_leq_perm)
   apply (simp)
  apply (simp add: add_use_env_def)
  apply (case_tac r)
    apply (auto)
   apply (case_tac ra)
     apply (auto)
   apply (case_tac "rx2a x")
     apply (auto)
  apply (case_tac ra)
    apply (auto)
  done

lemma stpx_app_case: "\<lbrakk>\<And>env x tau t rx1 r_se r_xe r_s1 rx2 r.
           \<lbrakk>well_typed (add_env env (Var x) t) (add_use_env rx1 (Var x) r) e1 tau r_se r_xe; well_typed env rx2 e' t rx2 rx2; rx1 (Var x) = NoPerm;
            x \<in> free_vars e1; lam_vars e1 \<inter> free_vars e' = {}; leq_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_s1; disj_use_env rx1 (lift_use_env rx2 r)\<rbrakk>
           \<Longrightarrow> well_typed env r_s1 (subst_exp e1 x e') tau
                (diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r))
                (diff_use_env (stpx_req (rem_use_env r_xe (Var x)) (lift_use_env rx2 (r_xe (Var x))) (r_xe (Var x))) (end_neg_use_env r_se (Var x) rx2 r));
        \<And>env x tau t rx1 r_se r_xe r_s1 rx2 r.
           \<lbrakk>well_typed (add_env env (Var x) t) (add_use_env rx1 (Var x) r) e2 tau r_se r_xe; well_typed env rx2 e' t rx2 rx2; rx1 (Var x) = NoPerm;
            x \<in> free_vars e2; lam_vars e2 \<inter> free_vars e' = {}; leq_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_s1; disj_use_env rx1 (lift_use_env rx2 r)\<rbrakk>
           \<Longrightarrow> well_typed env r_s1 (subst_exp e2 x e') tau
                (diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r))
                (diff_use_env (stpx_req (rem_use_env r_xe (Var x)) (lift_use_env rx2 (r_xe (Var x))) (r_xe (Var x))) (end_neg_use_env r_se (Var x) rx2 r));
        well_typed env rx2 e' t rx2 rx2; rx1 (Var x) = NoPerm; is_sexp e'; (lam_vars e1 \<union> lam_vars e2) \<inter> free_vars e' = {};
        leq_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_s1; disj_use_env rx1 (lift_use_env rx2 r);
        well_typed (add_env env (Var x) t) (add_use_env rx1 (Var x) r) e1 (FunTy t1 tau ra a) r_s2 rx1a; well_typed (add_env env (Var x) t) r_s2 e2 t1 r_s3 rx2a;
        leq_use_env r_se (diff_use_env r_s3 (comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex));
        leq_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_s3; disj_use_env rx1a (lift_use_env rx2a ra); leq_use_env r_xe r_se;
        leq_use_env r_ex (add_use_env rx1 (Var x) r); leq_use_env (app_req rx1a rx2a ra tau r_ex) r_xe\<rbrakk>
       \<Longrightarrow> \<exists>t1 ra a r_s2 rx1.
              well_typed env r_s1 (subst_exp e1 x e') (FunTy t1 tau ra a) r_s2 rx1 \<and>
              (\<exists>rx2a r_s3.
                  well_typed env r_s2 (subst_exp e2 x e') t1 r_s3 rx2a \<and>
                  (\<exists>r_ex. leq_use_env (diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r))
                           (diff_use_env r_s3 (comp_use_env (comp_use_env rx1 (lift_use_env rx2a ra)) r_ex)) \<and>
                          leq_use_env (comp_use_env rx1 (lift_use_env rx2a ra)) r_s3 \<and>
                          disj_use_env rx1 (lift_use_env rx2a ra) \<and>
                          leq_use_env
                           (diff_use_env (stpx_req (rem_use_env r_xe (Var x)) (lift_use_env rx2 (r_xe (Var x))) (r_xe (Var x)))
                             (end_neg_use_env r_se (Var x) rx2 r))
                           (diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r)) \<and>
                          leq_use_env r_ex r_s1 \<and>
                          leq_use_env (app_req rx1 rx2a ra tau r_ex)
                           (diff_use_env (stpx_req (rem_use_env r_xe (Var x)) (lift_use_env rx2 (r_xe (Var x))) (r_xe (Var x)))
                             (end_neg_use_env r_se (Var x) rx2 r))))"
    (* - prelim: r_s3 \<le> rx1 + x (used frequently) *)
  apply (cut_tac r_sc="r_s3" and r_sb="r_s2" and r_sa="add_use_env rx1 (Var x) r" in trans_leq_use_env)
    apply (rule_tac well_typed_perm_leq)
    apply (auto)
   apply (rule_tac well_typed_perm_leq)
   apply (auto)
    (* - prelim: rx1a x \<le> r *)
  apply (case_tac "\<not> leq_perm (rx1a (Var x)) r")
   apply (case_tac "\<not> (\<forall> x'. leq_perm (rx1a x') (add_use_env rx1 (Var x) r x'))")
    apply (cut_tac r_sc="rx1a" and r_sb="comp_use_env rx1a (lift_use_env rx2a ra)" and r_sa="add_use_env rx1 (Var x) r" in trans_leq_use_env)
      apply (rule_tac r_sb="r_s3" in trans_leq_use_env)
       apply (auto)
     apply (rule_tac self_comp_leq_use_env1)
    apply (simp add: leq_use_env_def)
   apply (erule_tac x="Var x" in allE)
   apply (simp add: add_use_env_def)
    (* - prelim: rx2a x \<le> r *)
  apply (case_tac "\<not> leq_perm (rx2a (Var x)) r")
   apply (case_tac "\<not> (\<forall> x'. leq_perm (rx2a x') (add_use_env rx1 (Var x) r x'))")
    apply (cut_tac r_sc="rx2a" and r_sb="comp_use_env rx1a (lift_use_env rx2a ra)" and r_sa="add_use_env rx1 (Var x) r" in trans_leq_use_env)
      apply (rule_tac r_sb="r_s3" in trans_leq_use_env)
       apply (auto)
     apply (rule_tac comp_leq_use_env2)
     apply (rule_tac self_lift_leq_use_env)
    apply (simp add: leq_use_env_def)
   apply (erule_tac x="Var x" in allE)
  apply (simp add: add_use_env_def)
    (* - prelim: either rx2a x = None or ra \<le> r *)
  apply (cut_tac ?rx1.0="rx1" and rx2a="rx2a" and x="Var x" and r="r" and ra="ra" in stpxac_lift_order)
   apply (rule_tac r_sb="comp_use_env rx1a (lift_use_env rx2a ra)" in trans_leq_use_env)
    apply (rule_tac r_sb="r_s3" in trans_leq_use_env)
     apply (simp_all)
   apply (rule_tac self_comp_leq_use_env2)
    (* initial e1 existentials *)
  apply (rule_tac x="t1" in exI)
  apply (rule_tac x="ra" in exI)
  apply (rule_tac x="a" in exI)
  apply (rule_tac x="diff_use_env (comp_use_env (rem_use_env r_s2 (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_s2 (Var x) rx2 r)" in exI)
  apply (rule_tac x="diff_use_env (stpx_req (rem_use_env rx1a (Var x)) (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x))) (end_neg_use_env r_s2 (Var x) rx2 r)" in exI)
  apply (auto)
    (* x \<notin> fv e1 *)
   apply (case_tac "x \<notin> free_vars e1")
    apply (rule_tac ?r_s1.0="comp_use_env (rem_use_env rx1 (Var x)) (lift_use_env rx2 r)" in well_typed_incr_start_perm)
     apply (rule_tac subst_type_preserve_no_fv)
      apply (rule_tac well_typed_diff_end_perm)
       apply (rule_tac well_typed_stpx_req)
       apply (rule_tac well_typed_comp_perms)
        apply (cut_tac r_s="rx1" and x="Var x" and r="r" in partial_rem_add_use_env)
        apply (simp)
         apply (rule_tac well_typed_rem_perms)
         apply (rule_tac x="x" and t="t" in well_typed_add_vars_rev)
           apply (simp_all)
        apply (simp add: non_prim_vars_def)
        apply (auto)
        apply (cut_tac x="x" and e="e1" in free_res_vars)
         apply (auto)
       apply (rule_tac disj_rem_use_envx)
       apply (simp)
      apply (rule_tac dist_lift_leq_use_env_gen)
      apply (simp)
     apply (rule_tac end_neg_leq_use_env)
     apply (rule_tac self_comp_leq_use_env2)
    apply (rule_tac r_sb="comp_use_env rx1 (lift_use_env rx2 r)" in trans_leq_use_env)
     apply (simp)
    apply (rule_tac dist_comp_leq_use_env)
     apply (rule_tac comp_leq_use_env1)
     apply (rule_tac self_rem_leq_use_env)
    apply (rule_tac self_comp_leq_use_env2)
    (* x \<in> fv e1, induction on e1 *)
   apply (case_tac "\<not> lam_vars e1 \<inter> free_vars e' = {}")
    apply (auto)
    (* x \<notin> fv e2. *)
  apply (rule_tac x="diff_use_env (stpx_req (rem_use_env rx2a (Var x)) (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) (end_neg_use_env r_s3 (Var x) rx2 r)" in exI)
  apply (rule_tac x="diff_use_env (comp_use_env (rem_use_env r_s3 (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_s3 (Var x) rx2 r)" in exI)
  apply (auto)
   apply (case_tac "x \<notin> free_vars e2")
    apply (rule_tac ?r_s1.0="diff_use_env (comp_use_env (rem_use_env r_s2 (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_s3 (Var x) rx2 r)" in well_typed_incr_start_perm)
     apply (rule_tac subst_type_preserve_no_fv)
      apply (rule_tac well_typed_diff_perms)
       apply (rule_tac well_typed_stpx_req)
        apply (rule_tac well_typed_comp_perms)
         apply (cut_tac r_s="r_s2" and x="Var x" and r="r" in partial_rem_add_use_env)
         apply (simp)
         apply (rule_tac well_typed_rem_perms)
          apply (rule_tac x="x" and t="t" in well_typed_add_vars_rev)
            apply (rule_tac ?r_s1.0="add_use_env r_s2 (Var x) (r_s2 (Var x))" in well_typed_incr_start_perm)
             apply (cut_tac r_s="r_s2" and x="Var x" in self_add_use_env)
             apply (simp_all)
        apply (rule_tac dist_add_leq_use_env_gen)
         apply (rule_tac id_leq_use_env)
        apply (cut_tac r_x="r_s2" and r_s="add_use_env rx1 (Var x) r" and x="Var x" in spec_leq_perm)
         apply (rule_tac well_typed_perm_leq)
         apply (auto)
         apply (simp add: add_use_env_def)
        apply (simp add: non_prim_vars_def)
        apply (cut_tac x="x" and e="e2" in free_res_vars)
         apply (auto)
       apply (rule_tac r_s="rx1" in disj_leq_use_env1)
        apply (simp)
       apply (rule_tac r="r" in rem_add_leq_use_env)
       apply (rule_tac well_typed_perm_leq)
       apply (auto)
      apply (rule_tac dist_lift_leq_use_env_gen)
      apply (simp)
    (* - prove rx2 is disjoint from the non-prim vars in e2 *)
     apply (simp add: own_env_vars_def)
     apply (simp add: end_neg_use_env_def)
     apply (case_tac "Var x = xa")
      apply (simp add: non_prim_vars_def)
      apply (cut_tac x="x" and e="e2" in free_res_vars)
       apply (auto)
     apply (case_tac "r_s3 (Var x) = NoPerm")
      apply (auto)
      apply (case_tac "r_s2 xa = NoPerm")
       apply (cut_tac env="add_env env (Var x) t" and ?r_s1.0="r_s2" and e="e2" and x="xa" in well_typed_no_npv_use)
         apply (auto)
       apply (simp add: non_prim_vars_def)
       apply (simp add: non_prim_entry_def)
       apply (simp add: add_env_def)
       apply (auto)
      apply (case_tac "rx1 xa = NoPerm")
       apply (cut_tac r_x="r_s2" and r_s="add_use_env rx1 (Var x) r" and x="xa" in leq_use_none)
         apply (rule_tac well_typed_perm_leq)
         apply (simp_all)
       apply (simp add: add_use_env_def)
      apply (simp add: disj_use_env_def)
      apply (auto)
      apply (simp add: mini_disj_use_env_def)
     apply (simp add: empty_use_env_def)
    (* - the rest of the bounds *)
    apply (rule_tac dist_diff_leq_use_env_gen)
     apply (rule_tac id_leq_use_env)
    apply (rule_tac dist_end_neg_leq_use_env)
    apply (rule_tac well_typed_perm_leq)
    apply (auto)
    (* x \<in> fv e2. induction on e2 *)
    (* - we start with the same lemma from the if case stating vars subtracted out by rx2 are primitive. *)
   apply (case_tac "\<not> (non_prim_vars env (subst_exp e2 x e') \<inter> own_env_vars (end_neg_use_env r_s2 (Var x) rx2 r) = {})")
    apply (auto)
    apply (rule_tac xa="xa" and env="env" and ?e1.0="e1" and ?e2.0="e2" and e'="e'" in stpxic_valid_diff)
    apply (auto)
(* - with that in mind we can remove the subtraction from the start permissions *)
   apply (rule_tac t="diff_use_env (comp_use_env (rem_use_env r_s3 (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_s3 (Var x) rx2 r)" and
      s="diff_use_env (diff_use_env (comp_use_env (rem_use_env r_s3 (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_s3 (Var x) rx2 r))
        (end_neg_use_env r_s2 (Var x) rx2 r)" in subst)
    apply (cut_tac r_s="comp_use_env (rem_use_env r_s3 (Var x)) (lift_use_env rx2 r)" and r_x="end_neg_use_env r_s2 (Var x) rx2 r" and
      r_c="end_neg_use_env r_s3 (Var x) rx2 r" in cancel_diff_use_env2)
     apply (rule_tac dist_end_neg_leq_use_env)
     apply (rule_tac well_typed_perm_leq)
     apply (auto)
   apply (rule_tac t="diff_use_env (stpx_req (rem_use_env rx2a (Var x)) (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) (end_neg_use_env r_s3 (Var x) rx2 r)" and
      s="diff_use_env (diff_use_env (stpx_req (rem_use_env rx2a (Var x)) (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) (end_neg_use_env r_s3 (Var x) rx2 r))
        (end_neg_use_env r_s2 (Var x) rx2 r)" in subst)
    apply (cut_tac r_s="stpx_req (rem_use_env rx2a (Var x)) (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))" and r_x="end_neg_use_env r_s2 (Var x) rx2 r" and
      r_c="end_neg_use_env r_s3 (Var x) rx2 r" in cancel_diff_use_env2)
     apply (rule_tac dist_end_neg_leq_use_env)
     apply (rule_tac well_typed_perm_leq)
     apply (auto)
   apply (rule_tac well_typed_diff_perms)
    apply (auto)
    (* - starts with well-typedness statement where rx1 = rem_use_env r_s2 x *)
   apply (case_tac "\<not> well_typed (add_env env (Var x) t) (add_use_env (rem_use_env r_s2 (Var x)) (Var x) (r_s2 (Var x))) e2 t1 r_s3 rx2a")
    apply (cut_tac r_s="r_s2" and x="Var x" and r="r_s2 (Var x)" in cancel_add_rem_use_env)
     apply (simp_all)
   apply (cut_tac env="add_env env (Var x) t" and ?r_s1.0="rem_use_env r_s2 (Var x)" and x="Var x" and r="r_s2 (Var x)" and p="r" in stpa_incr_ind_perm)
     apply (auto)
    apply (cut_tac ?r_s2.0="r_s2" and ?r_s1.0="add_use_env rx1 (Var x) r" and env="add_env env (Var x) t" and e="e1" in well_typed_perm_leq)
     apply (simp_all)
    apply (case_tac "\<not> (\<forall>xa. leq_perm (r_s2 xa) (add_use_env rx1 (Var x) r xa))")
     apply (simp add: leq_use_env_def)
     apply (auto)
    apply (erule_tac x="Var x" in allE)
    apply (simp add: add_use_env_def)
   apply (case_tac "\<not> lam_vars e2 \<inter> free_vars e' = {}")
    apply (auto)
   apply (case_tac "\<not> rem_use_env r_s2 (Var x) (Var x) = NoPerm")
    apply (simp add: rem_use_env_def)
   apply (cut_tac r="comp_use_env (rem_use_env r_s2 (Var x)) (lift_use_env rx2 r)" in id_leq_use_env)
   apply (case_tac "\<not> disj_use_env (rem_use_env r_s2 (Var x)) (lift_use_env rx2 r)")
    apply (cut_tac r_x="rem_use_env r_s2 (Var x)" and r_s="rx1" and r_ex="lift_use_env rx2 r" in disj_leq_use_env1)
      apply (simp)
     apply (rule_tac r="r" in rem_add_leq_use_env)
     apply (rule_tac well_typed_perm_leq)
     apply (auto)
    (* - final manipulation *)
  apply (rule_tac x="comp_use_env (norm_use_env (rem_use_env r_ex (Var x)) rx1) (end_neg_use_env r_se (Var x) rx2 r)" in exI)
  apply (auto)
    (* - put the lhs into a form where comp can be eliminated *)
        apply (rule_tac lhs_dist_dcl_use_env)
    (* - transformations useful for the entire inequality *)
    (* - proving the inequality for r_se, starting with canonicalizing rhs *)
        apply (rule_tac dist_comp_leq_use_env)
         apply (rule_tac rhs_fold_dcl_use_env)
    (* - create a target in-between for utilizing the r_se \<le> r_s3 inequality *)
         apply (rule_tac r_sb="diff_use_env (diff_use_env (rem_use_env r_s3 (Var x)) (comp_use_env
          (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex)) (end_neg_use_env r_se (Var x) rx2 r)" in trans_leq_use_env)
          apply (rule_tac lhs_fold_dcl_use_env)
    (* - creating an in-between splitting the set into parts that can be subsumed by the original
        and parts that are disjoint *)
          apply (rule_tac r_sb="diff_use_env (diff_use_env (rem_use_env r_s3 (Var x))
            (comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) (comp_use_env (norm_use_env (rem_use_env r_ex (Var x)) rx1) (end_neg_use_env r_se (Var x) rx2 r))))
            (comp_use_env (stpx_ex (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x))) (lift_use_env (stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) ra))" in trans_leq_use_env)
    (* - prove that this step is valid *)
           apply (rule_tac lhs_fold_dcl_use_env)
           apply (rule_tac dist_diff_leq_use_env_gen)
            apply (rule_tac self_comp_leq_use_env1)
           apply (rule_tac dist_comp_leq_use_env)
            apply (rule_tac comp_leq_use_env1)
            apply (rule_tac comp_leq_use_env2)
            apply (rule_tac comp_leq_use_env2)
            apply (rule_tac dist_end_neg_leq_use_env)
            apply (rule_tac r_sb="diff_use_env r_s3 (comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex)" in trans_leq_use_env)
             apply (rule_tac self_diff_leq_use_env)
            apply (simp)
           apply (rule_tac dist_comp_leq_use_env)
            apply (rule_tac dist_comp_leq_use_env)
             apply (rule_tac diff_leq_use_env)
             apply (rule_tac stpx_req_leq_use_env3)
             apply (rule_tac dist_comp_leq_use_env)
              apply (rule_tac comp_leq_use_env1)
              apply (rule_tac comp_leq_use_env1)
              apply (rule_tac comp_leq_use_env1)
              apply (rule_tac self_rem_leq_use_env)
             apply (rule_tac comp_leq_use_env2)
             apply (rule_tac self_comp_leq_use_env1)
            apply (rule_tac r_sb="lift_use_env (comp_use_env (rem_use_env rx2a (Var x)) (stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x)))) ra" in trans_leq_use_env)
             apply (cut_tac r_s="rem_use_env rx2a (Var x)" and r_x="stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))" and r="ra" in lift_comp_use_env)
             apply (simp)
             apply (rule_tac dist_comp_leq_use_env)
              apply (rule_tac comp_leq_use_env1)
              apply (rule_tac comp_leq_use_env1)
              apply (rule_tac comp_leq_use_env2)
              apply (rule_tac dist_lift_leq_use_env)
              apply (rule_tac self_rem_leq_use_env)
             apply (rule_tac comp_leq_use_env2)
             apply (rule_tac self_comp_leq_use_env2)
            apply (rule_tac dist_lift_leq_use_env)
            apply (rule_tac diff_leq_use_env)
            apply (rule_tac stpx_req_leq_use_env3)
            apply (rule_tac id_leq_use_env)
           apply (rule_tac comp_leq_use_env1)
           apply (rule_tac self_comp_leq_use_env2)
    (* - remove disjoint subtractant *)
          apply (rule_tac disj_diff_leq_use_env)
           apply (rule_tac comm_disj_use_env)
           apply (rule_tac r_s="rx1" in disj_leq_use_env1)
            apply (rule_tac r_s="lift_use_env rx2 r" in disj_leq_use_env2)
             apply (simp)
            apply (rule_tac dist_comp_leq_use_env)
             apply (rule_tac stpx_ex_leq_use_env)
             apply (rule_tac dist_lift_leq_use_env_gen)
             apply (auto)
    (* / if rx2a x = None, the lhs is empty *)
            apply (case_tac "rx2a (Var x) = NoPerm")
             apply (simp add: stpx_ex_def)
             apply (simp add: lift_empty_use_env)
             apply (rule_tac leq_empty_use_env)
    (* / if ra \<le> r, (which it is by prelim) then we can remove the lift *)
            apply (case_tac "leq_perm ra r")
             apply (rule_tac lhs_lift_leq_use_env_gen)
              apply (rule_tac stpx_ex_leq_use_env)
              apply (rule_tac dist_lift_leq_use_env_gen)
              apply (simp_all)
            apply (simp add: stpxac_lift_res_def)
           apply (rule_tac diff_leq_use_env)
           apply (rule_tac rem_add_leq_use_env)
           apply (simp)
    (* - prove that the in-between set subtracted subsumes the original set *)
          apply (rule_tac dist_diff_leq_use_env_gen)
           apply (rule_tac id_leq_use_env)
          apply (rule_tac dist_comp_leq_use_env)
           apply (rule_tac comp_leq_use_env1)
           apply (rule_tac self_comp_leq_use_env1)
          apply (rule_tac dist_comp_leq_use_env)
           apply (rule_tac comp_leq_use_env1)
           apply (rule_tac comp_leq_use_env2)
           apply (rule_tac norm_leq_use_env)
           apply (rule_tac self_rem_leq_use_env)
          apply (rule_tac self_comp_leq_use_env2)
    (* - use r_se \<le> r_s3 identity *)
         apply (rule_tac dist_diff_leq_use_env)
         apply (case_tac "\<not> diff_use_env (rem_use_env r_s3 (Var x)) (comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex) =
          rem_use_env (diff_use_env r_s3 (comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex)) (Var x)")
          apply (cut_tac r_s="r_s3" and r_x="comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex" and x="Var x" in comm_diff_rem_use_env)
          apply (auto)
         apply (rule_tac dist_rem_leq_use_env)
         apply (simp)
    (* - proving the inequality for rx2, creating an in-between splitting the set into parts that can be subsumed by the original
        and parts that are disjoint, being extremely careful to preserve certain properties of rx2 *)
        apply (rule_tac r_sb="diff_use_env (lift_use_env rx2 r)
          (comp_use_env (comp_use_env (end_neg_use_env r_se (Var x) rx2 r) (comp_use_env
            (diff_use_env (stpx_ex (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x))) (end_neg_use_env r_s2 (Var x) rx2 r))
            (diff_use_env (lift_use_env (stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) ra) (end_neg_use_env r_s3 (Var x) rx2 r))))
          (comp_use_env (rem_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) (Var x)) (norm_use_env (rem_use_env r_ex (Var x)) rx1)))" in trans_leq_use_env)
         apply (rule_tac rhs_fold_dcl_use_env)
    (* - prove that the subtracting set subsumes the original *)
         apply (rule_tac dist_diff_leq_use_env_gen)
          apply (rule_tac self_comp_leq_use_env2)
         apply (rule_tac dist_comp_leq_use_env)
          apply (rule_tac comp_leq_use_env1)
          apply (rule_tac comp_leq_use_env1)
          apply (rule_tac dist_end_neg_leq_use_env)
          apply (rule_tac r_sb="diff_use_env r_s3 (comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex)" in trans_leq_use_env)
           apply (rule_tac self_diff_leq_use_env)
          apply (simp)
         apply (rule_tac dist_comp_leq_use_env)
          apply (rule_tac dist_comp_leq_use_env)
           apply (rule_tac r_sb="diff_use_env (comp_use_env (rem_use_env rx1a (Var x)) (stpx_ex (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x)))) (end_neg_use_env r_s2 (Var x) rx2 r)" in trans_leq_use_env)
            apply (rule_tac lhs_dist_dcl_use_env)
            apply (rule_tac dist_comp_leq_use_env)
             apply (rule_tac diff_leq_use_env)
             apply (rule_tac comp_leq_use_env2)
             apply (rule_tac comp_leq_use_env1)
             apply (rule_tac dist_rem_leq_use_env)
             apply (rule_tac self_comp_leq_use_env1)
            apply (rule_tac comp_leq_use_env1)
            apply (rule_tac comp_leq_use_env2)
            apply (rule_tac self_comp_leq_use_env1)
           apply (rule_tac dist_diff_leq_use_env)
           apply (rule_tac stpx_req_leq_use_env3)
           apply (rule_tac id_leq_use_env)
          apply (rule_tac r_sb="lift_use_env (diff_use_env (comp_use_env (rem_use_env rx2a (Var x)) (stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x)))) (end_neg_use_env r_s3 (Var x) rx2 r)) ra" in trans_leq_use_env)
           apply (rule_tac t="diff_use_env (comp_use_env (rem_use_env rx2a (Var x)) (stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x)))) (end_neg_use_env r_s3 (Var x) rx2 r)" and
            s="comp_use_env (diff_use_env (rem_use_env rx2a (Var x)) (end_neg_use_env r_s3 (Var x) rx2 r)) (diff_use_env (stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) (end_neg_use_env r_s3 (Var x) rx2 r))" in subst)
            apply (rule_tac dist_diff_comp_use_env)
           apply (cut_tac r_s="diff_use_env (rem_use_env rx2a (Var x)) (end_neg_use_env r_s3 (Var x) rx2 r)" and r_x="diff_use_env (stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) (end_neg_use_env r_s3 (Var x) rx2 r)" and r="ra" in lift_comp_use_env)
           apply (simp)
           apply (rule_tac dist_comp_leq_use_env)
            apply (rule_tac comp_leq_use_env2)
            apply (rule_tac comp_leq_use_env1)
            apply (rule_tac r_sb="rem_use_env (lift_use_env rx2a ra) (Var x)" in trans_leq_use_env)
             apply (rule_tac dist_rem_leq_use_env)
             apply (rule_tac self_comp_leq_use_env2)
            apply (rule_tac t="rem_use_env (lift_use_env rx2a ra) (Var x)" and s="lift_use_env (rem_use_env rx2a (Var x)) ra" in subst)
             apply (rule_tac lift_rem_use_env)
            apply (rule_tac dist_lift_leq_use_env)
            apply (rule_tac self_diff_leq_use_env)
           apply (rule_tac comp_leq_use_env1)
           apply (rule_tac comp_leq_use_env2)
           apply (rule_tac comp_leq_use_env2)
           apply (rule_tac t="diff_use_env (lift_use_env (stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) ra) (end_neg_use_env r_s3 (Var x) rx2 r)" and
             s="lift_use_env (diff_use_env (stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) (end_neg_use_env r_s3 (Var x) rx2 r)) ra" in subst)
            apply (rule_tac outer_lift_diff_use_env)
           apply (rule_tac id_leq_use_env)
          apply (rule_tac dist_lift_leq_use_env)
          apply (rule_tac dist_diff_leq_use_env)
          apply (rule_tac stpx_req_leq_use_env3)
          apply (rule_tac id_leq_use_env)
         apply (rule_tac dist_comp_leq_use_env)
          apply (rule_tac comp_leq_use_env2)
          apply (rule_tac self_comp_leq_use_env2)
         apply (rule_tac comp_leq_use_env1)
         apply (rule_tac self_comp_leq_use_env1)
    (* - prove the disjointness of the second term to annihilate it *)
        apply (rule_tac rhs_unroll_dcl_use_env)
        apply (rule_tac disj_diff_leq_use_env)
         apply (rule_tac r_s="lift_use_env rx2 r" in disj_leq_use_env2)
          apply (rule_tac r_s="rx1" in disj_leq_use_env1)
           apply (simp)
          apply (rule_tac dist_comp_leq_use_env)
           apply (rule_tac r="r" in rem_add_leq_use_env)
           apply (rule_tac r_sb="r_s3" in trans_leq_use_env)
            apply (simp_all)
          apply (rule_tac norm_leq_use_env)
          apply (rule_tac rem_add_leq_use_env)
          apply (simp_all)
         apply (rule_tac self_diff_leq_use_env)
    (* - lastly we have to get rid of the actual subtractants. rx2 presents a number of challenges. *)
        apply (rule_tac prec_diff_leq_use_env)
         apply (rule_tac id_leq_use_env)
        apply (rule_tac prec_diff_leq_use_env)
    (* - if r = Use / r = None, then this inequality is trivial because rx2 is weak. *)
         apply (case_tac "\<not> is_own r")
          apply (case_tac r)
           apply (auto)
           apply (rule_tac rhs_weak_leq_use_env)
            apply (rule_tac weak_diff_use_env)
            apply (simp add: stpx_ex_def)
            apply (auto)
             apply (simp add: weak_use_env_def)
             apply (simp add: empty_use_env_def)
            apply (case_tac "rx1a (Var x)")
              apply (simp_all)
           apply (rule_tac self_diff_leq_use_env)
          apply (rule_tac rhs_weak_leq_use_env)
           apply (rule_tac weak_diff_use_env)
           apply (simp add: stpx_ex_def)
            apply (auto)
             apply (simp add: weak_use_env_def)
             apply (simp add: empty_use_env_def)
            apply (rule_tac drop_weak_use_env)
           apply (case_tac "rx1a (Var x)")
             apply (simp_all)
          apply (rule_tac self_diff_leq_use_env)
         apply (simp add: is_own_def)
    (* - if r_se x = None, then rx2 will annihilate itself *)
         apply (case_tac "r_se (Var x) = NoPerm")
          apply (case_tac "end_neg_use_env r_se (Var x) rx2 r \<noteq> lift_use_env rx2 r")
           apply (simp add: end_neg_use_env_def)
          apply (simp)
          apply (cut_tac r_s="rx2" and q="r" and r="r" in ann_lift_use_env)
           apply (simp add: is_own_def)
          apply (simp)
          apply (rule_tac leq_empty_use_env)
    (* - if r_se x \<noteq> None, rx1a x \<noteq> Own *)
         apply (case_tac "rx1a (Var x) = OwnPerm")
          apply (case_tac "\<not> comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex (Var x) = OwnPerm")
           apply (simp add: comp_use_env_def)
          apply (simp)
          apply (cut_tac r_x="r_se" and r_s="diff_use_env r_s3 (comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex)" and x="Var x" in leq_use_none)
            apply (simp)
           apply (rule_tac diff_use_none_ex)
           apply (simp_all)
    (* - based on this we claim the subtractant is weak *)
         apply (rule_tac rhs_weak_leq_use_env)
          apply (rule_tac weak_diff_use_env)
          apply (simp add: stpx_ex_def)
          apply (auto)
            apply (simp add: weak_use_env_def)
            apply (simp add: empty_use_env_def)
           apply (rule_tac drop_weak_use_env)
          apply (case_tac "rx1a (Var x)")
            apply (simp_all)
         apply (rule_tac self_diff_leq_use_env)
    (* - say that rx2a x = None, we claim then that the subtractant is weak *)
        apply (case_tac "rx2a (Var x)")
          apply (simp_all)
          apply (simp add: stpx_ex_def)
          apply (rule_tac rhs_weak_leq_use_env)
           apply (rule_tac weak_diff_use_env)
           apply (rule_tac weak_lift_empty_use_env)
         apply (rule_tac self_diff_leq_use_env)
    (* - otherwise say that rx2a x = Use. say that r = Use. then ra \<noteq> Own, because lift rx2a ra x \<le> (rx + x: r) x *)
         apply (case_tac "r = UsePerm")
          apply (case_tac "is_own ra")
           apply (cut_tac r_x="lift_use_env rx2a ra" and r_s="add_use_env rx1 (Var x) r" and x="Var x" in spec_leq_perm)
            apply (rule_tac r_sb="comp_use_env rx1a (lift_use_env rx2a ra)" in trans_leq_use_env)
             apply (rule_tac r_sb="r_s3" in trans_leq_use_env)
              apply (simp_all)
            apply (rule_tac self_comp_leq_use_env2)
          apply (simp add: add_use_env_def)
          apply (simp add: is_own_def)
    (* - then we can again show the subtractant is weak *)
          apply (rule_tac rhs_weak_leq_use_env)
           apply (rule_tac weak_diff_use_env)
          apply (simp add: stpx_ex_def)
          apply (simp add: is_own_def)
          apply (case_tac ra)
            apply (auto)
           apply (rule_tac drop_weak_use_env)
          apply (rule_tac drop_weak_use_env)
         apply (rule_tac self_diff_leq_use_env)
    (* - if r_se x = None, then all of rx2 will be subtracted out *)
         apply (case_tac "r_se (Var x) = NoPerm")
          apply (case_tac "end_neg_use_env r_se (Var x) rx2 r \<noteq> lift_use_env rx2 r")
           apply (simp add: end_neg_use_env_def)
          apply (simp)
          apply (cut_tac r_s="rx2" and q="r" and r="r" in ann_lift_use_env)
           apply (case_tac r)
             apply (simp_all)
          apply (rule_tac leq_empty_use_env)
    (* - if r_se x \<noteq> None, then we once again show that ra \<noteq> Own, since r_se \<le> r_s3 - (lift rx2 ra) *)
         apply (case_tac "ra = OwnPerm")
          apply (cut_tac r_x="r_se" and r_s="diff_use_env r_s3 (lift_use_env rx2a ra)" and x="Var x" in spec_leq_perm)
           apply (rule_tac r_sb="diff_use_env r_s3 (comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex)" in trans_leq_use_env)
            apply (rule_tac dist_diff_leq_use_env_gen)
             apply (rule_tac id_leq_use_env)
            apply (rule_tac comp_leq_use_env1)
            apply (rule_tac self_comp_leq_use_env2)
           apply (simp)
          apply (case_tac "is_own (lift_use_env rx2a ra (Var x))")
           apply (cut_tac r_s="r_s3" and r_ex="lift_use_env rx2a ra" and x="Var x" in diff_use_none_ex)
            apply (simp add: is_own_def)
           apply (simp)
           apply (case_tac "r_se (Var x)")
             apply (simp_all)
          apply (simp add: is_own_def)
    (* - with that in mind, we can again show that the subtractant is weak *)
         apply (case_tac ra)
           apply (auto)
         apply (rule_tac rhs_weak_leq_use_env)
          apply (rule_tac weak_diff_use_env)
          apply (simp add: stpx_ex_def)
          apply (rule_tac drop_weak_use_env)
         apply (rule_tac self_diff_leq_use_env)
        apply (rule_tac rhs_weak_leq_use_env)
         apply (rule_tac weak_diff_use_env)
         apply (simp add: stpx_ex_def)
         apply (rule_tac drop_weak_use_env)
        apply (rule_tac self_diff_leq_use_env)
    (* - lastly we show that if rx2a x = OwnPerm, r_se x = None *)
        apply (case_tac "\<not> r_se (Var x) = NoPerm")
         apply (cut_tac r_s="r_s3" and r_ex="comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex" and x="Var x" in diff_use_none_ex)
          apply (simp add: comp_use_env_def)
          apply (case_tac ra)
            apply (auto)
           apply (case_tac "rx1a (Var x)")
             apply (auto)
          apply (case_tac "rx1a (Var x)")
            apply (auto)
         apply (case_tac "rx1a (Var x)")
           apply (auto)
        apply (cut_tac r_x="r_se" and r_s="diff_use_env r_s3 (comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex)" and x="Var x" in leq_use_none)
          apply (simp_all)
    (* - with that we can show the rx2 completely subtracts itself out *)
        apply (case_tac "\<not> end_neg_use_env r_se (Var x) rx2 r = lift_use_env rx2 r")
         apply (simp add: end_neg_use_env_def)
        apply (auto)
        apply (cut_tac r_s="rx2" and q="r" and r="r" in ann_lift_use_env)
         apply (case_tac r)
           apply (auto)
        apply (rule_tac leq_empty_use_env)
    (* lift safety *)(*
       apply (rule_tac safe_lift_diff_use_env)
       apply (rule_tac r_s="comp_use_env (rem_use_env rx2a x) (stpx_ex (lift_use_env rx2 (rx2a x)) (rx2a x))" in safe_lift_leq_use_env)
        apply (rule_tac stpx_req_leq_use_env3)
        apply (rule_tac id_leq_use_env)
       apply (rule_tac safe_lift_comp_use_env)
        apply (rule_tac r_s="rx2a" in safe_lift_leq_use_env)
         apply (rule_tac self_rem_leq_use_env)
        apply (simp)
       apply (case_tac ra)
         apply (auto)
       apply (simp add: stpx_ex_def)
       apply (case_tac "rx2a x")
         apply (auto)
        apply (simp add: empty_use_env_def)
       apply (simp add: drop_use_env_def)
       apply (case_tac "rx2 xa")
         apply (auto)*)
    (* subtractibility bounds p1 *)
      apply (rule_tac dist_comp_leq_use_env)
       apply (rule_tac diff_leq_use_env)
       apply (rule_tac disj_diff_leq_use_env)
        apply (case_tac "r_s3 (Var x) = NoPerm")
         apply (simp add: end_neg_use_env_def)
         apply (case_tac "rx1a (Var x) \<noteq> NoPerm")
          apply (cut_tac r_x="rx1a" and r_s="r_s3" and x="Var x" in spec_leq_perm)
           apply (rule_tac r_sb="comp_use_env rx1a (lift_use_env rx2a ra)" in trans_leq_use_env)
            apply (simp)
           apply (rule_tac self_comp_leq_use_env1)
          apply (case_tac "rx1a (Var x)")
            apply (auto)
         apply (simp add: stpx_req_def)
         apply (rule_tac comm_disj_use_env)
         apply (rule_tac r_s="rx1" in disj_leq_use_env1)
          apply (simp)
         apply (rule_tac r="r" in rem_add_leq_use_env)
         apply (rule_tac r_sb="comp_use_env rx1a (lift_use_env rx2a ra)" in trans_leq_use_env)
          apply (rule_tac r_sb="r_s3" in trans_leq_use_env)
           apply (simp_all)
         apply (rule_tac self_comp_leq_use_env1)
        apply (simp add: end_neg_use_env_def)
        apply (rule_tac disj_empty_use_env2)
       apply (rule_tac stpx_req_leq_use_env)
       apply (rule_tac dist_comp_leq_use_env)
        apply (rule_tac comp_leq_use_env1)
        apply (rule_tac dist_rem_leq_use_env)
        apply (rule_tac r_sb="comp_use_env rx1a (lift_use_env rx2a ra)" in trans_leq_use_env)
         apply (simp)
        apply (rule_tac self_comp_leq_use_env1)
       apply (rule_tac comp_leq_use_env2)
       apply (rule_tac dist_lift_leq_use_env_gen)
       apply (simp)
    (* - part 2 *)
      apply (cut_tac r_s="stpx_req (rem_use_env rx2a (Var x)) (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))" and r_x="end_neg_use_env r_s3 (Var x) rx2 r" and r="ra" in outer_lift_diff_use_env)
      apply (simp)
      apply (rule_tac dist_diff_leq_use_env)
    (* - prove the lhs, which is necessary for both cases *)
      apply (case_tac "\<not> leq_use_env (lift_use_env (rem_use_env rx2a (Var x)) ra) (rem_use_env r_s3 (Var x))")
       apply (cut_tac r_s="rx2a" and x="Var x" and r="ra" in lift_rem_use_env)
       apply (simp)
       apply (cut_tac r_x="lift_use_env rx2a ra" and r_s="r_s3" and x="Var x" in dist_rem_leq_use_env)
        apply (rule_tac r_sb="comp_use_env rx1a (lift_use_env rx2a ra)" in trans_leq_use_env)
         apply (simp)
        apply (rule_tac self_comp_leq_use_env2)
       apply (rule_tac comp_leq_use_env2)
       apply (simp)
    (* - if rx2a x = None this case is easy *)
      apply (case_tac "rx2a (Var x) = NoPerm")
       apply (simp add: stpx_req_def)
       apply (rule_tac comp_leq_use_env1)
       apply (simp)
    (* - otherwise, conservatively assume lift rx2 is used *)
      apply (rule_tac r_sb="lift_use_env (comp_use_env (rem_use_env rx2a (Var x)) (lift_use_env rx2 (rx2a (Var x)))) ra" in trans_leq_use_env)
       apply (cut_tac r_s="rem_use_env rx2a (Var x)" and r_x="lift_use_env rx2 (rx2a (Var x))" and r="ra" in lift_comp_use_env)
       apply (simp)
       apply (rule_tac dist_comp_leq_use_env)
        apply (rule_tac comp_leq_use_env1)
        apply (simp)
    (* we know (lift rx2a ra x) is subtractible from r_s3
      which means r = OwnPerm unless both ra + x are use.
      therefore we expect (lift (lift rx2 ..) ra) to be
      subtractible from (lift rx2 r) *)
       apply (case_tac "\<not> is_own r")
        apply (simp add: is_own_def)
        apply (case_tac "\<not> lift_use_env rx2 (rx2a (Var x)) = rx2")
         apply (case_tac "rx2a (Var x)")
           apply (auto)
         apply (case_tac r)
           apply (auto)
        apply (cut_tac r_x="lift_use_env rx2a ra" and r_s="add_use_env rx1 (Var x) r" and x="Var x" in spec_leq_perm)
         apply (rule_tac r_sb="comp_use_env rx1a (lift_use_env rx2a ra)" in trans_leq_use_env)
          apply (rule_tac r_sb="r_s3" in trans_leq_use_env)
           apply (simp_all)
         apply (rule_tac self_comp_leq_use_env2)
        apply (simp add: add_use_env_def)
        apply (case_tac "ra = OwnPerm")
         apply (case_tac "rx2a (Var x)")
           apply (simp_all)
          apply (case_tac r)
            apply (simp_all)
        apply (case_tac "ra")
           apply (simp_all)
         apply (rule_tac comp_leq_use_env2)
         apply (rule_tac self_lift_leq_use_env)
        apply (case_tac "lift_use_env rx2 ra \<noteq> rx2")
         apply (case_tac "ra")
           apply (simp_all)
        apply (rule_tac comp_leq_use_env2)
        apply (rule_tac self_lift_leq_use_env)
    (* - if r is not Own, then rx2 is maximally lifted *)(*
       apply (case_tac "\<not> is_own r")
        apply (simp add: is_own_def)
        apply (case_tac r)
          apply (simp_all)
        apply (rule_tac comp_leq_use_env2)
        apply (case_tac "rx2a x")
          apply (auto)*)
       apply (rule_tac comp_leq_use_env2)
       apply (rule_tac lhs_lift_leq_use_env)
        apply (rule_tac lhs_lift_leq_use_env)
         apply (rule_tac self_lift_leq_use_env)
        apply (simp_all)
      apply (rule_tac dist_lift_leq_use_env)
      apply (rule_tac stpx_req_leq_use_env)
      apply (rule_tac id_leq_use_env)
    (* disjoint-ness *)
     apply (rule_tac r_s="comp_use_env (rem_use_env rx1a (Var x)) (stpx_ex (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x)))" in disj_leq_use_env1)
      apply (rule_tac disj_comp_use_env1)
       apply (rule_tac r_s="comp_use_env (lift_use_env rx2a ra) (lift_use_env (stpx_ex (lift_use_env rx2 r) (rx2a (Var x))) ra)" in disj_leq_use_env2)
        apply (rule_tac disj_comp_use_env2)
         apply (rule_tac disj_rem_use_envx)
         apply (simp)
        apply (case_tac "rx2a (Var x) = NoPerm")
         apply (simp add: stpx_ex_def)
         apply (simp add: lift_empty_use_env)
         apply (rule_tac disj_empty_use_env1)
        apply (rule_tac r_s="lift_use_env rx2 r" in disj_leq_use_env2)
         apply (rule_tac r_s="rx1" in disj_leq_use_env1)
          apply (simp)
         apply (rule_tac r="r" in rem_add_leq_use_env)
         apply (rule_tac r_sb="comp_use_env rx1a (lift_use_env rx2a ra)" in trans_leq_use_env)
          apply (rule_tac r_sb="r_s3" in trans_leq_use_env)
           apply (simp_all)
         apply (rule_tac self_comp_leq_use_env1)
        apply (rule_tac r_sb="lift_use_env (lift_use_env rx2 r) ra" in trans_leq_use_env)
         apply (rule_tac lhs_lift_leq_use_env_gen)
          apply (rule_tac id_leq_use_env)
         apply (simp add: stpxac_lift_res_def)
        apply (rule_tac dist_lift_leq_use_env)
        apply (rule_tac stpx_ex_leq_use_env)
        apply (rule_tac id_leq_use_env)
       apply (rule_tac t="comp_use_env (lift_use_env rx2a ra) (lift_use_env (stpx_ex (lift_use_env rx2 r) (rx2a (Var x))) ra)" and
          s="lift_use_env (comp_use_env rx2a (stpx_ex (lift_use_env rx2 r) (rx2a (Var x)))) ra" in subst)
        apply (rule_tac lift_comp_use_env)
       apply (rule_tac dist_lift_leq_use_env)
       apply (rule_tac diff_leq_use_env)
       apply (rule_tac stpx_req_leq_use_env3)
       apply (rule_tac dist_comp_leq_use_env)
        apply (rule_tac comp_leq_use_env1)
        apply (rule_tac self_rem_leq_use_env)
       apply (rule_tac comp_leq_use_env2)
       apply (rule_tac dist_stpx_ex_leq_use_env2)
       apply (rule_tac dist_lift_leq_use_env_gen)
       apply (simp)
      apply (rule_tac r_s="comp_use_env (lift_use_env (rem_use_env rx2a (Var x)) ra) (lift_use_env (stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) ra)" in disj_leq_use_env2)
       apply (rule_tac disj_comp_use_env2)
        apply (rule_tac comm_disj_use_env)
        apply (rule_tac r_s="rx1" in disj_leq_use_env1)
         apply (rule_tac r_s="lift_use_env rx2 r" in disj_leq_use_env2)
          apply (simp)
         apply (rule_tac stpx_ex_leq_use_env)
         apply (rule_tac dist_lift_leq_use_env_gen)
         apply (simp)
        apply (cut_tac r_s="rx2a" and x="Var x" and r="ra" in lift_rem_use_env)
        apply (simp)
        apply (rule_tac r="r" in rem_add_leq_use_env)
        apply (rule_tac r_sb="comp_use_env rx1a (lift_use_env rx2a ra)" in trans_leq_use_env)
         apply (rule_tac r_sb="r_s3" in trans_leq_use_env)
          apply (simp_all)
        apply (rule_tac self_comp_leq_use_env2)
       apply (case_tac "is_own ra")
        apply (case_tac "rx2a (Var x) \<noteq> NoPerm")
         apply (case_tac "rx1a (Var x) \<noteq> NoPerm")
          apply (case_tac "\<not> mini_disj_use_env (lift_use_env rx2a ra) rx1a")
           apply (simp add: disj_use_env_def)
          apply (simp add: mini_disj_use_env_def)
          apply (simp add: is_own_def)
         apply (case_tac "\<not> stpx_ex (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x)) = empty_use_env")
          apply (simp add: stpx_ex_def)
         apply (simp_all)
         apply (rule_tac disj_empty_use_env2)
        apply (case_tac "\<not> stpx_ex rx2 NoPerm = empty_use_env")
         apply (simp add: stpx_ex_def)
        apply (simp add: lift_empty_use_env)
        apply (rule_tac disj_empty_use_env1)
       apply (simp add: is_own_def)
       apply (case_tac "\<not> lift_use_env (stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) ra = stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))")
        apply (case_tac ra)
          apply (simp_all)
       apply (rule_tac r_xa="rx1a" and r_xb="rx2a" and x="Var x" in stpx_ex_disj_use_env)
       apply (rule_tac r_s="lift_use_env rx2a ra" in disj_leq_use_env2)
        apply (simp)
       apply (rule_tac self_lift_leq_use_env)
      apply (rule_tac t="comp_use_env (lift_use_env (rem_use_env rx2a (Var x)) ra) (lift_use_env (stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) ra)" and
        s="lift_use_env (comp_use_env (rem_use_env rx2a (Var x)) (stpx_ex (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x)))) ra" in subst)
       apply (rule_tac lift_comp_use_env)
      apply (rule_tac dist_lift_leq_use_env)
      apply (rule_tac diff_leq_use_env)
      apply (rule_tac stpx_req_leq_use_env3)
      apply (rule_tac id_leq_use_env)
     apply (rule_tac diff_leq_use_env)
     apply (rule_tac stpx_req_leq_use_env3)
     apply (rule_tac id_leq_use_env)
    (* relative bound *)
    apply (rule_tac dist_diff_leq_use_env)
    apply (rule_tac stpx_req_leq_use_env)
    apply (rule_tac dist_comp_leq_use_env)
     apply (rule_tac comp_leq_use_env1)
     apply (rule_tac dist_rem_leq_use_env)
     apply (simp)
    apply (rule_tac comp_leq_use_env2)
    apply (rule_tac dist_lift_leq_use_env_gen)
    apply (cut_tac r_x="r_xe" and r_s="add_use_env rx1 (Var x) r" and x="Var x" in spec_leq_perm)
     apply (rule_tac r_sb="diff_use_env r_s3 (comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex)" in trans_leq_use_env)
      apply (rule_tac diff_leq_use_env)
      apply (simp)
     apply (rule_tac r_sb="r_se" in trans_leq_use_env)
      apply (simp_all)
    apply (simp add: add_use_env_def)
    (* valid subtracter *)
   apply (rule_tac dist_comp_leq_use_env)
    apply (rule_tac r_sb="comp_use_env rx1 (lift_use_env rx2 r)" in trans_leq_use_env)
     apply (simp)
    apply (rule_tac comp_leq_use_env1)
    apply (rule_tac norm_leq_use_env)
    apply (rule_tac r="r" in rem_add_leq_use_env)
    apply (simp)
   apply (rule_tac r_sb="comp_use_env rx1 (lift_use_env rx2 r)" in trans_leq_use_env)
    apply (simp)
   apply (rule_tac comp_leq_use_env2)
   apply (simp add: end_neg_use_env_def)
   apply (auto)
    apply (rule_tac id_leq_use_env)
   apply (rule_tac leq_empty_use_env)
    (* - prelim: common inequality *)
  apply (cut_tac r_sc="comp_use_env rx1a (lift_use_env rx2a ra)" and r_sb="r_s3" and r_sa="add_use_env rx1 (Var x) r" in trans_leq_use_env)
    apply (auto)
    (* requirements bound *)
  apply (simp add: app_req_def)
  apply (auto)
   apply (rule_tac leq_empty_use_env)
    (* - we start by merging together rx1a + rx2a, since their inequality is proved in the same way
      of special note is the choice of (rx1a + rx2a x) as the marker for whether rx2 exists + r_se as the indicator for when to remove rx2
    *)
  apply (rule_tac r_sb="diff_use_env (diff_use_env (comp_use_env (rem_use_env (comp_use_env rx1a rx2a) (Var x))
     (stpx_ex (lift_use_env rx2 (comp_use_env rx1a rx2a (Var x))) (comp_use_env rx1a rx2a (Var x)))) (end_neg_use_env r_s2 (Var x) rx2 r))
           (comp_use_env
             (comp_use_env (diff_use_env (stpx_req (rem_use_env rx1a (Var x)) (lift_use_env rx2 (rx1a (Var x))) (rx1a (Var x))) (end_neg_use_env r_s2 (Var x) rx2 r))
               (lift_use_env (diff_use_env (stpx_req (rem_use_env rx2a (Var x)) (lift_use_env rx2 (rx2a (Var x))) (rx2a (Var x))) (end_neg_use_env r_s3 (Var x) rx2 r)) ra))
             (comp_use_env (norm_use_env (rem_use_env r_ex (Var x)) rx1) (end_neg_use_env r_se (Var x) rx2 r)))" in trans_leq_use_env)
    (* - we start by canonicalizing *)
   apply (rule_tac lhs_fold_dcl_use_env)
   apply (rule_tac lhs_dist_dcl_use_env)
    (* - restructure rhs stpx_req use to a more convenient form*)
   apply (rule_tac r_sb="diff_use_env (comp_use_env (rem_use_env r_xe (Var x)) (stpx_ex (lift_use_env rx2 (r_xe (Var x))) (r_xe (Var x)))) (end_neg_use_env r_se (Var x) rx2 r)" in trans_leq_use_env)
    apply (rule_tac dist_diff_leq_use_env)
    apply (simp add: stpx_req_def)
    apply (simp add: stpx_ex_def)
    apply (auto)
      apply (rule_tac id_leq_use_env)
     apply (rule_tac dist_comp_leq_use_env)
      apply (rule_tac id_leq_use_env)
     apply (rule_tac leq_empty_use_env)
    apply (rule_tac id_leq_use_env)
    (* - work out the inequality for rx1a + rx2a, re-canonicalizing *)
   apply (rule_tac dist_comp_leq_use_env)
    apply (rule_tac r_sb="diff_use_env (rem_use_env r_xe (Var x)) (end_neg_use_env r_se (Var x) rx2 r)" in trans_leq_use_env)
     apply (rule_tac dist_diff_leq_use_env_gen)
      apply (rule_tac self_comp_leq_use_env1)
    apply (rule_tac id_leq_use_env)
    apply (rule_tac r_sb="diff_use_env (diff_use_env (rem_use_env (comp_use_env rx1a rx2a) (Var x)) (comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) (rem_use_env r_ex (Var x))))
      (end_neg_use_env r_se (Var x) rx2 r)" in trans_leq_use_env)
    apply (rule_tac r_sb="diff_use_env (diff_use_env (rem_use_env (comp_use_env rx1a rx2a) (Var x)) (rem_use_env (comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex) (Var x)))
      (end_neg_use_env r_se (Var x) rx2 r)" in trans_leq_use_env)
      apply (rule_tac t="diff_use_env (rem_use_env (comp_use_env rx1a rx2a) (Var x)) (rem_use_env (comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex) (Var x))" and
      s="rem_use_env (diff_use_env (comp_use_env rx1a rx2a) (comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex)) (Var x)" in subst)
       apply (rule_tac dist_diff_rem_use_env)
      apply (rule_tac dist_diff_leq_use_env)
      apply (rule_tac dist_rem_leq_use_env)
      apply (simp)
     apply (rule_tac dist_diff_leq_use_env)
     apply (rule_tac dist_diff_leq_use_env_gen)
      apply (rule_tac id_leq_use_env)
     apply (cut_tac r_s="comp_use_env rx1a (lift_use_env rx2a ra)" and r_x="r_ex" and x="Var x" in dist_rem_comp_use_env)
     apply (simp)
     apply (rule_tac dist_comp_leq_use_env)
      apply (rule_tac comp_leq_use_env1)
      apply (rule_tac self_rem_leq_use_env)
     apply (rule_tac self_comp_leq_use_env2)
    (* - before we continue, we have to specifically deal with the norm-ed r_ex *)
    apply (rule_tac rhs_fold_dcl_use_env)
    apply (rule_tac rhs_flip_use_env)
    apply (rule_tac unroll_dcl_use_env)
    apply (rule_tac unroll_dcl_use_env)
    apply (rule_tac lhs_flip_use_env)
    apply (rule_tac lhs_unroll_dcl_use_env)
    apply (rule_tac diff_norm_leq_use_env_gen)
     apply (rule_tac diff_leq_use_env)
     apply (rule_tac diff_leq_use_env)
     apply (rule_tac diff_leq_use_env)
     apply (rule_tac r="r" in rem_add_leq_use_env)
     apply (rule_tac r_sb="comp_use_env rx1a (lift_use_env rx2a ra)" in trans_leq_use_env)
      apply (simp_all)
     apply (rule_tac dist_comp_leq_use_env)
      apply (rule_tac self_comp_leq_use_env1)
     apply (rule_tac comp_leq_use_env2)
     apply (rule_tac self_lift_leq_use_env)
    (* we prove that the subtracting set contains the original set *)
    apply (rule_tac fold_dcl_use_env)
    apply (rule_tac lhs_fold_dcl_use_env)
    apply (rule_tac lhs_fold_rem_use_env)
    apply (rule_tac lhs_fold_dcl_use_env)
    apply (rule_tac rhs_fold_rem_use_env)
    apply (rule_tac rhs_fold_dcl_use_env)
    apply (rule_tac dist_diff_leq_use_env_gen)
     apply (rule_tac id_leq_use_env)
    apply (rule_tac dist_comp_leq_use_env)
     apply (rule_tac self_comp_leq_use_env1)
    apply (rule_tac dist_comp_leq_use_env)
     apply (rule_tac comp_leq_use_env2)
     apply (rule_tac comp_leq_use_env2)
     apply (rule_tac self_comp_leq_use_env2)
    apply (rule_tac dist_comp_leq_use_env)
     apply (rule_tac x="Var x" in lhs_rem_leq_use_env)
      apply (rule_tac comp_leq_use_env2)
      apply (rule_tac comp_leq_use_env2)
      apply (rule_tac comp_leq_use_env1)
      apply (rule_tac comp_leq_use_env1)
      apply (rule_tac disj_diff_leq_use_env)
       apply (rule_tac comm_disj_use_env)
       apply (rule_tac r_s="rx1" in disj_leq_use_env1)
        apply (rule_tac r_s="lift_use_env rx2 r" in disj_leq_use_env2)
         apply (simp)
        apply (simp add: end_neg_use_env_def)
        apply (auto)
         apply (rule_tac id_leq_use_env)
        apply (rule_tac leq_empty_use_env)
       apply (rule_tac r="r" in rem_add_leq_use_env)
       apply (rule_tac r_sb="comp_use_env rx1a (lift_use_env rx2a ra)" in trans_leq_use_env)
        apply (simp)
       apply (rule_tac self_comp_leq_use_env1)
      apply (rule_tac stpx_req_leq_use_env2)
      apply (rule_tac id_leq_use_env)
     apply (rule_tac self_comp_leq_use_env1)
    apply (rule_tac x="Var x" in lhs_rem_leq_use_env)
     apply (rule_tac t="rem_use_env (lift_use_env rx2a ra) (Var x)" and s="lift_use_env (rem_use_env rx2a (Var x)) ra" in subst)
      apply (rule_tac lift_rem_use_env)
     apply (rule_tac comp_leq_use_env2)
     apply (rule_tac comp_leq_use_env2)
     apply (rule_tac comp_leq_use_env1)
     apply (rule_tac comp_leq_use_env2)
     apply (rule_tac dist_lift_leq_use_env)
     apply (rule_tac disj_diff_leq_use_env)
      apply (rule_tac comm_disj_use_env)
      apply (rule_tac r_s="rx1" in disj_leq_use_env1)
       apply (rule_tac r_s="lift_use_env rx2 r" in disj_leq_use_env2)
        apply (simp)
       apply (simp add: end_neg_use_env_def)
       apply (auto)
        apply (rule_tac id_leq_use_env)
       apply (rule_tac leq_empty_use_env)
      apply (rule_tac r="r" in rem_add_leq_use_env)
      apply (rule_tac r_sb="comp_use_env rx1a (lift_use_env rx2a ra)" in trans_leq_use_env)
       apply (simp)
      apply (rule_tac comp_leq_use_env2)
      apply (rule_tac self_lift_leq_use_env)
     apply (rule_tac stpx_req_leq_use_env2)
     apply (rule_tac id_leq_use_env)
    apply (rule_tac self_comp_leq_use_env1)
    (* work out the inequality for rx2. we need to use the end_neg subtractant to show that (rx1a + rx2a) x \<le> r_xe x *)
   apply (rule_tac r_sb="diff_use_env (stpx_ex (lift_use_env rx2 (comp_use_env rx1a rx2a (Var x))) (comp_use_env rx1a rx2a (Var x)))
      (end_neg_use_env r_se (Var x) rx2 r)" in trans_leq_use_env)
    apply (rule_tac rhs_dist_dcl_use_env)
    apply (rule_tac comp_leq_use_env2)
    (* if (rx1a + rx2a) x \<le> r_xe x, then we can prove easily *)
    apply (case_tac "leq_perm (comp_use_env rx1a rx2a (Var x)) (r_xe (Var x))")
     apply (rule_tac dist_diff_leq_use_env_gen)
      apply (rule_tac dist_stpx_ex_leq_use_env)
      apply (simp)
     apply (rule_tac id_leq_use_env)
    (* then (rx1a + rx2a) x \<noteq> None trivially *)
    apply (case_tac "comp_use_env rx1a rx2a (Var x) = NoPerm")
     apply (simp)
    (* else, say that r_xe x = None. then global r_ex = Own, which means r = Own. which means we can annihilate *)
    apply (case_tac "r_xe (Var x) = NoPerm")
     apply (case_tac "comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex (Var x) \<noteq> OwnPerm")
      apply (cut_tac r_x="comp_use_env rx1a rx2a" and r_ex="comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex" and r_s="r_xe" and x="Var x" in diff_use_leq)
        apply (simp_all)
     apply (case_tac "\<not> is_own r")
      apply (cut_tac r_x="comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex" and r_s="add_use_env rx1 (Var x) r" and x="Var x" in leq_use_own)
        apply (simp)
       apply (rule_tac dist_comp_leq_use_env)
        apply (simp_all)
      apply (simp add: add_use_env_def)
      apply (simp add: is_own_def)
     apply (case_tac "\<not> end_neg_use_env r_xe (Var x) rx2 r = lift_use_env rx2 r")
      apply (simp add: end_neg_use_env_def)
     apply (simp)
     apply (rule_tac r_sb="diff_use_env (lift_use_env rx2 (comp_use_env rx1a rx2a (Var x))) (lift_use_env rx2 r)" in trans_leq_use_env)
      apply (cut_tac r_s="rx2" and q="comp_use_env rx1a rx2a (Var x)" and r="r" in ann_lift_use_env)
       apply (simp add: is_own_def)
      apply (simp)
      apply (rule_tac leq_empty_use_env)
     apply (cut_tac r_x="r_se" and r_s="diff_use_env r_s3 (comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex)" and x="Var x" in leq_use_none)
       apply (simp)
      apply (rule_tac diff_use_none_ex)
      apply (simp)
     apply (case_tac "\<not> end_neg_use_env r_se (Var x) rx2 r = lift_use_env rx2 r")
      apply (simp add: end_neg_use_env_def)
     apply (simp)
     apply (rule_tac dist_diff_leq_use_env)
     apply (rule_tac stpx_ex_leq_use_env)
     apply (rule_tac id_leq_use_env)
    (* - this eliminates (rx1a + rx2a) x = Use. *)
    apply (case_tac "comp_use_env rx1a rx2a (Var x) = UsePerm")
     apply (case_tac "r_xe (Var x)")
       apply (simp_all)
    (* - (rx1a + rx2a) x = Own means r_se = None which means r_xe = None, a contradiction *)
    apply (cut_tac r_s="r_s3" and r_ex="comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex" and x="Var x" in diff_use_none_ex)
     apply (case_tac "\<not> comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex (Var x) = OwnPerm")
      apply (cut_tac r_x="comp_use_env rx1a rx2a" and r_s="comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex" and x="Var x" in leq_use_own)
        apply (case_tac "comp_use_env rx1a rx2a (Var x)")
          apply (simp_all)
     apply (rule_tac comp_leq_use_env1)
     apply (rule_tac dist_comp_leq_use_env)
      apply (rule_tac self_comp_leq_use_env1)
     apply (rule_tac comp_leq_use_env2)
     apply (rule_tac self_lift_leq_use_env)
    apply (cut_tac r_x="r_xe" and r_s="diff_use_env r_s3 (comp_use_env (comp_use_env rx1a (lift_use_env rx2a ra)) r_ex)" and x="Var x" in leq_use_none)
      apply (rule_tac r_sb="r_se" in trans_leq_use_env)
       apply (simp_all)
   apply (rule_tac dist_diff_leq_use_env_gen)
    apply (rule_tac id_leq_use_env)
   apply (rule_tac comp_leq_use_env2)
   apply (rule_tac comp_leq_use_env2)
   apply (rule_tac self_comp_leq_use_env2)
    (* - prove that the initial merge step was valid *)
  apply (rule_tac dist_diff_leq_use_env_gen)
   apply (rule_tac dist_comp_leq_use_env)
    apply (rule_tac dist_diff_leq_use_env_gen)
     apply (rule_tac stpx_req_leq_use_env3)
     apply (rule_tac dist_comp_leq_use_env)
      apply (rule_tac comp_leq_use_env1)
      apply (rule_tac dist_rem_leq_use_env)
      apply (rule_tac self_comp_leq_use_env1)
     apply (rule_tac comp_leq_use_env2)
     apply (rule_tac dist_stpx_ex_leq_use_env)
     apply (rule_tac x="Var x" in spec_leq_perm)
     apply (rule_tac self_comp_leq_use_env1)
    apply (rule_tac id_leq_use_env)
   apply (rule_tac dist_diff_leq_use_env_gen)
    apply (rule_tac stpx_req_leq_use_env3)
    apply (rule_tac dist_comp_leq_use_env)
     apply (rule_tac comp_leq_use_env1)
     apply (rule_tac dist_rem_leq_use_env)
     apply (rule_tac self_comp_leq_use_env2)
    apply (rule_tac comp_leq_use_env2)
    apply (rule_tac dist_stpx_ex_leq_use_env)
    apply (rule_tac x="Var x" in spec_leq_perm)
    apply (rule_tac self_comp_leq_use_env2)
   apply (rule_tac dist_end_neg_leq_use_env)
   apply (rule_tac well_typed_perm_leq)
   apply (auto)
  apply (rule_tac id_leq_use_env)
  done

    (*
      ####################################
        P6. statement of substitution type preservation
      ####################################
    *)

      (*
      we develop a notion of an "affine" function because otherwise we have no way of determining a
      function that can be freely used v. one restricted by owned values in the closure.

      this gives us a notion of affine vs unlimited substitution type preservation that motivates this lemma.

      the other notable constraint of this lemma is that it requires e' to have the same starting and end
      permissions. through another lemma, we know that any well-typed s-exp can be typed in such a way, so
      this lemma will be completed later by manipulating the permissions to allow for arbitrary ending
      permissions.
    *)

    (*
      - e' is given static permissions. the start and end permissions must be the same to ensure that we know
          substituting it into an expression will not consume any unexpected permissions. the requirements must
          also be the same in order to ensure that it can be substituted even after some permissions have been
          removed.
        -- the idea is that the requirements for e' will still be disjoint from the requirements for e, since
          both requirements were fully contained within the original end permissions, and new permissions come
          from outside the end permissions.
    *)

lemma subst_type_preserve_x: "\<lbrakk> well_typed (add_env env (Var x) t) (add_use_env rx1 (Var x) r) e tau r_se r_xe;
  well_typed env rx2 e' t rx2 rx2; rx1 (Var x) = NoPerm; x \<in> free_vars e; is_sexp e'; (*r \<noteq> NoPerm;*)
  lam_vars e \<inter> free_vars e' = {}; leq_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_s1;
  disj_use_env rx1 (lift_use_env rx2 r) \<rbrakk> \<Longrightarrow>
  well_typed env r_s1 (subst_exp e x e') tau (diff_use_env (comp_use_env (rem_use_env r_se (Var x)) (lift_use_env rx2 r)) (end_neg_use_env r_se (Var x) rx2 r))
    (diff_use_env (stpx_req (rem_use_env r_xe (Var x)) (lift_use_env rx2 (r_xe (Var x))) (r_xe (Var x))) (end_neg_use_env r_se (Var x) rx2 r))"
  apply (induct e arbitrary: env x tau t rx1 r_se r_xe r_s1 rx2 r)
       apply (auto)
    (* var case *)
           apply (rule_tac stpx_var_case)
                      apply (simp_all)
    (* pair cases 1-2. *)
         apply (rule_tac stpx_pair_case)
                      apply (simp_all)
        apply (rule_tac stpx_pair_case)
                      apply (simp_all)
    (* if cases 1-3. *)
       apply (rule_tac stpx_if_case)
                  apply (simp_all)
      apply (rule_tac stpx_if_case)
                 apply (simp_all)
     apply (rule_tac stpx_if_case)
                apply (simp_all)
    (* lambda case. *)(*
     apply (cut_tac y="x1a" and e="e" and x="x" and e="e'" in subst_ref_vars)
       apply (auto)*)
    apply (rule_tac stpx_lam_case)
                     apply (simp_all)
    (* app case 1. x \<in> free_vars e1. *)
   apply (rule_tac stpx_app_case)
                     apply (simp_all)
    (* app case 2. x \<in> free_vars e2. *)
  apply (rule_tac stpx_app_case)
                    apply (simp_all)
  done

end