Inductive wf : env -> Prop :=
    | wf_nil : wf nil
    | wf_var :
        forall (e : env) (T : term) (s : sort),
        typ e T (Srt s) -> wf (Ax T :: e)
    | wf_cst :
        forall (e : env) (t T : term) (s : sort),
        typ e t T -> typ e T (Srt s) -> wf (Def t T :: e)
with typ : env -> term -> term -> Prop :=
  | type_ax :
      forall (e : env) (s1 s2 : sort),
      wf e -> axiom s1 s2 -> typ e (Srt s1) (Srt s2)
  | type_var :
      forall (e : env) (v : nat) (t : term),
      wf e -> item_lift t e v -> typ e (Ref v) t
  | type_abs :
      forall (e : env) (T U M : term) (s : sort),
      typ e (Prod T U) (Srt s) ->
      typ (Ax T :: e) M U -> typ e (Abs T M) (Prod T U)
  | type_app :
      forall (e : env) (u v V Ur : term),
      typ e v V -> typ e u (Prod V Ur) -> typ e (App u v) (subst v Ur)
  | type_prod :
      forall (e : env) (T U : term) (s1 s2 s3 : sort),
      typ e T (Srt s1) ->
      typ (Ax T :: e) U (Srt s2) ->
      rule s1 s2 s3 -> typ e (Prod T U) (Srt s3)
  | type_conv :
      forall (e : env) (t U V : term) (s : sort),
      typ e t U ->
      le_type e U V ->
      typ e V (Srt s) ->
      typ e t V
      (* sert uniquement quand il y a des sortes non typees: *)
  | type_conv_srt :
      forall (e : env) (t U : term) (s : sort),
      typ e t U -> le_type e U (Srt s) -> typ e t (Srt s).Inductive wf : env -> Prop :=
    | wf_nil : wf nil
    | wf_var :
        forall (e : env) (T : term) (s : sort),
        typ e T (Srt s) -> wf (Ax T :: e)
    | wf_cst :
        forall (e : env) (t T : term) (s : sort),
        typ e t T -> typ e T (Srt s) -> wf (Def t T :: e)
with typ : env -> term -> term -> Prop :=
  | type_ax :
      forall (e : env) (s1 s2 : sort),
      wf e -> axiom s1 s2 -> typ e (Srt s1) (Srt s2)
  | type_var :
      forall (e : env) (v : nat) (t : term),
      wf e -> item_lift t e v -> typ e (Ref v) t
  | type_abs :
      forall (e : env) (T U M : term) (s : sort),
      typ e (Prod T U) (Srt s) ->
      typ (Ax T :: e) M U -> typ e (Abs T M) (Prod T U)
  | type_app :
      forall (e : env) (u v V Ur : term),
      typ e v V -> typ e u (Prod V Ur) -> typ e (App u v) (subst v Ur)
  | type_prod :
      forall (e : env) (T U : term) (s1 s2 s3 : sort),
      typ e T (Srt s1) ->
      typ (Ax T :: e) U (Srt s2) ->
      rule s1 s2 s3 -> typ e (Prod T U) (Srt s3)
  | type_conv :
      forall (e : env) (t U V : term) (s : sort),
      typ e t U ->
      le_type e U V ->
      typ e V (Srt s) ->
      typ e t V
      (* sert uniquement quand il y a des sortes non typees: *)
  | type_conv_srt :
      forall (e : env) (t U : term) (s : sort),
      typ e t U -> le_type e U (Srt s) -> typ e t (Srt s).Inductive wf : env -> Prop :=
    | wf_nil : wf nil
    | wf_var :
        forall (e : env) (T : term) (s : sort),
        typ e T (Srt s) -> wf (Ax T :: e)
    | wf_cst :
        forall (e : env) (t T : term) (s : sort),
        typ e t T -> typ e T (Srt s) -> wf (Def t T :: e)
with typ : env -> term -> term -> Prop :=
  | type_ax :
      forall (e : env) (s1 s2 : sort),
      wf e -> axiom s1 s2 -> typ e (Srt s1) (Srt s2)
  | type_var :
      forall (e : env) (v : nat) (t : term),
      wf e -> item_lift t e v -> typ e (Ref v) t
  | type_abs :
      forall (e : env) (T U M : term) (s : sort),
      typ e (Prod T U) (Srt s) ->
      typ (Ax T :: e) M U -> typ e (Abs T M) (Prod T U)
  | type_app :
      forall (e : env) (u v V Ur : term),
      typ e v V -> typ e u (Prod V Ur) -> typ e (App u v) (subst v Ur)
  | type_prod :
      forall (e : env) (T U : term) (s1 s2 s3 : sort),
      typ e T (Srt s1) ->
      typ (Ax T :: e) U (Srt s2) ->
      rule s1 s2 s3 -> typ e (Prod T U) (Srt s3)
  | type_conv :
      forall (e : env) (t U V : term) (s : sort),
      typ e t U ->
      le_type e U V ->
      typ e V (Srt s) ->
      typ e t V
      (* sert uniquement quand il y a des sortes non typees: *)
  | type_conv_srt :
      forall (e : env) (t U : term) (s : sort),
      typ e t U -> le_type e U (Srt s) -> typ e t (Srt s).Inductive wf : env -> Prop :=
    | wf_nil : wf nil
    | wf_var :
        forall (e : env) (T : term) (s : sort),
        typ e T (Srt s) -> wf (Ax T :: e)
    | wf_cst :
        forall (e : env) (t T : term) (s : sort),
        typ e t T -> typ e T (Srt s) -> wf (Def t T :: e)
with typ : env -> term -> term -> Prop :=
  | type_ax :
      forall (e : env) (s1 s2 : sort),
      wf e -> axiom s1 s2 -> typ e (Srt s1) (Srt s2)
  | type_var :
      forall (e : env) (v : nat) (t : term),
      wf e -> item_lift t e v -> typ e (Ref v) t
  | type_abs :
      forall (e : env) (T U M : term) (s : sort),
      typ e (Prod T U) (Srt s) ->
      typ (Ax T :: e) M U -> typ e (Abs T M) (Prod T U)
  | type_app :
      forall (e : env) (u v V Ur : term),
      typ e v V -> typ e u (Prod V Ur) -> typ e (App u v) (subst v Ur)
  | type_prod :
      forall (e : env) (T U : term) (s1 s2 s3 : sort),
      typ e T (Srt s1) ->
      typ (Ax T :: e) U (Srt s2) ->
      rule s1 s2 s3 -> typ e (Prod T U) (Srt s3)
  | type_conv :
      forall (e : env) (t U V : term) (s : sort),
      typ e t U ->
      le_type e U V ->
      typ e V (Srt s) ->
      typ e t V
      (* sert uniquement quand il y a des sortes non typees: *)
  | type_conv_srt :
      forall (e : env) (t U : term) (s : sort),
      typ e t U -> le_type e U (Srt s) -> typ e t (Srt s).Inductive wf : env -> Prop :=
    | wf_nil : wf nil
    | wf_var :
        forall (e : env) (T : term) (s : sort),
        typ e T (Srt s) -> wf (Ax T :: e)
    | wf_cst :
        forall (e : env) (t T : term) (s : sort),
        typ e t T -> typ e T (Srt s) -> wf (Def t T :: e)
with typ : env -> term -> term -> Prop :=
  | type_ax :
      forall (e : env) (s1 s2 : sort),
      wf e -> axiom s1 s2 -> typ e (Srt s1) (Srt s2)
  | type_var :
      forall (e : env) (v : nat) (t : term),
      wf e -> item_lift t e v -> typ e (Ref v) t
  | type_abs :
      forall (e : env) (T U M : term) (s : sort),
      typ e (Prod T U) (Srt s) ->
      typ (Ax T :: e) M U -> typ e (Abs T M) (Prod T U)
  | type_app :
      forall (e : env) (u v V Ur : term),
      typ e v V -> typ e u (Prod V Ur) -> typ e (App u v) (subst v Ur)
  | type_prod :
      forall (e : env) (T U : term) (s1 s2 s3 : sort),
      typ e T (Srt s1) ->
      typ (Ax T :: e) U (Srt s2) ->
      rule s1 s2 s3 -> typ e (Prod T U) (Srt s3)
  | type_conv :
      forall (e : env) (t U V : term) (s : sort),
      typ e t U ->
      le_type e U V ->
      typ e V (Srt s) ->
      typ e t V
      (* sert uniquement quand il y a des sortes non typees: *)
  | type_conv_srt :
      forall (e : env) (t U : term) (s : sort),
      typ e t U -> le_type e U (Srt s) -> typ e t (Srt s).Inductive wf : env -> Prop :=
    | wf_nil : wf nil
    | wf_var :
        forall (e : env) (T : term) (s : sort),
        typ e T (Srt s) -> wf (Ax T :: e)
    | wf_cst :
        forall (e : env) (t T : term) (s : sort),
        typ e t T -> typ e T (Srt s) -> wf (Def t T :: e)
with typ : env -> term -> term -> Prop :=
  | type_ax :
      forall (e : env) (s1 s2 : sort),
      wf e -> axiom s1 s2 -> typ e (Srt s1) (Srt s2)
  | type_var :
      forall (e : env) (v : nat) (t : term),
      wf e -> item_lift t e v -> typ e (Ref v) t
  | type_abs :
      forall (e : env) (T U M : term) (s : sort),
      typ e (Prod T U) (Srt s) ->
      typ (Ax T :: e) M U -> typ e (Abs T M) (Prod T U)
  | type_app :
      forall (e : env) (u v V Ur : term),
      typ e v V -> typ e u (Prod V Ur) -> typ e (App u v) (subst v Ur)
  | type_prod :
      forall (e : env) (T U : term) (s1 s2 s3 : sort),
      typ e T (Srt s1) ->
      typ (Ax T :: e) U (Srt s2) ->
      rule s1 s2 s3 -> typ e (Prod T U) (Srt s3)
  | type_conv :
      forall (e : env) (t U V : term) (s : sort),
      typ e t U ->
      le_type e U V ->
      typ e V (Srt s) ->
      typ e t V
      (* sert uniquement quand il y a des sortes non typees: *)
  | type_conv_srt :
      forall (e : env) (t U : term) (s : sort),
      typ e t U -> le_type e U (Srt s) -> typ e t (Srt s).Inductive wf : env -> Prop :=
    | wf_nil : wf nil
    | wf_var :
        forall (e : env) (T : term) (s : sort),
        typ e T (Srt s) -> wf (Ax T :: e)
    | wf_cst :
        forall (e : env) (t T : term) (s : sort),
        typ e t T -> typ e T (Srt s) -> wf (Def t T :: e)
with typ : env -> term -> term -> Prop :=
  | type_ax :
      forall (e : env) (s1 s2 : sort),
      wf e -> axiom s1 s2 -> typ e (Srt s1) (Srt s2)
  | type_var :
      forall (e : env) (v : nat) (t : term),
      wf e -> item_lift t e v -> typ e (Ref v) t
  | type_abs :
      forall (e : env) (T U M : term) (s : sort),
      typ e (Prod T U) (Srt s) ->
      typ (Ax T :: e) M U -> typ e (Abs T M) (Prod T U)
  | type_app :
      forall (e : env) (u v V Ur : term),
      typ e v V -> typ e u (Prod V Ur) -> typ e (App u v) (subst v Ur)
  | type_prod :
      forall (e : env) (T U : term) (s1 s2 s3 : sort),
      typ e T (Srt s1) ->
      typ (Ax T :: e) U (Srt s2) ->
      rule s1 s2 s3 -> typ e (Prod T U) (Srt s3)
  | type_conv :
      forall (e : env) (t U V : term) (s : sort),
      typ e t U ->
      le_type e U V ->
      typ e V (Srt s) ->
      typ e t V
      (* sert uniquement quand il y a des sortes non typees: *)
  | type_conv_srt :
      forall (e : env) (t U : term) (s : sort),
      typ e t U -> le_type e U (Srt s) -> typ e t (Srt s).Inductive wf : env -> Prop :=
    | wf_nil : wf nil
    | wf_var :
        forall (e : env) (T : term) (s : sort),
        typ e T (Srt s) -> wf (Ax T :: e)
    | wf_cst :
        forall (e : env) (t T : term) (s : sort),
        typ e t T -> typ e T (Srt s) -> wf (Def t T :: e)
with typ : env -> term -> term -> Prop :=
  | type_ax :
      forall (e : env) (s1 s2 : sort),
      wf e -> axiom s1 s2 -> typ e (Srt s1) (Srt s2)
  | type_var :
      forall (e : env) (v : nat) (t : term),
      wf e -> item_lift t e v -> typ e (Ref v) t
  | type_abs :
      forall (e : env) (T U M : term) (s : sort),
      typ e (Prod T U) (Srt s) ->
      typ (Ax T :: e) M U -> typ e (Abs T M) (Prod T U)
  | type_app :
      forall (e : env) (u v V Ur : term),
      typ e v V -> typ e u (Prod V Ur) -> typ e (App u v) (subst v Ur)
  | type_prod :
      forall (e : env) (T U : term) (s1 s2 s3 : sort),
      typ e T (Srt s1) ->
      typ (Ax T :: e) U (Srt s2) ->
      rule s1 s2 s3 -> typ e (Prod T U) (Srt s3)
  | type_conv :
      forall (e : env) (t U V : term) (s : sort),
      typ e t U ->
      le_type e U V ->
      typ e V (Srt s) ->
      typ e t V
      (* sert uniquement quand il y a des sortes non typees: *)
  | type_conv_srt :
      forall (e : env) (t U : term) (s : sort),
      typ e t U -> le_type e U (Srt s) -> typ e t (Srt s).Inductive wf : env -> Prop :=
    | wf_nil : wf nil
    | wf_var :
        forall (e : env) (T : term) (s : sort),
        typ e T (Srt s) -> wf (Ax T :: e)
    | wf_cst :
        forall (e : env) (t T : term) (s : sort),
        typ e t T -> typ e T (Srt s) -> wf (Def t T :: e)
with typ : env -> term -> term -> Prop :=
  | type_ax :
      forall (e : env) (s1 s2 : sort),
      wf e -> axiom s1 s2 -> typ e (Srt s1) (Srt s2)
  | type_var :
      forall (e : env) (v : nat) (t : term),
      wf e -> item_lift t e v -> typ e (Ref v) t
  | type_abs :
      forall (e : env) (T U M : term) (s : sort),
      typ e (Prod T U) (Srt s) ->
      typ (Ax T :: e) M U -> typ e (Abs T M) (Prod T U)
  | type_app :
      forall (e : env) (u v V Ur : term),
      typ e v V -> typ e u (Prod V Ur) -> typ e (App u v) (subst v Ur)
  | type_prod :
      forall (e : env) (T U : term) (s1 s2 s3 : sort),
      typ e T (Srt s1) ->
      typ (Ax T :: e) U (Srt s2) ->
      rule s1 s2 s3 -> typ e (Prod T U) (Srt s3)
  | type_conv :
      forall (e : env) (t U V : term) (s : sort),
      typ e t U ->
      le_type e U V ->
      typ e V (Srt s) ->
      typ e t V
      (* sert uniquement quand il y a des sortes non typees: *)
  | type_conv_srt :
      forall (e : env) (t U : term) (s : sort),
      typ e t U -> le_type e U (Srt s) -> typ e t (Srt s).Inductive wf : env -> Prop :=
    | wf_nil : wf nil
    | wf_var :
        forall (e : env) (T : term) (s : sort),
        typ e T (Srt s) -> wf (Ax T :: e)
    | wf_cst :
        forall (e : env) (t T : term) (s : sort),
        typ e t T -> typ e T (Srt s) -> wf (Def t T :: e)
with typ : env -> term -> term -> Prop :=
  | type_ax :
      forall (e : env) (s1 s2 : sort),
      wf e -> axiom s1 s2 -> typ e (Srt s1) (Srt s2)
  | type_var :
      forall (e : env) (v : nat) (t : term),
      wf e -> item_lift t e v -> typ e (Ref v) t
  | type_abs :
      forall (e : env) (T U M : term) (s : sort),
      typ e (Prod T U) (Srt s) ->
      typ (Ax T :: e) M U -> typ e (Abs T M) (Prod T U)
  | type_app :
      forall (e : env) (u v V Ur : term),
      typ e v V -> typ e u (Prod V Ur) -> typ e (App u v) (subst v Ur)
  | type_prod :
      forall (e : env) (T U : term) (s1 s2 s3 : sort),
      typ e T (Srt s1) ->
      typ (Ax T :: e) U (Srt s2) ->
      rule s1 s2 s3 -> typ e (Prod T U) (Srt s3)
  | type_conv :
      forall (e : env) (t U V : term) (s : sort),
      typ e t U ->
      le_type e U V ->
      typ e V (Srt s) ->
      typ e t V
      (* sert uniquement quand il y a des sortes non typees: *)
  | type_conv_srt :
      forall (e : env) (t U : term) (s : sort),
      typ e t U -> le_type e U (Srt s) -> typ e t (Srt s).Inductive wf : env -> Prop :=
    | wf_nil : wf nil
    | wf_var :
        forall (e : env) (T : term) (s : sort),
        typ e T (Srt s) -> wf (Ax T :: e)
    | wf_cst :
        forall (e : env) (t T : term) (s : sort),
        typ e t T -> typ e T (Srt s) -> wf (Def t T :: e)
with typ : env -> term -> term -> Prop :=
  | type_ax :
      forall (e : env) (s1 s2 : sort),
      wf e -> axiom s1 s2 -> typ e (Srt s1) (Srt s2)
  | type_var :
      forall (e : env) (v : nat) (t : term),
      wf e -> item_lift t e v -> typ e (Ref v) t
  | type_abs :
      forall (e : env) (T U M : term) (s : sort),
      typ e (Prod T U) (Srt s) ->
      typ (Ax T :: e) M U -> typ e (Abs T M) (Prod T U)
  | type_app :
      forall (e : env) (u v V Ur : term),
      typ e v V -> typ e u (Prod V Ur) -> typ e (App u v) (subst v Ur)
  | type_prod :
      forall (e : env) (T U : term) (s1 s2 s3 : sort),
      typ e T (Srt s1) ->
      typ (Ax T :: e) U (Srt s2) ->
      rule s1 s2 s3 -> typ e (Prod T U) (Srt s3)
  | type_conv :
      forall (e : env) (t U V : term) (s : sort),
      typ e t U ->
      le_type e U V ->
      typ e V (Srt s) ->
      typ e t V
      (* sert uniquement quand il y a des sortes non typees: *)
  | type_conv_srt :
      forall (e : env) (t U : term) (s : sort),
      typ e t U -> le_type e U (Srt s) -> typ e t (Srt s).Inductive wf : env -> Prop :=
    | wf_nil : wf nil
    | wf_var :
        forall (e : env) (T : term) (s : sort),
        typ e T (Srt s) -> wf (Ax T :: e)
    | wf_cst :
        forall (e : env) (t T : term) (s : sort),
        typ e t T -> typ e T (Srt s) -> wf (Def t T :: e)
with typ : env -> term -> term -> Prop :=
  | type_ax :
      forall (e : env) (s1 s2 : sort),
      wf e -> axiom s1 s2 -> typ e (Srt s1) (Srt s2)
  | type_var :
      forall (e : env) (v : nat) (t : term),
      wf e -> item_lift t e v -> typ e (Ref v) t
  | type_abs :
      forall (e : env) (T U M : term) (s : sort),
      typ e (Prod T U) (Srt s) ->
      typ (Ax T :: e) M U -> typ e (Abs T M) (Prod T U)
  | type_app :
      forall (e : env) (u v V Ur : term),
      typ e v V -> typ e u (Prod V Ur) -> typ e (App u v) (subst v Ur)
  | type_prod :
      forall (e : env) (T U : term) (s1 s2 s3 : sort),
      typ e T (Srt s1) ->
      typ (Ax T :: e) U (Srt s2) ->
      rule s1 s2 s3 -> typ e (Prod T U) (Srt s3)
  | type_conv :
      forall (e : env) (t U V : term) (s : sort),
      typ e t U ->
      le_type e U V ->
      typ e V (Srt s) ->
      typ e t V
      (* sert uniquement quand il y a des sortes non typees: *)
  | type_conv_srt :
      forall (e : env) (t U : term) (s : sort),
      typ e t U -> le_type e U (Srt s) -> typ e t (Srt s).Definition rule_sat (s1 s2 s3 : sort) : Prop :=
    exists2 x1 : _,
      le_sort s1 x1 & (exists2 x2 : _, le_sort s2 x2 & rule x1 x2 s3).

(* Specifications: *)
Lemma type_prod_sat : forall (e : env) (T U : term) (s1 s2 s3 : sort), typ e T (Srt s1) -> typ (Ax T :: e) U (Srt s2) -> rule_sat s1 s2 s3 -> typ e (Prod T U) (Srt s3).
Theorem typ_wf : forall (e : env) (t T : term), typ e t T -> wf e.
Theorem inv_wf : forall (e : env) (d : decl), wf (d :: e) -> wf e.
Lemma inv_wf_sort : forall (e : env) (d : decl), wf (d :: e) -> exists s : sort, typ e (typ_of_decl d) (Srt s).
Theorem wf_sort : forall (e : env) (n : nat) (d : decl), item d e n -> wf e -> forall f : env, trunc (S n) e f -> exists s : _, typ f (typ_of_decl d) (Srt s).
Theorem wf_definition : forall (n : nat) (e : env) (m t : term), item (Def m t) e n -> wf e -> forall f : env, trunc (S n) e f -> typ f m t.