Lectures onType Theory
Chapter 89
Chapter 89Core route

The Calculus of Inductive Constructions

The Calculus of Constructions has dependent products but no kernel primitive for a vector declaration, a terminating recursive definition over vectors, or case analysis whose result lives in a cumulative universe. A proof-assistant kernel must integrate all of these operations in one conversion judgment. The integration studied here is one frozen calculus, not the intersection of all systems called CIC.

The frozen PCUIC system

Convention 89.1 — Historical PCUIC system card

Here PCUIC means the Predicative Calculus of Cumulative Inductive Constructions formalized by the checksum-pinned Coq Coq Correct! artifact, archive commit 914e4c6c8b9a5c7c87454c2da960dd8d4b8c81cd. Its sorts are Prop, Set, and predicative universes represented by universe expressions. It has universe polymorphism, a cumulative conversion relation, primitive projections, fixpoints, and cofixpoints. Its frozen leq_term clause for two Ind terms nevertheless compares their universe instances by eq_Ind in PCUICEquality.v; that clause has no FIXME marker. Separately, the Cumulative_ctx branch of consistent_instance in PCUICTyping.v is marked FIXME Cumulative. It omits the module system, template polymorphism, casts that select a conversion algorithm, function η, and primitive-record η.

The theorem statuses in remark 89.20 are part of this card. Results from the living MetaRocq checkout or another CIC presentation do not fill an open cell of the historical system.

The base pure type system is the Calculus of Constructions vertex of chapter 22.

Convention 89.2 — The PCUIC delta over CoC

The PCUIC sorts are Prop, Set, and constrained universe expressions. This sort grammar replaces the CoC pure-type-system sort set. The successor-sort operation replaces the CoC axioms, and sortOfProduct replaces the product triples. The three-clause declarative cumulative relation replaces beta-convertibility in typing. PCUIC adds local definitions and ordered global declarations, universe instances, inductive and coinductive blocks, cases, primitive projections, guarded fixpoints, configured cofixpoints, and the corresponding root contractions. No CoC sort axiom, PTS triple (s1,s2,s3), or bare equivalence-closure conversion rule remains as a second typing path.

Definition 89.3 — Raw PCUIC terms

The raw terms of the frozen artifact are generated by the following constructors: t,u::=Rel(n)Var(x)Evar(n,t¯)Sort(U)Prod(x,A,B)Lambda(x,A,t)Let(x,b,A,t)App(t,u)Const(c,u¯)Ind(I,u¯)Construct(I,k,u¯)Case((I,np),P,c,b¯)Proj(p,c)Fix(d¯,k)CoFix(d¯,k). Here n is a de Bruijn index; names on binders are printing annotations; u¯ is a universe instance; np is the number of uniform parameters; b¯ is a list of branches with arities; and d¯ is a mutually recursive block with one selected component k. The raw syntax contains Var and Evar for quotation and goal-level data, but the typing family below has no rule for either constructor. They are therefore not closed kernel terms.

Definition 89.4 — Contexts and global environments

A local declaration is either an assumption x:A or a definition x:=b:A. A local context is a snoc-ordered list of such declarations; de Bruijn index zero denotes its last declaration. A global environment Σ is an ordered list whose entries are constants or mutual inductive bodies. A constant body contains a type, an optional body, and a universe declaration. A mutual inductive body contains

  1. one shared parameter context and its length np;

  2. one or more inductive bodies, each with an arity, constructor list, primitive-projection list, and allowed elimination sort families;

  3. a Finite, CoFinite, or BiFinite tag and one universe declaration. These mean inductive, coinductive, and nonrecursive record, respectively.

A reference may use only an earlier global declaration. We write Σ;Γt:T for the artifact’s typing family.

The order on global declarations prevents a constant body from referring to itself except through a checked fixpoint. Mutual inductive references are introduced as one block because constructor types may mention every family in that block.

Definition 89.5 — Frozen well-formedness and typing

Write WF(Σ) for the artifact’s well-formed global-environment family and WFΣ(Γ) for its local-context family. The empty global environment is well formed. An extension Σ,d is well formed exactly when Σ is well formed, the name of d is fresh, the universe declaration of d introduces fresh levels and satisfiable constraints, and d satisfies its declaration condition. A constant body has its declared type; an axiom’s type inhabits a sort. A mutual inductive block has a well-formed parameter context with the recorded number of assumptions, checked arities, constructors and projections, valid universe and elimination data, and a true ind_guard oracle. Writing UDeclOK(Σ,U) for fresh declared levels, constraints over declared levels, monomorphic-level discipline, and satisfiability, and DeclOK(Σ,U,d) for the preceding constant or inductive condition, the global family has the exact outer rules

WF([])
PCUIC-Global-empty
WF(Σ)fresh(d,Σ)UDeclOK(Σ,Ud)DeclOK(Σ,Ud,d)
WF(Σ,d)
PCUIC-Global-extend

For a transparent constant, DeclOK is the typing judgment for its body at its declared type; for an axiom it is the existence of a sort for the declared type. For a mutual block it is exactly the parameter, body, constructor, projection, universe, elimination, and guard tuple listed above.

The term-typing family is the least family generated by the following named rules. Here Inst(u,U) checks a universe instance, d[n] lifts by n, and WfTypeΣ,Γ(B) means that B is a well-formed arity or has some sort.

WFΣ(Γ)Γ[n]=d
Σ;ΓRel(n):d.type[n+1]
PCUIC-Rel
WFΣ(Γ)levels(Σ)
Σ;ΓSort():Sort(super())
PCUIC-Sort
Σ;ΓA:Sort(s1)Σ;Γ,x:AB:Sort(s2)
Σ;ΓProd(x,A,B):Sort(sortOfProduct(s1,s2))
PCUIC-Prod
Σ;ΓA:Sort(s)Σ;Γ,x:At:B
Σ;ΓLambda(x,A,t):Prod(x,A,B)
PCUIC-Lambda
Σ;ΓA:Sort(s)Σ;Γb:AΣ;Γ,x:=b:At:B
Σ;ΓLet(x,b,A,t):Let(x,b,A,B)
PCUIC-Let
Σ;Γf:Prod(x,A,B)Σ;Γu:A
Σ;ΓApp(f,u):B[u/x]
PCUIC-App

Global lookup has three distinct rules. In the constructor conclusion, ctorType performs universe instantiation and substitutes the mutual families for the block-local de Bruijn references.

WFΣ(Γ)declConst(Σ,c,d)Inst(u,d.universes)
Σ;ΓConst(c,u):d.type[u]
PCUIC-Const
WFΣ(Γ)declInd(Σ,I,M,D)Inst(u,M.universes)
Σ;ΓInd(I,u):D.arity[u]
PCUIC-Ind
WFΣ(Γ)declCtor(Σ,I,k,M,D,C)Inst(u,M.universes)
Σ;ΓConstruct(I,k,u):ctorType(M,C,I,k,u)
PCUIC-Construct

For the case rule, define CaseOKΣ,Γ to be the exact conjunction declInd(Σ,I,M,D),M.np=np,p¯=firstn(np,a¯),Σ;ΓP:PT,typesOfCase(I,M,D,p¯,u,P,PT)=(ictx,pctx,s,B¯),correctArity(Σ,D,I,u,ictx,p¯,pctx),allowedFamily(s,D.kelim),Σ;Γc:apps(Ind(I,u),a¯),All2(λ(q,b),(q,B).q=q×(Σ;Γb:B)×(Σ;ΓB:Sort(s)),b¯,B¯). Here allowedFamily(s,D.kelim) is the artifact’s existential Boolean test that compares the sort family against the stored elimination families. Nothing is hidden behind a source-language coverage judgment. The rule is

CaseOKΣ,Γ(I,np,u,P,c,b¯,a¯)
Σ;ΓCase((I,np),P,c,b¯):apps(P,skipn(np,a¯)++[c])
PCUIC-Case

The paired branch arities must agree exactly, and a branch binds only the nonparameter constructor arguments; PCUIC-Case creates no induction hypotheses.

If p=(I,np,na) is a declared projection with stored type Tp, the projection rule is

declProj(Σ,p,M,D,Tp)Σ;Γc:apps(Ind(I,u),a¯)|a¯|=M.np
Σ;ΓProj(p,c):Tp[u][c,rev(a¯)]
PCUIC-Proj

Let Δd¯:=fixContext(d¯) and let |Δd¯| also denote the lift cutoff used below. The two recursive rules are exactly

fix_guard(d¯)=trued¯[k]=dWFΣ(Γ,Δd¯)ed¯.Σ;Γ,Δd¯e.body:e.type[|Δd¯|]ed¯.isLambda(e.body)
Σ;ΓFix(d¯,k):d.type
PCUIC-Fix
allow_cofixd¯[k]=dWFΣ(Γ,Δd¯)ed¯.Σ;Γ,Δd¯e.body:e.type[|Δd¯|]
Σ;ΓCoFix(d¯,k):d.type
PCUIC-CoFix

The historical cofix rule has neither a cofix guard nor a lambda-shape premise. Finally,

Σ;Γt:AWfTypeΣ,Γ(B)CumulΣ,Γ(A,B)
Σ;Γt:B
PCUIC-Cumul

There are no rules for Var or Evar. These declaration and term clauses, rather than the raw grammar alone, are the frozen well-formed syntax.

Construction 89.6 — A rule-coverage trace

Let dN be the ordinary natural-number block, and let dV contain Vector@{u}(A:Type@{u}):NType@{u},vnil:Vector(A,0),vcons:Π(n:N).AVector(A,n)Vector(A,suc(n)). Rule PCUIC-Global-empty derives WF([]). Two uses of PCUIC-Global-extend, first for dN and then for dV, derive WF([dN,dV]). The first extension is necessary because the arity and constructor types of dV refer to N. In a well-formed context Γ=(A:Sort(u),x:A), the local rules give Σ;ΓSort(u):Sort(super(u))PCUICSort,Σ;ΓRel(0):APCUICRel,Σ;A:Sort(u)Lambda(x,A,Rel(0)):Prod(x,A,A)PCUICLambda,Σ;A:Sort(u)Prod(x,A,A):Sort(u)PCUICProd. For a:A, application and local naming continue the same derivation: Σ;A,aApp(Lambda(x,A,x),a):APCUICApp,Σ;A,aLet(y,a,A,y):Let(y,a,A,A)PCUICLet. Let did be the transparent constant declaration with type A:Sort(u)AA and body λA.λx.x. After global lookup in [dN,dV,did], the three lookup rules derive the declared types of Const(id,u), Ind(IV,u), and Construct(IV,0,u). For v:Vector(A,suc(n)), put C(0):=1, C(suc(m)):=A, and Phead:=λm.λv.C(m). The complete vector-head term with predicate and branches Case((IV,1),Phead,v,[(0,),(3,λm.λx.λxs.x)]):A then concludes by PCUIC-Case: the nil branch has type C(0) and the cons branch has type C(suc(m)). The generated vector-induction block records the vector position as principal. Its cons branch recurses only on the constructor field xs, so fix_guard returns true and PCUIC-Fix derives the declared type. A constructor-headed vector later enables PCUIC-Fix-unfold.

For the two remaining raw forms, extend the environment by the concrete blocks Box@{u}(A:Type@{u}):Type@{u},box:ABox(A),unbox:Box(A)A,(dBox) and, writing KA:=KStream@{u}(A), let KA:Type@{u},kcons:AKAKA.(dStream). Declare dBox BiFinite with primitive projection punbox, and declare dStream CoFinite. For a:A, PCUIC-Proj derives ba:=box(A,a):Box(A),Proj(punbox,ba):A. Let the selected cofix body be repeat:AKStream(A):=λx.kcons(x,repeat(x)). When allow_cofix holds, its lifted body checks in the one-entry mutual context, and PCUIC-CoFix derives the declared type of the selected component. Finally, if an inferred type A is cumulative to a well-formed B, PCUIC-Cumul derives the widened judgment Σ;Γt:B. These terms give a concrete edge for every rule on the card; reduction remains a separate relation.

Sorts, constraints, and cumulativity

PCUIC does not identify universe levels with natural numerals in its syntax. It separates expressions, constraints, and valuations.

Definition 89.7 — Universe expressions and consistency

A universe level is one of Prop,Set,Level(x),Var(n). A universe expression is a nonempty maximum of terms and +1. A universe constraint is <, , or =. A valuation sends Prop to 1, Set to 0, monomorphic named levels to positive integers, and polymorphic variables to natural numbers. A constraint set is consistent when some valuation satisfies every constraint.

The order UϕV holds when every valuation satisfying ϕ gives the integer denotation of U at most that of V. Equality of universes is mutual order. This semantic definition is the specification; the checker uses a graph algorithm whose correctness is a separate obligation.

The sort rule assigns a successor universe to a type universe. Products use the artifact operation sortOfProduct(s1,s2)={Prop,s2=Prop,max(s1,s2),s2Prop. Thus propositions remain impredicative in their domain, whereas informative products follow the cumulative hierarchy.

Definition 89.8 — Cumulative conversion

Write Σ;Γt0u for a root contraction. Its rules are the following named inferences; apps forms a left-associated application spine.

Σ;ΓApp(Lambda(x,A,t),a)0t[a/x]
PCUIC-β
Σ;ΓLet(x,b,A,t)0t[b/x]
PCUIC-ζ
Γ[n].body=b
Σ;ΓRel(n)0b[n+1]
PCUIC-Rel-δ
declConst(Σ,c,d)d.body=b
Σ;ΓConst(c,u)0b[u]
PCUIC-Global-δ

Define iotaRed(np,k,a¯,b¯):=apps(snd(b¯[k]),skipn(np,a¯)). Abbreviate ck:=apps(Construct(I,k,u),a¯),rk:=iotaRed(np,k,a¯,b¯). Then constructor case reduction is

Σ;ΓCase((I,np),P,ck,b¯)0rk
PCUIC-ι

The three guarded unfolding rules expose their side conditions.

unfoldFix(d¯,k)=(na,f)isConstructor(na,a¯)=true
Σ;Γapps(Fix(d¯,k),a¯)0apps(f,a¯)
PCUIC-Fix-unfold

For the cofix rules, abbreviate c:=apps(CoFix(d¯,k),a¯) and c:=apps(f,a¯).

unfoldCoFix(d¯,k)=(na,f)
Σ;ΓCase(q,P,c,b¯)0Case(q,P,c,b¯)
PCUIC-CoFix-case
unfoldCoFix(d¯,k)=(na,f)
Σ;ΓProj(p,c)0Proj(p,c)
PCUIC-CoFix-proj
p=(I,np,na)a¯[np+na]=a
Σ;ΓProj(p,ck)0a
PCUIC-Proj-ι

The compatible one-step relation tu closes these root contractions under every argument position of every raw constructor, using the extended local context under binders. The artifact’s declarative cumulativity is generated by exactly three clauses:

leq_termΣ(t,u)
CumulΣ,Γ(t,u)
Cumul-refl
tvCumulΣ,Γ(v,u)
CumulΣ,Γ(t,u)
Cumul-red-l
CumulΣ,Γ(t,v)uv
CumulΣ,Γ(t,u)
Cumul-red-r

The base comparison leq_termΣ is relative to the global universe constraints. At sorts it includes constraint-relative eq_universe and universe order; at products it compares domains by conversion and codomains covariantly. Historical PCUIC does not use contravariant domain cumulativity. The artifact’s Conv relation has the same reduction clauses and uses the equality comparison eq_term in its base clause. Neither relation is defined as an equivalence closure. Transitivity of Cumul, and symmetry of Conv, are derived theorems using confluence. The Cumul premise in PCUIC-Cumul is therefore PCUIC term cumulativity, not subtyping from an earlier programming calculus.

Each root rule has a visible instance: App(Lambda(x,A,x),a)0a,PCUICβLet(x,b,A,x)0b.PCUICζ A reference to a local definition contracts by PCUIC-Rel-δ; a transparent declared constant contracts by PCUIC-Global-δ after universe instantiation. For the vector constructor spine [A,m,x,xs], PCUIC-ι drops the single parameter and applies the cons branch to [m,x,xs]. A checked fixpoint unfolds only when its recorded principal argument is constructor-headed. A cofixpoint unfolds when placed under either a case or a projection, by the two separate cofix rules; after the latter exposes a constructor, PCUIC-Proj-ι selects the field at np+na. These are reductions of raw terms, not equations inferred from the source-language names.

Example 89.9 — One polymorphic declaration

Let the identity’s polymorphic universe declaration be Uid=({u},), where ulevels(Σ). Then UDeclOK(Σ,Uid) holds: the sole level is fresh, there are no ill-scoped or monomorphic constraints, and the empty constraint set is satisfied by every valuation. In that declaration context, the identity constant has type id@{u}:A:Type@{u}AA and body λ(A:Type@{u}).λ(x:A).x. At an instance uv, universe substitution changes every occurrence of u to v. Application to B:Type@{v} checks after the constraint solver verifies the instantiated declaration. A later use at a larger level w may use cumulativity only after establishing vw; the checker does not infer equality of those levels from their printed names.

Exercise 89.1

★☆☆ For universe variables u,v, list the constraints required to type A:Type@{u}AType@{v}. Compute its sort using sortOfProduct and explain why replacing the codomain by Prop changes that sort.

Mutual inductive blocks

An inductive declaration must distinguish data shared by every constructor from data selected by a constructor result.

Definition 89.10 — Parameters, indices, and constructor uniformity

In a mutual block, parameters are the initial telescope copied unchanged into every family and constructor conclusion. indices are the remaining arguments of an inductive family and may vary between constructor conclusions. A block is constructor-uniform when each constructor concludes in a family from the block applied first to exactly the declared parameters in their original order.

The historical artifact records strict positivity through the Boolean oracle ind_guard. A well-formed block requires ind_guard(M)=true. The polynomial arrow fragment uses the strict-positivity condition of remark 28.36: a recursive family may occur only as the final result of a recursive arity, never to the left of an arrow. The kernel guard also delta-unfolds transparent aliases and admits a nested occurrence only when it appears as a uniform parameter of a previously declared inductive whose stored positivity information permits that occurrence. Thus the simple arrow condition is exact for the declarations printed in this chapter, but is not a complete definition of the kernel’s nested-positivity criterion. The artifact does not prove that its Boolean oracle implements this mathematical account, so the oracle belongs to the trusted theory boundary.

Definition 89.11 — Cases and generated induction schemes

For each inductive family I with parameters p¯, indices i¯, and constructors c1,,cm, a case term contains

  1. a predicate P over the indices and scrutinee;

  2. the scrutinee c:Ip¯i¯;

  3. one branch for each constructor, binding exactly that constructor’s nonparameter arguments.

The declaration stores a list kelim(I) of target sort families among Prop, Set, and Type. The case rule checks that the sort family of P belongs below one of those stored families. When I lives in Prop, singleton elimination means that well-formedness permits an informative target only when there is at most one constructor and every nonparameter constructor field has sort Prop. A proposition with two constructors fails the first test, just as an existential carrying x:A fails the second. For a predicative inductive, the frozen check_ind_sorts checks constructor universes and checks index universes only when the configuration flag indices_matter is true. Every checker_flags instance shipped with the artifact sets that flag to false. The function does not validate kelim. Thus the vector trace below explicitly records [Prop,Set,Type] as declaration data; this list is not derived as a well-formedness invariant for every Type-valued inductive.

The kernel case rule is nonrecursive. A generated induction scheme is a separate constant whose body is a guarded fixpoint containing such a case. Its recursive branch invokes the fixpoint on each recursive constructor argument and passes those results to the branch method. Thus induction hypotheses belong to the type and fixpoint body of the generated scheme; they are not additional arguments passed by ι-reduction of Case.

The elimination list is data checked with the declaration, not a slogan that all propositions erase. Equality has singleton elimination into informative sorts. An existential proposition whose constructor carries a witness from an arbitrary informative type cannot reveal that witness by elimination into Set or Type.

Example 89.12 — Strict positivity rejects a loop

The declaration Bad:Type,roll:(BadBad)Bad places Bad in the domain of an arrow inside a constructor argument. A strict-positivity implementation of ind_guard rejects the block. If it were admitted, the self-application construction used in the strict-positivity boundary of chapter 28 would recover a reduction cycle. Positivity is therefore a normalization premise, not a formatting check on constructor conclusions.

Fixpoints and cofixpoints

Definition 89.13 — Historical recursive guards

A mutual fixpoint body records a name, type, body, and the position of its principal recursive argument. The historical PCUIC typing rule requires the Boolean oracle fix_guard(d¯)=true and selects one well-typed component. Root reduction unfolds that component only when its principal argument is constructor-headed. The artifact assumes that the guard is stable under reduction, universe equality, renaming, lifting, and substitution.

A cofixpoint uses the same mutual-body representation and unfolds only when the surrounding term is a case or primitive projection. In the frozen artifact, however, PCUIC-CoFix requires only that the configuration flag allow_cofix is enabled, the selected component exists, the mutual context is well formed, and every body has its declared lifted type. It has no cofix guard premise. This asymmetry with PCUIC-Fix is an exact historical boundary, not an omitted source-language check. Tactics that synthesize decreasing evidence or elaborate an equation compiler are not kernel rules.

The guard excludes a loop that satisfies every other premise of PCUIC-Fix. Let the one-entry block be d¯Ω:=[f:NN:=λ(n:N).fn],F:=Fix(d¯Ω,0). In the mutual context f:NN, the body is a lambda and has the declared lifted type. Its recursive call is not made on a constructor field, so fix_guard(d¯Ω)true and PCUIC-Fix cannot derive a type for F. If that sole premise were deleted, the constructor-headed argument 0 would trigger PCUIC-Fix-unfold and give the one-step loop apps(F,[0])0PCUICFixunfoldapps(F,[0]). Thus the guard blocks a concrete divergence rather than merely classifying a source definition.

The observation-triggered unfolding sites avoid immediate unobserved expansion of a cofixpoint; they include no static productivity premise. They also do not turn the constructor presentation into the destructor-corecursor calculus of chapter 33; the two systems have different syntax and subject-reduction obligations.

Remark 89.14 — The cofixpoint subject-reduction boundary

The Coq Coq Correct! paper records a subject-reduction difficulty for cofixpoint introduction in its selected conversion. The historical formalization therefore contains no unconditional full-PCUIC subject reduction theorem. No result from the destructor presentation of chapter 33 repairs this constructor/cofix system without a translation and preservation proof.

Three declarations through the checker

The following traces distinguish declaration checking from later term checking. Each declaration is first parsed to the raw constructors of definition 89.3; the checker then validates universe instances, arities, constructor types, guards, and elimination data before extending the global environment.

Example 89.15 — Vectors

Work over the well-formed environment [dN] containing the natural-number block. At universe u, declare Vector@{u}(A:Type@{u}):NType@{u},vnil:Vector(A,0),vcons:Π(n:N).AVector(A,n)Vector(A,suc(n)). The checker trace is:

  1. look up N in dN, then parse one finite inductive body with parameter A and index n;

  2. take the block universe declaration UV=({u},),UDeclOK([dN],UV), where the second judgment follows by freshness and satisfiability;

  3. verify that its arity ends in Type@{u}, then run the constructor-universe check check_constructors_smaller. The collected sorts of the two complete constructor types are ind_ctors_sort=[u,u]. Deriving the full vcons product sort uses N:Set and the A and Vector domains at u. The check asks for uu twice against the inductive sort, and both comparisons are entailed;

  4. check both constructor types in the context containing the family and the uniform parameter A;

  5. check that each recursive occurrence of Vector is positive and that each conclusion begins with the same A;

  6. store the chosen ind_kelim entries Prop, Set, and Type;

  7. generate the nonrecursive case predicate over n and the scrutinee; then, as a separate declaration, check the guarded fixpoint that defines the induction scheme.

For P:n:NVector(A,n)Uw, the generated induction constant has methods z:P(0,vnil),s:m:Nx:Axs:Vector(A,m)P(m,xs)P(suc(m),vcons(m,x,xs)). Its fixpoint body cases on the vector. The raw cons branch binds only m,x,xs; the body itself makes the recursive call on xs and passes the result to s. If IV=(kn,0) is the block’s inductive identifier, the raw case information is (IV,1) and the two branch entries have arities [(0,bnil),(3,bcons)]. The single parameter A is discarded by iotaRed before either branch is applied; no induction hypothesis is among those three cons arguments.

Kernel branch checking remains complete even when the caller knows a successor index. Define C(0):=1,C(suc(m)):=A. A head case uses predicate λm.λv.C(m), nil branch :C(0), and cons branch λm.λx.λxs.x:C(suc(m)). Applying that complete case to v:Vector(A,suc(n)) has type C(suc(n))A. The nil branch is checked but cannot be selected by a well-typed constructor-headed scrutinee at that index.

Example 89.16 — Equality

Declare Eq@{u}(A:Type@{u})(x:A):AProp,refl:Eq(A,x,x). The family has parameters A,x and one index. It is strictly positive and has one constructor with no informative nonparameter field. The declaration therefore records singleton elimination, allowing the motive of an equality case to live in Type@{v}. The branch index is x, so the generated eliminator is the equality eliminator after its parameters and universe instances are restored.

Example 89.17 — An existential proposition

For A:Type@{u} and P:AProp, declare Exists(A,P):Prop,intro:x:AP(x)Exists(A,P). The constructor is positive, but it carries the informative witness x:A. The checker records elimination into Prop, not arbitrary Type. A predicate returning N and a branch returning x must therefore be rejected at the elimination-sort check. A predicate returning a proposition may use both x and the proof of P(x). If the N-valued motive were admitted, source case reduction could return a value determined by x. Erasure replaces the proposition-valued scrutinee by a box, which retains no witness to select that value; the target could not simulate the source reduction described in remark 89.22. The elimination restriction prevents this failure of the box-erasure simulation.

Remark 89.18 — What the three traces establish

The traces in example 89.15, example 89.16 and example 89.17 establish that the displayed declarations satisfy the chapter’s printed arity, uniformity, positivity, and elimination checks. They do not prove normalization, consistency, canonicity, or correctness of the artifact’s executable checker. Each trace ends with one accepted or rejected declaration-checking obligation. None constructs a reduction normalization function, a model, a closed-value classification theorem, or a simulation between checker output and typing derivations. Those are exactly the missing conclusions named in this qualification.

Exercise 89.2

★★☆ Declare binary trees parameterized by a universe-polymorphic label type. Classify parameters, indices, recursive occurrences, universe constraints, and allowed elimination sorts. Then change one constructor field from Tree(A) to Tree(A)A and identify the path at which strict positivity fails.

The historical theorem boundary

The artifact contains both completed proofs and explicit assumptions or admissions. A checker theorem depending on an admitted metatheorem is a conditional theorem about the executable, not an unconditional theorem about PCUIC.

Theorem 89.19 — Imported: confluence of historical reduction

For a well-formed historical PCUIC global environment Σ, if tu and tv in one local context Γ, then there is w such that uw and vw.

Proof of Theorem 89.19 — Imported: confluence of historical reduction

Proof. This is the endpoint red_confluence in pcuic/theories/PCUICConfluence.v of the frozen artifact. The file constructs parallel reduction, proves its triangle property, transfers the diamond to context-sensitive one-step reduction, and closes under reflexive–transitive reduction. The proof assumes well-formedness of Σ but does not use the strong-normalization axiom. This import has the raw syntax of definition 89.3. Its reduction and conversion are exactly those of definition 89.8. ◻

Remark 89.20 — Historical metatheorem status

For the archive fixed in convention 89.1, the status cells are:

Endpoint Historical artifact status
Confluence proved; imported as theorem 89.19.
Subject reduction open: PCUICSR.v admits sr_red1, from which subject_reduction is derived.
Validity open: PCUICValidity.v admits validity.
Strengthening open: PCUICSafeLemmata.v admits the declaration strengthening (line 1283 in the frozen file).
Principality open: PCUICPrincipality.v admits principal_typing.
Strong normalization assumed/open: PCUICSN.v declares normalisation as an axiom and admits the corollary normalisation’.
Canonicity and consistency open at this frozen signature; the paper notes that they would follow from the normalization statement axiomatized in PCUICSN.v at this signature, but the archive does not prove that statement.
Proof irrelevance used by graph equality template-coq/theories/common/uGraph.v marks the comment immediately before graph_eq as the proof-irrelevance step; the lemma proves equality of canonical graph representations and is used by the safe checker.
Safe-checker soundness conditional on the trusted theory base; safechecker/theories/PCUICSafeChecker.v defines typecheck_program with a dependent typing conclusion and additionally admits check_one_ind_body, add_uctx_make_graph, gc_of_constraints_union, and no_prop_levels_union, and assumes graph_eq.
Checker completeness open: pcuic/theories/ PCUICCheckerCompleteness.v contains only its license header and no completeness declaration or proof.
Erasure-relation correctness erasure/theories/ErasureCorrectness.v proves erases_correct, relative to well-formed typing and the same metatheory assumptions, for the artifact’s weak call-by-value target.
First-order erasure corollaries stated in the paper as nonmechanized observations; no corresponding theorem occurs in the pinned archive.

No open row is filled by a theorem from a different CIC variant.

Theorem 89.21 — Conditional checker endpoint

Assume the historical artifact’s normalization, subject-reduction, validity, strengthening, principality, fix-guard stability, proof-irrelevance, universe-graph, and inductive-body obligations. Assume also the selected checker configuration, including its unguarded allow_cofix flag. If its safe checker returns a typing result for a closed program (Σ,t), then the returned type is backed by a squashed derivation in the PCUIC typing relation for the checked environment.

Proof of Theorem 89.21 — Conditional checker endpoint

Proof. The definition typecheck_program constructs its result in the type of checked values rather than returning an unverified Boolean. Its normalization and conversion procedures invoke the listed metatheory interfaces, while environment checking invokes the graph and inductive-body interfaces. Under the stated assumptions, projecting the dependent result yields the typing derivation. Without any one of those assumptions, the artifact term still runs but this projection no longer establishes the corresponding PCUIC theorem; this is why the conclusion is conditional. ◻

Remark 89.22 — Erasure endpoint

The historical erasure replaces types and proofs by a box in an untyped lambda calculus. Its mechanized Theorem 4.7 proves a weak call-by-value simulation: if a well-typed source term erases by the erasure relation and evaluates, then the target evaluates to a value related to the source value. The paper then states Lemma 4.8 and Corollaries 4.8.1–4.8.2 for first-order inductive results under the heading “non-mechanised observations.” Those corollaries identify relational erasure with the executable erasure function, but they are not artifact theorems. Neither endpoint proves source normalization, semantic consistency of added axioms, or correctness for another evaluation order.

Versioned deltas are separate systems

The living MetaRocq checkout in the source library is at the following commit: c8cd46054518193103c3bb33aa6e15c7f489e72c. The repository citation is [The26b]. This checkout contains results and syntax absent from the 2019 archive. The comparison below is deliberately syntactic: it records only facts visible in the two pinned abstract syntaxes and imports no theorem from one column into the other.

Feature Frozen 2019 PCUIC Pinned 2026 MetaRocq snapshot
Proof irrelevance A metatheory assumption used by the checker development; there is no distinct judgmentally proof-irrelevant raw sort. Universes.v has raw sort sSProp, family tag fSProp, order constructors ltPropSProp and ltSPropType, and maps fSProp to Irrelevant. These syntax and order declarations do not discharge the 2019 metatheory assumption.
Primitive records BiFinite blocks and tProj; primitive-record η is absent from conversion. BasicAst.v retains BiFinite; the raw term syntax retains tProj. A primitive-record η result is not imported or claimed here.
Quotients No raw quotient constructor or quotient reduction rule. No raw quotient constructor; a library encoding or package is therefore not a new PCUIC kernel rule.
Other primitives The term grammar ends at fixpoints and cofixpoints. The raw grammar adds tPrim for the snapshot’s primitive values.

Thus SProp is not another name for Prop. The table establishes only its separate raw sort, order, and relevance data. Its elimination and conversion theorems are status-gated from this chapter and are not inferred from those constructors. Nor does an ordinary quotient package create a quotient computation rule, or a primitive projection create judgmental record η.

The following second card records the exact assistant deltas used for that comparison. It is a dated access card for the cited mutable language references, not a frozen kernel card or an amalgamated calculus [Agd26, Lea26, Roc26].

Reference card Exact delta from the frozen 2019 PCUIC rows above
Agda latest record card A nonrecursive record has judgmental η by default, controllable by eta-equality/no-eta-equality; a coinductive record uses copattern observations and disallows η by default. This is not the frozen BiFinite/tProj conversion.
Lean 2026 type-system card Definitional equality adds proof irrelevance and η for functions and single-constructor structures. The primitive type former Quot and its lift reduction add a quotient computation absent from frozen PCUIC.
Rocq master record card An ordinary record elaborates to a one-constructor variant with case-defined projections. The optional projections(primitive) representation instead disables matching and gives nonrecursive records judgmental η in the documented cases; recursive primitive records do not receive that η rule.

The card compares only the named record, equality, and quotient clauses. Agda, Lean, and Rocq also differ in universes, inductive admissibility, and recursion checks, but none of those unprinted rules is imported here. Thus the card is neither a translation nor a theorem about every release of any assistant.

Exercise 89.3

★★☆ For each hypothesis of theorem 89.21, identify the checker phase that uses it: environment checking, weak-head normalization, conversion, type inference, or declaration checking. Explain why confluence alone does not make weak-head normalization an executable total function.

Exercise 89.4

★★☆ Compare the equality and existential declarations in example 89.16, example 89.17. Write a Type-valued motive for each. State which case is admitted, which is rejected, and which constructor field makes the difference.

Suggested first pass.

None of these problems is a prerequisite. Begin with exercise 89.5, then complete exercise 89.8.

Exercise 89.5

★★★ Expand the vector block of example 89.15 into raw Ind and Construct references with a universe instance. Derive the type of its dependent case predicate and both raw branch types; verify that neither branch receives an induction hypothesis. Then derive the type of the separate generated induction constant. In its cons method, mark the parameter, index, recursive vector, and induction hypothesis separately.

Exercise 89.6

★★★ Take a constructor-headed raw vector case and a primitive projection from a cofixpoint. Give their complete one-step reductions under definition 89.8. Then remove the constructor head from the fixpoint’s principal argument and explain why fix unfolding no longer applies. State separately where a recursive call appears in the fixpoint-built vector induction constant.

Exercise 89.7

★★☆ Reconstruct the status table of remark 89.20 directly from the frozen archive. For every open or conditional cell, record the exact file and declaration name. Do not use the living MetaRocq checkout to change a historical status.

Exercise 89.8

★★★ Practical project.pcuic-declaration-trace Implement in Kappa a small declaration checker for the printed fragment containing universe levels, one inductive family, constructors, strict-positivity paths, and an allowed-elimination flag. Maintain the invariant that every accepted constructor ends in the declared family with all parameters uniform and has no family occurrence in a negative position. Its five verdict lines must record these cases:

  1. accept the vector summary of example 89.15 with ACCEPT Vector;

  2. record ACCEPT Equality for the equality summary in example 89.16;

  3. record constructor-arg/domain for the rejection in example 89.12;

  4. reject informative elimination in example 89.17 with Prop-witness-blocks-Type-elimination;

  5. reject a two-constructor proposition named Or, whose fields all have sort Prop, with Prop-not-singleton-for-Type-elimination.

Derive informative elimination from at most one constructor and constructor fields of sort Prop; do not accept a caller-supplied Boolean certificate. The exact five verdict lines followed by the summary line form the six-line acceptance report. This program checks only the printed fragment; it is not an implementation or proof of the historical PCUIC checker.

Sources. The historical calculus and status audit use Sozeau, Boulier, Forster, Tabareau, and Winterhalter [SBF^+20], together with its exact Zenodo archive [SBF^+19]. The Calculus of Constructions is due to Coquand and Huet [CH88]. The living MetaRocq repository [The26b] is consulted only for the explicitly versioned delta above.

Search the book

Type to search the local edition.