LogRel.Algorithmic.UntypedConvSoundness: untyped conversion implies declarative typing.

Relation to weak-head normal forms


Section UAlgoConvWh.

  Let PEq (A B : term) := True.
  Let PNeEq (m n : term) :=
    whne m × whne n.
  Let PRedEq (t u : term) :=
    whnf t × whnf u.

  Theorem algo_uconv_wh :
    UAlgoConvInductionConcl PEq PRedEq PNeEq.
  Proof.
    subst PEq PRedEq PNeEq ; cbn.
    apply UAlgoConvInduction.
    all: intros ; prod_splitter ; prod_hyp_splitter.
    all: now constructor.
  Qed.


End UAlgoConvWh.

Notation "[ A ≅ B ]" := (UConvAlg A B).
Notation "[ A ≅h B ]" := (UConvRedAlg A B).
Notation "[ m ~ n ]" := (UConvNeuAlg m n).

Extra preservation lemmas for untyped conversion


Section PremisePreserve.
  Context `{!TypingSubst de} `{!TypeConstructorsInj de} `{!TypeReductionComplete de}.

  Lemma LamCongUAlg_prem0_red Γ T A t A' t' :
    [Γ |-[ de ] tLambda A t : T] × [Γ |-[ de ] tLambda A' t' : T]
     A'' B, [T ⤳* tProd A'' B], [Γ ,, A'' |-[de] t : B] & [Γ ,, A'' |-[de] t' : B]].
  Proof.
    intros [[? [[B []] Hconv]]%termGen' [? [[B' []] Hconv']]%termGen'].
    eapply red_compl_prod_l in Hconv as (A''&B''&[Hred]).
    edestruct prod_ty_inj.
    {
     etransitivity ; tea.
     now eapply RedConvTyC.
    }

    do 2 eexists ; split.
    - now eapply redty_sound.
    - now econstructor ; [eapply stability1|..] ; cycle 1.
    - now econstructor ; [eapply stability1|..].
  Qed.


  Lemma LamCongUAlg_prem0 Γ T A t A' t' :
    [Γ |-[ de ] tLambda A t : T] × [Γ |-[ de ] tLambda A' t' : T]
     B, [Γ ,, A |-[de] t : B], [Γ ,, A t' : B] & [Γ |-[de] tProd A B T]].
  Proof.
    intros [[? [[B []] Hconv]]%termGen' [? [[B' []] Hconv']]%termGen'].
    edestruct prod_ty_inj.
    {
     etransitivity ; [..|symmetry] ; [eapply Hconv'|eapply Hconv].
    }

    eexists ; split ; tea.
    econstructor ; tea.
    now eapply stability1.
  Qed.


  Lemma LamCongUAlg_concl Γ T A t A' t' B :
    [Γ |-[ de ] tLambda A t : T] × [Γ |-[ de ] tLambda A' t' : T]
    [Γ ,, A |-[de] t t' : B]
    [Γ |-[de] tProd A B T]
    [Γ |-[de] tLambda A t tLambda A' t' : T].
  Proof.
    intros [[? []]%LamCongUAlg_prem0 [_ Ht']]%dup ??.
    econstructor ; tea.
    econstructor ; tea.
    2: constructor.
    1-2: eapply prod_ty_inv ; boundary.
    eapply termGen' in Ht' as (?&[? []]&?).
    eapply prod_ty_inj.
    etransitivity ; tea.
    now symmetry.
  Qed.


  Lemma LamNeUAlg_prem0_red Γ T A t n' :
    [Γ |-[ de ] tLambda A t : T] × [Γ |-[ de ] n' : T]
     A'' B, [T ⤳* tProd A'' B], [Γ ,, A'' t : B] & [Γ ,, A'' eta_expand n' : B]].
  Proof.
    intros [[? [[B []] Hconv]]%termGen' Hn].
    eapply red_compl_prod_l in Hconv as (A''&B''&[Hred]).
    do 2 eexists ; split.

    - now eapply redty_sound.
    - now econstructor ; [eapply stability1 |..].
    - eapply typing_eta' ; econstructor ; tea.
      now eapply RedConvTyC.
  Qed.


  Lemma LamNeUAlg_prem0 Γ T A t n' :
    [Γ |-[ de ] tLambda A t : T] × [Γ |-[ de ] n' : T]
     B, [Γ ,, A |-[de] t : B], [Γ ,, A eta_expand n' : B] & [Γ |-[de] tProd A B T]].
  Proof.
    intros [[? [[B []] Hconv]]%termGen' ?].

    eexists ; split ; tea.
    eapply typing_eta'.
    now econstructor.
  Qed.


  Lemma LamNeUAlg_concl Γ T A t n' B :
    [Γ |-[ de ] tLambda A t : T] × [Γ |-[ de ] n' : T]
    [Γ ,, A |-[de] t eta_expand n' : B]
    [Γ |-[de] tProd A B T]
    [Γ |-[de] tLambda A t n' : T].
  Proof.
    intros [[? []]%LamNeUAlg_prem0 [_ Ht']]%dup ??.
    econstructor ; tea.
    etransitivity.
    2: eapply TermFunEta ; refold ; now econstructor.
    econstructor ; tea.
    2-3: constructor.
    all: eapply prod_ty_inv ; boundary.
  Qed.


  Lemma NeLamUAlg_prem0_red Γ T n A' t' :
    [Γ |-[ de ] n : T] × [Γ |-[ de ] tLambda A' t' : T]
     A'' B, [T ⤳* tProd A'' B], [Γ ,, A'' eta_expand n : B] & [Γ ,, A'' t' : B]].
  Proof.
    intros [Hn [? [[B []] Hconv]]%termGen'].
    eapply red_compl_prod_l in Hconv as (A''&B''&[Hred]).
    do 2 eexists ; split.

    - now eapply redty_sound.
    - eapply typing_eta' ; econstructor ; tea.
      now eapply RedConvTyC.
    - now econstructor ; [eapply stability1 | ..].
  Qed.


  Lemma NeLamUAlg_prem0 Γ T n A' t' :
    [Γ |-[ de ] n : T] × [Γ |-[ de ] tLambda A' t' : T]
     B, [Γ ,, A' |-[de] eta_expand n : B], [Γ ,, A' t' : B] & [Γ |-[de] tProd A' B T]].
  Proof.
    intros [? [? [[B []] Hconv]]%termGen'].

    eexists ; split ; tea.
    eapply typing_eta'.
    now econstructor.
  Qed.


  Lemma NeLamUAlg_concl Γ T n A' t' B :
    [Γ |-[ de ] n : T] × [Γ |-[ de ] tLambda A' t' : T]
    [Γ ,, A' |-[de] eta_expand n t' : B]
    [Γ |-[de] tProd A' B T]
    [Γ |-[de] n tLambda A' t' : T].
  Proof.
    intros [[? []]%NeLamUAlg_prem0 [Ht _]]%dup ??.
    econstructor ; tea.
    etransitivity.
    1: symmetry ; eapply TermFunEta ; refold ; now econstructor.
    econstructor ; tea.
    2-3: constructor.
    all: eapply prod_ty_inv ; boundary.
  Qed.


  Lemma PairCongUAlg_prem0_red Γ T A B p q A' B' p' q' :
    [Γ |-[ de ] tPair A B p q : T] × [Γ |-[ de ] tPair A' B' p' q' : T]
     A'' B'', [T ⤳* tSig A'' B''] × ([Γ p : A''] × [Γ p' : A'']).
  Proof.
    intros [[? [[] Hconv]]%termGen' [? [[] Hconv']]%termGen'].
    eapply red_compl_sig_l in Hconv as (A''&B''&[Hred]).

    edestruct sig_ty_inj.
    {
      etransitivity ; tea.
      now eapply RedConvTyC.
    }
    do 2 eexists ; split ; [..|split].
    - now eapply redty_sound.
    - now econstructor.
    - now econstructor.
  Qed.


  Lemma PairCongUAlg_prem1_red Γ A B p q A' B' p' q' A'' B'' T :
    [Γ |-[ de ] tPair A B p q : T] × [Γ |-[ de ] tPair A' B' p' q' : T]
    [T ⤳* tSig A'' B'']
    [Γ |-[de] p p' : A'']
    [Γ q : B''[(tFst (tPair A B p q))..]] × [Γ q' : B''[(tFst (tPair A B p q))..]].
  Proof.
    intros * [[? [[] Hconv]]%termGen' [? [[] Hconv']]%termGen'] ? ?.
    eapply (TypeTrans (B := T)), sig_ty_inj in Hconv as [].
    2: eapply RedConvTyC, subject_reduction_type ; boundary.
    eapply (TypeTrans (B := T)), sig_ty_inj in Hconv' as [].
    2: eapply RedConvTyC, subject_reduction_type ; boundary.

    assert [Γ |-[de] p' : A]
      by (econstructor ; tea ; etransitivity ; tea ; now symmetry).
    assert [Γ |-[ de ] p tFst (tPair A B p q) : A] by
      (econstructor ; symmetry ; now econstructor).

    split.
    all: econstructor ; tea.
    all: eapply typing_subst1 ; tea.
    etransitivity.
    all: eapply TermConv ; refold ; tea.
    3: etransitivity ; tea.
    all: now symmetry.
  Qed.


  Lemma PairCongUAlg_prem0 Γ T A B p q A' B' p' q' :
    [Γ |-[ de ] tPair A B p q : T] × [Γ |-[ de ] tPair A' B' p' q' : T]
    [Γ p : A] × [Γ p' : A].
  Proof.
    intros * [[? [[] Hconv]]%termGen' [? [[] Hconv']]%termGen'].
    split ; tea.
    econstructor ; tea.
    eapply sig_ty_inj.
    etransitivity ; tea.
    now symmetry.
  Qed.


  Lemma PairCongUAlg_prem1 Γ T A B p q A' B' p' q' :
    [Γ |-[ de ] tPair A B p q : T] × [Γ |-[ de ] tPair A' B' p' q' : T]
    [Γ |-[de] p p' : A]
    [Γ q : B[p..]] × [Γ q' : B[p..]].
  Proof.
    intros * [[? [[] Hconv]]%termGen' [? [[] Hconv']]%termGen'].
    split ; tea.
    econstructor ; tea.
    symmetry.
    eapply typing_subst1 ; tea.
    eapply sig_ty_inj.
    etransitivity ; tea.
    now symmetry.
  Qed.


  Lemma PairCongUAlg_concl Γ T A B p q A' B' p' q' :
    [Γ |-[ de ] tPair A B p q : T] × [Γ |-[ de ] tPair A' B' p' q' : T]
    [Γ |-[de] p p' : A]
    [Γ |-[de] q q' : B[p..]]
    [Γ |-[de] tPair A B p q tPair A' B' p' q' : T].
  Proof.
    intros * [[? [[] Hconv]]%termGen' [? [[] Hconv']]%termGen'] ??.
    econstructor.
    2: apply Hconv.
    econstructor ; tea.
    1: constructor ; boundary.
    all: eapply sig_ty_inj.
    all: etransitivity ; tea.
    all: now symmetry.
  Qed.


  Lemma PairNeUAlg_prem0_red Γ T A B p q n' :
    [Γ |-[ de ] tPair A B p q : T] × [Γ |-[ de ] n' : T]
     A'' B'', [T ⤳* tSig A'' B''] × ([Γ p : A''] × [Γ tFst n' : A'']).
  Proof.
    intros [[? [[] [Hconv Hconv']%dup]]%termGen' ?].
    eapply red_compl_sig_l in Hconv as (?&?&[Hred]).

    do 2 eexists ; split ; [..|split].
    - now eapply redty_sound.
    - now econstructor.
    - do 2 econstructor ; tea.
      now eapply RedConvTyC.
  Qed.


  Lemma PairNeUAlg_prem1_red Γ A B p q n' A'' B'' T :
    [Γ |-[ de ] tPair A B p q : T] × [Γ |-[ de ] n' : T]
    [T ⤳* tSig A'' B'']
    [Γ |-[de] p tFst n' : A'']
    [Γ q : B''[(tFst (tPair A B p q))..]] × [Γ tSnd n' : B''[(tFst (tPair A B p q))..]].
  Proof.
    intros * [[? [[] Hconv]]%termGen'?] ? ?.

    assert [Γ |-[de] T tSig A'' B''] by
      (eapply RedConvTyC, subject_reduction_type ; boundary).
    eapply (TypeTrans (B := T)), sig_ty_inj in Hconv as [] ; tea.

    assert [Γ |-[ de ] p tFst (tPair A B p q) : A] by
      (econstructor ; symmetry ; now econstructor).

    split.
    - econstructor ; tea.
      now eapply typing_subst1.
    - econstructor.
      1: now do 2 econstructor.
      eapply typing_subst1.
      2: constructor ; boundary.
      etransitivity ; tea.
      econstructor.
      all: now symmetry.
  Qed.


  Lemma PairNeUAlg_prem0 Γ T A B p q n' :
    [Γ |-[ de ] tPair A B p q : T] × [Γ |-[ de ] n' : T]
    [Γ p : A] × [Γ tFst n' : A].
  Proof.
    intros * [[? [[] Hconv]]%termGen' ?].
    split ; tea.
    do 2 (econstructor ; tea).
    now symmetry.
  Qed.


  Lemma PairNeUAlg_prem1 Γ T A B p q n' :
    [Γ |-[ de ] tPair A B p q : T] × [Γ |-[ de ] n' : T]
    [Γ |-[de] p tFst n' : A]
    [Γ q : B[p..]] × [Γ tSnd n' : B[p..]].
  Proof.
    intros * [[? [[] Hconv]]%termGen' ?].
    split ; tea.
    econstructor ; tea.
    1: do 2 (econstructor ; tea).
    1: now symmetry.
    symmetry.
    eapply typing_subst1 ; tea.
    constructor.
    eapply sig_ty_inv.
    boundary.
  Qed.


  Lemma PairNeUAlg_concl Γ T A B p q n' :
    [Γ |-[ de ] tPair A B p q : T] × [Γ |-[ de ] n' : T]
    [Γ |-[de] p tFst n' : A]
    [Γ |-[de] q tSnd n' : B[p..]]
    [Γ |-[de] tPair A B p q n' : T].
  Proof.
    intros * [[? [[] Hconv]]%termGen' ?] ??.
    econstructor ; tea.
    etransitivity.
    2: do 2 (econstructor ; tea) ; now symmetry.
    econstructor ; eauto.
    all: eapply sig_ty_inj.
    all: etransitivity ; tea.
    all: now symmetry.
  Qed.


  Lemma NePairUAlg_prem0_red Γ T n A' B' p' q' :
    [Γ |-[ de ] n : T] × [Γ |-[ de ] tPair A' B' p' q' : T]
     A'' B'', [T ⤳* tSig A'' B''] × ([Γ tFst n : A''] × [Γ p' : A'']).
  Proof.
    intros [? [? [[] [Hconv Hconv']%dup]]%termGen'].
    eapply red_compl_sig_l in Hconv as (?&?&[Hred]).
    do 2 eexists ; split ; [..|split].
    - now eapply redty_sound.
    - do 2 econstructor ; tea.
      now eapply RedConvTyC.
    - now econstructor.
  Qed.


  Lemma NePairUAlg_prem1_red Γ n A' B' p' q' A'' B'' T :
    [Γ |-[ de ] n : T] × [Γ |-[ de ] tPair A' B' p' q' : T]
    [T ⤳* tSig A'' B'']
    [Γ |-[de] tFst n p' : A'']
    [Γ tSnd n : B''[(tFst n)..]] × [Γ q' : B''[(tFst n)..]].
  Proof.
    intros * [? [? [[] Hconv]]%termGen'] ? ?.

    assert [Γ |-[de] T tSig A'' B''] by
      (eapply RedConvTyC, subject_reduction_type ; boundary).
    eapply (TypeTrans (B := T)), sig_ty_inj in Hconv as [] ; tea.

    split.
    - now do 2 econstructor.
    - econstructor ; tea.
      eapply typing_subst1 ; tea.
      econstructor.
      all: now symmetry.
  Qed.


  Lemma NePairUAlg_prem0 Γ T n A' B' p' q' :
    [Γ |-[ de ] n : T] × [Γ |-[ de ] tPair A' B' p' q' : T]
    [Γ tFst n : A'] × [Γ p' : A'].
  Proof.
    intros * [? [? [[] Hconv]]%termGen'].
    split ; tea.
    do 2 (econstructor ; tea).
    now symmetry.
  Qed.


  Lemma NePairUAlg_prem1 Γ T n A' B' p' q' :
    [Γ |-[ de ] n : T] × [Γ |-[ de ] tPair A' B' p' q' : T]
    [Γ |-[de] tFst n p' : A']
    [Γ tSnd n : B'[p'..]] × [Γ q' : B'[p'..]].
  Proof.
    intros * [? [? [[] Hconv]]%termGen'].
    split ; tea.
    econstructor ; tea.
    1: do 2 (econstructor ; tea).
    1: now symmetry.
    eapply typing_subst1 ; tea.
    constructor.
    eapply sig_ty_inv.
    boundary.
  Qed.


  Lemma NePairUAlg_concl Γ T n A' B' p' q' :
    [Γ |-[ de ] n : T] × [Γ |-[ de ] tPair A' B' p' q' : T]
    [Γ |-[de] tFst n p' : A']
    [Γ |-[de] tSnd n q' : B'[p'..]]
    [Γ |-[de] n tPair A' B' p' q' : T].
  Proof.
    intros * [? [? [[] Hconv]]%termGen'] ??.
    econstructor ; tea.
    symmetry.
    etransitivity.
    2: do 2 (econstructor ; tea) ; now symmetry.
    econstructor ; eauto.
    5-6: now symmetry.
    all: eapply sig_ty_inj.
    all: etransitivity ; tea.
    all: now symmetry.
  Qed.


  Lemma AppCongUAlg_bridge Γ T m n t u :
    [Γ |-[de] m n : T]
    well_typed Γ (tApp m t) × well_typed Γ (tApp n u)
     A B,
      [Γ |-[de] T tProd A B] ×
      [Γ |-[ de ] m n : tProd A B].
  Proof.
    intros Hal [[? [? [(A&B&[ Hm])]]%termGen'] [? [? [(A'&B'&[])]]%termGen']].
    unshelve epose proof (conv_neu_typing _ _ _ _ _ _ _) ; cycle -3 ; tea.
    do 2 eexists ; split ; tea.
    now econstructor.
  Qed.


  Lemma NatElimCongUAlg_bridge Γ T P hz hs n P' hz' hs' n' :
    [Γ |-[de] n n' : T]
    well_typed Γ (tNatElim P hz hs n) × well_typed Γ (tNatElim P' hz' hs' n')
    [Γ |-[de] T tNat] × [Γ |-[ de ] n n' : tNat].
  Proof.
    intros ? [[? [? [[ ??? Hn]]]%termGen'] [? [? [[]]]%termGen']].
    unshelve epose proof (conv_neu_typing _ _ _ _ _ _ _) ; cycle -3 ; tea.
    split ; tea.
    now econstructor.
  Qed.


  Lemma EmptyElimCongUAlg_bridge Γ T P n P' n' :
    [Γ |-[de] n n' : T]
    well_typed Γ (tEmptyElim P n) × well_typed Γ (tEmptyElim P' n')
    [Γ |-[de] T tEmpty] × [Γ |-[ de ] n n' : tEmpty].
  Proof.
    intros ? [[? [? [[ ? Hn]]]%termGen'] [? [? [[]]]%termGen']].
    unshelve epose proof (conv_neu_typing _ _ _ _ _ _ _) ; cycle -3 ; tea.
    split ; tea.
    now econstructor.
  Qed.


  Lemma FstCongUAlg_bridge Γ T m n :
    [Γ |-[de] m n : T]
    well_typed Γ (tFst m) × well_typed Γ (tFst n)
     A B, [Γ |-[de] T tSig A B] × [Γ |-[ de ] m n : tSig A B].
  Proof.
    intros Hal [[? [? [(A&B&[ Hm])]]%termGen'] [? [? [(A'&B'&[])]]%termGen']].
    unshelve epose proof (conv_neu_typing _ _ _ _ _ _ _) ; cycle -3 ; tea.
    do 2 eexists ; split ; tea.
    now econstructor.
  Qed.


  Lemma SndCongUAlg_bridge Γ T m n :
    [Γ |-[de] m n : T]
    well_typed Γ (tSnd m) × well_typed Γ (tSnd n)
     A B, [Γ |-[de] T tSig A B] × [Γ |-[ de ] m n : tSig A B].
  Proof.
    intros Hal [[? [? [(A&B&[ Hm])]]%termGen'] [? [? [(A'&B'&[])]]%termGen']].
    unshelve epose proof (conv_neu_typing _ _ _ _ _ _ _) ; cycle -3 ; tea.
    do 2 eexists ; split ; tea.
    now econstructor.
  Qed.


  Lemma IdElimCongUAlg_bridge Γ T A x P hr y e A' x' P' hr' y' e' :
    [Γ |-[de] e e' : T]
    well_typed Γ (tIdElim A x P hr y e) × well_typed Γ (tIdElim A' x' P' hr' y' e')
     A'' x'' y'', [Γ |-[de] T tId A'' x'' y''] × [Γ |-[ de ] e e' : tId A'' x'' y''].
  Proof.
    intros Hal [[? [? [[ ????? He]]]%termGen'] [? [? [[]]]%termGen']].
    unshelve epose proof (conv_neu_typing _ _ _ _ _ _ _) ; cycle -3 ; tea.
    do 3 eexists ; split ; tea.
    now econstructor.
  Qed.


End PremisePreserve.

Untyped algorithmic conversion implies declarative conversion


Section UConvSound.
  Context `{!TypingSubst de} `{!TypeConstructorsInj de}.

  Lemma uconv_sound_decl :
    UAlgoConvInductionConcl
      (fun t u
        ( Γ, [Γ |-[de] t] × [Γ |-[de] u] [Γ |-[de] t u]) ×
        ( Γ A, [Γ |-[de] t : A] × [Γ |-[de] u : A] [Γ |-[de] t u : A]))

      (fun t u
        ( Γ, [Γ |-[de] t] × [Γ |-[de] u] [Γ |-[de] t u]) ×
        ( Γ A, [Γ |-[de] t : A] × [Γ |-[de] u : A] [Γ |-[de] t u : A]))

      (fun m n
         Γ, well_typed Γ m × well_typed Γ n
         A, [Γ |-[de] m n : A]).

  Proof.
    apply UAlgoConvInduction.

    - intros * Ht Hu Ht' [Hty Htm].
      split.
      + intros * [Hconcl]%dup.
        eapply typeConvRed_prem2 in Hconcl ; tea.
        now eapply typeConvRed_concl ; eauto.

      + intros * [Hconcl]%dup.
        eapply termConvRed_prem3 in Hconcl ; tea.
        2: reflexivity.
        eapply termConvRed_concl ; eauto.
        reflexivity.

    - split.
      + now econstructor.
      + intros * [[? [[] ]]%termGen' _].

    - intros * HA [IHA_ty IHA_tm] HB [IHB_ty IHB_tm].
      split.
      + intros ? [Hconcl]%dup.
        eapply typePiCongAlg_prem0 in Hconcl as [ []]%dup.
        eapply IHA_ty, typePiCongAlg_prem1 in ; tea.
        now econstructor.

      + intros * [Hconcl [[Hty]%dup]]%dup.

        eapply termGen' in Hty as (?&[]&Hconv) ; tea.
        econstructor ; tea.
        eapply termPiCongAlg_concl.
        2: eapply IHB_tm, termPiCongAlg_prem1.
        1-2: eapply IHA_tm, termPiCongAlg_prem0.
        all: split ; now eapply ty_conv.

    - split.
      1: now constructor.
      intros * [].
      now constructor.

    - split.

      + intros * [Hz%type_isType _].
        2: constructor.
        inversion Hz ; inv_whne.

      + intros * [].
        now constructor.

    - intros * ? [? IH].
      split.

      + intros * [Hz%type_isType _].
        2: constructor.
        inversion Hz ; inv_whne.

      + intros * [Hconcl [Hty]]%dup.

        eapply termGen' in Hty as (?&[]&?) ; tea.
        econstructor ; tea.
        eapply termSuccCongAlg_concl.
        1: eapply IH, termSuccCongAlg_prem0.
        all: split ; now eapply ty_conv.

    - split.
      1: now econstructor.
      intros * [].
      now constructor.

    - intros * ? [].
      split.

      + intros * [Hz%type_isType _].
        2: constructor.
        inversion Hz ; inv_whne.

      + intros * [Hconv]%dup.
        eapply LamCongUAlg_prem0 in Hconv as (?&[]).
        eapply LamCongUAlg_concl ; eauto.

    - intros * ?? [].
      split.

      + intros * [Hz%type_isType _].
        2: constructor.
        inversion Hz ; inv_whne.

      + intros * [Hconv]%dup.
        eapply LamNeUAlg_prem0 in Hconv as (?&[]).
        eapply LamNeUAlg_concl ; eauto.

    - intros * ?? [].
      split.

      + intros * [_ Hz%type_isType].
        2: constructor.
        inversion Hz ; inv_whne.

      + intros * [Hconv]%dup.
        eapply NeLamUAlg_prem0 in Hconv as (?&[]).
        eapply NeLamUAlg_concl ; eauto.

    - intros * HA [IHA_ty IHA_tm] HB [IHB_ty IHB_tm].
      split.
      + intros ? [Hconcl]%dup.
        eapply typeSigCongAlg_prem0 in Hconcl as [ []]%dup.
        eapply IHA_ty, typeSigCongAlg_prem1 in ; tea.
        now econstructor.

      + intros * [Hconcl [[Hty]%dup]]%dup.

        eapply termGen' in Hty as (?&[]&Hconv) ; tea.
        econstructor ; tea.
        eapply termSigCongAlg_concl.
        2: eapply IHB_tm, termSigCongAlg_prem1.
        1-2: eapply IHA_tm, termSigCongAlg_prem0.
        all: split ; now eapply ty_conv.

    - intros * Hp [_ IHp] Hq [_ IHq].
      split.

      + intros * [Hz%type_isType _].
        2: constructor.
        inversion Hz ; inv_whne.

      + intros * [Hconcl ?]%dup.
        eapply PairCongUAlg_concl ; tea.
        2:eapply IHq, PairCongUAlg_prem1 ; tea.
        all: now eapply IHp, PairCongUAlg_prem0.

    - intros * ? Hp [_ IHp] Hq [_ IHq].
      split.

      + intros * [Hz%type_isType _].
        2: constructor.
        inversion Hz ; inv_whne.

      + intros * [Hconcl ?]%dup.
        eapply PairNeUAlg_concl ; tea.
        2:eapply IHq, PairNeUAlg_prem1 ; tea.
        all: now eapply IHp, PairNeUAlg_prem0.

    - intros * ? Hp [_ IHp] Hq [_ IHq].
      split.

      + intros * [_ Hz%type_isType].
        2: constructor.
        inversion Hz ; inv_whne.

      + intros * [Hconcl ?]%dup.
        eapply NePairUAlg_concl ; tea.
        2:eapply IHq, NePairUAlg_prem1 ; tea.
        all: now eapply IHp, NePairUAlg_prem0.

    - intros * HA [IHA_ty IHA_tm] Hx [_ IHx_tm] Hy [_ IHy_tm].
      split.

      + intros ? [Hconcl]%dup.
        eapply typeIdCongAlg_prem0 in Hconcl as [ []]%dup.
        eapply IHA_ty in as []%dup; eauto.
        eapply typeIdCongAlg_prem1 in as [ []]%dup ; eauto.
        eapply IHx_tm, typeIdCongAlg_prem2 in as []%dup; eauto.
        now econstructor.

      + intros * [Hconcl [[Hty]%dup]]%dup.

        eapply termGen' in Hty as (?&[]&?) ; tea.
        econstructor ; tea.
        eapply termIdCongAlg_concl.
        3: eapply IHy_tm, termIdCongAlg_prem2.
        2,4: eapply IHx_tm, termIdCongAlg_prem1.
        1,2,4,6: eapply IHA_tm, termIdCongAlg_prem0.
        all: split ; now eapply ty_conv.

    - split.

      + intros * [Hz%type_isType _].
        2: constructor.
        inversion Hz ; inv_whne.

      + intros * [[[? [[] Hconv]]%termGen'] ?]%dup.
        econstructor ; tea.
        eapply termIdReflCong_concl.
        split ; now eapply ty_conv.

    - intros * Hconv IH.
      split.

      + intros * [Hconcl]%dup.
        eapply algo_uconv_wh in Hconv as [].
        eapply typeNeuConvAlg_prem2 in Hconcl; tea.
        edestruct IH ; tea.
        now eapply typeNeuConvAlg_concl.

      + intros * [Hconcl []]%dup.
        edestruct IH.
        1: split ; now eexists.
        econstructor.
        1: now eapply conv_neu_sound.
        now eapply conv_neu_typing.

    - intros * [[[? (?&[? []]&?)%termGen']]]%dup.
      eexists.
      now eapply neuVarConvAlg_concl.

    - intros * Hconv IHm ? [_ IHt] * [Hconcl]%dup.

      eapply neuAppCongAlg_prem0 in Hconcl as [ []]%dup ; eauto.
      eapply IHm in as [? []%dup].
      eapply AppCongUAlg_bridge in as (?&?&[? []%dup]); tea.
      eapply neuAppCongAlg_prem1, IHt in ; eauto.
      eexists.
      now eapply neuAppCongAlg_concl.

    - intros * ? IH ? [IHP] ? [_ IHz] ? [_ IHs] ? [Hconcl]%dup.

      eapply neuNatElimCong_prem0 in Hconcl as [ []]%dup ; eauto.
      eapply IH in as [? []%dup].
      eapply NatElimCongUAlg_bridge in as [? []%dup]; eauto.
      eapply neuNatElimCong_prem1 in as [ []]%dup ; eauto.
      eapply IHP in as []%dup ; eauto.
      eapply neuNatElimCong_prem2 in as [ []]%dup ; eauto.
      eapply IHz in as []%dup ; eauto.
      eapply neuNatElimCong_prem3 in as [ []]%dup ; eauto.
      eapply IHs in as ; eauto.
      eexists.
      now eapply neuNatElimCong_concl.

    - intros * ? IH ? [IHP] ? [Hconcl]%dup.

      eapply neuEmptyElimCong_prem0 in Hconcl as [ []]%dup ; eauto.
      eapply IH in as [? []%dup].
      eapply EmptyElimCongUAlg_bridge in as [? []%dup]; eauto.
      eapply neuEmptyElimCong_prem1 in as [ []]%dup ; eauto.
      eapply IHP in as []%dup ; eauto.
      eexists.
      now eapply neuEmptyElimCong_concl.

    - intros * ? IH ? [Hconcl]%dup.

      eapply neuFstCongAlg_prem0 in Hconcl as [ []]%dup ; eauto.
      eapply IH in as [? []%dup].
      eapply FstCongUAlg_bridge in as (?&?&[? ]); eauto.
      eexists.
      now eapply neuFstCongAlg_concl.

    - intros * ? IH ? [Hconcl]%dup.

      eapply neuSndCongAlg_prem0 in Hconcl as [ []]%dup ; eauto.
      eapply IH in as [? []%dup].
      eapply SndCongUAlg_bridge in as (?&?&[? ]); eauto.
      eexists.
      now eapply neuSndCongAlg_concl.

    - intros * ? IH ? [IHP] ? [_ IHr] ? [Hconcl]%dup.

      eapply neuIdElimCong_prem0 in Hconcl as [ []]%dup ; eauto.
      eapply IH in as [? []%dup].
      eapply IdElimCongUAlg_bridge in as [? (?&?&?&[]%dup)]; eauto.
      eapply neuIdElimCong_prem1 in as [ []]%dup ; eauto.
      eapply IHP in as []%dup ; eauto.
      eapply neuIdElimCong_prem2 in as [ []]%dup ; eauto.
      eapply IHr in as []%dup ; eauto.
      eexists.
      now eapply neuIdElimCong_concl.
  Qed.


End UConvSound.