Lectures onType Theory
Chapter 51
Chapter 51Optional

Capture Types and Capture-Set Polymorphism

Prerequisites. Direct starred prerequisites: Chapter 19, Chapter 50. No later core chapter depends on this route.

A closure can perform no effect when it is created and can outlive every region used during its creation, yet still retain authority. For example, let c denote a printing capability and consider λz.cz. The latent print effect describes what a later call may do. A region annotation bounds where the closure may live. Neither annotation identifies the binding c stored in the closure. The type of the value must record that binding. Capability calculi and affine borrowing systems make authority and aliasing explicit, but their judgments do not by themselves compute this closure capture [WCM00, RST20].

A capture-annotated core

The core calculus is CF<:, the capture-set extension of System F<: formalized by Boruch-Gruszecki, Brachthäuser, Lee, Lhoták, and Odersky [BGBL^+21]. A capture set is either a finite set C={x1,,xn} of term variables or the universal capture set . The finite empty set is . Types and pretypes are distinct: T::=XCU,U::=Π(x:S).T(X<:S).T,v::=λ(x:S).tΛ(X<:S).t,t::=vxttt[T]. The type CU classifies a U-value whose free tracked variables are bounded indirectly by C. In particular, U is pure. A type variable stands for a whole type and therefore is not a pretype.

The dependent arrow Π(x:S).T binds x only inside capture sets in T. This restricted dependency is needed by the first useful polymorphic example. Let forward=λ(f:Π(z:).).f. Its precise result type is Π(f:Π(z:).).{f}Π(z:).. The singleton {f} says that the returned value captures no more than the argument supplied for f; it does not assert that the result captures every variable captured by every possible argument.

Definition 51.1 — Capture of a type

For a well-formed context Γ, define cv(CU,Γ)=C,cv(X,Γ)=cv(T,Γ)if X<:TΓ. The second equation follows the unique upper-bound chain in the well-formed System F<: context.

Capture-set substitution replaces a variable by a set: C2[C1/x]:={(C2{x})C1,xC2,C2,xC2.[C/x]:=. It extends homomorphically through types and through type annotations in terms. Ordinary term substitution remains postfix and capture avoiding.

Exercise 51.1

★☆☆ Compute {x,y}[{a,b}/x][/y] and [{a}/x]. State which equation makes the universal case unresponsive to substitution.

Indirect bounds and subcapturing

Subset inclusion is insufficient because a variable can stand for a value with a smaller capture. The judgment ΓC1capC2 is the least relation generated by

ΓCcap
SC-Star
Γ{xi}capC(1in)
Γ{x1,,xn}capC
SC-Set-L
1in
Γ{xi}cap{x1,,xn}
SC-Set-R
x:TΓΓcv(T,Γ)capC
Γ{x}capC
SC-Var

Reflexivity and transitivity are admissible; they are not primitive rules.

Lemma 51.2 — Subcapturing preorder

For every well-formed Γ, subcapturing is reflexive and transitive.

Proof of Lemma 51.2 — Subcapturing preorder

Proof. For reflexivity, split a finite capture set by SC-Set-L and reinsert each singleton by SC-Set-R; the universal case is SC-Star.

For transitivity, induct on the first derivation. A last SC-Star can be followed only by a judgment whose right side is universal, so SC-Star closes the composite. A last SC-Set-L composes each singleton premise and rebuilds the finite left side. For a last SC-Set-R, invert the second derivation: SC-Star closes immediately, SC-Set-L exposes the selected singleton premise, and when the intermediate set is itself a singleton the second derivation already has the required source. A last SC-Var first composes its declared capture bound with the second derivation, then reapplies SC-Var. Each recursive call removes the last rule of the first derivation, so the induction terminates. ◻

Let Γ=y:,x:. Then Γ{x,y}cap{x}. The x-premise follows from SC-Set-R. For y, rule SC-Var reduces the goal to cap{x}, which SC-Set-L derives with no singleton premises. Thus a pure binding can be removed from a capture bound.

The converse indirect step need not hold. If x:{y}UΓ, then Γ{x}cap{y} follows by SC-Var; no rule derives {y}cap{x} unless the context gives an independent path from y to x.

Lemma 51.3 — Finite subcapturing decomposition

For every finite capture set C={x1,,xn}, ΓCcapDΓ{xi}capD for every i.

Proof of Lemma 51.3 — Finite subcapturing decomposition

Proof. The reverse implication is SC-Set-L. For the forward implication, compose the premise with Γ{xi}capC, derived by SC-Set-R, and use admissible transitivity. ◻

Exercise 51.2

★☆☆ Let Γ=p:U,q:{p}U. Derive Γ{q}cap. Explain why the derivation records an upper bound rather than equality of free-variable sets.

Typing and the capture-polymorphic application

Type subtyping separates outer capture bounds from pretype structure. Its decisive rules are ΓC1capC2ΓU1<:U2ΓC1U1<:C2U2Capt. The function rule is contravariant in its domain and covariant in its codomain: ΓS2<:S1Γ,x:S2T1<:T2ΓΠ(x:S1).T1<:Π(x:S2).T2Fun The ordinary F<: rules govern , bounded universal types, variables, reflexivity, and transitivity.

The term rules that expose capture information are

x:CUΓ
Γx:{x}U
Var-C
x:XΓ
Γx:X
Var-X
Γ,x:St:TΓΠ(x:S).Twf
Γλ(x:S).t:fv(λ(x:S).t)Π(x:S).T
Abs-C
Γt:CΠ(x:S).TΓs:S
Γts:T[cv(S,Γ)/x]
App-C
Γ,X<:St:TΓ(X<:S).Twf
ΓΛ(X<:S).t:fv(Λ(X<:S).t)(X<:S).T
TAbs-C
Γt:C(X<:R).TΓS<:RΓSwf
Γt[S]:T[S/X]
TApp-C
Γt:TΓT<:S
Γt:S
Sub-C

Rule Var-C records the binding x, not the bound C attached to its declared type. Rule App-C later replaces x in the codomain by the argument type’s capture bound. This pair of choices is the mechanism of capture-set polymorphism.

Let g:{c}Π(z:).. Applying forward to g yields ({f}Π(z:).)[cv({c}Ug,Γ)/f]={c}Π(z:).. The equality unfolds definition 51.1 and capture-set substitution. The function’s own empty capture is discarded by App-C; the returned value retains exactly the upper bound of its argument.

These rules also delimit inference. With all parameter, bound, and pretype annotations supplied, Var-C generates a singleton, Abs-C computes free variables, and App-C substitutes the argument bound. Subsumption may then widen the result. Thus local capture bounds are calculable, but the declarative calculus states no principal-type or annotation-inference theorem. Rule Var-X is a deliberate precision boundary: because X is a type and not a pretype, the grammar has no type {x}X.

Exercise 51.3

★☆☆ Apply forward to a pure argument of type Ug. Calculate the result type and name the rule that removes the formal capture {f}.

Reduction, variance, and substitution

Call-by-value beta reduction substitutes both the value and its exact free variables: (λ(x:S).t)vcapt[fv(v)/x][v/x]. The capture-set substitution acts only in annotations; the term substitution acts only in term positions. Type beta and evaluation-context congruence are as in call-by-value F<:.

Typing an application uses the possibly widened set cv(S,Γ), whereas reduction uses the exact set fv(v). The relation between them is subcapturing, not equality. Consequently, a variable bound by Π(x:S).T may occur in capture annotations of T only covariantly with respect to that binder. The well-formedness judgment Γ;A+;ATwf records the variables permitted in positive and negative positions; an arrow swaps A+ and A in its domain and adds its binder to A+ in its codomain.

The restriction is load bearing. Consider f=λ(x:U).λ(y:{x}U).y. If the negative occurrence of x in the inner parameter type were allowed, a pure v:U could first be widened to U. Static application would then assign a domain U to the reduct. Beta reduction instead substitutes fv(v)=, producing a function whose domain is U. Function subtyping reverses domains, so the latter type is not a subtype of the former.

Lemma 51.4 — Covariant capture substitution

Assume Γ and Γ,x:S are well formed. Let C1 and C2 be well-formed capture sets in Γ. Assume also Γ,x:S;{x}dom(Γ);dom(Γ)Twf and ΓC1capC2. Then ΓT[C1/x]<:T[C2/x].

Proof of Lemma 51.4 — Covariant capture substitution

Proof. Use simultaneous induction on the formation of types and pretypes. For an outer capture annotation containing x, capture-set substitution replaces x by C1 and C2; Capt applies to the assumed subcapturing derivation. In an arrow domain the polarity sets exchange, so x is not available in the positive set and cannot occur there. In the codomain the binder formation rule places x only in the positive set, where the induction hypothesis gives covariance. Bounded universal types repeat the arrow argument with a type-variable binder. The and type-variable cases contain no capture occurrence. ◻

Lemma 51.5 — Capture bound of a value

If Γv:S and v is a value, then Γfv(v)capcv(S,Γ).

Proof of Lemma 51.5 — Capture bound of a value

Proof. Induct on the value-typing derivation. If its last introduction is Abs-C or TAbs-C, the outer annotation is exactly fv(v), and reflexivity applies. If the last rule is Sub-C, the induction hypothesis bounds the free variables by the smaller type’s outer capture. Inversion of outer type subtyping gives the subcapturing premise to the larger annotation; admissible transitivity composes the two bounds. These are the only last rules for a value. ◻

Lemma 51.6 — Value substitution

Assume Γ,x:S is well formed, Γ,x:St:T, Γ,x:S;{x}dom(Γ);dom(Γ)Twf, Γv:S, and v is a value. Then Γt[fv(v)/x][v/x]:T[cv(S,Γ)/x].

Proof of Lemma 51.6 — Value substitution

Proof. Induct on the typing derivation of t. The variable case t=x uses the precise-capture typing of values: some pretype U satisfies Γv:fv(v)U<:S. The abstraction case chooses its bound variable outside fv(v)dom(Γ){x}, applies the induction hypothesis to the opened body, and reconstructs Abs-C. In the application case, capture-set substitution composes with the codomain substitution from App-C. The induction hypotheses reconstruct both premises. Finally, lemma 51.5 gives Γfv(v)capcv(S,Γ); lemma 51.4 and Sub-C widen the exact reduct type to the stated static type. Type abstraction, type application, and subsumption repeat these three mechanisms with the corresponding System F<: substitution or transitivity lemma. ◻

Theorem 51.7 — Preservation and progress for

  1. If Γt:T and tcapt, then Γt:T.

  2. If t:T, then t is a value or some t satisfies tcapt.

Proof of Theorem 51.7 — Preservation and progress for

Proof. For preservation, induct on the reduction rule. Congruence cases rebuild the typing rule after applying the induction hypothesis. Type beta uses ordinary type substitution. Term beta uses lemma 51.6; its conclusion is exactly the result type printed by App-C.

For progress, induct on the closed typing derivation. Subsumption invokes the induction hypothesis. In an application, either the function steps, the argument steps after the function is a value, or both are values. By canonical forms for the capture-annotated arrow, the function is a term abstraction, so term beta applies. Type application uses the corresponding canonical form for a bounded type abstraction. Variables cannot occur in an empty context. ◻

The source’s Coq development proves the full versions of these lemmas, including weakening, narrowing, type substitution, and the polarity-indexed formation infrastructure. The local proof isolates the nonstandard term-beta case; the complete mechanized development owns the remaining F<: cases.

Theorem 51.8 — Capture prediction

Let Γ contain only term bindings. If Γt:T and tcapv, then Γfv(v)capcv(T,Γ).

Proof of Theorem 51.8 — Capture prediction

Proof. Repeated preservation gives Γv:T. Apply lemma 51.5. ◻

Capture prediction is an upper-bound theorem. It does not state literal set inclusion, because SC-Var follows indirect capture bounds.

Hiding, tunneling, and escape

Bounded type variables provide the core’s one hiding mechanism. In Λ(X<:).λ(x:X).x, rule Var-X retains the abstract type X, rather than manufacturing an ill-formed annotation {x}X. Instantiating X later restores the complete argument type. Capture information can therefore tunnel through this parametric term while it is hidden by X. The price is exact: the core cannot express capture-polymorphic data structures whose element is an abstract type variable with a fresh outer capture annotation. This is not the boxed tunneling discipline of later capture calculi, and no theorem about those calculi is imported into CF<:.

A separate boxed capture card

Fourment and Xu’s CC<: changes both the type grammar and the operational signature [FX23]. Its pure types include type variables, , arrows, bounded universals, and boxed captured types (CR); a captured type has the outer form CR. Type application accepts a pure type. A captured argument must therefore be boxed first and recovered explicitly by an unbox term whose written capture set is in scope. This is the boxed tunneling discipline. It is not the abstract-type tunneling derived above.

The boxed calculus is in monadic normal form. Its machine states are Σ=SEe, with a value store S, a list of continuations E, and a focused expression e. Write ΣokV for the source artifact’s state-typing judgment: some environment types the store, the continuation from the focused type to V, and the focused expression at that focused type. A final state has the form Sa for an answer a.

Theorem 51.9 — Mechanized boxed-state safety

For the pinned CC<: signature:

  1. if ΣokV and ΣΣ, then ΣokV;

  2. if ΣokV, then Σ is final or some Σ satisfies ΣΣ.

Proof of Theorem 51.9 — Mechanized boxed-state safety

Mechanized import. The theorem is the direct reading of preservation and progress in the pinned Coq development. The paper’s Figures 2–5, on physical pages 4–6, fix the pure/captured grammar, well-formedness, and machine reductions. The artifact’s CCsub_Soundness.v lines 273–276 and 529–532 state the two results. No boxed rule or theorem is used in the preceding CF<: proofs. ◻

The paper’s non-local-return and region extensions turn capture prediction into an escape check. Their delimiter rule binds a local capability k and requires the non-derivability condition Γ,k:Return[T]{k}capcv(T,Γ). If a returned value contains k free, capture prediction would derive the forbidden judgment. The condition therefore excludes that return. This extension is not a new theorem of the core: it adds capability syntax, dynamics, and typing rules before applying the core prediction theorem.

Capture sets are not effect rows, region sets, ownership quantities, or proofs that an authority is safe to exercise. They bound the tracked bindings retained by values. The selected source proves no closure-conversion theorem, so this chapter makes no claim that a particular environment layout preserves CF<: typing or reduction.

Sources.

The archived paper’s PDF pages 5–6 print syntax, reduction, and subcapturing; pages 9–11 print the polarity condition, progress, preservation, prediction, and the two capture-substitution lemmas; pages 14–15 print the non-local-return escape argument. Its archived Coq 8.10.0 sources contain the complete formal development: CFsub_Soundness.v lines 2033–2285 prove covariant capture substitution, lines 2924–2990 prove value substitution, and lines 3325 and 3424 begin preservation and progress [BGBL^+21]. The Scala reference supplies surface examples only and is not theorem evidence. The paper’s printed SC-Var premise uses Γx:T; this chapter follows the pinned locally nameless mechanization’s environment-lookup premise, written x:TΓ, and does not transfer the paper theorem across any other change of signature.

Suggested first pass.

Do exercise 51.4, exercise 51.6 before the implementation problem.

Exercise 51.4

★★☆ Derive the type of λ(f:Π(z:S).T).f and then apply it to g:{c,d}Π(z:S).T. Display the Var-C, Abs-C, and App-C steps and calculate the result capture.

Exercise 51.5

★★☆ Reconstruct the failed negative-occurrence example in section 51.4. Give both candidate function types after substituting a pure value and show the failed arrow-subtyping premise.

Exercise 51.6

★★☆ Assume k:Return[T] is the only binding whose indirect capture chain reaches k. Prove that a returned value containing k free cannot pass the displayed delimiter check. Identify where capture prediction and transitivity are used.

Exercise 51.7

★★★ Practical project.capture-bound-checker Implement the finite subcapturing closure and closure-bound check in Kappa. Maintain the invariant that every work-list edge is justified by membership or one environment expansion. Accept direct membership, a two-step indirect capture, and elimination of a pure binding; reject a reversed indirect edge and a declared universal-capture capability escaping into an empty result. Use artifacts/ch51-capture-set/corpus.kp; the accepted run must end with All 6 capture-set corpus cases passed. Mutate the checker so that it treats indirect edges as symmetric: the mutant must typecheck and audit cleanly but fail the reversed-edge oracle. The program illustrates lemma 51.3, theorem 51.8; it does not prove either result.

Search the book

Type to search the local edition.