Lectures onType Theory
Chapter 18
Chapter 18Core route

Subtyping, Records, and Bounded Quantification

A function that reads an x coordinate should accept both of the following values: p={x=0},c={x=0,color=true}. Their record types are not equal. Requiring equality would force every caller to rebuild c as a one-field record before calling the function. Allowing every type mismatch, on the other hand, would let a function ask for a field that is absent. We add records, top, bottom, and bounded universals to a simply typed term language. The judgment A<:B means that an A-value may be used wherever a B-value is required; in that case, A is a subtype of B.

The operational base is the call-by-value simply typed calculus of section 2.1, section 2.5, section 2.6: functions and Booleans, then products, sums, and Unit with their typing and reduction rules. We also use the primitive natural numbers Nat, 0, and suc. Relative to the inherited term and value grammars, the syntax delta is t::=0suc(t)natrec(t;t0;x.y.ts),v::=0suc(v). Their eliminator is natrec(t;t0;x.y.ts), with predecessor x and recursive result y bound in ts. The complete delta is XΓ0:NatTZero,Γt:NatΓsuc(t):NatTSuc, Γt:NatΓt0:AΓ,x:Nat,y:Ats:AΓnatrec(t;t0;x.y.ts):ATNatRec. Call-by-value evaluation is completed by the following congruence and root rules. The metavariable v in E-NatSuc already ranges over values, so the recursive equation cannot fire before the successor argument is a value. Its right-hand side uses simultaneous capture-avoiding substitution, so neither replacement is substituted into the other.

tt
suc(t)suc(t)
E-Suc
tt
natrec(t;t0;x.y.ts)natrec(t;t0;x.y.ts)
E-NatRec
natrec(0;t0;x.y.ts)t0
E-NatZero
natrec(suc(v);t0;x.y.ts)ts[xv,ynatrec(v;t0;x.y.ts)]
E-NatSuc

Thus (v1,v2) and its projections are the term notation of chapter 2; they are not the constructor-level pairs and two-context judgments of chapter 9. Here T-Var, T-Lam, T-App, and T-Pair denote the Var, Lam, App, and Pair rules of chapter 2. We retain that chapter’s names Unit-I, Inl, Inr, Case, Fst, and Snd for the other inherited introduction and elimination rules.

First-order term contexts are generated by X ctxCEmpty,Γ ctxΓA typexdom(Γ)Γ,x:A ctxCTerm.

Every type has kind Ty, so type formation is written ΓA type. Records are immutable finite maps.

Forgetting information safely

Fix a countable set of labels with a total order. A record type is a finite map from labels to types, and a record term is a finite map from labels to terms: {i:Ai}iI,{i=ti}iI. The labels in a display are distinct. Reordering a display does not change the map; thus {x:Nat,color:Bool} and {color:Bool,x:Nat} are literally the same type, not merely isomorphic types. The fixed order of labels is used only to choose a deterministic evaluation order for record fields.

The formation judgment used throughout the first-order development is generated by the following complete rule sheet, together with the inherited base types K{Unit,Bool,Nat}:

K{Unit,Bool,Nat,Top,Bot}
ΓK type
F-Base
ΓA typeΓB type
ΓAB type
F-Arr
ΓA typeΓB type
ΓA×B type
F-Prod
ΓA typeΓB type
ΓA+B type
F-Sum
ΓAi type(iI)i pairwise distinct
Γ{i:Ai}iI type
F-Rcd

The empty record is covered by F-Rcd with I=.

Definition 8.1 — The first-order subtype calculus

The types added to the inherited simple types are A,B::=TopBot{i:Ai}iI. Here Top forgets all usable information. By contrast, Bot is below every type and has no introduction form in this calculus. In a language with nonreturning constructs it could also be the result type of an operation such as throw; no such operation is added here. The judgment ΓA<:B is generated by the following rules. The context contains term variables only in this section.

ΓA type
ΓA<:A
S-Refl
ΓA<:BΓB<:C
ΓA<:C
S-Trans
ΓA type
ΓA<:Top
S-Top
ΓA type
ΓBot<:A
S-Bot
ΓB1<:A1ΓA2<:B2
ΓA1A2<:B1B2
S-Arr
ΓA1<:B1ΓA2<:B2
ΓA1×A2<:B1×B2
S-Prod
ΓA1<:B1ΓA2<:B2
ΓA1+A2<:B1+B2
S-Sum
JIΓAj<:Bjfor every jJ
Γ{i:Ai}iI<:{j:Bj}jJ
S-Rcd

Each subtyping rule presupposes formation of every type in its conclusion; later rule displays omit these formation premises.

Structural subtyping gives Top the role of a universal interface without introducing classes.

The record rule performs three jobs. Taking JI forgets fields; this is width subtyping. Comparing Aj<:Bj changes a retained field to a less informative type; this is depth subtyping. Treating the components as a finite map gives permutation invariance: reordering fields changes no record type. These are consequences of one representation and one rule, not three independent axioms.

Put Point:={x:Nat},ColorPoint:={x:Nat,color:Bool}. Here S-Refl discharges the sole depth premise Nat<:Nat, and S-Rcd then derives ColorPoint<:Point. The reverse judgment cannot be derived: its record-rule instance would need color in the domain of Point.

Example 8.2 — A complete width-and-depth derivation

Let A={x:Nat,q:Bot,color:Bool},B={q:Nat,x:Top}. The target labels are both present in A. The two depth premises are Bot<:Nat and Nat<:Top. Hence XBot<:NatSBotXNat<:TopSTopA<:BSRcd. The field order in the conclusion has no mathematical role.

Example 18.3 — Aliasing failure under hypothetical update

The calculus has no in-place update rule. If one hypothetically added the usual shared assignment rule while retaining covariant record depth, the following calculation would destroy preservation. Suppose a mutable record is shared through two aliases. Its precise alias has type {q:Nat}: r={q=0}:{q:Nat}. Depth subtyping also exposes the same object through an alias of type {q:Top}. If update were allowed through that alias, the assignment r.q:=unit would be accepted because unit:Top. Reading r.q through the original alias would still be assigned Nat but would now return unit. The records used below cannot perform this update: evaluation reconstructs immutable values and projection only observes a stored field.

The same aliasing mechanism explains why Java’s covariant mutable arrays need a dynamic ArrayStoreException: the runtime check compensates for a covariance rule that the immutable record calculus can validate statically.

The four nonrecord rules have direct behavioral readings. Every value can be handed to a function that promises to use it only at Top; no closed value can be handed out at Bot. Products preserve the order in each component because their consumers are the two projections. Sums also preserve the order: case analysis retains the injection tag and applies the appropriate branch to the enclosed value. For example, ColorPoint×Nat<:Point×Top,ColorPoint+Nat<:Point+Top, by one use of S-Prod or S-Sum, followed by the already derived record judgment and S-Top. Projection or case analysis can use exactly the information promised on the right. No value-introduction rule concludes Bot, so subsumption from bottom does not itself manufacture a closed source value.

Arrows have two directions. A value of type A1A2 may stand in for a value of type B1B2 only when it accepts every B1 input and produces an acceptable B2 output. Thus B1<:A1 but A2<:B2. The words covariant and contravariant name only these directions: a covariant premise follows source to target, while a contravariant premise reverses it.

Proposition 8.3 — Why arrow domains reverse

Replacing the first premise of S-Arr by A1<:B1 destroys preservation.

Proof of Proposition 8.3 — Why arrow domains reverse

Proof. The false covariant rule and Nat<:Top would give NatNat<:TopNat. Therefore the identity λn:Nat.n could be used at TopNat. Since unit:Top, the application (λn:Nat.n)unit would have type Nat. It takes one beta step to unit, which has no type below Nat. A well-typed term would reduce to a term without its alleged type. ◻

This counterexample constructs the failure rather than attaching the word “contravariant” to the rule. The domain premise reverses precisely to stop the construction. In nominal languages the same constraint appears when a method override is forbidden from narrowing the type of an accepted parameter: callers are entitled to supply every argument admitted by the supertype interface.

The corresponding coercion makes the reversal mechanical. To turn f:A1A2 into a function B1B2, first convert the incoming B1 value in the reversed direction, apply f, and convert the result in the forward direction: cA1A2,B1B2(f)=λx:B1.cA2,B2(f(cB1,A1(x))). This calculation is an explanation of S-Arr, not an additional subtyping rule. Order-theoretically, the domain conversion is precomposition: f is first composed with cB1,A1:B1A1. Precomposition reverses the order of its input interface, whereas postcomposition with cA2,B2:A2B2 preserves the order of the output interface. This is the mathematical content of contravariance and covariance in S-Arr; the callback example below is one operational consequence.

The same failure appears in an ordinary callback interface. Let Event={tag:Nat},Click={tag:Nat,x:Nat}. A callback registry that accepts a handler of type EventNat may invoke it on {tag=0}. The click-only handler λe:Click.e.x must therefore not be accepted by that registry. Covariant arrow domains would accept it because Click<:Event; the eventual call reduces to the missing projection {tag=0}.x. This is the programming-language form of the formal preservation counterexample, not a second variance principle.

Exercise 8.1

★☆☆ For each ordered pair among {x:Nat},{x:Top},{x:Nat,color:Bool}, derive the subtype judgment or identify the first premise of S-Rcd that fails. Draw every successful rule tree.

Exercise 8.2

★☆☆ Decide which of the following judgments hold and give a derivation or a counterexample application: TopNat<:NatTop,NatTop<:TopNat.

Subsumption and the dynamics of records

Subtyping becomes a property of programs through one typing rule.

Γt:AΓA<:B
Γt:B
T-Sub
Γti:Aifor every iI
Γ{i=ti}iI:{i:Ai}iI
T-Rcd
Γt:{i:Ai}iIkI
Γt.k:Ak
T-Proj

Rule T-Sub is subsumption: once a term has a more informative type, it may be checked at any supertype.

For example, define xOf:=λp:Point.p.x. Then c:ColorPoint,c:Point,xOf c:Nat. The middle judgment is the only new step. Evaluation still projects from the original two-field value and returns 0.

Record evaluation is left to right in the fixed label order. A record is a value when all its fields are values. In addition to the inherited congruence rules, we use

tktkti is a value for every i<k
{,k=tk,}{,k=tk,}
E-Rcd
kI
{i=vi}iI.kvk
E-Proj
tt
t.kt.k
E-ProjCong

There is no reduction rule for subsumption. It is evidence used by the type system, not a wrapper present in the term.

Definition 8.4 — Intrinsic and coercive readings

Subsumption leaves the source term unchanged. A syntax-directed subtype derivation can instead elaborate to a function cA,B:AB in the same explicitly typed lambda calculus with records. For width subtyping, one possible coercion is cColorPoint,Point(r)={x=r.x}. For an arrow derivation with B1<:A1 and A2<:B2, the coercion is exactly (18.1). For the opening application, coercion insertion gives xOf c(λp:Point.p.x)(cColorPoint,Pointc)(λp:Point.p.x){x=0}0. The declarative typing relation retains subsumption. No coherence theorem is claimed for two elaborations of the same declarative judgment.

The safety proof must account for derivations ending in T-Sub. Ordinary typing inversion is no longer strong enough: from Γv:B we cannot infer the last introduction rule for B. We first recover the outer shape hidden by subtyping.

Lemma 18.6 — Top is maximal in the first-order calculus

If ΓTop<:C in definition 8.1, then C=Top.

Proof of Lemma 18.6 — Top is maximal in the first-order calculus

Proof. Induct on the derivation. Reflexivity and S-Top give the conclusion directly. In a transitivity case, the induction hypotheses give B=Top and then C=Top. No first-order rule has Top as its source. ◻

Lemma 8.5 — First-order subtype shape

No subtype rule inspects a term declaration, so all ten judgments below omit the fixed first-order context Γ:

  1. Bot-Down: if A<:Bot, then A=Bot;

  2. Arr-Down: if A<:B1B2, then A=Bot or A=A1A2 with B1<:A1 and A2<:B2;

  3. Rcd-Down: if A<:{j:Bj}jJ, then A=Bot or A={i:Ai}iI, where JI and Aj<:Bj for every jJ;

  4. Prod-Down: if A<:B1×B2, then A=Bot or A=A1×A2 with A1<:B1 and A2<:B2;

  5. Sum-Down: if A<:B1+B2, then A=Bot or A=A1+A2 with A1<:B1 and A2<:B2.

The corresponding upward statements are:

  1. Rcd-Up: if {i:Ai}iI<:B, then B=Top or B={j:Bj}jJ, where JI and Aj<:Bj for every jJ;

  2. Arr-Up: if A1A2<:B, then B=Top or B=B1B2 with B1<:A1 and A2<:B2;

  3. Prod-Up: if A1×A2<:B, then B=Top or B=B1×B2 with A1<:B1 and A2<:B2;

  4. Sum-Up: if A1+A2<:B, then B=Top or B=B1+B2 with A1<:B1 and A2<:B2.

  5. Base-Both: for K{Unit,Bool,Nat}, if A<:K, then A=Bot or A=K; and if K<:B, then B=Top or B=K.

Proof of Lemma 8.5 — First-order subtype shape

Proof. First prove Bot-Down by induction on a derivation A<:Bot. Reflexivity gives A=Bot. In a transitivity case A<:C<:Bot, the induction hypothesis for the second premise gives C=Bot, and the induction hypothesis for the first premise then gives A=Bot. No other rule has bottom as its target.

Induct simultaneously on the remaining subtype-shape claims. A last structural rule fixes the outer constructor and gives its component comparisons. For example, S-Arr concludes A1A2<:B1B2 from B1<:A1 and A2<:B2. The downward and upward clauses select the corresponding side of this conclusion. Rule S-Bot gives the exceptional source Bot, S-Top gives the exceptional target Top, and S-Refl gives equality of the two outer types.

Only transitivity can hide the fieldwise information. Consider {i:Ai}iI<:C<:{k:Dk}kK. The upward induction hypothesis for the first premise says that C is Top or a record. The first alternative is impossible: substituting C=Top into the second premise gives Top<:{k:Dk}kK, while lemma 18.6 would force that record type to equal Top. Thus C={j:Bj}jJ with JI and Aj<:Bj. The downward induction hypothesis for the second premise gives KJ and Bk<:Dk. Hence KJI,Ak<:Bk<:Dk(kK), and one use of S-Trans per retained field proves the record clause. The downward record clause is the same calculation with the two induction hypotheses read in the opposite order; if the intermediate type is bottom, Bot-Down forces the original source to be bottom.

For arrows, if the intermediate is Bot, Bot-Down makes the original source bottom; if it is Top, the second premise can target an arrow only by contradicting lemma 18.6. The remaining transitivity case factors as A1A2<:C1C2<:B1B2. The two induction hypotheses give B1<:C1<:A1,A2<:C2<:B2, which are composed in their displayed directions. The same two exceptional intermediates are disposed of before the product and sum calculations. For products they give A1<:C1<:B1 and A2<:C2<:B2; for sums they give those same two covariant chains. These calculations prove both the downward and upward product and sum clauses. No remaining last rule has one of the indicated source or target shapes. The three base-type claims use the same induction: only reflexivity, bottom, top, and transitivity can occur, and transitivity composes the two displayed alternatives. ◻

Projection preservation requires a term-level consequence of subtype inversion: a literal record typed through subsumption still contains every field demanded by its record type.

Lemma 8.6 — Literal-record inversion through subsumption

Let r={i=vi}iI be a record value.

  1. There is no derivation Γr:Bot.

  2. If Γr:{j:Bj}jJ, then JI and, for every jJ, there is a type Aj such that Γvj:AjandΓAj<:Bj.

Proof of Lemma 8.6 — Literal-record inversion through subsumption

Proof. Prove the two clauses simultaneously by induction on the typing derivation of the fixed literal r. If the last rule is T-Rcd, clause (a) is impossible, while clause (b) has J=I: take the field types from the premises and use S-Refl for each comparison.

Suppose the last rule is T-Sub, with premises Γr:C and ΓC<:D. If D=Bot, Bot-Down in lemma 8.5 gives C=Bot, contrary to the first induction hypothesis. If D={j:Bj}jJ, the downward record clause of lemma 8.5 says that C is bottom or C={k:Ck}kK, with JK and Cj<:Bj. The bottom alternative is again excluded by the first induction hypothesis. Apply the second induction hypothesis to the typing premise Γr:C. It yields, for every jJK, a type Aj with Γvj:Aj,Aj<:Cj<:Bj. Compose the last two judgments by S-Trans. No other typing rule can conclude a judgment for the literal syntax r. ◻

Lemma 8.7 — Introduction inversion through subsumption

Fix a term context Γ.

  1. No lambda, pair, injection, or successor value has type Bot.

  2. If Γλx:C.t:AB, then there is a type D such that Γ,x:Ct:D,ΓA<:C,ΓD<:B.

  3. If Γv1,v2:A1×A2, then there are C1,C2 such that Γvi:CiandΓCi<:Ai(i=1,2).

  4. If Γinl(v):A1+A2, then some C satisfies Γv:C and ΓC<:A1. If Γinr(v):A1+A2, then some C satisfies Γv:C and ΓC<:A2.

  5. If Γsuc(v):Nat, then Γv:Nat.

Proof of Lemma 8.7 — Introduction inversion through subsumption

Proof. Induct on the typing derivation of the fixed value. Its introduction rule gives the required component typings with reflexive subtypings. The remaining case ends in Γv:EΓE<:FΓv:FTSub. For a lambda λx:C0.t with F=AB, the downward arrow clause gives E=Bot or E=C1C2 with A<:C1 and C2<:B. Clause (a) excludes the first alternative; in the second, the induction hypothesis gives Γ,x:C0t:D, C1<:C0, and D<:C2. Transitivity yields A<:C0 and D<:B.

For a pair with F=A1×A2, the product clause gives E=C1×C2 after excluding bottom. The induction hypothesis gives types Di with Γvi:Di, Di<:Ci, and the subtype premise gives Ci<:Ai; transitivity gives Di<:Ai. For an injection, the sum clause gives the corresponding payload chain D<:Ci<:Ai. For suc(v) at Nat, Base-Both leaves E=Nat after bottom is excluded, and the induction hypothesis gives Γv:Nat. Finally, if F=Bot, Bot-Down gives E=Bot, contradicting clause (a). ◻

Lemma 8.8 — Canonical forms through subsumption

Let v be a closed value.

  1. There is no derivation v:Bot.

  2. If v:AB, then v is a lambda abstraction.

  3. If v:{j:Bj}jJ, then v={i=vi}iI with JI, and for each jJ there is an Aj such that vj:Aj and Aj<:Bj.

  4. If v:A1×A2, then v=v1,v2.

  5. If v:A1+A2, then v=inlv1 or v=inrv2.

  6. If v:Unit, then v=unit.

  7. If v:Bool, then v=true or v=false.

  8. If v:Nat, then v is a numeral: v=0 or v=suc(v) with v:Nat.

Proof of Lemma 8.8 — Canonical forms through subsumption

Proof. Induct simultaneously on the typing derivation for the eight conclusions. An introduction rule fixes the value constructor; in the record case, lemma 8.6 also gives the field judgments. Suppose the last rule is T-Sub, with v:E and E<:A. If A=A1A2, downward arrow shape gives E=Bot or E=C1C2. The first alternative contradicts clause (a); the induction hypothesis for the second shows that v is a lambda. Downward product and sum shape give the same conclusion for pairs and injections. Downward record shape, followed by lemma 8.6, gives the literal and all retained field typings. If A is Unit, Bool, or Nat, Base-Both gives E=Bot or E=A; the first alternative is impossible and the induction hypothesis classifies the value at A.

For clause (a), an introduction rule has a nonbottom conclusion. A final subsumption to Bot has source Bot by Bot-Down, contradicting the induction hypothesis at the shorter derivation. ◻

Lemma 8.9 — Weakening and term substitution

If Γt:A, then inserting a fresh term binding into Γ preserves the judgment. If Γ,x:A,Δt:B and Γv:A, then Γ,Δt[v/x]:B. The same weakening statement holds for first-order subtyping.

Proof of Lemma 8.9 — Weakening and term substitution

Proof. Weakening is an induction on the given typing derivation Γt:A, and the subtype variant is an induction on ΓA<:B. For substitution, induct on the typing derivation. In the variable case, x is replaced by the premise Γv:A; every other variable is recovered from the shortened context. The lambda case alpha-renames its binder before applying the induction hypothesis. In T-Rcd, apply the hypothesis separately to every finite-map entry. In T-Proj, apply it to the record premise. In T-Sub, apply it to the term premise and retain the unchanged first-order subtype derivation. The inherited application, pair, injection, case, Boolean, and natural-number cases reconstruct their last rule from the substituted premises. ◻

Theorem 8.10 — Preservation

If Γt:A and tt, then Γt:A.

Proof of Theorem 8.10 — Preservation

Proof. Induct on the typing derivation, with an inner analysis of the reduction. A final T-Sub has premise Γt:B and B<:A; the induction hypothesis gives Γt:B, after which the same subsumption restores A. In E-Rcd, the induction hypothesis replaces the one reducing field at its declared type, and T-Rcd rebuilds the record. In E-Proj, the typing conclusion for the receiver is a record type {i:Ci}iI containing the projected label. The receiver is a literal record value, so lemma 8.6 gives Γvk:Dk,Dk<:Ck for some Dk; T-Sub therefore gives Γvk:Ck.

For beta reduction, inversion of the application rule gives Γλx:C.e:A0B0 and Γv:A0. By lemma 8.7(b), for some D, Γ,x:Ce:D,A0<:C,D<:B0. Subsumption converts v:A0 to v:C; term substitution yields e[v/x]:D; a final subsumption gives e[v/x]:B0.

For fstv1,v2 and sndv1,v2, product inversion gives Γvi:Ci and Ci<:Ai. Select the relevant premise and subsume it to the projection’s result type. For a left case contraction, sum inversion gives Γv:C with C<:A1; subsume the payload to A1 and substitute it into the left branch. The right contraction is symmetric. In the successor branch of natural-number elimination, lemma 8.7(e) gives Γv:Nat. Rule T-NatRec types r:=natrec(v;t0;x.y.ts):A. Weaken r beneath x:Nat, then apply lemma 8.9 first to yr and then to xv. The binders are fresh for Γ, so neither replacement contains the other binder free; the result is exactly the simultaneous substitution printed in E-NatSuc, at type A. Boolean roots have no hidden payload type. Congruence cases use the induction hypothesis and rebuild their typing rule. ◻

Theorem 8.11 — Progress

If t:A, then t is a value or there is a t with tt.

Proof of Theorem 8.11 — Progress

Proof. Induct on the typing derivation. A final T-Sub uses the induction hypothesis for its term premise; changing a type cannot change whether a term is a value or can step. For a record, step its least nonvalue field; if none exists, the record is a value. For a projection, the induction hypothesis shows that the receiver steps or is a value. In the first case E-ProjCong advances the receiver. In the value case, lemma 8.8(c) shows that it is a record containing the named field, so E-Proj applies. Application uses the arrow clause of the same lemma. Products, sums, Booleans, and naturals use their corresponding clauses. There is no closed value of Bot by clause (a), so the bottom rule does not create an unhandled value form. ◻

Corollary 8.12 — Safety

A closed well-typed term never reaches a closed stuck term by finitely many steps.

Proof of Corollary 8.12 — Safety

Proof. Apply preservation along the reduction sequence, then progress at its final term. ◻

Exercise 8.3

★★☆ Write the projection case of preservation as a complete rule tree for c.x0, including the width-subtyping and subsumption steps. Then explain why the proof needs immutability: if a retained field could be updated through two differently typed aliases, depth covariance would no longer be justified.

Exercise 8.4

★★☆ Fix a closed value v and prove, by induction on a derivation of v:A, that A cannot be Bot. Treat the possible outer value forms simultaneously. At a final subsumption, apply the appropriate clause of lemma 8.5; the typing premise of T-Sub is the strictly smaller derivation.

Joins and meets in the first-order calculus

An if expression needs one result type even when its branches have different record types. For this grammar the strongest possible claim holds: any two types have a least common supertype and a greatest common subtype. It holds because types are finite syntax trees and the subtype rules admit the constructor-shape inversions just proved; merely having finitely many grammar productions would not suffice. Adding recursive types, type variables with bounds, or mutable fields would require a different argument.

Lemma 18.15 — The first-order subtype order

On closed first-order types, <: is reflexive and transitive. It is also antisymmetric: if A<:B and B<:A, then A=B as finite-map types. Hence the closed types form a partial order.

Proof of Lemma 18.15 — The first-order subtype order

Proof. Reflexivity and transitivity are rules. For antisymmetry, use simultaneous induction on the combined sizes of A and B and apply lemma 8.5 in both directions. Top and bottom can be mutual only with themselves. Every other pair has the same outer constructor. Arrow inversion gives mutual domain and codomain comparisons (with the domain directions reversed twice); products and sums give the component comparisons directly. Mutual record width forces equal label sets, and field inversion gives mutual comparisons at every common label. The induction hypotheses give equality of every pair of corresponding components, so the two finite maps are equal. ◻

Definition 8.13 — Join and meet

A type J is a join of A and B when A<:J,B<:J,A<:U and B<:UJ<:U. A type M is a meet when M<:A,M<:B,L<:A and L<:BL<:M. These are properties, not new type constructors.

Definition 18.17 — Recursive bounds

The recursive bounds AB and AB are mutually recursive operations on closed first-order types. The equations involving top and bottom are BotA=A,TopA=Top,BotA=Bot,TopA=A,ABot=A,ATop=Top,ABot=Bot,ATop=A. For K{Unit,Bool,Nat}, put KK=KK=K. Matching compound constructors use (A1A2)(B1B2)=(A1B1)(A2B2),(A1A2)(B1B2)=(A1B1)(A2B2),(A1×A2)(B1×B2)=(A1B1)×(A2B2),(A1×A2)(B1×B2)=(A1B1)×(A2B2),(A1+A2)(B1+B2)=(A1B1)+(A2B2),(A1+A2)(B1+B2)=(A1B1)+(A2B2). The arrow join uses a meet in its domain for the same reason that S-Arr reverses its domain premise: a common upper function must accept every input accepted by either source function. The arrow meet reverses the same calculation. For records R={i:Ai}iI and S={j:Bj}jJ, define RS={k:AkBk}kIJ,RS={i:Ai}iIJ{k:AkBk}kIJ{j:Bj}jJI. The unions are unions of finite maps. For two remaining types whose outer constructors differ and are neither Top nor Bot, define the join to be Top and the meet to be Bot.

Disjoint labels expose a useful edge case: {x:Nat}{y:Nat}={}. The empty record is the record analogue of Top: every record type is below it by width, although a nonrecord type need not be. Thus it is more precise than the global Top and is the least common upper bound of these two record types.

Every recursive call in this definition is on component types whose combined syntax size is smaller. Thus the simultaneous definition terminates; it is not an appeal to the bounds it is about to construct.

Theorem 18.18 — First-order types form a lattice

For all closed first-order types A and B, the type AB is their join and AB is their meet in the sense of definition 8.13.

Proof of Theorem 18.18 — First-order types form a lattice

Proof. Prove the upper- and lower-bound clauses and their two optimality clauses simultaneously by induction on the combined syntax size of A and B. The top and bottom equations use S-Top and S-Bot. Equal base types use reflexivity. For distinct outer constructors covered by the fallback clause, subtype-shape inversion says that every common upper bound is Top and every common lower bound is Bot, so the fallback equations are optimal.

Consider the arrow join. The induction hypotheses give A1B1<:A1,B1,A2,B2<:A2B2. Put J=(A1B1)(A2B2). Two uses of S-Arr derive A1A2<:J,B1B2<:J, so J is a common upper bound. If A1A2<:U and B1B2<:U, upward shape inversion shows that U is either Top or C1C2. The top case is immediate. In the arrow case inversion gives C1<:A1,B1,A2,B2<:C2. Meet optimality for the domains and join optimality for the codomains give C1<:A1B1 and A2B2<:C2; one final S-Arr proves leastness. For the arrow meet the same calculation reverses roles: a common lower arrow has a domain above both A1,B1 and a codomain below both A2,B2, so the domain join and codomain meet are forced.

Products and sums use the component induction hypotheses covariantly. For records, the join retains precisely the labels that every common upper record may require, and its field joins are least by induction. The meet contains the union of the two label sets, and its common fields use the inductively greatest field meets. Rule S-Rcd proves the four bound judgments; record shape inversion proves optimality field by field. These cases exhaust the first-order grammar. ◻

Let R={i:Ai}iI and S={j:Bj}jJ be closed record types. Suppose that Ak=Bk for every kIJ. Define RrS:={k:Ak}kIJ, and RrS:={i:Ai}iIJ{k:Ak}kIJ{j:Bj}jJI, where the unions are unions of finite maps.

Proposition 8.14 — Conditional record bounds

Under the identical-common-field hypothesis, RrS is a join and RrS is a meet in the closed first-order calculus.

Proof of Proposition 8.14 — Conditional record bounds

Proof. By theorem 18.18, AkAk is the join of Ak with itself and AkAk is the meet. Since Ak itself has both universal properties by reflexivity, antisymmetry gives AkAk=Ak=AkAk. Thus the two displayed records are exactly RS and RS from definition 18.17. Apply theorem 18.18. ◻

For a concrete calculation, put H={x:Nat,horizontal:Nat},C={x:Nat,color:Bool}. Then HrC=Point,HrC={x:Nat,horizontal:Nat,color:Bool}. Consequently an if with an H branch and a C branch can be checked at Point by subsuming each branch. When common field types differ, the global algorithm recursively computes their bounds instead of stopping at the identical-field abbreviation.

Exercise 8.5

★★☆ Compute the record join and meet of {x:Nat,q:Bool}and{q:Bool,r:Unit}, and verify all four bound judgments by S-Rcd. Then replace the second q type by Top. Compute the resulting global record join and meet from definition 18.17, and explain why the shorter identical-field abbreviation no longer applies.

Why a bound belongs on a type variable

We use method records only to keep the example object-like without mutation: PointObj:={getX:UnitNat},ColorPointObj:={getX:UnitNat,getColor:UnitBool}.

The function xOf forgets extra fields in its result because its result is merely a natural number. Consider instead an operation that must return its input unchanged and also remember the coordinate it observed. If we give it the monomorphic type PointObjPointObj×Nat, then applying it to a colored object forgets, at the type level, that the returned object still has a color method. Ordinary universal quantification X.XX×Nat retains X but provides no reason why an X has a coordinate method. We need both facts at once: X<:PointObj.

Bounded quantification retains the type variable X while recording the coordinate-method bound X<:PointObj.

Definition 8.15 — Kernel F_<: over the record core

Extend types and terms by A,B::=XX<:A.B,t,u::=ΛX<:A.tt[B]. A context is an ordered list of term declarations x:A and type bounds X<:A. In Γ,X<:A, the type A is formed in Γ; in particular, A cannot mention the newly bound X. Lookup is written Γ(X)=A. The universal type is formed when the following two additional formation rules apply:

Γ(X)=A
ΓX type
F-Var
ΓA typeΓ,X<:AB type
ΓX<:A.B type
F-All

In addition to the preceding subtype rules, Kernel F<: has

Γ(X)=A
ΓX<:A
S-Var
Γ,X<:AB<:C
ΓX<:A.B<:X<:A.C
S-AllK

The two displayed bounds in S-AllK must be alpha-identical. This invariance is what the word Kernel records.

The term rules are

Γ,X<:At:B
ΓΛX<:A.t:X<:A.B
T-TAbs
Γt:X<:A.BΓC<:A
Γt[C]:B[C/X]
T-TApp

with the reduction (ΛX<:A.t)[C]t[C/X]. Type abstractions are values, and evaluation first reduces the operator of a type application. Type annotations and type applications are static; the substitution rule above is nevertheless convenient for proving preservation of the typed source calculus.

Lemma 18.21 — Top is maximal in Kernel

If ΓTop<:C in definition 8.15, then C=Top.

Proof of Lemma 18.21 — Top is maximal in Kernel

Proof. Induct on the derivation. Reflexivity and S-Top give the result, and transitivity uses the two induction hypotheses. The remaining first-order rules, S-Var, and S-AllK cannot have Top as source. ◻

The bound has two logically separate uses. From a variable declaration o:X and X<:PointObj, S-Var and T-Sub give o:PointObj, so o.getX is available. The result may still mention X, so returning o retains the caller’s precise type.

Example 8.16 — A bounded object operation

Define rememberX:=ΛX<:PointObj.λo:X.o,o.getX unit,colored:={getX=λu:Unit.0,getColor=λu:Unit.true}. Put Ω=X<:PointObj,o:X. The observation part is the following complete derivation; the receiver is subsumed before projection: (o:X)ΩΩo:XTVarΩ(X)=PointObjΩX<:PointObjSVarΩo:PointObjTSubgetXdom(PointObj)Ωo.getX:UnitNatTProjXΩunit:UnitUnitIΩo.getX unit:NatTApp. Pair this conclusion with the original variable, then introduce the term and type binders: Ωo:XΩo.getX unit:NatΩo,o.getX unit:X×NatTPairX<:PointObjλo:X.o,o.getX unit:XX×NatTLamrememberX:X<:PointObj.XX×NatTTAbs. Thus rememberX:X<:PointObj.XX×Nat. Since ColorPointObj<:PointObj, write C=ColorPointObj in the next two trees. The complete instantiation step is rememberX:X<:PointObj.XX×NatC<:PointObjrememberX[C]:CC×NatTTApp. Applying the result is a separate ordinary application step: rememberX[C]:CC×Natcolored:CrememberX[C] colored:C×NatTApp. The final premise follows by T-Rcd from the two lambda typings displayed in the definition of colored. Its calculation is rememberX[ColorPointObj] coloredtypeβ(λo:ColorPointObj.o,o.getX unit) coloredβcolored,colored.getX unitprojectionandβcolored,0. The first component retains its color method in both the term and its type. This is the modest object encoding needed here: an immutable record of methods. The dedicated object-calculus and self-type developments own receiver recursion, self types, and state. None of those mechanisms is a premise here.

Type application need not compute. Put g:X<:PointObj.XX in the context. Rule T-TApp gives g[ColorPointObj]:ColorPointObjColorPointObj, but its operator is a variable, so this neutral term takes no type-beta step.

Exercise 8.6

★★☆ Construct a term of type X<:{getColor:UnitBool}.XX×Bool that returns its argument and the observed Boolean. Give the complete derivation of the projection from a variable of type X, and reduce one application to a two-method record.

Exercise 8.7

★★☆ Form the unbounded variant. rememberXTop. It replaces the bound PointObj by Top in the definition of rememberX. Show that it cannot be typed at X<:Top.XX×Nat. Identify the first judgment that cannot be derived; “X is abstract” is not a rule-level answer. Hint: first prove by induction that if Γ(X)=Top and ΓX<:B, then B is X or Top; the transitivity case uses lemma 18.21.

The structural proof for Kernel F<:

A type-variable declaration is unlike an assumption in ordinary System F. Changing X<:Q to the stronger fact X<:P, where P<:Q, must preserve every derivation in the suffix Δ. This property is narrowing: if ΓP<:Q, a derivation under Γ,X<:Q,Δ remains derivable under Γ,X<:P,Δ. In the critical S-Var case, the new lookup gives X<:P; weakening P<:Q through the suffix and applying transitivity recovers X<:Q. Type substitution replaces the distinguished lookup by Γ,Δ[P/X]P<:Q, obtained by weakening the premise ΓP<:Q.

Write Δ[P/X] for pointwise capture-avoiding substitution in every type appearing in the suffix Δ of a context. Term-variable names and type-variable names are distinct. Before substitution, alpha-rename every binder that would capture a free variable of P.

Definition 8.17 — Formation of mixed contexts

Mixed-context formation retains C-Empty and C-Term from the first-order calculus and adds Γ ctxΓA typeXdom(Γ)Γ,X<:A ctxCType Thus every declaration is checked in the prefix to its left. A type variable is formed when its bound is found by lookup. We write J for any of the three judgments A type,A<:B,t:A, and write J[P/X] for substitution in every type occurring in the judgment, including annotations in t.

Theorem 8.18 — Strengthened structural package

For Kernel F<:, the following statements include preservation of context formation as well as preservation of judgments.

  1. Weakening. Suppose Γ0,Γ1 ctx, Γ0D type, and d is a fresh declaration, either x:D or X<:D. Then Γ0,d,Γ1 ctx. If additionally Γ0,Γ1J, then Γ0,d,Γ1J.

  2. Narrowing. If ΓP<:Q and Γ,X<:Q,Δ ctx, then Γ,X<:P,Δ ctx. Moreover, Γ,X<:Q,ΔJΓ,X<:P,ΔJ.

  3. Type substitution. If ΓP<:Q and Γ,X<:Q,Δ ctx, then Γ,Δ[P/X] ctx, and Γ,X<:Q,ΔJΓ,Δ[P/X]J[P/X].

  4. Term substitution. If Γv:A and Γ,x:A,Δ ctx, then Γ,Δ ctx and Γ,x:A,Δt:BΓ,Δt[v/x]:B.

In (ii), types and terms in the conclusion are unchanged; only the bound in the context is stronger. In (iii), substitution acts on the term’s type annotations and type applications as well as on its result type.

Proof of Theorem 8.18 — Strengthened structural package

Proof. Weakening, narrowing, and type substitution are simultaneous inductions over context formation, type formation, subtyping, and typing. In the latter two proofs, weakening transports ΓP<:Q through the transformed suffix.

Weakening. For context formation, induct on the length of the suffix Γ1. With an empty suffix, append d by C-Term or C-Type. If the last declaration of the suffix is y:E or Y<:E, the induction hypothesis forms the prefix containing the insertion; the simultaneous judgment hypothesis weakens the old derivation of E type to that prefix. Reapply the corresponding context rule.

For the judgment component, induct on the derivation. A lookup before or after the insertion returns the same declaration. In a term abstraction, apply the induction hypothesis with its fresh term binder appended to Γ1; in type formation, S-AllK, and T-TAbs, do the same with the fresh type binder. The application and type-application rules use the hypothesis on each premise. Arrows, products, sums, and records apply the hypothesis to each component premise.

Narrowing. Context formation and preservation of judgments are simultaneous because a declaration in Δ may contain X. At an empty suffix, Γ,X<:P is formed by C-Type; formation of P follows from the well-formed subtype premise ΓP<:Q. If Δ ends in y:E or Y<:E, the context induction hypothesis forms the narrowed prefix, while the simultaneous formation hypothesis changes Γ,X<:Q,ΔE typetoΓ,X<:P,ΔE type. The appropriate context rule then restores the final declaration.

In the simultaneous induction on formation, subtyping, and typing derivations, the critical rule is S-Var. A variable declared before X or in Δ has the same lookup after narrowing. For the distinguished variable, the new lookup gives X<:P. The premise ΓP<:Q weakens to the narrowed context: ΓP<:QΓ,X<:P,ΔP<:Q. Transitivity with the new lookup gives: XΓ,X<:P,ΔX<:PSVarΓ,X<:P,ΔP<:QΓ,X<:P,ΔX<:QSTrans. For universal formation and S-AllK, alpha-rename the binder Y away from X and regard Y<:A as one more declaration in the suffix. The formation induction hypothesis first preserves A; the body induction hypothesis then applies under Γ,X<:P,Δ,Y<:A. A lambda binder is handled identically with a term declaration. Rule T-TAbs uses the type-binder case, T-TApp uses the typing hypothesis for its operator and the subtype hypothesis for its bound check, and T-Sub uses both simultaneous hypotheses. The arrow, product, sum, and finite record rules apply the appropriate hypothesis to each component premise.

Type substitution. Induct on the suffix for context formation. The empty suffix removes X<:Q and leaves Γ. Suppose the final declaration is y:E. The simultaneous formation induction gives Γ,Δ[P/X]E[P/X] type, so C-Term forms the substituted declaration y:E[P/X]; C-Type gives the identical argument for Y<:E. This proves Γ,Δ[P/X] ctx.

For judgments, induct simultaneously on their derivations. Type-variable formation and S-Var each have three lookup cases. If the variable is the distinguished X, then its old bound Q was formed in Γ and hence does not contain X. The substituted conclusion is P<:Q in the transformed context, obtained by weakening the assumption through the substituted suffix: ΓP<:QΓ,Δ[P/X]P<:Q. The formation case for this occurrence uses weakening: ΓP typeΓ,Δ[P/X]P type. A variable declared before X is unchanged. A declaration Y<:R in Δ becomes Y<:R[P/X] in Δ[P/X], so lookup gives Y<:R[P/X]. A term-variable lookup has two positions: a declaration before X is unchanged, while the type attached to a declaration in Δ is substituted.

For a universal representative Y0<:A.B, choose a new binder name Y so that Y{X,Y0}FV(Γ)FV(Δ)FV(P)FV(A)FV(B), and alpha-rename Y0 and its bound occurrences to Y. In the T-TApp case choose Y additionally outside FV(C). The formation hypothesis gives A[P/X] type, and the body hypothesis is applied with Y<:A appended to the old suffix. It yields a body under Y<:A[P/X], establishing (Y<:A.B)[P/X]=Y<:A[P/X].B[P/X]. The same suffix argument proves the binder cases of S-AllK and T-TAbs; in particular, the two Kernel bounds remain alpha-identical. A term abstraction appends y:A to the suffix and uses the corresponding term-binder argument. In T-TApp, the simultaneous hypotheses give Γ,Δ[P/X]t[P/X]:Y<:A[P/X].B[P/X],Γ,Δ[P/X]C[P/X]<:A[P/X]. Put CP:=C[P/X]. Rebuilding T-TApp derives Γ,Δ[P/X](t[P/X])[CP]:B[P/X][CP/Y]. Its result type satisfies B[P/X][CP/Y]=B[C/Y][P/X], where YX and YFV(P) justify the substitution-commutation equality. Thus this derivation has the required type B[C/Y][P/X]. For T-Sub, substitute in both the typing and subtype premises; for each finite-record rule, substitute independently in every field premise.

Term substitution. Types contain no term variables, so erasing x:A does not alter the types of declarations in Δ. Induction on that suffix therefore forms Γ,Δ. We first prove the corresponding term-declaration strengthening for type formation and subtyping: Γ,x:A,ΔC typeΓ,ΔC type,Γ,x:A,ΔC<:DΓ,ΔC<:D. Prove both statements simultaneously by induction on their derivations. Type-variable lookup ignores term declarations; in every binder case append the freshly bound declaration to the suffix and use the induction hypothesis. Every other formation or subtype rule applies the induction hypothesis to its premises. The same induction forms the shortened suffix.

Induct on the typing derivation for the term judgment. In T-Var, an occurrence of x is replaced by the premise Γv:A, weakened through Δ by clause (i); a different variable is recovered by lookup in the shortened context. A lambda alpha-renames its binder and applies the hypothesis with that declaration appended to the suffix. A type abstraction does the same with its type binder. A type application substitutes in its operator and applies term-declaration strengthening to its subtype premise. Rule T-Sub substitutes in the term premise and strengthens its subtype derivation in the same way. Applications, products, sums, records, projections, Booleans, and naturals apply their typing rule to the substituted premises. Therefore Γ,x:A,Δt:B,Γv:AΓ,Δt[v/x]:B. ◻

Lemma 8.19 — Universal subtype inversion in Kernel F_<:

The invariant-bound rule has the following two consequences.

  1. If ΓX<:A.B<:C, then C=Top or, after alpha-renaming, C=X<:A.DandΓ,X<:AB<:D.

  2. If Γ contains no type-bound declarations and ΓC<:X<:A.B, then C=Bot or, after alpha-renaming, C=X<:A.DandΓ,X<:AD<:B.

The hypothesis in (b) follows for the contexts used by closed progress. It cannot be dropped: in a context containing Y<:X<:A.B, rule S-Var derives Y<:X<:A.B, although Y is neither bottom nor a universal type.

Proof of Lemma 8.19 — Universal subtype inversion in Kernel F_<:

Proof. Induct on subtype derivations. For (a), S-Refl, S-Top, and S-AllK give the two alternatives. In a transitivity case X<:A.B<:E<:C, the first induction hypothesis gives E=Top or E=X<:A.E0,Γ,X<:AB<:E0. In the first case, lemma 18.21 gives C=Top. In the second, the induction hypothesis on E<:C gives C=Top or C=X<:A.D with Γ,X<:AE0<:D; transitivity gives Γ,X<:AB<:D.

For (b), S-Bot, S-Refl, and S-AllK give the alternatives. There is no S-Var case because the context has no type-bound declaration. In transitivity, the second induction hypothesis gives a bottom intermediate or a universal intermediate with bound A. The first alternative and Bot-Down give a bottom source. In the second, the two body judgments compose under X<:A. ◻

Lemma 8.20 — Concrete inversion in Kernel F_<:

The following first-order inversion facts remain valid in every well-formed mixed Kernel context.

  1. Upward shape inversion for records, arrows, products, sums, and the three base types holds unchanged. Moreover, a concrete type other than Bot is not a subtype of Bot.

  2. The literal-record conclusion of lemma 8.6 and the introduction conclusions of lemma 8.7 hold unchanged in a mixed Kernel context.

Proof of Lemma 8.20 — Concrete inversion in Kernel F_<:

Proof. For (a), repeat the simultaneous induction on the Kernel subtype derivation. The two new last rules cannot disturb a concrete source: S-Var has a type variable as its source, while S-AllK has a universal source and target. The transitivity case uses the same intermediate-shape calculation as lemma 8.5; if the intermediate is Top, lemma 18.21 gives C=Top. Prove the last assertion in the same simultaneous induction. In the transitivity case K<:E<:Bot, upward shape for the first premise forces E to be Top or to have the same concrete head as the non-bottom K; in particular, E is not a variable. Maximality excludes the first alternative, and the induction hypothesis applied to E<:Bot excludes the second. Outside transitivity, S-Var has the wrong source and the other rules with target Bot can only have source Bot.

For (b), compose all final T-Sub premises into Γv:K,ΓK<:A, where the introduction rule fixes the concrete type K. For a lambda, K=CD and the introduction premise is Γ,x:Ce:D; part (a) applied to CD<:A1A2 gives A1<:C and D<:A2. For a record literal, K contains every written field, and part (a) gives the retained labels and their fieldwise subtypings. Products, sums, and successors yield the component, payload, and predecessor judgments in the same way. Part (a) excludes a target Bot. ◻

Lemma 18.27 — Type-abstraction inversion in Kernel

If ΓΛX<:A.t:C, then either C=Top or, after alpha-renaming, C=X<:A.B,and there is a B0 such thatΓ,X<:At:B0,Γ,X<:AB0<:B.

Proof of Lemma 18.27 — Type-abstraction inversion in Kernel

Proof. Induct on the typing derivation. A final T-TAbs gives the universal alternative with B0=B. Suppose the last rule is T-Sub, with typing premise at E and subtype premise E<:C. Apply the induction hypothesis to the typing premise. If E=Top, then lemma 18.21 forces C=Top. Otherwise E=X<:A.D, with a body type B0 satisfying B0<:D under X<:A. Clause (a) of lemma 8.19 applied to E<:C gives C=Top or C=X<:A.B with D<:B under the same bound. In the latter case, transitivity gives B0<:B. No other typing rule concludes a judgment for type-abstraction syntax. ◻

Corollary 8.21 — Safety of the bounded extension

Preservation, progress, and safety hold for the call-by-value Kernel F<: calculus of definition 8.15.

Proof of Corollary 8.21 — Safety of the bounded extension

Proof. For the ordinary syntax, repeat the typing inductions of theorem 8.10, theorem 8.11. Their substitution steps now use theorem 8.18(iv), and their value-root cases use lemma 8.20; no downward shape claim for a type variable is being imported. For preservation, first dispose of a typing derivation whose last rule is T-Sub: apply the induction hypothesis to its premise and restore the same target type with the same subtype derivation. Thus the type-beta case may assume that the whole redex was typed last by T-TApp.

We also strip final subsumption steps from its operator. The preceding type-abstraction inversion lemma, applied to ΓΛX<:A.t:X<:A.B gives a type B0 such that Γ,X<:At:B0andΓX<:A.B0<:X<:A.B. The bounds are the same because S-AllK is invariant. More explicitly, an induction on this universal-to-universal subtype derivation strips S-Trans; its S-AllK cases compare the bodies and its transitivity case composes the resulting body judgments. Hence Γ,X<:AB0<:B.

For the type-beta root (ΛX<:A.t)[C]t[C/X], whose T-TApp premise also gives ΓC<:A. Type substitution from theorem 8.18(iii), applied once to typing and once to subtyping, gives Γt[C/X]:B0[C/X],ΓB0[C/X]<:B[C/X]. One T-Sub therefore gives the reduct the result type B[C/X] demanded by T-TApp. If the original whole redex had then been subsumed to a further type, the first paragraph restores that target after the step. Congruence for type application follows from the induction hypothesis.

For progress the empty context has no type-bound declaration. In the type-application case, induction on the final subsumption chain, using lemma 8.19(b), shows that a closed value of universal type is ΛX<:A.t. Therefore t[C] either takes an operator congruence step or is the type-beta redex (ΛX<:A.t0)[C]. The term-application and projection cases use the arrow and record clauses of lemma 8.8; the remaining constructors take their introduction or congruence rules. ◻

Exercise 8.8

★★☆ Give all three lookup subcases in the type-substitution proof for S-Var: the looked-up variable is X, occurs before X, or occurs in Δ. Write the conclusion context in each case.

Exercise 8.9

★★☆ Write the narrowing proof for T-TApp in full. Your derivation must show both the narrowed type of the operator and the narrowed proof that the actual type argument satisfies its bound.

A syntax-directed subtype algorithm

The declarative judgment answers what counts as a subtype proof, but it is not yet a program. Rule S-Trans guesses an intermediate type, and S-Refl overlaps every structural rule. The deterministic relation below removes the intermediate-type guess while preserving derivability.

Write ΓaA<:B when the following deterministic procedure succeeds. The tests have priority in their enumerated order, and a matching test returns without inspecting a lower-priority branch. The procedure’s input contract includes derivations of Γ ctx, ΓA type, and ΓB type. An implementation validates those three conditions once at its entry point and reports an ill-formed-input diagnostic when, for example, a source variable has no declaration; that diagnostic is not the negative answer to a well-formed subtype query.

  1. If A and B are alpha-identical, succeed.

  2. Otherwise, if B=Top, succeed.

  3. Otherwise, if A=Bot, succeed.

  4. Otherwise, if A=X, look up Γ(X)=U and recursively check ΓaU<:B.

  5. Otherwise, if both types are arrows, check their domains in reverse order and their codomains in forward order.

  6. Otherwise, if both types are products, check both components in forward order.

  7. Otherwise, if both types are sums, check both components in forward order.

  8. Otherwise, if both types are records, first fail if a target label is absent from the source; if none is absent, check every target field against the source field with the same label.

  9. Otherwise, if the types are X<:A.B and X<:C.D, fail unless AαC; when the bounds are alpha-identical, alpha-rename them to the same X and check Γ,X<:AaB<:D.

  10. In every other case, fail.

Thus X<:X never follows a chain of bounds, X<:Top takes the top branch rather than the promotion branch, and an identical pair of structured types takes the equality branch rather than a componentwise branch.

Proposition 18.29 — Source-only promotion

Every promotion step replaces a source variable by its declared bound. No algorithmic clause replaces the target of a subtype query by its bound.

Proof of Proposition 18.29 — Source-only promotion

Proof. Only clause 4 consults a bound, and its recursive query is U<:B, with the target B unchanged. Every other recursive clause descends through matching outer constructors. ◻

The successful branches produce proof trees with the following rules. Each side condition records that all earlier tests failed, so this rule presentation has exactly the same control as the procedure.

AαB
ΓaA<:B
A-Eq
AαTop
ΓaA<:Top
A-Top
BαBotBαTop
ΓaBot<:B
A-Bot
XαBBαTopΓ(X)=UΓaU<:B
ΓaX<:B
A-Var
A1A2αB1B2ΓaB1<:A1ΓaA2<:B2
ΓaA1A2<:B1B2
A-Arr
A1×A2αB1×B2ΓaA1<:B1ΓaA2<:B2
ΓaA1×A2<:B1×B2
A-Prod
A1+A2αB1+B2ΓaA1<:B1ΓaA2<:B2
ΓaA1+A2<:B1+B2
A-Sum
{i:Ai}iIα{j:Bj}jJJIΓaAj<:Bjfor every jJ
Γa{i:Ai}iI<:{j:Bj}jJ
A-Rcd
X<:A.BαX<:A.CΓ,X<:AaB<:C
ΓaX<:A.B<:X<:A.C
A-AllK

The absence of a universal rule with two different bounds is the failure branch in the procedure. The displayed guards make the successful root unique. Since the recursive calls are themselves evaluated by the same priority list, a successful query also has a unique algorithmic proof tree.

Example 8.22 — A successful and a failed trace

In the context X<:ColorPoint, the query X<:Point is not an outer-shape comparison. Clause 4 produces the following complete tree, where Γ=X<:ColorPoint: XαPointPointαTopΓ(X)=ColorPointColorPointαPoint{x}{x,color}NatαNatΓaNat<:NatAEqΓaColorPoint<:PointARcdΓaX<:PointAVar. The record clause checks the single x field by the equality clause. In contrast, Point<:X fails. Its target is neither Top nor a record, and the algorithm deliberately has no target-promotion clause. The bound says that every X can be used as a point; it does not say that every point is an X.

Why the search terminates

Write JaJ when one algorithmic step replaces a source type variable by the bound found for it in the ordered context. This relation is on subtype queries; the term relation ee instead denotes coercion elaboration.

Because contexts are ordered, following a variable bound cannot return to the same variable. Raw syntax size is not a decreasing measure: A-Var replaces a source variable X of size one by its bound Γ(X), which may be arbitrarily larger, X<:BaΓ(X)<:B. The measure must charge X for the size of the bound it exposes. The following numerical measure turns that observation into a termination proof without recursing on an extended context. First construct a finite weight map ρΓ by induction from left to right through the ordered context. Term declarations leave the map unchanged; extending a prefix Γ by X<:A records ρΓ,X<:A(X)=1+wρΓ(A) and preserves the weights of earlier variables. Now define wρ structurally on types: wρ(Top)=wρ(Bot)=wρ(Nat)=wρ(Bool)=wρ(Unit)=1,wρ(X)=ρ(X),wρ(AB)=1+wρ(A)+wρ(B), with the same sum for products and sums, wρ({i:Ai}iI)=1+iIwρ(Ai), and wρ(X<:A.B)=1+wρ(A)+wρ[X1+wρ(A)](B). Finally write wΓ(A):=wρΓ(A). The map construction is structural on the context because a bound mentions only its strict prefix; the second construction is structural on the type. In particular, the universal clause extends a finite map while recursing on the proper subterm B, rather than claiming that the context itself decreases.

Theorem 8.23 — Algorithm termination

For every well-formed Γ,A,B, the algorithm returns exactly one of success and failure after finitely many recursive calls.

Proof of Theorem 8.23 — Algorithm termination

Proof. Use wΓ(A)+wΓ(B) as the recursive-call measure. By proposition 18.29, promoting a source X replaces weight 1+wΓ(Γ(X)) by wΓ(Γ(X)). A structural clause replaces the pair by proper components; the universal body is a proper summand measured in the extended context. Record premises are finite. Thus every recursive call strictly decreases a natural number. The priority list chooses a unique clause, finite map lookup is deterministic, and every recursive result is deterministic; induction on the measure gives the claim. ◻

The two lemmas hidden by transitivity

Soundness of each algorithmic rule is immediate except promotion, where S-Var is followed by declarative transitivity. Completeness is harder: a declarative derivation may end with S-Trans, although the algorithm has no such clause. We must prove that transitivity is admissible for the algorithm itself. Narrowing then uses it, because strengthening the bound used by A-Var replaces one recursive premise by two composable ones.

Lemma 8.24 — Algorithmic weakening

Suppose Γ0,Γ1aA<:B and the context obtained by inserting a fresh, well-formed declaration sequence Σ is well formed. Then Γ0,Σ,Γ1aA<:B. The types A and B are unchanged.

Proof of Lemma 8.24 — Algorithmic weakening

Proof. Induct on the algorithmic proof tree. The alpha-equality and the top and bottom tests do not inspect the context. For A-Var, lookup of a variable declared in Γ0 or Γ1 returns the same textual bound after the fresh insertion; apply the induction hypothesis to its recursive comparison and rebuild A-Var. All its guards are equations between unchanged types. The arrow, product, sum, and record rules apply the induction hypothesis to each displayed recursive premise. Under A-AllK, alpha-rename the bound variable away from Σ and apply the induction hypothesis with that binder appended to Γ1: Γ0,Γ1,X<:CaD<:EΓ0,Σ,Γ1,X<:CaD<:E. The extended conclusion context is well formed by theorem 8.18(i). Applying A-AllK to the transformed body judgment derives the required universal comparison. ◻

Lemma 8.25 — Algorithmic transitivity and narrowing

The following assertions hold.

  1. If ΓaA<:B and ΓaB<:C, then ΓaA<:C.

  2. If Γ,X<:Q,ΔaA<:B and ΓaP<:Q, then Γ,X<:P,ΔaA<:B.

In (a), Γ, A, B, and C are well formed. In (b), both Γ,X<:Q,Δ and Γ,X<:P,Δ, together with the types in their judgments, are well formed.

Proof of Lemma 8.25 — Algorithmic transitivity and narrowing

Proof. Induction on the middle type alone fails in the source-promotion case: D1:ΓaU<:BD1:ΓaX<:BAVarD2:ΓaB<:C. The recursive composition of D1 with D2 has the same middle type B. Its left derivation is, however, strictly shorter; this forces the height tiebreaker in the following lexicographic measure. Prove (a) simultaneously for every well-formed context Γ, by lexicographic induction on (wΓ(B),h(D1)), where D1 derives A<:B; the height of the right derivation D2 is not a measure coordinate. In the source-promotion case the height coordinate decreases even when promotion reaches a nonvariable middle type. The case analysis below uses proposition 18.29: a bound can change the source of a query but never its target. In the universal case the induction hypothesis is therefore available at the extended context Γ,X<:A; its context-relative weight is strictly smaller than the enclosing universal weight.

If D1 ends in A-Eq, then AαB and D2 is the desired derivation. If D2 ends in A-Eq, then BαC and D1 is the desired derivation. No recursive call occurs in either case.

Suppose D1 ends in A-Var. Then A=X, Γ(X)=U, and its recursive premise D1 derives U<:B. The induction hypothesis applies to D1 and D2: the middle type B is unchanged, while h(D1)<h(D1). It gives U<:C. If C=X, equality gives X<:X; if C=Top, use A-Top; in every other case rebuild A-Var to obtain X<:C. This includes X<:Bot when Γ(X)=Bot.

For a derivation not ending in source promotion, C=Top uses A-Top and A=Bot uses A-Bot. If the middle type B is Top, its right derivation can only conclude C=Top. If B=Bot, the left derivation, which no longer ends in source promotion, forces A=Bot. If B is a base type or variable, a derivation D1 concluding A<:B can end only in A-Eq, A-Bot, or A-Var: structural rules have a different target shape, and target promotion does not exist. Excluding A-Var and A-Bot leaves A-Eq; hence D1 ends in A-Eq, so A=B and D2 is the desired derivation.

Let the middle type be an arrow, product, sum, record, or universal. With source promotion and the top/bottom cases separated, the two derivations have compatible outer shapes. Apply the transitivity hypothesis to corresponding components. Every component of the middle type has smaller weight than the whole middle type, so the first lexicographic coordinate decreases. Arrow domains are composed in the order C1<:B1<:A1, and codomains in the order A2<:B2<:C2. For records, every field demanded by C is demanded by B and therefore present in A; fieldwise transitivity rebuilds A-Rcd. Products rebuild A-Prod from their two covariant component chains, and sums rebuild A-Sum from theirs. If the reconstructed source and target happen to be alpha-identical, the procedure takes A-Eq instead; otherwise the relevant structural guard holds. For a universal middle type, the identical-bound test forces all three bounds to be the same after alpha-renaming; otherwise one of the two premises could not have succeeded. Apply transitivity to the bodies under that common bound and rebuild A-AllK. This is precisely where Kernel invariance is used.

For (b), induct on the height of the algorithmic derivation being narrowed. All clauses except source promotion apply the narrowing induction hypothesis to their strictly smaller recursive premises. If the promoted source is not X, its lookup remains available. Apply the narrowing induction hypothesis to its recursive comparison—whether the variable was declared before X or in Δ—and then rebuild A-Var. If the source is X, the recursive premise derives Q<:B; the induction hypothesis gives Γ,X<:P,ΔaQ<:B. By lemma 8.24, the assumption ΓaP<:Q gives Γ,X<:P,ΔaP<:Q. Transitivity in that context gives P<:B. The A-Var guards say BX and BTop, so rebuild X<:B with A-Var. Under a universal binder, alpha-rename away from X and invoke the narrowing induction hypothesis on its body. Each recursive narrowing premise has smaller derivation height. ◻

Kernel type and context formation are decidable independently of subtyping: scan an ordered context from left to right, checking each bound in its prefix, and recurse structurally through the finite type grammar. Alpha-equality is decidable by the same binder-normalization used in the algorithmic rules.

Theorem 8.26 — Soundness and completeness of algorithmic subtyping

For formed Kernel F<: types, ΓaA<:BΓA<:B. Consequently Kernel F<: subtyping for the grammar of definition 8.15 is decidable.

Proof of Theorem 8.26 — Soundness and completeness of algorithmic subtyping

Proof. For soundness, induct on the successful algorithmic trace. A-Eq uses S-Refl; A-Top, A-Bot, and each matching structural clause use their declarative counterparts. In the promotion clause, lookup gives X<:U by S-Var, the induction hypothesis gives U<:B, and S-Trans gives X<:B. The universal clause is exactly S-AllK.

For completeness, induct on the declarative derivation. Reflexivity takes A-Eq. Top and bottom take their priority branch unless equality has already succeeded. Arrows, products, sums, records, and invariant universals take A-Eq when the whole types are alpha-identical and otherwise take the corresponding guarded structural rule after applying the induction hypotheses. For S-Var with bound U, the query X<:U takes A-Top when U=Top; otherwise it promotes X to U and the recursive query succeeds by A-Eq. For S-Trans, apply the two induction hypotheses and then lemma 8.25(a). Reflexivity, top, bottom, variable promotion, arrows, products, sums, records, invariant universals, and transitivity exhaust the declarative derivation. Decidability follows from equivalence and theorem 8.23. ◻

The selected equal-bound rule is Laird’s decidable Kernel baseline [Lai23]. The local theorem extends that boundary with records and bottom and proves its own algorithmic equivalence. Laird’s Propositions 8.4–8.5 instead establish decidable type checking for a richer two-quantifier system; that result is not imported here.

Ghelli’s nameless presentation and complexity analysis concern Kernel Fun at their own grammar and representation [Ghe96]. They supply a complexity boundary, not the soundness or completeness proof for the record-and-bottom extension.

Remark 8.27 — What has and has not been decided

The decision procedure takes a formed query ΓA<:B and returns whether that judgment is derivable. A bidirectional term checker may call it after synthesizing A and obtaining an expected type B. Synthesis for a variable-headed application additionally requires an operation that promotes the variable through its bound. A conditional can instead check both branches against one expected type. To synthesize a conditional type, one must define a join for Kernel F<:; the operations and of definition 18.17 apply only to closed first-order types.

Exercise 8.10

★★☆ Run the algorithm, listing every recursive query, on X<:{x:Nat,q:Bool} a X<:{x:Top} and on the reversed query. State the decreasing weight at each source promotion.

Exercise 8.11

★★☆ Fill in the record case of algorithmic transitivity. For a target label , write A, B, and C for its field types in the source, intermediate, and target records, respectively, and show exactly where the derivations of A<:B and B<:C enter fieldwise transitivity.

Exercise 8.12 — *

★★★ Translate the priority list into pseudocode returning either a finite algorithmic derivation tree or failure. Prove by induction on the recursive measure that every returned tree checks against the rules above. This is a mathematical specification exercise; no executable supplement is required here.

The exact boundary: full bounded quantification

Kernel F<: compares universal bodies under the same bound. Full F<: also compares bounds contravariantly: replace S-AllK by

ΓT1<:S1Γ,X<:T1S2<:T2
ΓX<:S1.S2<:X<:T1.T2
S-AllF

Notice the context of the second premise: occurrences of X in both bodies are checked under the target bound T1. This rebinding is absent from Kernel F<:.

Call the calculus with grammar A::=XAAX<:A.ATop, ordered bound contexts, reflexivity, transitivity, top, variable promotion, arrow subtyping, and S-AllF full F<:. This name refers to that exact subtyping signature; records, products, sums, and bottom play no part in the negative theorem. No undecidability claim for an extension with those additional rules follows merely from syntactic inclusion: such a claim would also require conservativity on judgments in the displayed fragment.

All contexts, types, terms, machines, and configurations in this section are finite strings with an effective coding. “Recursive procedure” means a Turing-computable partial function on those codes; “total” means that it halts on every well-formed input. A many-one reduction below is therefore a total computable map preserving yes- and no-instances.

Lemma 18.36 — Top is maximal in full

If ΓTop<:C in the exact full-F<: rule set just fixed, then C=Top.

Proof of Lemma 18.36 — Top is maximal in full

Proof. Induct on the derivation. Reflexivity and S-Top give the result, and transitivity uses the two induction hypotheses. Variable promotion, S-Arr, and S-AllF cannot have Top as source. ◻

The difficulty is visible before the undecidability proof, but it must not be confused with that proof. To make a comparison regenerate itself, we first need a type operation that reverses a subtype query. A bounded universal does exactly that in its bound. Keep the descriptive notation Rev throughout the calculation: RevA:=X<:A.X,X.B:=X<:Top.B. Rev is an abbreviation for reversal of the bound premise, not a Curry–Howard negation connective. Comparing RevA with RevB asks for B<:A in the contravariant bound premise; their bodies then compare by reflexivity.

The reversed query must rebuild the quantified target from the variable just introduced. The body Rev(Y<:X.RevY) was chosen for precisely that purpose: its outer Rev layer reverses the comparison once, and the inner layer reverses it again after a fresh bounded variable has entered the context. Package this body under an unbounded quantifier: Θ:=X.Rev(Y<:X.RevY). Consider the following well-formed subtyping statement: X0<:Θ  X0<:X1<:X0.RevX1. Promotion first replaces X0 by its bound Θ. The first complete iteration then has two nested uses of S-AllF: alpha-renaming its binders at this iteration gives Θ=X1.Rev(X2<:X1.RevX2), The inner comparison is Z<:(X2<:X1.RevX2).Z<:Z<:X1.Z. Γ0X0<:TopΓ1X1<:X2<:X1.RevX2Γ1,Z<:X1Z<:ZΓ1Rev(X2<:X1.RevX2)<:RevX1SAllFΓ0Θ<:X1<:X0.RevX1SAllF, where Γ0=X0<:Θ and Γ1=Γ0,X1<:X0. The first premise is S-Top; the innermost body premise is S-Refl. The recursive inner bound premise is Γ1X1<:X2<:X1.RevX2. Its first source promotion replaces X1 by X0. Γ1X1<:X2<:X1.RevX2aΓ1X0<:X2<:X1.RevX2aΓ1Θ<:X2<:X1.RevX2. The last query begins a second complete iteration: Γ1X1<:TopΓ2X2<:X3<:X2.RevX3Γ2,Z<:X2Z<:ZΓ2Rev(X3<:X2.RevX3)<:RevX2SAllFΓ1Θ<:X2<:X1.RevX2SAllF, where Γ2=Γ1,X2<:X1. The fresh Z is the binder introduced by the inner S-AllF; it is distinct from X3, the binder already written inside the source bound. The remaining recursive premise now promotes X2 through X1 and X0 to expose Θ once more. Each iteration therefore recreates the same query shape in a context with one more bounded variable.

This calculation motivates the negative result: the full rule can manufacture unbounded computational state in contexts. It does not prove the result. Cycle detection for this one input might still leave some other total decision procedure. Undecidability requires a reduction from two-counter-machine halting.

Definition 8.28 — Closed full-F_<: statements

A bound context Γ=X1<:A1,,Xn<:An is closed when the variables are distinct and FV(Ai){X1,,Xi1}(1in). A statement ΓS<:T is closed when Γ is closed and every free variable of S and T is declared in Γ. Thus a closed statement may have a nonempty context; “closed” does not mean Γ=.

Definition 18.38 — The two machine models in the import

A two-counter machine is a finite labeled program together with two nonnegative integer counters. An instruction either halts, increments one counter and jumps, or tests one counter: at zero it jumps to one label, and otherwise it decrements that counter and jumps to another. A configuration is a program label and the two counter values. From a supplied initial configuration, write cn for the configuration reached after n deterministic steps, when it is defined. The halting problem asks whether there is an nN for which cn is defined and its program label is a halt instruction; this problem is undecidable [Pie92].

Pierce’s rowing machine is the conservative deterministic intermediate calculus used by the reduction. At a fixed width w, a row has grammar ρ::=xiHaltλx1,,xw.ρ1,,ρw,1iw. A machine state is a vector of w closed rows. When its first row is an abstraction, one step simultaneously substitutes the current w rows for x1,,xw in the displayed output vector. A state halts when its first row is Halt. The point of this intermediate syntax is that one rowing step is substitution, the operation that bounded-variable promotion and S-AllF can reproduce in subtype derivations.

At width two, put r=λx1,x2.x2,x1. One rowing step is the visible simultaneous substitution step(r,Halt)=Halt,r. In the subtype encoding, an occurrence of x2 becomes the second bounded variable; S-Var promotes it to the type encoding the second current row, and the surrounding S-AllF reconstructs the two-component successor. Thus the substitution in this concrete row step is exactly the promotion-under-binder operation repeated by the reduction.

Theorem 8.29 — Undecidability of full F_<: subtyping; exact import

There is no total recursive procedure which, given a closed statement ΓS<:T in the sense of definition 8.28, decides its derivability for the full-F<: grammar and rules fixed in section 8.7.

Proof of Theorem 8.29 — Undecidability of full F_<: subtyping; exact import

Source import. Pierce’s Theorem 10.7 proves exactly this statement. His Definition 2.2 gives the grammar X, arrow, bounded universal, and Top; Figure 2 gives the six rules corresponding to reflexivity, transitivity, top, variable promotion, arrows, and S-AllF. Let R(M) be his rowing-machine encoding of a two-counter-machine instance M, and let J(R) be the closed full-F<: statement obtained from a rowing machine after the conservative deterministic intermediate calculus is embedded into the full-F<: rules of section 8.7. Sections 5–10 establish the two reductions M haltsR(M) halts,R haltsJ(R) is derivable. Their composition maps M to J(R(M)). Therefore a total subtyping decider would decide two-counter-machine halting. This is the terminal imported reduction; no stronger claim about records, bottom, inference, or implementation behavior is used here. [Pie92] ◻

Lemma 18.40 — Arrow shape in full

If ΓA1A2<:C in the full-F<: rules, then either C=Top or C=C1C2 with ΓC1<:A1 and ΓA2<:C2.

Proof of Lemma 18.40 — Arrow shape in full

Proof. By lemma 18.36, ΓTop<:C forces C=Top in the full system as well.

Induct on the given derivation. Reflexivity gives C=A1A2. Rule S-Top gives the first alternative, and S-Arr gives the second with exactly its two premises. Source-variable promotion and S-AllF cannot have an arrow source. In the transitivity case, write the intermediate type as U. The induction hypothesis for A1A2<:U shows that U is either Top or an arrow. In the first case the preliminary observation applied to U<:C gives C=Top. In the second, say U=D1D2 with D1<:A1 and A2<:D2. Apply the induction hypothesis to the proper premise D1D2<:C. If it gives C=Top, the first alternative holds. Otherwise C=C1C2 with premises C1<:D1 and D2<:C2; two uses of transitivity give C1<:A1 and A2<:C2. ◻

For the term-level consequence, fix the annotated arrow fragment over full F<:. Its terms are t::=xλx:A.ttt, its types and ordered type-bound contexts are exactly those of section 8.7, and its typing rules are T-Var, T-Lam, T-App, and T-Sub. A typechecking input is a formed type-bound context Γ, an annotated term t, and a formed target type A; the question is whether Γt:A is derivable.

Lemma 18.41 — Lambda inversion in the full- arrow fragment

If Γ,Δλx:A.t:B1B2, then there is a type C such that Γ,Δ,x:At:C,ΓB1<:A,ΓC<:B2. Here Γ is the type-bound context and Δ the term context.

Proof of Lemma 18.41 — Lambda inversion in the full- arrow fragment

Proof. Prove the following stronger claim by induction on the typing derivation: if Γ,Δλx:A.t:D, then either D=Top or D=D1D2 and some C satisfies Γ,Δ,x:At:C,ΓD1<:A,ΓC<:D2. A final T-Lam gives the arrow alternative by reflexivity. In a final T-Sub, let E be the type of its typing premise and apply the induction hypothesis there. If E=Top, lemma 18.36 forces the target D to be Top. Otherwise E=E1E2. By lemma 18.40, the subtype premise E1E2<:D makes D top or an arrow D1D2 with D1<:E1 and E2<:D2. In the arrow branch, compose these judgments with the two induction-hypothesis judgments. No other rule concludes a judgment for lambda syntax. Instantiate the stronger claim at D=B1B2; the top alternative is syntactically impossible. ◻

Corollary 8.30 — Undecidability of full-F_<: typechecking

Typechecking the annotated arrow fragment over full F<:, under supplied well-formed bound contexts, is undecidable.

Proof of Corollary 8.30 — Undecidability of full-F_<: typechecking

Proof. Given a well-formed subtyping statement ΓS<:T, where S and T are closed relative to the supplied bound context Γ, form λf:TTop.λa:S.fa. Check this term under the type-bound context Γ and the empty term context. It has type (TTop)STop exactly when the application fa can use a:S where T is required, equivalently when ΓS<:T. Thus a typechecker accepting an input bound context would decide subtyping. This is the reduction stated in Pierce’s Section 11. For the reverse implication, apply lemma 18.41 to the two abstractions and then invert the application, collecting any intervening subsumption chains. The function variable begins at TTop; by lemma 18.40, every non-Top type at which it can be applied still has an arrow domain below T. The argument variable begins at S, so application plus transitivity yields S<:T. Thus the term has type (TTop)STop exactly when the original subtype statement holds. The term has no free term variables, but it may contain the type variables bound by Γ; we do not call it closed without that qualification. ◻

The Kernel measure fails at the full universal rule for a visible reason. For X<:S1.S2 <: X<:T1.T2, S-AllF checks the bodies under X<:T1. Occurrences of X in the source body are therefore reweighted from 1+wΓ(S1) to 1+wΓ(T1). Although the other premise gives T1<:S1, the syntactic weight wΓ(T1) may be arbitrarily larger than wΓ(S1). Hence the body call need not decrease the Kernel query measure.

We have reached a sharp rule-level boundary. With identical quantifier bounds, the context-relative weight decreases and the Kernel procedure terminates. With contravariantly comparable bounds and rebinding by the target bound, full F<: subtyping is undecidable. This does not make bounded abstraction unusable: rememberX needed only the decidable Kernel rule.

It does determine what an implementation may promise. A checker can restrict itself to Kernel and return a Boolean answer; it can run a complete search for derivable full-F<: judgments that may diverge on a negative query; or it can impose fuel and return a third result, unknown, when the fuel is exhausted. Treating exhaustion as “not a subtype” would turn an incomplete search into an unsound decision procedure. The optional artifact follows the third policy; its resource diagnostic is deliberately distinct from rejection.

The complete search just mentioned is a semidecision procedure: enumerate finite labeled rule trees by size and mechanically check their formation, context, and inference-rule obligations. It halts exactly on derivable queries. If the complement were also semidecidable, dovetailing the two enumerations would decide full F<:, contradicting theorem 8.29.

Sources.

Cardelli and Wegner give record/function subtyping in Section 6.1, bounded quantification in Section 6.2, and a rule appendix [CW85]. The finite-map presentation, bottom, safety proof, and Kernel algorithm above are local. Pierce fixes the minimal full-F<: grammar in Definition 2.2 and Figure 2, then gives the trace (crediting the example to Giorgio Ghelli), undecidability theorem, and typechecking reduction in Example 4.1, Theorem 10.7, and Section 11 [Pie92].

Suggested first pass.

None of these problems is a prerequisite for later chapters. Begin with exercise 8.13, exercise 8.14; then use the starred problem to reconstruct the typechecking reduction in full.

Exercise 8.13

★☆☆ Continue the trace for two iterations, displaying both S-AllF premises at every step. Explain why the fresh alpha-renamed binders make the contexts strictly grow.

Exercise 8.14

★★☆ Use the two if-and-only-if propositions displayed in the source import. Assuming a total subtyping decider, write the three-step decision procedure for two-counter-machine halting on input M: construct R(M), construct J(R(M)), and invoke the decider. Justify both answers from the biconditionals, and explain why one divergent subtype search alone could not establish this undecidability result.

Exercise 8.15 — *

★★★ Given a derivable closed statement ΓS<:T in the sense of definition 8.28, derive Γλf:TTop.λa:S.fa:(TTop)STop. Here Γ is the supplied mixed context, containing only type bounds in this instance; there is no second term-context zone. Mark the direct subsumption step using S<:T. Conversely, recover this subtyping statement from the displayed typing by applying lemma 18.40 while inverting the application and its subsumption chains. Reconstruct the lemma’s transitivity case without looking back at its proof, and state the term’s exact closure relative to Γ.

Exercise 18.16

★★★ Practical project.bounded-subtyping-worklist Implement the finite Kernel worklist in artifacts/ch18-subtyping/corpus.kp. Preserve alpha-fresh universal binders and the invariant that every recursive obligation is equivalent to its source query. The accepted run must print the seven named PASS cases and All 7 subtyping corpus cases passed.; the audit must be empty. Run the four commands

kappa check artifacts/ch18-subtyping/corpus.kp
kappa test artifacts/ch18-subtyping/corpus.kp
kappa run artifacts/ch18-subtyping/corpus.kp
kappa audit artifacts/ch18-subtyping/corpus.kp

then replay the three mutations in artifacts/ch18-subtyping/README.md for arrow variance, source-bound promotion, and universal freshening. Each mutant must still typecheck and must fail the stdout oracle. The final Full-F<: case is a boundary test, not a claimed decider.

Search the book

Type to search the local edition.