DecSyn.structural

Structural rules for the typing relation (renaming, substitution)


Require Import Autosubst2.core Autosubst2.unscoped Autosubst2.syntax common typing.
From Hammer Require Import Tactics.
Require Import ssreflect.
Require Import Psatz.

Lemma wff_mutual :
  ( Γ, Γ True)
  ( Γ (a A : PTm), Γ a A Γ)
  ( Γ (a b A : PTm), Γ a b A Γ)
  ( Γ (A B : PTm), Γ A B Γ).
Proof. apply wt_mutual; eauto. Qed.

#[export]Hint Constructors Wt Wff Eq : wt.

Lemma T_Nat' Γ :
   Γ
  Γ PNat PUniv 0.
Proof. apply T_Nat. Qed.

Lemma renaming_up (ξ : ) Δ Γ A :
  renaming_ok Δ Γ ξ
  renaming_ok (cons (ren_PTm ξ A) Δ) (cons A Γ) (upRen_PTm_PTm ξ) .
Proof.
  move h i .
  elim /lookup_inv //=_.
  - move Γ0 ? [*]. subst. apply here'. by asimpl.
  - move Γ0 B h' ? [*]. subst.
    apply : there'; eauto. by asimpl.
Qed.


Lemma Su_Wt Γ a i :
  Γ a PUniv i
  Γ a a.
Proof. hauto lq:on ctrs:LEq, Eq. Qed.

Lemma Wt_Univ Γ a A i
  (h : Γ a A) :
  Γ @PUniv i PUniv (S i).
Proof.
  hauto lq:on ctrs:Wt use:wff_mutual.
Qed.


Lemma Bind_Inv Γ p (A : PTm) B U :
  Γ PBind p A B U
   i, Γ A PUniv i
  (cons A Γ) B PUniv i
  Γ PUniv i U.
Proof.
  move E :(PBind p A B) T h.
  move : p A B E.
  elim : Γ T U / h //=.
  - move Γ i p A B hA _ hB _ [*]. subst.
    exists i. repeat split //=.
    eapply wff_mutual in hA.
    apply Su_Univ; eauto.
  - hauto lq:on rew:off ctrs:LEq.
Qed.


Lemma T_App' Γ (b a : PTm) A B U :
  U = subst_PTm (scons a VarPTm) B
  Γ b PBind PPi A B
  Γ a A
  Γ PApp b a U.
Proof. move . apply T_App. Qed.

Lemma T_Pair' Γ (a b : PTm ) A B i U :
  U = subst_PTm (scons a VarPTm) B
  Γ a A
  Γ b U
  Γ PBind PSig A B (PUniv i)
  Γ PPair a b PBind PSig A B.
Proof.
  move . eauto using T_Pair.
Qed.


Lemma E_IndCong' Γ P0 P1 (a0 a1 : PTm ) b0 b1 c0 c1 i U :
  U = subst_PTm (scons VarPTm)
  (cons PNat Γ) PUniv i
  (cons PNat Γ) PUniv i
  Γ PNat
  Γ subst_PTm (scons PZero VarPTm)
  (cons (cons PNat Γ)) ren_PTm shift (subst_PTm (scons (PSuc (VarPTm var_zero)) (funcomp VarPTm shift) ) )
  Γ PInd PInd U.
Proof. move . apply E_IndCong. Qed.

Lemma T_Ind' Γ P (a : PTm) b c i U :
  U = subst_PTm (scons a VarPTm) P
  cons PNat Γ P PUniv i
  Γ a PNat
  Γ b subst_PTm (scons PZero VarPTm) P
  cons P (cons PNat Γ) c ren_PTm shift (subst_PTm (scons (PSuc (VarPTm var_zero)) (funcomp VarPTm shift) ) P)
  Γ PInd P a b c U.
Proof. move . apply T_Ind. Qed.

Lemma T_Proj2' Γ (a : PTm) A B U :
  U = subst_PTm (scons (PProj PL a) VarPTm) B
  Γ a PBind PSig A B
  Γ PProj PR a U.
Proof. move . apply T_Proj2. Qed.

Lemma E_Proj2' Γ i (a b : PTm) A B U :
  U = subst_PTm (scons (PProj PL a) VarPTm) B
  Γ PBind PSig A B (PUniv i)
  Γ a b PBind PSig A B
  Γ PProj PR a PProj PR b U.
Proof. move . apply E_Proj2. Qed.

Lemma E_Bind' Γ i p (A0 A1 : PTm) B0 B1 :
  Γ PUniv i
  Γ PUniv i
  cons Γ PUniv i
  Γ PBind p PBind p PUniv i.
Proof. hauto lq:on use:E_Bind, wff_mutual. Qed.

Lemma E_App' Γ i (b0 b1 a0 a1 : PTm) A B U :
  U = subst_PTm (scons VarPTm) B
  Γ PBind PPi A B (PUniv i)
  Γ PBind PPi A B
  Γ A
  Γ PApp PApp U.
Proof. move . apply E_App. Qed.

Lemma E_AppAbs' Γ (a : PTm) b A B i u U :
  u = subst_PTm (scons b VarPTm) a
  U = subst_PTm (scons b VarPTm ) B
  Γ PBind PPi A B PUniv i
  Γ b A
  cons A Γ a B
  Γ PApp (PAbs a) b u U.
  move . apply E_AppAbs. Qed.

Lemma E_ProjPair2' Γ (a b : PTm) A B i U :
  U = subst_PTm (scons a VarPTm) B
  Γ PBind PSig A B (PUniv i)
  Γ a A
  Γ b subst_PTm (scons a VarPTm) B
  Γ PProj PR (PPair a b) b U.
Proof. move . apply E_ProjPair2. Qed.

(* Lemma E_AppEta' Γ (b : PTm ) A B i u : *)
(*   u = (PApp (ren_PTm shift b) (VarPTm var_zero)) -> *)
(*   Γ ⊢ PBind PPi A B ∈ (PUniv i) -> *)
(*   Γ ⊢ b ∈ PBind PPi A B -> *)
(*   Γ ⊢ PAbs u ≡ b ∈ PBind PPi A B. *)
(* Proof. qauto l:on use:wff_mutual, E_AppEta. Qed. *)

Lemma Su_Pi_Proj2' Γ (a0 a1 A0 A1 : PTm ) B0 B1 U T :
  U = subst_PTm (scons VarPTm)
  T = subst_PTm (scons VarPTm)
  Γ PBind PPi PBind PPi
  Γ
  Γ U T.
Proof. move . apply Su_Pi_Proj2. Qed.

Lemma Su_Sig_Proj2' Γ (a0 a1 A0 A1 : PTm) B0 B1 U T :
  U = subst_PTm (scons VarPTm)
  T = subst_PTm (scons VarPTm)
  Γ PBind PSig PBind PSig
  Γ
  Γ U T.
Proof. move . apply Su_Sig_Proj2. Qed.

Lemma E_IndZero' Γ P i (b : PTm) c U :
  U = subst_PTm (scons PZero VarPTm) P
  cons PNat Γ P PUniv i
  Γ b subst_PTm (scons PZero VarPTm) P
  cons P (cons PNat Γ) c ren_PTm shift (subst_PTm (scons (PSuc (VarPTm var_zero)) (funcomp VarPTm shift) ) P)
  Γ PInd P PZero b c b U.
Proof. move . apply E_IndZero. Qed.

Lemma Wff_Cons' Γ (A : PTm) i :
  Γ A PUniv i
  (* -------------------------------- *)
   cons A Γ.
Proof. hauto lq:on rew:off use:Wff_Cons, wff_mutual. Qed.

Lemma E_IndSuc' Γ P (a : PTm) b c i u U :
  u = subst_PTm (scons (PInd P a b c) (scons a VarPTm)) c
  U = subst_PTm (scons (PSuc a) VarPTm) P
  cons PNat Γ P PUniv i
  Γ a PNat
  Γ b subst_PTm (scons PZero VarPTm) P
  (cons P (cons PNat Γ)) c ren_PTm shift (subst_PTm (scons (PSuc (VarPTm var_zero)) (funcomp VarPTm shift) ) P)
  Γ PInd P (PSuc a) b c u U.
Proof. move . apply E_IndSuc. Qed.

Lemma renaming :
  ( Γ, Γ True)
  ( Γ (a A : PTm), Γ a A Δ (ξ : ), Δ renaming_ok Δ Γ ξ
     Δ ren_PTm ξ a ren_PTm ξ A)
  ( Γ (a b A : PTm), Γ a b A Δ (ξ : ), Δ renaming_ok Δ Γ ξ
     Δ ren_PTm ξ a ren_PTm ξ b ren_PTm ξ A)
  ( Γ (A B : PTm), Γ A B Δ (ξ : ), Δ renaming_ok Δ Γ ξ
    Δ ren_PTm ξ A ren_PTm ξ B).
Proof.
  apply wt_mutual //=; eauto 3 with wt.
  - hauto lq:on rew:off ctrs:Wt, Wff use:renaming_up.
  - move Γ a A B i hP ihP ha iha Δ ξ .
    apply : T_Abs; eauto.
    move : ihP() (); repeat move/[apply]. move/Bind_Inv.
    hauto lq:on rew:off ctrs:Wff,Wt use:renaming_up.
  - move *. apply : T_App'; eauto. by asimpl.
  - move Γ a A b B i hA ihA hB ihB hS ihS Δ ξ .
    eapply T_Pair' with (U := ren_PTm ξ (subst_PTm (scons a VarPTm) B));eauto. by asimpl.
  - move Γ a A B ha iha Δ ξ . apply : T_Proj2'; eauto. by asimpl.
  - move Γ P a b c i hP ihP ha iha hb ihb hc ihc Δ ξ .
    move [:hP].
    apply : T_Ind'; eauto. by asimpl.
    abstract :hP. apply ihP. by eauto using Wff_Cons', T_Nat'.
    hauto l:on use:renaming_up.
    set x := subst_PTm _ _. have : x = ren_PTm ξ (subst_PTm (scons PZero VarPTm) P) by subst x; asimpl.
    by subst x; eauto.
    set Ξ := cons _ _.
    have : Ξ. subst Ξ.
    apply : Wff_Cons'; eauto. apply hP.
    move /(_ Ξ (upRen_PTm_PTm (upRen_PTm_PTm ξ)) ) : ihc.
    set Ξ' := (cons _ _) .
    have : renaming_ok Ξ Ξ' (upRen_PTm_PTm (upRen_PTm_PTm ξ)).
    by do 2 apply renaming_up.
    move /[swap] /[apply].
    by asimpl.
  - hauto lq:on ctrs:Wt,LEq.
  - hauto lq:on ctrs:Eq.
  - hauto lq:on rew:off use:E_Bind', Wff_Cons, renaming_up.
  - move *. apply : E_App'; eauto. by asimpl.
  - move *. apply : E_Proj2'; eauto. by asimpl.
  - move Γ i hP ihP ha iha hb ihb hc ihc.
    move Δ ξ [:hP' hren].
    apply E_IndCong' with (i := i); eauto with wt.
    by asimpl.
    apply .
    abstract : hP'.
    qauto l:on use:renaming_up, Wff_Cons', T_Nat'.
    abstract : hren.
    qauto l:on use:renaming_up, Wff_Cons', T_Nat'.
    apply ihP; eauto with wt.
    move : ihb () (); do! move/[apply]. by asimpl.
    set Ξ := cons _ _.
    have : Ξ.
    subst Ξ. apply :Wff_Cons'; eauto.
    move /(_ Ξ (upRen_PTm_PTm (upRen_PTm_PTm ξ)) ) : ihc.
    move /(_ ltac:(qauto l:on use:renaming_up)).
    suff : ren_PTm (upRen_PTm_PTm (upRen_PTm_PTm ξ))
      (ren_PTm shift
         (subst_PTm
            (scons (PSuc (VarPTm var_zero)) (funcomp VarPTm shift)) )) = ren_PTm shift
      (subst_PTm (scons (PSuc (VarPTm var_zero)) (funcomp VarPTm shift))
         (ren_PTm (upRen_PTm_PTm ξ) )) by scongruence.
    by asimpl.
  - qauto l:on ctrs:Eq, LEq.
  - move Γ a b A B i hP ihP hb ihb ha iha Δ ξ .
    move : ihP () (). repeat move/[apply].
    move /Bind_Inv.
    move [j][][].
    have ? : Δ PBind PPi (ren_PTm ξ A) (ren_PTm (upRen_PTm_PTm ξ) B) PUniv j by qauto l:on ctrs:Wt.
    apply : E_AppAbs'; eauto. by asimpl. by asimpl.
    hauto lq:on ctrs:Wff use:renaming_up.
  - move Γ a b A B i hP ihP ha iha hb ihb Δ ξ .
    move : {hP} ihP () (). repeat move/[apply].
    move /Bind_Inv [][][].
    have ? : Δ PBind PSig (ren_PTm ξ A) (ren_PTm (upRen_PTm_PTm ξ) B) PUniv by qauto l:on ctrs:Wt.
    apply : E_ProjPair1; eauto.
    move : ihb . repeat move/[apply]. by asimpl.
  - move Γ a b A B i hP ihP ha iha hb ihb Δ ξ .
    apply : E_ProjPair2'; eauto. by asimpl.
    move : ihb ; repeat move/[apply]. by asimpl.
  - move Γ P i b c hP ihP hb ihb hc ihc Δ ξ .
    apply E_IndZero' with (i := i); eauto. by asimpl.
    sauto lq:on use:Wff_Cons', T_Nat', renaming_up.
    move /(_ Δ ξ ) : ihb.
    asimpl. by apply.
    set Ξ := cons _ _.
    have : Ξ by sauto lq:on use:Wff_Cons', T_Nat', renaming_up.
    move /(_ Ξ (upRen_PTm_PTm (upRen_PTm_PTm ξ)) ) : ihc.
    set p := renaming_ok _ _ _.
    have : p. by do 2 apply renaming_up.
    move /[swap]/[apply].
    suff : ren_PTm (upRen_PTm_PTm (upRen_PTm_PTm ξ))
      (ren_PTm shift
         (subst_PTm
            (scons (PSuc (VarPTm var_zero)) (funcomp VarPTm shift)) P))= ren_PTm shift
      (subst_PTm (scons (PSuc (VarPTm var_zero)) (funcomp VarPTm shift))
         (ren_PTm (upRen_PTm_PTm ξ) P)) by scongruence.
    by asimpl.
  - move Γ P a b c i hP ihP ha iha hb ihb hc ihc Δ ξ .
    apply E_IndSuc' with (i := i). by asimpl. by asimpl.
    sauto lq:on use:Wff_Cons', T_Nat', renaming_up.
    by eauto with wt.
    move /(_ Δ ξ ) : ihb. asimpl. by apply.
    set Ξ := cons _ _.
    have : Ξ by sauto lq:on use:Wff_Cons', T_Nat', renaming_up.
    move /(_ Ξ (upRen_PTm_PTm (upRen_PTm_PTm ξ)) ) : ihc.
    move /(_ ltac:(by eauto using renaming_up)).
    by asimpl.
  - move Γ a b A B i hPi ihPi ha iha hb ihb Δ ξ .
    apply : E_FunExt; eauto. move : . asimpl. apply.
    hfcrush use:Bind_Inv.
    by apply renaming_up.
  - move Γ a b A B i hPi ihPi ha iha hb ihb hL ihL hR ihR Δ ξ .
    apply : E_PairExt; eauto. move : ihR. asimpl. by apply.
  - hauto lq:on ctrs:LEq.
  - qauto l:on ctrs:LEq.
  - hauto lq:on ctrs:Wff use:renaming_up, Su_Pi.
  - hauto lq:on ctrs:Wff use:Su_Sig, renaming_up.
  - hauto q:on ctrs:LEq.
  - hauto lq:on ctrs:LEq.
  - qauto l:on ctrs:LEq.
  - move *; apply : Su_Pi_Proj2'; eauto; by asimpl.
  - move *. apply : Su_Sig_Proj2'; eauto; by asimpl.
Qed.


Definition morphing_ok Δ Γ (ρ : PTm) :=
   i A, lookup i Γ A Δ ρ i subst_PTm ρ A.

Lemma morphing_ren Ξ Δ Γ
  (ρ : PTm) (ξ : ) :
   Ξ
  renaming_ok Ξ Δ ξ morphing_ok Δ Γ ρ
  morphing_ok Ξ Γ (funcomp (ren_PTm ξ) ρ).
Proof.
  move hρ i A.
  rewrite {1}/funcomp.
  have :
    subst_PTm (funcomp (ren_PTm ξ) ρ) A =
    ren_PTm ξ (subst_PTm ρ A) by asimpl.
  move ?. eapply renaming; eauto.
Qed.


Lemma morphing_ext Δ Γ (ρ : PTm) (a : PTm) (A : PTm) :
  morphing_ok Δ Γ ρ
  Δ a subst_PTm ρ A
  morphing_ok
    Δ (cons A Γ) (scons a ρ).
Proof.
  move h ha i B.
  elim /lookup_inv //=_.
  - move Γ0 ? [*]. subst.
    by asimpl.
  - move Γ0 ? [*]. subst.
    asimpl. by apply h.
Qed.


Lemma renaming_wt : Γ (a A : PTm), Γ a A Δ (ξ : ), Δ renaming_ok Δ Γ ξ Δ ren_PTm ξ a ren_PTm ξ A.
Proof. sfirstorder use:renaming. Qed.

Lemma renaming_wt' : Δ Γ a A (ξ : ) u U,
    u = ren_PTm ξ a U = ren_PTm ξ A
    Γ a A Δ
    renaming_ok Δ Γ ξ Δ u U.
Proof. hauto use:renaming_wt. Qed.

Lemma morphing_up Γ Δ (ρ : PTm) (A : PTm) k :
  morphing_ok Γ Δ ρ
  Γ subst_PTm ρ A PUniv k
  morphing_ok (cons (subst_PTm ρ A) Γ) (cons A Δ) (up_PTm_PTm ρ).
Proof.
  move h [:hp]. apply morphing_ext.
  rewrite /morphing_ok.
  move i .
  apply : renaming_wt'; last by apply renaming_shift.
  rewrite /funcomp. reflexivity.
  2 : { eauto. }
  by asimpl.
  abstract : hp. qauto l:on ctrs:Wff use:wff_mutual.
  apply : T_Var;eauto. apply here'. by asimpl.
Qed.


Lemma weakening_wt : Γ (a A B : PTm) i,
    Γ B PUniv i
    Γ a A
    cons B Γ ren_PTm shift a ren_PTm shift A.
Proof.
  move Γ a A B i hB ha.
  apply : renaming_wt'; eauto.
  apply : Wff_Cons'; eauto.
  apply : renaming_shift; eauto.
Qed.


Lemma weakening_wt' : Γ (a A B : PTm) i U u,
    u = ren_PTm shift a
    U = ren_PTm shift A
    Γ B PUniv i
    Γ a A
    cons B Γ u U.
Proof. move > . apply weakening_wt. Qed.

Lemma morphing :
  ( Γ, Γ True)
    ( Γ a A, Γ a A Δ ρ, Δ morphing_ok Δ Γ ρ
     Δ subst_PTm ρ a subst_PTm ρ A)
    ( Γ a b A, Γ a b A Δ ρ, Δ morphing_ok Δ Γ ρ
     Δ subst_PTm ρ a subst_PTm ρ b subst_PTm ρ A)
    ( Γ A B, Γ A B Δ ρ, Δ morphing_ok Δ Γ ρ
    Δ subst_PTm ρ A subst_PTm ρ B).
Proof.
  apply wt_mutual //=.
  - hauto l:on unfold:morphing_ok.
  - hauto lq:on use:morphing_up, Wff_Cons', T_Bind.
  - move Γ a A B i hP ihP ha iha Δ ρ hρ.
    move : ihP () (hρ); repeat move/[apply].
    move /Bind_Inv [j][][]. move {hP}.
    have ? : Δ PBind PPi (subst_PTm ρ A) (subst_PTm (up_PTm_PTm ρ) B) PUniv i by hauto lq:on ctrs:Wt.
    apply : T_Abs; eauto.
    apply : iha.
    hauto lq:on use:Wff_Cons', Bind_Inv.
    apply : morphing_up; eauto.
  - move *; apply : T_App'; eauto; by asimpl.
  - move Γ a A b B i hA ihA hB ihB hS ihS Δ ρ hρ .
    eapply T_Pair' with (U := subst_PTm ρ (subst_PTm (scons a VarPTm) B));eauto. by asimpl.
  - hauto lq:on use:T_Proj1.
  - move *. apply : T_Proj2'; eauto. by asimpl.
  - hauto lq:on ctrs:Wt,LEq.
  - qauto l:on ctrs:Wt.
  - qauto l:on ctrs:Wt.
  - qauto l:on ctrs:Wt.
  - move Γ P a b c i hP ihP ha iha hb ihb hc ihc Δ ξ .
    have hξ' : morphing_ok (cons PNat Δ) (cons PNat Γ) (up_PTm_PTm ξ).
    move /morphing_up : . move /(_ PNat 0).
    apply. by apply T_Nat.
    move [:hP].
    apply : T_Ind'; eauto. by asimpl.
    abstract :hP. apply ihP. by eauto using Wff_Cons', T_Nat'.
    move /morphing_up : . move /(_ PNat 0).
    apply. by apply T_Nat.
    move : ihb ; do!move/[apply]. by asimpl.
    set Ξ := cons _ _.
    have : Ξ. subst Ξ.
    apply : Wff_Cons'; eauto. apply hP.
    move /(_ Ξ (up_PTm_PTm (up_PTm_PTm ξ)) ) : ihc.
    set Ξ' := (cons _ _) .
    have : morphing_ok Ξ Ξ' (up_PTm_PTm (up_PTm_PTm ξ)).
    eapply morphing_up; eauto. apply hP.
    move /[swap]/[apply].
    set x := (x in _ _ x).
    set y := (y in _ _ _ y).
    suff : x = y by scongruence.
    subst x y. asimpl. substify. by asimpl.
  - qauto l:on ctrs:Wt.
  - hauto lq:on ctrs:Eq.
  - hauto lq:on ctrs:Eq.
  - hauto lq:on ctrs:Eq.
  - hauto lq:on rew:off use:E_Bind', Wff_Cons, morphing_up.
  - move *. apply : E_App'; eauto. by asimpl.
  - hauto q:on ctrs:Eq.
  - move *. apply : E_Proj2'; eauto. by asimpl.
  - move Γ i hP ihP ha iha hb ihb hc ihc.
    move Δ ξ .
    have hξ' : morphing_ok (cons PNat Δ)
                   (cons PNat Γ) (up_PTm_PTm ξ).
    move /morphing_up : . move /(_ PNat 0).
    apply. by apply T_Nat.
    move [:hP'].
    apply E_IndCong' with (i := i).
    by asimpl.
    abstract : hP'.
    qauto l:on use:morphing_up, Wff_Cons', T_Nat'.
    qauto l:on use:renaming_up, Wff_Cons', T_Nat'.
    by eauto with wt.
    move : ihb () (); do! move/[apply]. by asimpl.
    set Ξ := cons _ _.
    have : Ξ.
    subst Ξ. apply :Wff_Cons'; eauto. apply hP'.
    move /(_ Ξ (up_PTm_PTm (up_PTm_PTm ξ)) ) : ihc.
    move /(_ ltac:(qauto l:on use:morphing_up)).
    asimpl. substify. by asimpl.
  - eauto with wt.
  - qauto l:on ctrs:Eq, LEq.
  - move Γ a b A B i hP ihP hb ihb ha iha Δ ρ hρ.
    move : ihP (hρ) (). repeat move/[apply].
    move /Bind_Inv.
    move [j][][].
    have ? : Δ PBind PPi (subst_PTm ρ A) (subst_PTm (up_PTm_PTm ρ) B) PUniv j by qauto l:on ctrs:Wt.
    apply : E_AppAbs'; eauto. by asimpl. by asimpl.
    hauto lq:on ctrs:Wff use:morphing_up.
  - move Γ a b A B i hP ihP ha iha hb ihb Δ ρ hρ.
    move : {hP} ihP (hρ) (). repeat move/[apply].
    move /Bind_Inv [][][].
    have ? : Δ PBind PSig (subst_PTm ρ A) (subst_PTm (up_PTm_PTm ρ) B) PUniv by qauto l:on ctrs:Wt.
    apply : E_ProjPair1; eauto.
    move : ihb hρ . repeat move/[apply]. by asimpl.
  - move Γ a b A B i hP ihP ha iha hb ihb Δ ρ hρ.
    apply : E_ProjPair2'; eauto. by asimpl.
    move : ihb hρ ; repeat move/[apply]. by asimpl.
  - move Γ P i b c hP ihP hb ihb hc ihc Δ ξ .
    have hξ' : morphing_ok (cons PNat Δ)(cons PNat Γ) (up_PTm_PTm ξ).
    move /morphing_up : . move /(_ PNat 0).
    apply. by apply T_Nat.
    apply E_IndZero' with (i := i); eauto. by asimpl.
    qauto l:on use:Wff_Cons', T_Nat', renaming_up.
    move /(_ Δ ξ ) : ihb.
    asimpl. by apply.
    set Ξ := cons _ _.
    have : Ξ by qauto l:on use:Wff_Cons', T_Nat', renaming_up.
    move /(_ Ξ (up_PTm_PTm (up_PTm_PTm ξ)) ) : ihc.
    move /(_ ltac:(sauto lq:on use:morphing_up)).
    asimpl. substify. by asimpl.
  - move Γ P a b c i hP ihP ha iha hb ihb hc ihc Δ ξ .
    have hξ' : morphing_ok (cons PNat Δ) (cons PNat Γ) (up_PTm_PTm ξ).
    move /morphing_up : . move /(_ PNat 0).
    apply. by apply T_Nat'.
    apply E_IndSuc' with (i := i). by asimpl. by asimpl.
    qauto l:on use:Wff_Cons', T_Nat', renaming_up.
    by eauto with wt.
    move /(_ Δ ξ ) : ihb. asimpl. by apply.
    set Ξ := cons _ _.
    have : Ξ by qauto l:on use:Wff_Cons', T_Nat', renaming_up.
    move /(_ Ξ (up_PTm_PTm (up_PTm_PTm ξ)) ) : ihc.
    move /(_ ltac:(sauto l:on use:morphing_up)).
    asimpl. substify. by asimpl.
  - move Γ a b A B i hPi ihPi ha iha hb ihb Δ ξ .
    move : ihPi () (); repeat move/[apply]. move /[dup] /Bind_Inv ihPi ?.
    decompose [and ex] ihPi.
    apply : E_FunExt; eauto. move : . asimpl. apply.
    by eauto with wt.
    by eauto using morphing_up with wt.
  - move Γ a b A B i hPi ihPi ha iha hb ihb hL ihL hR ihR Δ ξ .
    apply : E_PairExt; eauto. move : ihR. asimpl. by apply.
  - hauto lq:on ctrs:LEq.
  - qauto l:on ctrs:LEq.
  - hauto lq:on ctrs:Wff use:morphing_up, Su_Pi.
  - hauto lq:on ctrs:Wff use:Su_Sig, morphing_up.
  - hauto q:on ctrs:LEq.
  - hauto lq:on ctrs:LEq.
  - qauto l:on ctrs:LEq.
  - move *; apply : Su_Pi_Proj2'; eauto; by asimpl.
  - move *. apply : Su_Sig_Proj2'; eauto; by asimpl.
Qed.


Lemma morphing_wt : Γ (a A : PTm ), Γ a A Δ (ρ : PTm), Δ morphing_ok Δ Γ ρ Δ subst_PTm ρ a subst_PTm ρ A.
Proof. sfirstorder use:morphing. Qed.

Lemma morphing_wt' : Δ Γ a A (ρ : PTm) u U,
    u = subst_PTm ρ a U = subst_PTm ρ A
    Γ a A Δ
    morphing_ok Δ Γ ρ Δ u U.
Proof. hauto use:morphing_wt. Qed.

Lemma morphing_id : Γ, Γ morphing_ok Γ Γ VarPTm.
Proof.
  rewrite /morphing_ok Γ i. asimpl.
  eauto using T_Var.
Qed.


Lemma substing_wt : Γ (a : PTm) (b A : PTm) B,
    (cons A Γ) a B
    Γ b A
    Γ subst_PTm (scons b VarPTm) a subst_PTm (scons b VarPTm) B.
Proof.
  move Γ a b A B ha hb [:]. apply : morphing_wt; eauto.
  abstract : . sfirstorder use:wff_mutual.
  apply morphing_ext; last by asimpl.
  by apply morphing_id.
Qed.


(* Could generalize to all equal contexts *)
Lemma ctx_eq_subst_one (A0 A1 : PTm) i j Γ a A :
  (cons Γ) a A
  Γ PUniv i
  Γ PUniv j
  Γ
  (cons Γ) a A.
Proof.
  move .
  replace a with (subst_PTm VarPTm a); last by asimpl.
  replace A with (subst_PTm VarPTm A); last by asimpl.
  have ? : Γ by sfirstorder use:wff_mutual.
  apply : morphing_wt; eauto.
  apply : Wff_Cons'; eauto.
  move k . elim/lookup_inv //=_; cycle 1.
  - move Γ0 B hi ? [*]. subst.
    asimpl.
    eapply weakening_wt' with (a := VarPTm );eauto using T_Var.
    by substify.
  - move Γ0 ? [*]. subst.
    move [:hΓ'].
    apply : T_Conv.
    apply T_Var.
    abstract : hΓ'.
    eauto using Wff_Cons'. apply here.
    asimpl. renamify.
    eapply renaming; eauto.
    apply : renaming_shift; eauto.
Qed.


Lemma bind_inst Γ p (A : PTm) B i a0 a1 :
  Γ PBind p A B PUniv i
  Γ A
  Γ subst_PTm (scons VarPTm) B subst_PTm (scons VarPTm) B.
Proof.
  move h .
  have {}h : Γ PBind p A B PBind p A B by eauto using E_Refl, Su_Eq.
  case : p h //=; hauto l:on use:Su_Pi_Proj2, Su_Sig_Proj2.
Qed.


Lemma Cumulativity Γ (a : PTm ) i j :
  i j
  Γ a PUniv i
  Γ a PUniv j.
Proof.
  move . apply : T_Conv; eauto.
  apply Su_Univ //=.
  sfirstorder use:wff_mutual.
Qed.


Lemma T_Bind' Γ i j p (A : PTm ) (B : PTm) :
  Γ A PUniv i
  (cons A Γ) B PUniv j
  Γ PBind p A B PUniv (max i j).
Proof.
  move .
  have [*] : i max i j j max i j by lia.
  qauto l:on ctrs:Wt use:Cumulativity.
Qed.


Hint Resolve T_Bind' : wt.

Lemma regularity :
  ( Γ, Γ i A, lookup i Γ A j, Γ A PUniv j)
    ( Γ a A, Γ a A i, Γ A PUniv i)
    ( Γ a b A, Γ a b A Γ a A Γ b A i, Γ A PUniv i)
    ( Γ A B, Γ A B i, Γ A PUniv i Γ B PUniv i).
Proof.
  apply wt_mutual //=; eauto with wt.
  - move i A. elim/lookup_inv //=_.
  - move Γ A i ihΓ hA _ j .
    elim /lookup_inv //=_; cycle 1.
    + move Γ0 B + ? [*]. subst.
      move : ihΓ /[apply]. move [j ].
      exists j. apply : renaming_wt' //=; eauto using renaming_shift. done.
      apply : Wff_Cons'; eauto.
    + move Γ0 ? [*]. subst.
      exists i. apply : renaming_wt'; eauto. reflexivity.
      econstructor; eauto.
      apply : renaming_shift; eauto.
  - move Γ b a A B hb [i ihb] ha [j iha].
    move /Bind_Inv : ihb [k][][].
    move : substing_wt ha ; repeat move/[apply].
    move h. exists k.
    move : h. by asimpl.
  - hauto lq:on use:Bind_Inv.
  - move Γ a A B ha [i /Bind_Inv[j][][]].
    exists j. have : Γ PProj PL a A by qauto use:T_Proj1.
    move : substing_wt ; repeat move/[apply].
    by asimpl.
  - move Γ P a b c i + ? + *. clear. move h ha. exists i.
    hauto lq:on use:substing_wt.
  - sfirstorder.
  - sfirstorder.
  - sfirstorder.
  - move Γ i p ihΓ
             [ ] hA [ihA [ihA' [ ihA'']]].
    repeat split //=.
    qauto use:T_Bind.
    apply T_Bind; eauto.
    sfirstorder.
    apply : ctx_eq_subst_one; eauto using Su_Eq, E_Symmetric.
    hauto lq:on.
  - move n i A B hP _ hb [ [ [ ]]]
ha [ [ [ ]]].
    repeat split.
    qauto use:T_App.
    apply : T_Conv; eauto.
    qauto use:T_App.
    move /E_Symmetric in ha.
    by eauto using bind_inst.
    hauto lq:on ctrs:Wt,Eq,LEq lq:on use:Bind_Inv, substing_wt.
  - hauto lq:on use:Bind_Inv db:wt.
  - move Γ i a b A B hS _ hab [iha][ihb][j]ihs.
    repeat split //=; eauto with wt.
    apply : T_Conv; eauto with wt.
    move /E_Symmetric /E_Proj1 in hab.
    eauto using bind_inst.
    move /T_Proj1 in iha.
    hauto lq:on ctrs:Wt,Eq,LEq use:Bind_Inv, substing_wt.
  - move Γ i _ _ hPE [ [ _]] hae [ [ _]] _ [ [ ]] _ [ [ [j ]]].
    have wfΓ : Γ by hauto use:wff_mutual.
    have wfΓ' : (PNat :: Γ) by qauto use:Wff_Cons', T_Nat'.
    repeat split. by eauto using T_Ind.
    apply : T_Conv. apply : T_Ind; eauto.
    apply : T_Conv; eauto.
    eapply morphing; by eauto using Su_Eq, morphing_ext, morphing_id with wt.
    apply : T_Conv. apply : ctx_eq_subst_one; eauto.
    by eauto using Su_Eq, E_Symmetric.
    eapply renaming; eauto.
    eapply morphing. apply : Su_Eq. apply hPE. apply wfΓ'.
    apply morphing_ext.
    replace (funcomp VarPTm shift) with (funcomp (@ren_PTm shift) VarPTm); last by asimpl.
    apply : morphing_ren; eauto using morphing_id, renaming_shift.
    apply T_Suc. apply T_Var//. apply here. apply : Wff_Cons'; eauto using T_Nat'.
    apply renaming_shift.
    have /E_Symmetric /Su_Eq : Γ PBind PSig PNat PBind PSig PNat PUniv i by eauto with wt.
    move /E_Symmetric in hae.
    by eauto using Su_Sig_Proj2.
    sauto lq:on use:substing_wt.
  - hauto lq:on ctrs:Wt.
  - hauto lq:on ctrs:Wt.
  - hauto q:on use:substing_wt db:wt.
  - hauto l:on use:bind_inst db:wt.
  - move Γ P i b c hP _ hb _ hc _.
    have ? : Γ by hauto use:wff_mutual.
    repeat split//.
    by eauto with wt.
    sauto lq:on use:substing_wt.
  - move Γ P a b c i hP _ ha _ hb _ hc _.
    have ? : Γ by hauto use:wff_mutual.
    repeat split//.
    apply : T_Ind; eauto with wt.
    set Ξ := (X in X _ _) in hc.
    have : morphing_ok Γ Ξ (scons (PInd P a b c) (scons a VarPTm)).
    apply morphing_ext. apply morphing_ext. by apply morphing_id.
    by eauto. by eauto with wt.
    subst Ξ.
    move : morphing_wt hc; repeat move/[apply]. asimpl. by apply.
    sauto lq:on use:substing_wt.
  - move Γ A B C hA [i [ ]] hC [j [ ]].
    have ? : Γ by sfirstorder use:wff_mutual.
    exists (max i j).
    have [? ?] : i Nat.max i j j Nat.max i j by lia.
    qauto l:on use:T_Conv, Su_Univ.
  - move Γ i j *. exists (S (max i j)).
    have [? ?] : S i S (Nat.max i j) S j S (Nat.max i j) by lia.
    hauto lq:on ctrs:Wt,LEq.
  - move Γ i _ [][] hB[][].
    exists (max ).
    split; eauto with wt.
    apply T_Bind'; eauto.
    sfirstorder use:ctx_eq_subst_one.
  - move n i _ [][] hB[][].
    exists (max ). repeat split; eauto with wt.
    apply T_Bind'; eauto.
    sfirstorder use:ctx_eq_subst_one.
  - sfirstorder.
  - move Γ _ [i][ ].
    move /Bind_Inv : [][h _].
    move /Bind_Inv : [][h' _].
    exists (max ).
    have [? ?] : Nat.max Nat.max by lia.
    eauto using Cumulativity.
  - move Γ _ [i][ ].
    move /Bind_Inv : [][h _].
    move /Bind_Inv : [][h' _].
    exists (max ).
    have [? ?] : Nat.max Nat.max by lia.
    eauto using Cumulativity.
  - move Γ /Su_Pi_Proj1 .
    move [i][].
    move ha [][][j].
    move /Bind_Inv : [][][ _].
    move /Bind_Inv : [][][ _].
    have [*] : max max by lia.
    exists (max ).
    split.
    + apply Cumulativity with (i := ); eauto.
      have : Γ by eauto using T_Conv.
      move : substing_wt ;repeat move/[apply]. by asimpl.
    + apply Cumulativity with (i := ); eauto.
      move : substing_wt ;repeat move/[apply]. by asimpl.
  - move Γ /Su_Sig_Proj1 .
    move [i][].
    move ha [][][j].
    move /Bind_Inv : [][][ _].
    move /Bind_Inv : [][][ _].
    have [*] : max max by lia.
    exists (max ).
    split.
    + apply Cumulativity with (i := ); eauto.
      move : substing_wt ;repeat move/[apply]. by asimpl.
    + apply Cumulativity with (i := ); eauto.
      have : Γ by eauto using T_Conv.
      move : substing_wt ;repeat move/[apply]. by asimpl.
      Unshelve. all: exact 0.
Qed.


Lemma Var_Inv Γ (i : ) A :
  Γ VarPTm i A
   Γ B, lookup i Γ B Γ B A.
Proof.
  move E : (VarPTm i) u hu.
  move : i E.
  elim : Γ u A / hu//=.
  - move i Γ A hi [*]. subst.
    split //.
    exists A. split //.
    have h : Γ VarPTm i A by eauto using T_Var.
    eapply regularity in h.
    move : h []?.
    apply : Su_Eq. apply E_Refl; eassumption.
  - sfirstorder use:Su_Transitive.
Qed.


Lemma renaming_su' : Δ Γ ξ (A B : PTm) u U ,
    u = ren_PTm ξ A
    U = ren_PTm ξ B
    Γ A B
     Δ renaming_ok Δ Γ ξ
    Δ u U.
Proof. move > . hauto l:on use:renaming. Qed.

Lemma weakening_su : Γ (A0 A1 B : PTm) i,
    Γ B PUniv i
    Γ
    (cons B Γ) ren_PTm shift ren_PTm shift .
Proof.
  move Γ B i hB hlt.
  apply : renaming_su'; eauto.
  apply : Wff_Cons'; eauto.
  apply : renaming_shift; eauto.
Qed.


Lemma regularity_sub0 : Γ (A B : PTm), Γ A B i, Γ A PUniv i.
Proof. hauto lq:on use:regularity. Qed.

Lemma Su_Pi_Proj2_Var Γ (A0 A1 : PTm) B0 B1 :
  Γ PBind PPi PBind PPi
  cons Γ .
Proof.
  move h.
  have /Su_Pi_Proj1 := h.
  have /regularity_sub0 [i ] := .
  move /weakening_su : (h) . move => /[apply].
  move => .
  apply : Su_Pi_Proj2'; try eassumption; rewrite -?/ren_PTm; cycle 2.
  apply E_Refl. apply T_Var with (i := var_zero); eauto.
  sfirstorder use:wff_mutual.
  apply here.
  by asimpl; rewrite subst_scons_id.
  by asimpl; rewrite subst_scons_id.
Qed.


Lemma Su_Sig_Proj2_Var Γ (A0 A1 : PTm) B0 B1 :
  Γ PBind PSig PBind PSig
  (cons Γ) .
Proof.
  move => h.
  have /Su_Sig_Proj1 := h.
  have /regularity_sub0 [i ] := .
  move /weakening_su : (h) . move => /[apply].
  move => .
  apply : Su_Sig_Proj2'; try eassumption; rewrite -?/ren_PTm; cycle 2.
  apply E_Refl. apply T_Var with (i := var_zero); eauto.
  sfirstorder use:wff_mutual.
  apply here.
  by asimpl; rewrite subst_scons_id.
  by asimpl; rewrite subst_scons_id.
Qed.