Lectures onType Theory
Chapter 68
Chapter 68Core route

Abstract Interpretation, Type Systems, and Verified Static Analysis

Testing the command below at inputs 0,1,2 reveals three traces. Its input, however, ranges over all natural numbers, and its loop makes the set of reachable states infinite. (Countdown)x:=inputN;y:=x;while 0<x doassert 0y;assert xy;x:=x1;assert x=0. The collecting semantics records exactly every execution, but computing it is as hard as executing every input. A sound static analyzer must forget enough to terminate and remember enough to justify its alarms. The analyzer below is derived from those two obligations rather than presented as an oracle, following the fixed-point view that founded abstract interpretation [CC77].

Concrete and collecting semantics

Let variables range over a finite set Var, integers over Z, and stores over total maps σ:VarZ. Expressions, tests, and commands are e::=nxe+eee,b::=eee=e¬b,c::=skipx:=ec;cif b then c else cwhile b do cassert b. A strict comparison abbreviates negated non-strict comparison; in particular, 0<x means ¬(x0). The opening x:=inputN is metanotation for the initial store family I={c,σnnN,σn(x)=n}, not an extra command constructor. A configuration is c,σ or the terminal state error. The deterministic small-step rules are the usual rules for assignment, sequencing, conditionals, and loop unfolding. An assertion steps to skip,σ when its test is true and to error otherwise. The input command is represented by the initial set of stores; it is not a nondeterministic expression in later states.

For input 2, the loop-head projections are visit012σ(x)210σ(y)222 and both loop assertions hold at the first two visits. The last assertion holds at the third. This finite trace is a calculation, not the general safety proof.

Definition 68.1 — Collecting transformer

Fix a program c0 and an initial configuration set I. For a set X of configurations, let Fc0(X):=I{κκX. κκ}. The state collecting semantics is Reach(c0,I):=lfp(Fc0). The trace collecting semantics contains every finite or infinite sequence beginning in I whose adjacent configurations satisfy .

Theorem 68.2 — Fixed-point characterization of reachability

The transformer Fc0 is monotone on the complete lattice of configuration sets. Its least fixed point is exactly the set of configurations reachable from I in finitely many steps.

Proof of Theorem 68.2 — Fixed-point characterization of reachability

Proof. If XY, every predecessor chosen from X is also in Y; hence Fc0(X)Fc0(Y). Knaster–Tarski therefore supplies a least fixed point. Let Rn={κκ0I. κ0nκ}. Induction on n gives Fc0n+1()=Rn. Their union is closed under one step and contains I, so it is a fixed point. Every pre-fixed point containing I contains every Rn, by the same induction. The union is therefore least. This uses only the powerset instance of the fixed-point machinery developed in chapter 12. ◻

Exercise 68.1

★☆☆ Replace inputN by a choice from {0,1,2}. Enumerate the complete reachable set, including command components. Mark the six distinct loop-head stores and verify that the set of reachable predecessors of error is empty. (One page.)

A first abstraction: signs

Let Sgn:=P({,0,+}) ordered by inclusion. Bottom is the empty set and top is {,0,+}. For ZZ, define αs(Z):={sgn(n)nZ},γs(S):={nZsgn(n)S}. An abstract store maps each variable to a sign set. Its concretization is pointwise.

Lemma 68.3 — Sign Galois insertion

For all ZZ and SSgn, αs(Z)SZγs(S). Moreover αs(γs(S))=S.

Proof of Lemma 68.3 — Sign Galois insertion

Proof. Both directions unfold to nZ.sgn(n)S. For the insertion equation, every sign has a representative integer: 1,0,1. ◻

Define abstract addition by joining all possible sign-table entries: S1+S2={sgn(m+n)sgn(m)S1, sgn(n)S2}. Subtraction is addition after sign reversal. A test refines the store by removing sign combinations that cannot satisfy it. When signs alone cannot decide a comparison between two non-singleton variables, both branches remain.

Lemma 68.4 — Local soundness of signs

If σγs(σ^), then [[e]]σγs([[e]]σ^). If the concrete test b succeeds, then σ belongs to the concretization of the true refinement; if it fails, it belongs to the false refinement.

Proof of Lemma 68.4 — Local soundness of signs

Proof. Induct on e. Constants and variables follow from the definitions. For addition, the two induction hypotheses put the operands in sign classes enumerated by +, so their concrete sum is included. Subtraction is identical after reversal. The test claim follows by inspecting the retained sign pairs; an undecidable pair is deliberately kept on both sides. ◻

At the first loop head of Countdown, signs infer x{,0,+},y{0,+}. The true guard refines x to {+}, but the sign table for subtracting the positive constant 1 must still contain all three signs. Joining the back edge therefore makes x top. Signs prove 0y, but prove neither 0x nor xy. These are false alarms caused by forgotten magnitude and relation, not unsound results.

Exercise 68.2

★★☆ Invent an abstract subtraction table that returns only {0,+} for {0,+}{0,+}. Give the smallest concrete counterexample to lemma 68.4. Then repair the table by calculating its best result from αs and γs.

Galois connections package sound approximation

Definition 68.5 — Galois connection

For posets C,A, maps α:CA and γ:AC form a Galois connection, written αγ, when α(c)AacCγ(a). It is a Galois insertion when αγ=idA.

Lemma 68.6 — Consequences of the adjunction

If αγ, then cγα(c),αγ(a)a, both maps are monotone, γα is an extensive idempotent closure, and αγ is a reductive idempotent kernel.

Proof of Lemma 68.6 — Consequences of the adjunction

Proof. Put a=α(c) and use reflexivity for extensiveness. Put c=γ(a) for reductiveness. If cc, then ccγα(c), so the correspondence gives α(c)α(c); the proof for γ is dual. Compose extensiveness and reductiveness with monotonicity to obtain both idempotence equations. ◻

Theorem 68.7 — Best correct approximation

Let F:CC and αγ. Then Fbest:=αFγ is sound: FγγFbest. If G:AA is any sound transformer, then FbestG.

Proof of Theorem 68.7 — Best correct approximation

Proof. Extensiveness at F(γ(a)) gives Fγ(a)γαFγ(a). For optimality, soundness of G says Fγ(a)γG(a). The adjunction moves this inequality across αγ, yielding αFγ(a)G(a). ◻

Best does not mean complete. It means most precise among sound functions on the selected abstract domain. A coarser domain can have a best transformer and still lose the invariant needed by a client.

Intervals and compositional transformers

Let lower bounds range over Z{} and upper bounds over Z{+}. The interval domain consists of bottom and pairs [l,u] with lu, ordered by inclusion of their integer meanings: γi([l,u])={nZlnu}. The abstraction of a nonempty integer set is its least enclosing extended interval; the empty set maps to bottom.

Lemma 68.8 — Interval Galois insertion

The hull map αi and membership map γi form a Galois insertion.

Proof of Lemma 68.8 — Interval Galois insertion

Proof. The hull of Z lies within [l,u] exactly when every member of Z lies between l and u. Taking the hull of all integers in an interval recovers its endpoints; bottom is immediate. ◻

Interval addition and subtraction are [l1,u1]+[l2,u2]=[l1+l2,u1+u2],[l1,u1][l2,u2]=[l1u2,u1l2], where a lower-bound calculation containing yields , and an upper-bound calculation containing + yields +. The separated endpoint sets ensure that no indeterminate ++() case occurs. A true filter for x<n replaces the upper bound of x by min(ux,n1); the false filter replaces its lower bound by max(lx,n). Empty results become bottom.

Definition 68.9 — Structural analyzer

An abstract store is a total map from the finite variable set to intervals. Order, join, and concretization are pointwise: ABx. A(x)B(x),(AB)(x)=A(x)B(x), γst(A)={σx. σ(x)γi(A(x))}. The filter assume(b,A) narrows the interval endpoints entailed by an atomic comparison and returns bottom when the bounds cross. It must satisfy (AssumeSound)σγst(A),[[b]]σ=trueσγst(assume(b,A)). Negation supplies the false filter.

Write post(c,A) for terminal stores and err(c,A)Bool for a possible assertion error. Put Ab=assume(b,A) and A¬b=assume(¬b,A). The store clauses are post(skip,A)=A,post(x:=e,A)=A[x[[e]]A],post(c1;c2,A)=post(c2,post(c1,A)),post(if b then ct else cf,A)=post(ct,Ab)post(cf,A¬b),post(assert b,A)=Ab. Error flags are false for skip and assignment; err(assert b,A) is true exactly when A¬b. Sequencing takes the disjunction of the first flag and the second flag at the first post-state; conditionals take the disjunction of their branch flags. A loop uses the least pre-fixed invariant X of ΦA(X)=Apost(c,assume(b,X)). The loop’s post-state and error flag are, respectively, assume(¬b,X)anderr(c,assume(b,X)). The result is a store/error pair, not an abstract store expected to contain intermediate configurations.

Theorem 68.10 — Compositional analyzer soundness

Suppose expression evaluation and both test refinements are locally sound. If σγst(A), then:

  1. if c,σskip,σ, then σγst(post(c,A));

  2. if c,σerror, then err(c,A)=true.

Proof of Theorem 68.10 — Compositional analyzer soundness

Proof. Induct on the syntax of c. Assignment uses expression soundness. Sequencing composes the two induction hypotheses. A conditional uses the sound refinement corresponding to the concrete Boolean and then the selected branch hypothesis. Assertion soundness follows because a concrete false state is retained by the false refinement, so its nonbottom test sets the flag. For sequencing, an error occurs either in the first command or in the second from a terminal first-command store, exactly matching the disjunction. For a loop, induction on the number of completed iterations shows that every loop-head store lies in every pre-fixed point X satisfying ΦA(X)X; leastness puts it in the selected invariant. The exit filter handles a terminal failed guard and the body flag handles an assertion error during an iteration. ◻

For Countdown, interval filtering gives at the loop head x[0,+],y[0,+]. The transfer x:=x1 followed by the loop-head filter restores the same invariant. The analyzer proves the first assertion and, at loop exit, refines x to [0,0], proving the final assertion. Like signs, it cannot prove the relational assertion xy.

Exercise 68.3

★★☆ Analyze Countdown from input interval [0,4]. Display every iterate before convergence, the true and false guard refinements, and the three assertion results. Repeat after replacing x:=x1 by x:=x2, and identify the reachable negative exit state.

Fixed-point transfer, widening, and narrowing

Theorem 68.11 — Fixed-point transfer

Let F:CC and F:AA be monotone on complete lattices, and let γ:AC be monotone. If FγγF, then lfp(F)γ(lfp(F)).

Proof of Theorem 68.11 — Fixed-point transfer

Proof. The abstract least fixed point is a fixed point, so soundness gives F(γ(lfpF))γ(F(lfpF))=γ(lfpF). Thus its concretization is a pre-fixed point of F. Leastness of lfp(F) gives the result. ◻

Exact interval iteration need not terminate. The commands x:=0;while true do x:=x+1 generate [0,0][0,1][0,2].

Definition 68.12 — Interval widening

For nonbottom intervals, define [l,u][l,u]=[{l<llll,{+u>uuuu.]. Bottom is neutral. Widening iteration is A0=,An+1=AnF(An).

Theorem 68.13 — Widening coverage and termination

Let F:CC and F:AA be monotone, let αγ, and assume FγγF. On a finite product of interval domains, ABAB, and the displayed widening iteration stabilizes. If it stabilizes at AN, then F(AN)AN,lfp(F)γ(AN).

Proof of Theorem 68.13 — Widening coverage and termination

Proof. Each widened endpoint either stays fixed or moves once to its corresponding infinity. With finitely many program variables, only finitely many such moves exist, so the sequence stabilizes. Coverage is immediate from the two endpoint cases. At stability, AN=ANF(AN) and coverage gives F(AN)AN. Soundness and monotonicity of γ give F(γAN)γ(FAN)γAN. Thus γAN is a concrete pre-fixed point. Park induction—leastness of lfp(F) among pre-fixed points—gives the second claim. ◻

A selected interval endpoint replacement narrows an infinite endpoint to the corresponding finite endpoint proposed by F(A), leaving finite endpoints unchanged. This chapter applies a narrowing step only when a subsequent check confirms F(A)A. That check preserves soundness. Without that check, this particular endpoint replacement has no soundness theorem. Standard narrowing operators instead carry their own coverage and descending-chain conditions; those conditions are not claimed for this deliberately small operator.

Exercise 68.4

★★★ Design a threshold widening that preserves the constants {1,0,1,10} before jumping to infinity. Prove coverage and termination. Calculate its result on the ascending chain above and compare it with definition 68.12. (One page.)

A relational refinement

Independent intervals cannot remember that the initialization y:=x makes xy, nor that decrementing only x preserves it. Add difference constraints uvk over program variables and a distinguished zero variable. A relational abstract store is a difference-bound matrix D; its concretization contains the stores satisfying every finite entry. Assignment by a copy plus a constant updates both the row and column for the assigned variable. For every variable or distinguished zero node w, before closure, Dxw=Dyw+k,Dwx=Dwyk,Dxx=0,Duv=Duvwhen u,vx. Closure then composes bounds by the triangle inequality. Forgetting either the row or the column is not an assignment transformer.

Lemma 68.14 — Sound reduction with intervals

Let A=(I,D) denote the intersection of an interval store and a difference-bound matrix. Tightening interval endpoints with bounds entailed by the closed matrix, and tightening matrix entries with interval endpoints, produces ρ(A) such that γ(ρ(A))=γ(A). Consequently ρ is a sound reduced-product operation.

Proof of Lemma 68.14 — Sound reduction with intervals

Proof. Each tightening is a logical consequence of constraints already present in the other component. It therefore removes no concrete store from the intersection. Conversely, tightening only removes stores that violated such a consequence, so it adds none. Apply any finite schedule of these closure and propagation rules; equality of concretizations is preserved at every step. This lemma claims semantic preservation, not termination of an unrestricted alternating saturation procedure. ◻

At entry to the loop of Countdown, the matrix contains xy0 and yx0. The assignment x:=x1 changes these to xy1 and yx1. Joining loop iterations preserves xy0, but the reverse bound grows through 1,2,. The loop solver therefore widens DBM entries: a bound that weakens is replaced by +, while a stable or strengthening bound is retained, followed by closure. Each of the finitely many entries is dropped at most once, so the iteration terminates. For this loop, yx is dropped and xy0 remains. The latter is inductive and proves the relational assertion. Together with the interval facts x,y0, it proves that no assertion in Countdown can reach error.

Corollary 68.15 — Countdown safety

Every execution of Countdown from a natural-number input avoids error.

Proof of Corollary 68.15 — Countdown safety

Proof. The interval–difference reduced product establishes the inductive loop invariant 0x,0y,xy. Local assertion soundness excludes the two loop errors. The false loop guard and 0x imply x=0, excluding the final error. ◻

Exercise 68.5

★★★ Extend Countdown with z:=y at the loop head. Calculate the interval component before and after reduction, add the required matrix row and column, and prove that xz. Give one unsound reduction rule and its smallest counterexample.

A bounded borrow-graph case

Move’s reference-safety analysis supplies a less numerical instance of the same design. An abstract location names a local variable or operand-stack slot. A path is a finite field sequence, optionally ending in to denote all extensions. An edge Borrow(m,p,n) says that the reference at n is borrowed from the location reached by path p from m. Eliminating a temporary node composes every incoming edge with every outgoing edge before deleting the node; a field borrow extends the edge label. These operations deliberately forget concrete addresses but retain the rooted-path relation needed after a temporary is popped.

The abstract program annotation is computed by a forward fixed point. Its order keeps local and stack types equal and permits each borrow edge in the smaller graph to be subsumed by an edge in the larger graph. Transfer rejects a move or overwrite when an outgoing edge witnesses a live borrow. The soundness relation Inv(s,s^) packages four obligations: type agreement, no leaked allocated location, every reference rooted by a realized acyclic borrow path, and referential transparency for mutation.

Theorem 68.16 — Move borrow-graph preservation

For the paper’s bytecode semantics and verifier, let P be well typed. If Inv(s,Abs(s)) and Pss, then Inv(s,Abs(s)). Consequently the four obligations hold at every state reachable from a valid initial transaction state.

Proof of Theorem 68.16 — Move borrow-graph preservation

Proof. This is Theorem 1 and its stated corollary in the frozen Move borrow-checker paper, at printed pages 8–9 [BMNQ22]. The source proof decomposes the step into a local abstract transition, proves that transition preserves Inv, and then uses annotation subsumption to reach the fixed-point annotation at the successor program counter. We import that theorem only at its bytecode, abstraction, and invariant signature. It is not a theorem about the place calculus of chapter 48 or about the interval analyzer above, and the archived implementation is evidence of lineage rather than a machine-checked refinement proof. ◻

Exercise 68.6

★★☆ Suppose the graph contains Borrow(a,p,u)andBorrow(u,q,b). Calculate the edge required before eliminating u. Give a concrete rooted path that becomes unrepresented if the composed edge is omitted, and name the clause of Inv that then fails.

A type system as an abstract semantics

Use a separate call-by-value expression language e::=ntruefalsexe+eλx.ee e, with integer, Boolean, and closure values. This is not an instance of the first-order command semantics above. Interpret simple types as sets of values: γ(Int)=Z,γ(Bool)={true,false}. The arrow interpretation is γ(AB)={λx.e,ρv,v. vγ(A) ande,ρ[xv]v imply vγ(B)}. The arrow clause is a partial-correctness abstraction: it constrains every terminating application and does not assert termination. The sound abstract addition transformer accepts Int×Int and returns Int; application accepts (AB)×A and returns B. Writing these transfer conditions as judgments gives the usual variable, integer, Boolean, addition, abstraction, and application rules. In particular, Γ,x:Ae:BΓλx.e:ABTyAbsΓe1:ABΓe2:AΓe1 e2:BTyApp.

Theorem 68.17 — Type safety from abstraction

If Γe:A and an environment ρ maps every x:BΓ into γ(B), then every terminating evaluation e,ρv satisfies vγ(A) and encounters no primitive tag error.

Proof of Theorem 68.17 — Type safety from abstraction

Proof. Induct on the typing derivation together with the terminating evaluation. Variables use the environment hypothesis. Addition inverts both premises to integer denotations, so the primitive is defined and returns an integer. For Ty-Abs, the resulting closure satisfies the displayed universal condition by the induction hypothesis for the body. For Ty-App, the operator induction hypothesis supplies a closure in γ(AB), the operand hypothesis supplies an argument in γ(A), and the arrow condition gives the result in γ(B). These cases cover every primitive that can raise a tag error. ◻

This is type-system soundness, proved for the expression semantics just defined. It does not imply completeness: after adding conditionals, if true then 0 else false evaluates safely but has no simple type. It does not imply principality either: that property requires type variables and an instantiation relation, neither of which this monomorphic fragment contains. A union or singleton-refinement domain may type more safe terms, which is a precision or completeness change rather than a principality theorem. Command-analyzer soundness, type-system soundness, completeness, and principality are separate statements. The general derivation of types as abstract interpretations belongs to Cousot’s exact framework [Cou97]; the local theorem above needs only the displayed tag abstraction.

Exercise 68.7

★★☆ Add a union type constructor with γ(AB)=γ(A)γ(B). State the induced precision order and analyze the constant-guard example. Prove soundness, disprove completeness, and explain exactly why principality is not formulated without type variables and an instantiation relation.

Higher-order analysis by abstracting a machine

A CEK state e,ρ,κ contains an expression, an environment from variables to closures, and a continuation. For the expression language of section 68.8, use frames κ::=mtar(e,ρ,κ)fn(v,κ), and the representative rules Xe0 e1,ρ,κe0,ρ,ar(e1,ρ,κ)CEKApp v0 valuev0,ρ,ar(e1,ρ1,κ)e1,ρ1,fn(v0,κ)CEKArg v1 valuev1,ρ1,fn(λx.e,ρ0,κ)e,ρ0[xv1],κCEKBeta. Variable lookup replaces x by the closure ρ(x); integer primitives add explicit left- and right-operand frames of the same shape. Recursive environments and continuations make the reachable state space infinite even for one finite program. The route to a finite analysis is operational.

First store-allocate bindings: ρ:VarAddr,σ:AddrP(Closure). Then store-allocate continuation tails as storable values. Add a finite time component and parameterize the machine by tick:ΣTime,alloc:ΣAddr. The abstract address and time sets are finite. Reusing an address changes store overwrite to join, and lookup becomes nondeterministic over every value in the stored set. Syntax is finite for the analyzed program; the remaining state components are finite maps over finite sets. Reachability is therefore decidable.

Fix maps αa and αt from concrete addresses and times to their finite counterparts. Abstraction maps an environment pointwise through αa; at an abstract address a^, it joins all closures and continuation tails stored at concrete addresses mapped to a^. Abstract states are ordered by equality on control expression and environment, and subset inclusion at every store address. The parameter contracts are (MachineParameters)αt(tick(ς))=tick^(ας),αa(alloc(ς))=alloc^(ας). Allowing inclusion instead of equality yields the same simulation after choosing a related abstract address or time.

Theorem 68.18 — Abstract-machine simulation

Suppose tick^ and alloc^ satisfy (Machine-Parameters) and the abstract store order is the pointwise subset order just defined. If ςςandα(ς)ς^, then there exists ς^ such that ς^ς^andα(ς)ς^.

Proof of Theorem 68.18 — Abstract-machine simulation

Proof. Proceed by cases on the displayed CEK rules and their store-allocated counterparts. Variable lookup is included because the abstract store entry contains the abstraction of the concrete closure. In CEK-App, storing the continuation tail at the concrete allocation maps to the address selected by the abstract allocation equation; store join retains that tail and any old occupants. CEK-Arg changes only the finite frame payload. In CEK-Beta, the argument closure is joined at the allocated binding address and the abstract environment points to it. Return does the same for a store-allocated continuation. All control expressions and environments commute with α, while the tick equation relates successor times. Selecting the joined occupant that abstracts the concrete one supplies the required nondeterministic successor. Integer-frame cases repeat the CEK-Arg argument and variable lookup uses the defining store union. ◻

This is the CESK-star simulation pattern of Van Horn and Might, whose exact Theorem 2 states the same one-step obligation after store allocation and finite-address abstraction [VHM12]. Allocation policy controls precision: one address per variable gives a monovariant analysis; including a bounded call string distinguishes contexts. No theorem from the control calculi of chapter 17 is transferred here.

Exercise 68.8

★★★ Replace monovariant addresses by pairs of variable and last call site. Prove the allocation clause needed by theorem 68.18. On (λf.(f0,ftrue))(λx.x), show which closure sets become more precise. (One page.)

Constructive Galois connections and extraction

A classical powerset abstraction α:P(C)A may be noncomputable even when the resulting analyzer is executable. A constructive Galois connection separates the pure calculation from the specification effect.

Definition 68.19 — Constructive Galois connection

For sets C,A, an extraction η:CA and an interpretation μ:AP(C) form a constructive Galois connection when cμ(a)η(c)=a. For ordered abstractions, replace equality on the right by η(c)a. Powerset lifting is confined to the specification side; η remains a pure function.

Lemma 68.20 — Constructive calculation of a transformer

Let f:CC and suppose a pure, monotone f:AA satisfies η(f(c))f(η(c)) for every c. Then f(μ(a))μ(f(a)).

Proof of Lemma 68.20 — Constructive calculation of a transformer

Proof. Take cμ(a). The correspondence gives η(c)a. Monotonicity of f and the local hypothesis yield η(f(c))f(η(c))f(a). Apply the correspondence in reverse. ◻

For the binary form used in arithmetic, take ciμ(ai). The correspondence and monotonicity in the two coordinates give the complete calculation η(g(c1,c2))g(η(c1),η(c2))g(a1,a2). Applying the correspondence in reverse therefore proves the following instance. If g:C×CC, g:A×AA is monotone in both arguments, and η(g(c1,c2))g(ηc1,ηc2), then g(μ(a1)×μ(a2))μ(g(a1,a2)).

For intervals, η(n)=[n,n] and μ([l,u])={nlnu}. Calculating addition through lemma 68.20 yields the executable endpoint function, while the set image remains in the proof. Darais and Van Horn’s constructive framework mechanizes this separation and its calculational rules in Agda [DVH19]. The pinned artifact is evidence for that formalization; it is not silently imported as the proof of this chapter’s imperative analyzer.

Theorem 68.21 — Extracted analyzer boundary

The interval expression operations, atomic filters, structural post/error functions, interval widening, checked narrowing, copy-plus-constant DBM transformer, and finite DBM closure used above are pure functions. When their loop worklist stabilizes at a checked pre-fixed point, composing their local soundness proofs yields an executable analyzer whose terminal store and error flag satisfy theorem 68.10.

Proof of Theorem 68.21 — Extracted analyzer boundary

Proof. Every named component except the specification relation is defined by structural recursion or a finite worklist; widening supplies termination for the interval product, and DBM extrapolation drops each unstable entry at most once. Lemma 68.20 eliminates the specification effect at primitive transformers; theorem 68.10, theorem 68.13 compose the resulting local simulations and justify checked loop invariants. Difference-bound reduction is sound by lemma 68.14. Erasing proofs therefore leaves only the pure functions. The Kappa artifact checks selected interval, widening, and relational calculations on one finite trace; it is not the extracted analyzer asserted by this theorem. ◻

A verified analyzer trust case

Verasco analyzes C#minor, an intermediate language immediately before CompCert’s Cminor. Its concrete semantics is continuation-based small-step execution. Its state abstraction combines local and memory environments, nonrelational and relational numerical domains, congruences, intervals, floating-point bounds, and a memory abstraction. Domain interfaces are written in γ-only form: each operation carries a theorem that its concrete inputs and outputs lie in the concretization. This avoids computing a powerset abstraction inside Coq.

Loops and gotos are solved by a structural interpreter and pre-fixed-point iteration. Widening and narrowing use explicit fuel. The paper discusses an untrusted iterator whose candidate would be accepted only by a verified checker, but the exact theorem imported below is for the pinned implemented pipeline, not for that alternative architecture. The polyhedral component locally uses certificates checked by verified code. The extracted OCaml analyzer is linked with CompCert’s verified front end and compiler; the OCaml runtime and extraction mechanism remain outside the Coq kernel.

Theorem 68.22 — Verasco's exact safety conclusion

Fix the five section parameters kind:num_dom_kind, max_concretize:N, two Boolean flags trace,verbose, and unroll:N. For the resulting pinned function, if vanalysiskind,max_concretize,trace,verbose,unroll(prog)=(tt,nil) and a behavior of the C#minor semantics on input trace tr is Goes_wrong(tr), then false follows. Thus an empty alarm list excludes run-time error for every input trace represented by that semantics.

Proof of Theorem 68.22 — Verasco's exact safety conclusion

Proof. This is the paper’s final Coq theorem vanalysis_correct, imported at its C#minor signature [JLB^+15]. The proof factors through the verified C#minor program logic, sound abstract-domain interfaces, and checked pre-fixed points. CompCert semantics preservation transfers the established safety property to generated assembly. The theorem does not claim absence of alarms, functional correctness, termination, or correctness of unverified performance heuristics rejected by their checkers. ◻

Paths are not traces

Consider if x=0 then y:=0 else y:=1;if y=0 thenassert x=0 else skip. A syntactic control-flow path records the chosen edges and composed transfer functions. A semantic trace also records the stores that make those edges feasible and the values computed along them. The apparent path combining the first else edge x0 with the later then edge y=0 is syntactically describable but semantically infeasible: the first edge assigns y=1.

Definition 68.23 — Two soundness targets

Syntactic-path soundness over-approximates the abstract effect of every path in the control-flow graph, whether feasible or not. Semantic-trace soundness over-approximates the abstraction of every trace generated by the concrete semantics.

Proposition 68.24 — Neither target is a renaming of the other

For a non-disjunctive abstraction, a syntactic-path analysis may be strictly less precise than a semantic-trace analysis because it joins infeasible paths. Conversely, a transfer system proved sound only for syntactic edge composition has no semantic-trace theorem until its edge transformers are related to concrete state transitions.

Proof of Proposition 68.24 — Neither target is a renaming of the other

Proof. The displayed program supplies the first claim. Joining after the first conditional gives x[,+] and y[0,1]; filtering the second then edge leaves x unconstrained, so an interval analysis cannot prove its assertion. Every semantic trace taking that edge came from the first then branch and has x=0. Thus the infeasible combination contributes to the joined path state but to no trace. For the second claim, alter an assignment edge transformer so that it leaves the abstract state unchanged. The equations still describe their own syntactic paths, but the concrete assignment changes the store and violates transition simulation. ◻

Cousot’s structural trace development derives the two specifications from different abstractions and exhibits examples involving liveness and deadness where a syntactic statement does not establish the intended semantic property [Cou19]. We use that result only for this distinction; it does not replace the compositional soundness theorem proved above.

Exercise 68.9

★★☆ Construct a program with two branching points and one infeasible edge combination on which interval analysis produces a false assertion alarm. State and prove its syntactic-path result and semantic-trace result separately.

A source-gated probabilistic application

The interval-trace semantics of Beutner, Ong, and Zaiser assigns each finite interval trace t=[a1,b1],,[an,bn] a volume vol(t)=i(biai), an interval weight wtPI(t), and an interval result valPI(t). Two traces are compatible when some common-coordinate intervals are almost disjoint; a family is compatible when this holds pairwise. A countable family is exhaustive when its cylinders cover almost every infinite sample trace. For measurable U, define lowerBdPT(U)=tTvol(t)minwtPI(t)[valPI(t)U],upperBdPT(U)=tTvol(t)supwtPI(t)[valPI(t)U]. The brackets are (0/1) indicators.

Theorem 68.25 — Sound unnormalized measure bounds

For the paper’s typed recursive probabilistic language:

  1. if T is countable and compatible, then lowerBdPT[[P]];

  2. if T is countable and exhaustive, then [[P]]upperBdPT.

The inequalities are pointwise on measurable result sets. The middle term is the program’s unnormalized measure, not its normalized posterior.

Proof of Theorem 68.25 — Sound unnormalized measure bounds

Proof. For the lower bound, interval evaluation soundness bounds each concrete trace’s weight below by the interval minimum and its result inside the return interval. Compatibility makes the represented boxes almost disjoint, so their integrals may be summed without double counting. Their union is a subset of all traces, giving the lower inequality.

For the upper bound, interval soundness bounds each represented trace from above. Exhaustivity covers almost every concrete infinite trace, and subadditivity bounds the integral by the sum of interval maxima. These are Theorems 4.1–4.2 of the frozen interval-trace calculus [BOZ22]. We do not import its Theorem 4.3 completeness result. ◻

Posterior bounds additionally require bounds on the normalizing constant and a justified division rule; no normalized claim is made here. This application follows the same approximation pattern, but its concrete objects are measures and traces rather than imperative states. It is static analysis of a probabilistic program, not a semantics-preserving inference transformation.

What the comparisons do and do not identify

Dataflow analysis joins facts at program points. The tag analysis above instead abstracts values and expressions, while the machine abstraction keeps control components explicit. A path-sensitive abstraction may retain guard formulas rather than joining all represented inputs; the two-conditional example in section 68.12 proves that this can be strictly more precise than non-disjunctive intervals. Deductive verification begins from a candidate invariant and checks proof obligations, whereas the analyzer above computes a candidate and then checks the same pre-fixed-point inequality. These are explicit abstraction or algorithmic differences, not a catalogue of systems that happen to share lattice vocabulary.

The chapter’s verified conclusion is narrower and stronger: for the stated integer language, local transformer proofs, fixed-point transfer, widening, checked narrowing, and reduced-product soundness compose into corollary 68.15. Floating point, concurrency, quantitative cost, and arbitrary production analyzers require their own concrete semantics and abstraction proofs.

Chapter seminar

The Kappa corpus at artifacts/ch68-verified-analyzer/ executes the countdown recurrence at input 3, checks that [0,3] contains both state components along that trace, performs one interval widening and a narrowing proposal checked against the same finite trace, checks xy pointwise, and rejects a nonnegative-subtraction claim at 01. It does not implement the sign analyzer, structural command analyzer, or DBM closure. This finite implementation witnesses the displayed calculations; it is not a mechanization of the total theorems or a replay of Verasco.

Suggested first pass.

Do exercise 68.10, exercise 68.11 before exercise 68.14.

Exercise 68.10

★★☆ For interval addition, calculate αi(+(γi[1,3]×γi[2,4])) and recover the endpoint formula as the best correct approximation. Give a sound but less precise result and prove the pointwise comparison.

Exercise 68.11

★★★ Reconstruct the sequencing and while cases of theorem 68.10. Treat terminal stores and the error flag separately, and use “pre-fixed point” with the order stated in definition 68.9.

Exercise 68.12

★★★ Calculate the first three DBM loop-head iterates for Countdown. Apply entrywise widening, show that yx is dropped while xy0 is retained, and verify the resulting pre-fixed-point inequality.

Exercise 68.13

★★☆ List the trusted hypotheses of the local analyzer, the abstract-machine simulation, the pinned Verasco theorem, and the interval-trace bound. Give one conclusion that would be invalid if a hypothesis were moved from one card to another.

Exercise 68.14

★★★ Practical project.verified-analyzer Run the corpus and reproduce its five named passes. Maintain the invariant that every concrete result represented by an interval operation lies inside the returned interval. Add multiplication first with the unsound endpoint rule [l1l2,u1u2]: on [2,3] and [4,5] the missing result 10 must fail its oracle. Replace it by the four-product hull, which must return [10,15]. Add threshold 10; the chain must visit [0,0],[0,1],[0,10],[0,+], with coverage checked at every step. Finally add State(4,3) to the relational fixture: the unchanged xy oracle must fail. State the strengthened input invariant needed to restore the five original passes and the new multiplication and threshold passes.

Search the book

Type to search the local edition.