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. 𝑥:=𝗂𝗇𝗉𝗎𝗍ℕ;𝑦:=𝑥;𝐰𝐡𝐢𝐥𝐞 0<𝑥 𝐝𝐨𝐚𝐬𝐬𝐞𝐫𝐭 0≤𝑦;𝐚𝐬𝐬𝐞𝐫𝐭 𝑥≤𝑦;𝑥:=𝑥−1;𝐚𝐬𝐬𝐞𝐫𝐭 𝑥=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 𝖵𝖺𝗋, integers over ℤ, and stores over total maps 𝜎 :𝖵𝖺𝗋 →ℤ. Expressions, tests, and commands are 𝑒::=𝑛∣𝑥∣𝑒+𝑒∣𝑒−𝑒,𝑏::=𝑒≤𝑒∣𝑒=𝑒∣¬𝑏,𝑐::=𝐬𝐤𝐢𝐩∣𝑥:=𝑒∣𝑐;𝑐∣𝐢𝐟 𝑏 𝐭𝐡𝐞𝐧 𝑐 𝐞𝐥𝐬𝐞 𝑐∣𝐰𝐡𝐢𝐥𝐞 𝑏 𝐝𝐨 𝑐∣𝐚𝐬𝐬𝐞𝐫𝐭 𝑏. A strict comparison abbreviates negated non-strict comparison; in particular, 0 <𝑥 means ¬(𝑥 ≤0). The opening 𝑥 :=𝗂𝗇𝗉𝗎𝗍ℕ is metanotation for the initial store family 𝐼 ={⟨𝑐,𝜎𝑛⟩ ∣𝑛 ∈ℕ,𝜎𝑛(𝑥) =𝑛}, not an extra command constructor. A configuration is ⟨𝑐,𝜎⟩ or the terminal state 𝖾𝗋𝗋𝗈𝗋. The deterministic small-step rules are the usual rules for assignment, sequencing, conditionals, and loop unfolding. An assertion steps to ⟨𝐬𝐤𝐢𝐩,𝜎⟩ when its test is true and to 𝖾𝗋𝗋𝗈𝗋 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𝜎(𝑥)210𝜎(𝑦)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.
The transformer F𝑐0 is monotone on the complete lattice of configuration sets. Its least fixed point is exactly the set of configurations reachable from 𝐼 in finitely many steps.
Referenced from 2 locations
Proof of Theorem 68.2 — Fixed-point characterization of reachability
Proof. If 𝑋 ⊆𝑌, every predecessor chosen from 𝑋 is also in 𝑌; hence F𝑐0(𝑋) ⊆F𝑐0(𝑌). Knaster–Tarski therefore supplies a least fixed point. Let 𝑅𝑛={𝜅∣∃𝜅0∈𝐼. 𝜅0⟶≤𝑛𝜅}. Induction on 𝑛 gives F𝑛+1𝑐0(∅) =𝑅𝑛. Their union is closed under one step and contains 𝐼, so it is a fixed point. Every pre-fixed point containing 𝐼 contains every 𝑅𝑛, by the same induction. The union is therefore least. This uses only the powerset instance of the fixed-point machinery developed in chapter 12. ◻
★☆☆ Replace 𝗂𝗇𝗉𝗎𝗍ℕ 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 𝖾𝗋𝗋𝗈𝗋 is empty. (One page.)
Referenced from 3 locations
A first abstraction: signs
Let 𝖲𝗀𝗇:=P({−,0,+}) ordered by inclusion. Bottom is the empty set and top is { −,0, +}. For 𝑍 ⊆ℤ, define 𝛼𝗌(𝑍):={sgn(𝑛)∣𝑛∈𝑍},𝛾𝗌(𝑆):={𝑛∈ℤ∣sgn(𝑛)∈𝑆}. An abstract store maps each variable to a sign set. Its concretization is pointwise.
For all 𝑍 ⊆ℤ and 𝑆 ∈𝖲𝗀𝗇, 𝛼𝗌(𝑍)⊆𝑆⟺𝑍⊆𝛾𝗌(𝑆). Moreover 𝛼𝗌(𝛾𝗌(𝑆)) =𝑆.
Referenced from 2 locations
Proof of Lemma 68.3 — Sign Galois insertion
Proof. Both directions unfold to ∀𝑛 ∈𝑍.sgn(𝑛) ∈𝑆. For the insertion equation, every sign has a representative integer: −1,0,1. ◻
Define abstract addition by joining all possible sign-table entries: 𝑆1+♯𝑆2={sgn(𝑚+𝑛)∣sgn(𝑚)∈𝑆1, sgn(𝑛)∈𝑆2}. 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.
If 𝜎 ∈𝛾𝗌(̂𝜎), then [[𝑒]]𝜎∈𝛾𝗌([[𝑒]]♯̂𝜎). If the concrete test 𝑏 succeeds, then 𝜎 belongs to the concretization of the true refinement; if it fails, it belongs to the false refinement.
Referenced from 3 locations
Proof of Lemma 68.4 — Local soundness of signs
Proof. Induct on 𝑒. 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 𝖢𝗈𝗎𝗇𝗍𝖽𝗈𝗐𝗇, signs infer 𝑥↦{−,0,+},𝑦↦{0,+}. The true guard refines 𝑥 to { +}, but the sign table for subtracting the positive constant 1 must still contain all three signs. Joining the back edge therefore makes 𝑥 top. Signs prove 0 ≤𝑦, but prove neither 0 ≤𝑥 nor 𝑥 ≤𝑦. These are false alarms caused by forgotten magnitude and relation, not unsound results.
★★☆ 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 𝛼𝗌 and 𝛾𝗌.
Referenced from 3 locations
Galois connections package sound approximation
For posets 𝐶,𝐴, maps 𝛼 :𝐶 →𝐴 and 𝛾 :𝐴 →𝐶 form a Galois connection, written 𝛼 ⊣𝛾, when 𝛼(𝑐)⊑𝐴𝑎⟺𝑐⊑𝐶𝛾(𝑎). It is a Galois insertion when 𝛼𝛾 =id𝐴.
Referenced from 2 locations
If 𝛼 ⊣𝛾, then 𝑐⊑𝛾𝛼(𝑐),𝛼𝛾(𝑎)⊑𝑎, both maps are monotone, 𝛾𝛼 is an extensive idempotent closure, and 𝛼𝛾 is a reductive idempotent kernel.
Referenced from 2 locations
Proof of Lemma 68.6 — Consequences of the adjunction
Proof. Put 𝑎 =𝛼(𝑐) and use reflexivity for extensiveness. Put 𝑐 =𝛾(𝑎) for reductiveness. If 𝑐 ⊑𝑐′, then 𝑐 ⊑𝑐′ ⊑𝛾𝛼(𝑐′), so the correspondence gives 𝛼(𝑐) ⊑𝛼(𝑐′); the proof for 𝛾 is dual. Compose extensiveness and reductiveness with monotonicity to obtain both idempotence equations. ◻
Let 𝐹 :𝐶 →𝐶 and 𝛼 ⊣𝛾. Then 𝐹♯best:=𝛼𝐹𝛾 is sound: 𝐹𝛾⊑𝛾𝐹♯best. If 𝐺 :𝐴 →𝐴 is any sound transformer, then 𝐹♯best⊑𝐺.
Referenced from 2 locations
Proof of Theorem 68.7 — Best correct approximation
Proof. Extensiveness at 𝐹(𝛾(𝑎)) gives 𝐹𝛾(𝑎)⊑𝛾𝛼𝐹𝛾(𝑎). For optimality, soundness of 𝐺 says 𝐹𝛾(𝑎) ⊑𝛾𝐺(𝑎). The adjunction moves this inequality across 𝛼 ⊣𝛾, yielding 𝛼𝐹𝛾(𝑎) ⊑𝐺(𝑎). ◻
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 ℤ ∪{ −∞} and upper bounds over ℤ ∪{ +∞}. The interval domain consists of bottom and pairs [𝑙,𝑢] with 𝑙 ≤𝑢, ordered by inclusion of their integer meanings: 𝛾𝗂([𝑙,𝑢])={𝑛∈ℤ∣𝑙≤𝑛≤𝑢}. The abstraction of a nonempty integer set is its least enclosing extended interval; the empty set maps to bottom.
The hull map 𝛼𝗂 and membership map 𝛾𝗂 form a Galois insertion.
Referenced from 2 locations
Proof of Lemma 68.8 — Interval Galois insertion
Proof. The hull of 𝑍 lies within [𝑙,𝑢] exactly when every member of 𝑍 lies between 𝑙 and 𝑢. Taking the hull of all integers in an interval recovers its endpoints; bottom is immediate. ◻
Interval addition and subtraction are [𝑙1,𝑢1]+♯[𝑙2,𝑢2]=[𝑙1+𝑙2,𝑢1+𝑢2],[𝑙1,𝑢1]−♯[𝑙2,𝑢2]=[𝑙1−𝑢2,𝑢1−𝑙2], 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 𝑥 <𝑛 replaces the upper bound of 𝑥 by min(𝑢𝑥,𝑛 −1); the false filter replaces its lower bound by max(𝑙𝑥,𝑛). Empty results become bottom.
An abstract store is a total map from the finite variable set to intervals. Order, join, and concretization are pointwise: 𝐴⊑𝐵⟺∀𝑥. 𝐴(𝑥)⊑𝐵(𝑥),(𝐴⊔𝐵)(𝑥)=𝐴(𝑥)⊔𝐵(𝑥), 𝛾𝗌𝗍(𝐴)={𝜎∣∀𝑥. 𝜎(𝑥)∈𝛾𝗂(𝐴(𝑥))}. The filter 𝖺𝗌𝗌𝗎𝗆𝖾♯(𝑏,𝐴) narrows the interval endpoints entailed by an atomic comparison and returns bottom when the bounds cross. It must satisfy 𝜎∈𝛾𝗌𝗍(𝐴),[[𝑏]]𝜎=𝗍𝗋𝗎𝖾⟹𝜎∈𝛾𝗌𝗍(𝖺𝗌𝗌𝗎𝗆𝖾♯(𝑏,𝐴)).(𝐴𝑠𝑠𝑢𝑚𝑒−𝑆𝑜𝑢𝑛𝑑) Negation supplies the false filter.
Write 𝗉𝗈𝗌𝗍♯(𝑐,𝐴) for terminal stores and 𝖾𝗋𝗋♯(𝑐,𝐴) ∈𝖡𝗈𝗈𝗅 for a possible assertion error. Put 𝐴𝑏 =𝖺𝗌𝗌𝗎𝗆𝖾♯(𝑏,𝐴) and 𝐴¬𝑏 =𝖺𝗌𝗌𝗎𝗆𝖾♯(¬𝑏,𝐴). The store clauses are 𝗉𝗈𝗌𝗍♯(𝐬𝐤𝐢𝐩,𝐴)=𝐴,𝗉𝗈𝗌𝗍♯(𝑥:=𝑒,𝐴)=𝐴[𝑥↦[[𝑒]]♯𝐴],𝗉𝗈𝗌𝗍♯(𝑐1;𝑐2,𝐴)=𝗉𝗈𝗌𝗍♯(𝑐2,𝗉𝗈𝗌𝗍♯(𝑐1,𝐴)),𝗉𝗈𝗌𝗍♯(𝐢𝐟 𝑏 𝐭𝐡𝐞𝐧 𝑐𝑡 𝐞𝐥𝐬𝐞 𝑐𝑓,𝐴)=𝗉𝗈𝗌𝗍♯(𝑐𝑡,𝐴𝑏)⊔𝗉𝗈𝗌𝗍♯(𝑐𝑓,𝐴¬𝑏),𝗉𝗈𝗌𝗍♯(𝐚𝐬𝐬𝐞𝐫𝐭 𝑏,𝐴)=𝐴𝑏. Error flags are false for skip and assignment; 𝖾𝗋𝗋♯(𝐚𝐬𝐬𝐞𝐫𝐭 𝑏,𝐴) is true exactly when 𝐴¬𝑏 ≠⊥. 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 𝑋 of Φ𝐴(𝑋)=𝐴⊔𝗉𝗈𝗌𝗍♯(𝑐,𝖺𝗌𝗌𝗎𝗆𝖾♯(𝑏,𝑋)). The loop’s post-state and error flag are, respectively, 𝖺𝗌𝗌𝗎𝗆𝖾♯(¬𝑏,𝑋)and𝖾𝗋𝗋♯(𝑐,𝖺𝗌𝗌𝗎𝗆𝖾♯(𝑏,𝑋)). The result is a store/error pair, not an abstract store expected to contain intermediate configurations.
Referenced from 3 locations
Suppose expression evaluation and both test refinements are locally sound. If 𝜎 ∈𝛾𝗌𝗍(𝐴), then:
if ⟨𝑐,𝜎⟩ ⟶∗⟨𝐬𝐤𝐢𝐩,𝜎′⟩, then 𝜎′ ∈𝛾𝗌𝗍(𝗉𝗈𝗌𝗍♯(𝑐,𝐴));
if ⟨𝑐,𝜎⟩ ⟶∗𝖾𝗋𝗋𝗈𝗋, then 𝖾𝗋𝗋♯(𝑐,𝐴) =𝗍𝗋𝗎𝖾.
Referenced from 5 locations
Proof of Theorem 68.10 — Compositional analyzer soundness
Proof. Induct on the syntax of 𝑐. 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 𝑋 satisfying Φ𝐴(𝑋) ⊑𝑋; 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 𝖢𝗈𝗎𝗇𝗍𝖽𝗈𝗐𝗇, interval filtering gives at the loop head 𝑥↦[0,+∞],𝑦↦[0,+∞]. The transfer 𝑥 :=𝑥 −1 followed by the loop-head filter restores the same invariant. The analyzer proves the first assertion and, at loop exit, refines 𝑥 to [0,0], proving the final assertion. Like signs, it cannot prove the relational assertion 𝑥 ≤𝑦.
★★☆ Analyze 𝖢𝗈𝗎𝗇𝗍𝖽𝗈𝗐𝗇 from input interval [0,4]. Display every iterate before convergence, the true and false guard refinements, and the three assertion results. Repeat after replacing 𝑥 :=𝑥 −1 by 𝑥 :=𝑥 −2, and identify the reachable negative exit state.
Referenced from 3 locations
Fixed-point transfer, widening, and narrowing
Let 𝐹 :𝐶 →𝐶 and 𝐹♯ :𝐴 →𝐴 be monotone on complete lattices, and let 𝛾 :𝐴 →𝐶 be monotone. If 𝐹𝛾⊑𝛾𝐹♯, then lfp(𝐹)⊑𝛾(lfp(𝐹♯)).
Referenced from 2 locations
Proof of Theorem 68.11 — Fixed-point transfer
Proof. The abstract least fixed point is a fixed point, so soundness gives 𝐹(𝛾(lfp𝐹♯))⊑𝛾(𝐹♯(lfp𝐹♯))=𝛾(lfp𝐹♯). Thus its concretization is a pre-fixed point of 𝐹. Leastness of lfp(𝐹) gives the result. ◻
Exact interval iteration need not terminate. The commands 𝑥:=0;𝐰𝐡𝐢𝐥𝐞 𝗍𝗋𝗎𝖾 𝐝𝐨 𝑥:=𝑥+1 generate [0,0]⊏[0,1]⊏[0,2]⊏⋯.
For nonbottom intervals, define [𝑙,𝑢]∇[𝑙′,𝑢′]=[{−∞𝑙′<𝑙𝑙𝑙′≥𝑙,{+∞𝑢′>𝑢𝑢𝑢′≤𝑢.]. Bottom is neutral. Widening iteration is 𝐴0=⊥,𝐴𝑛+1=𝐴𝑛∇𝐹♯(𝐴𝑛).
Referenced from 3 locations
Let 𝐹 :𝐶 →𝐶 and 𝐹♯ :𝐴 →𝐴 be monotone, let 𝛼 ⊣𝛾, and assume 𝐹𝛾 ⊑𝛾𝐹♯. On a finite product of interval domains, 𝐴 ⊔𝐵 ⊑𝐴∇𝐵, and the displayed widening iteration stabilizes. If it stabilizes at 𝐴𝑁, then 𝐹♯(𝐴𝑁)⊑𝐴𝑁,lfp(𝐹)⊑𝛾(𝐴𝑁).
Referenced from 3 locations
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, 𝐴𝑁=𝐴𝑁∇𝐹♯(𝐴𝑁) and coverage gives 𝐹♯(𝐴𝑁) ⊑𝐴𝑁. Soundness and monotonicity of 𝛾 give 𝐹(𝛾𝐴𝑁)⊑𝛾(𝐹♯𝐴𝑁)⊑𝛾𝐴𝑁. Thus 𝛾𝐴𝑁 is a concrete pre-fixed point. Park induction—leastness of lfp(𝐹) among pre-fixed points—gives the second claim. ◻
A selected interval endpoint replacement narrows an infinite endpoint to the corresponding finite endpoint proposed by 𝐹♯(𝐴), leaving finite endpoints unchanged. This chapter applies a narrowing step only when a subsequent check confirms 𝐹♯(𝐴′) ⊑𝐴′. 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.
★★★ 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.)
Referenced from 3 locations
A relational refinement
Independent intervals cannot remember that the initialization 𝑦 :=𝑥 makes 𝑥 ≤𝑦, nor that decrementing only 𝑥 preserves it. Add difference constraints 𝑢−𝑣≤𝑘 over program variables and a distinguished zero variable. A relational abstract store is a difference-bound matrix 𝐷; 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 𝑤, before closure, 𝐷′𝑥𝑤=𝐷𝑦𝑤+𝑘,𝐷′𝑤𝑥=𝐷𝑤𝑦−𝑘,𝐷′𝑥𝑥=0,𝐷′𝑢𝑣=𝐷𝑢𝑣when 𝑢,𝑣≠𝑥. Closure then composes bounds by the triangle inequality. Forgetting either the row or the column is not an assignment transformer.
Let 𝐴 =(𝐼,𝐷) 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 𝜌(𝐴) such that 𝛾(𝜌(𝐴))=𝛾(𝐴). Consequently 𝜌 is a sound reduced-product operation.
Referenced from 3 locations
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 𝖢𝗈𝗎𝗇𝗍𝖽𝗈𝗐𝗇, the matrix contains 𝑥 −𝑦 ≤0 and 𝑦 −𝑥 ≤0. The assignment 𝑥 :=𝑥 −1 changes these to 𝑥 −𝑦 ≤ −1 and 𝑦 −𝑥 ≤1. Joining loop iterations preserves 𝑥−𝑦≤0, 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, 𝑦 −𝑥 is dropped and 𝑥 −𝑦 ≤0 remains. The latter is inductive and proves the relational assertion. Together with the interval facts 𝑥,𝑦 ≥0, it proves that no assertion in 𝖢𝗈𝗎𝗇𝗍𝖽𝗈𝗐𝗇 can reach 𝖾𝗋𝗋𝗈𝗋.
Every execution of 𝖢𝗈𝗎𝗇𝗍𝖽𝗈𝗐𝗇 from a natural-number input avoids 𝖾𝗋𝗋𝗈𝗋.
Referenced from 3 locations
Proof of Corollary 68.15 — Countdown safety
Proof. The interval–difference reduced product establishes the inductive loop invariant 0≤𝑥,0≤𝑦,𝑥≤𝑦. Local assertion soundness excludes the two loop errors. The false loop guard and 0 ≤𝑥 imply 𝑥 =0, excluding the final error. ◻
★★★ Extend 𝖢𝗈𝗎𝗇𝗍𝖽𝗈𝗐𝗇 with 𝑧 :=𝑦 at the loop head. Calculate the interval component before and after reduction, add the required matrix row and column, and prove that 𝑥 ≤𝑧. Give one unsound reduction rule and its smallest counterexample.
Referenced from 3 locations
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 𝖡𝗈𝗋𝗋𝗈𝗐(𝑚,𝑝,𝑛) says that the reference at 𝑛 is borrowed from the location reached by path 𝑝 from 𝑚. 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 𝖨𝗇𝗏(𝑠,̂𝑠) packages four obligations: type agreement, no leaked allocated location, every reference rooted by a realized acyclic borrow path, and referential transparency for mutation.
For the paper’s bytecode semantics and verifier, let 𝑃 be well typed. If 𝖨𝗇𝗏(𝑠,𝖠𝖻𝗌(𝑠)) and 𝑃 ⊢𝑠 →𝑠′, then 𝖨𝗇𝗏(𝑠′,𝖠𝖻𝗌(𝑠′)). Consequently the four obligations hold at every state reachable from a valid initial transaction state.
Referenced from 2 locations
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 𝖨𝗇𝗏, 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. ◻
★★☆ Suppose the graph contains 𝖡𝗈𝗋𝗋𝗈𝗐(𝑎,𝑝,𝑢)and𝖡𝗈𝗋𝗋𝗈𝗐(𝑢,𝑞,𝑏). Calculate the edge required before eliminating 𝑢. Give a concrete rooted path that becomes unrepresented if the composed edge is omitted, and name the clause of 𝖨𝗇𝗏 that then fails.
Referenced from 3 locations
A type system as an abstract semantics
Use a separate call-by-value expression language 𝑒::=𝑛∣𝗍𝗋𝗎𝖾∣𝖿𝖺𝗅𝗌𝖾∣𝑥∣𝑒+𝑒∣𝜆𝑥.𝑒∣𝑒 𝑒, 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: 𝛾(𝖨𝗇𝗍)=ℤ,𝛾(𝖡𝗈𝗈𝗅)={𝗍𝗋𝗎𝖾,𝖿𝖺𝗅𝗌𝖾}. The arrow interpretation is 𝛾(𝐴→𝐵)={⟨𝜆𝑥.𝑒,𝜌⟩∣∀𝑣,𝑣′. 𝑣∈𝛾(𝐴) and𝑒,𝜌[𝑥↦𝑣]⇓𝑣′ imply 𝑣′∈𝛾(𝐵)}. The arrow clause is a partial-correctness abstraction: it constrains every terminating application and does not assert termination. The sound abstract addition transformer accepts 𝖨𝗇𝗍 ×𝖨𝗇𝗍 and returns 𝖨𝗇𝗍; application accepts (𝐴 →𝐵) ×𝐴 and returns 𝐵. Writing these transfer conditions as judgments gives the usual variable, integer, Boolean, addition, abstraction, and application rules. In particular, Γ,𝑥:𝐴⊢𝑒:𝐵Γ⊢𝜆𝑥.𝑒:𝐴→𝐵Ty−AbsΓ⊢𝑒1:𝐴→𝐵Γ⊢𝑒2:𝐴Γ⊢𝑒1 𝑒2:𝐵Ty−App.
If Γ ⊢𝑒 :𝐴 and an environment 𝜌 maps every 𝑥 :𝐵 ∈Γ into 𝛾(𝐵), then every terminating evaluation 𝑒,𝜌 ⇓𝑣 satisfies 𝑣 ∈𝛾(𝐴) and encounters no primitive tag error.
Referenced from 2 locations
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 𝛾(𝐴 →𝐵), the operand hypothesis supplies an argument in 𝛾(𝐴), and the arrow condition gives the result in 𝛾(𝐵). 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, 𝐢𝐟 𝗍𝗋𝗎𝖾 𝐭𝐡𝐞𝐧 0 𝐞𝐥𝐬𝐞 𝖿𝖺𝗅𝗌𝖾 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.
★★☆ Add a union type constructor with 𝛾(𝐴 ∨𝐵) =𝛾(𝐴) ∪𝛾(𝐵). 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.
Referenced from 3 locations
Higher-order analysis by abstracting a machine
A CEK state ⟨𝑒,𝜌,𝜅⟩ contains an expression, an environment from variables to closures, and a continuation. For the expression language of section 68.8, use frames 𝜅::=𝗆𝗍∣𝖺𝗋(𝑒,𝜌,𝜅)∣𝖿𝗇(𝑣,𝜅), and the representative rules 𝑋⟨𝑒0 𝑒1,𝜌,𝜅⟩⟶⟨𝑒0,𝜌,𝖺𝗋(𝑒1,𝜌,𝜅)⟩CEK−App 𝑣0 𝗏𝖺𝗅𝗎𝖾⟨𝑣0,𝜌,𝖺𝗋(𝑒1,𝜌1,𝜅)⟩⟶⟨𝑒1,𝜌1,𝖿𝗇(𝑣0,𝜅)⟩CEK−Arg 𝑣1 𝗏𝖺𝗅𝗎𝖾⟨𝑣1,𝜌1,𝖿𝗇(⟨𝜆𝑥.𝑒,𝜌0⟩,𝜅)⟩⟶⟨𝑒,𝜌0[𝑥↦𝑣1],𝜅⟩CEK−Beta. Variable lookup replaces 𝑥 by the closure 𝜌(𝑥); 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: 𝜌:𝖵𝖺𝗋→𝖠𝖽𝖽𝗋,𝜎:𝖠𝖽𝖽𝗋→P(𝖢𝗅𝗈𝗌𝗎𝗋𝖾). Then store-allocate continuation tails as storable values. Add a finite time component and parameterize the machine by 𝗍𝗂𝖼𝗄:Σ♯→𝖳𝗂𝗆𝖾♯,𝖺𝗅𝗅𝗈𝖼:Σ♯→𝖠𝖽𝖽𝗋♯. 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 𝛼𝑎 and 𝛼𝑡 from concrete addresses and times to their finite counterparts. Abstraction maps an environment pointwise through 𝛼𝑎; at an abstract address ̂𝑎, it joins all closures and continuation tails stored at concrete addresses mapped to ̂𝑎. Abstract states are ordered by equality on control expression and environment, and subset inclusion at every store address. The parameter contracts are 𝛼𝑡(𝗍𝗂𝖼𝗄(𝜍))=̂𝗍𝗂𝖼𝗄(𝛼𝜍),𝛼𝑎(𝖺𝗅𝗅𝗈𝖼(𝜍))=̂𝖺𝗅𝗅𝗈𝖼(𝛼𝜍).(𝑀𝑎𝑐ℎ𝑖𝑛𝑒−𝑃𝑎𝑟𝑎𝑚𝑒𝑡𝑒𝑟𝑠) Allowing inclusion instead of equality yields the same simulation after choosing a related abstract address or time.
Suppose ̂𝗍𝗂𝖼𝗄 and ̂𝖺𝗅𝗅𝗈𝖼 satisfy (Machine-Parameters) and the abstract store order is the pointwise subset order just defined. If 𝜍⟶𝜍′and𝛼(𝜍)⊑̂𝜍, then there exists ̂𝜍′ such that ̂𝜍⟶♯̂𝜍′and𝛼(𝜍′)⊑̂𝜍′.
Referenced from 3 locations
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.
★★★ Replace monovariant addresses by pairs of variable and last call site. Prove the allocation clause needed by theorem 68.18. On (𝜆𝑓.(𝑓 0,𝑓 𝗍𝗋𝗎𝖾))(𝜆𝑥.𝑥), show which closure sets become more precise. (One page.)
Referenced from 3 locations
Constructive Galois connections and extraction
A classical powerset abstraction 𝛼 :P(𝐶) →𝐴 may be noncomputable even when the resulting analyzer is executable. A constructive Galois connection separates the pure calculation from the specification effect.
For sets 𝐶,𝐴, an extraction 𝜂 :𝐶 →𝐴 and an interpretation 𝜇 :𝐴 →P(𝐶) form a constructive Galois connection when 𝑐∈𝜇(𝑎)⟺𝜂(𝑐)=𝑎. For ordered abstractions, replace equality on the right by 𝜂(𝑐) ⊑𝑎. Powerset lifting is confined to the specification side; 𝜂 remains a pure function.
Referenced from 2 locations
Proof of Lemma 68.20 — Constructive calculation of a transformer
Proof. Take 𝑐 ∈𝜇(𝑎). The correspondence gives 𝜂(𝑐) ⊑𝑎. Monotonicity of 𝑓♯ and the local hypothesis yield 𝜂(𝑓(𝑐))⊑𝑓♯(𝜂(𝑐))⊑𝑓♯(𝑎). Apply the correspondence in reverse. ◻
For the binary form used in arithmetic, take 𝑐𝑖 ∈𝜇(𝑎𝑖). The correspondence and monotonicity in the two coordinates give the complete calculation 𝜂(𝑔(𝑐1,𝑐2))⊑𝑔♯(𝜂(𝑐1),𝜂(𝑐2))⊑𝑔♯(𝑎1,𝑎2). Applying the correspondence in reverse therefore proves the following instance. If 𝑔 :𝐶 ×𝐶 →𝐶, 𝑔♯ :𝐴 ×𝐴 →𝐴 is monotone in both arguments, and 𝜂(𝑔(𝑐1,𝑐2)) ⊑𝑔♯(𝜂𝑐1,𝜂𝑐2), then 𝑔(𝜇(𝑎1)×𝜇(𝑎2))⊆𝜇(𝑔♯(𝑎1,𝑎2)).
For intervals, 𝜂(𝑛) =[𝑛,𝑛] and 𝜇([𝑙,𝑢]) ={𝑛 ∣𝑙 ≤𝑛 ≤𝑢}. 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.
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.
Fix the five section parameters kind :𝗇𝗎𝗆_𝖽𝗈𝗆_𝗄𝗂𝗇𝖽, max_concretize :ℕ, two Boolean flags trace,verbose, and unroll :ℕ. For the resulting pinned function, if 𝗏𝖺𝗇𝖺𝗅𝗒𝗌𝗂𝗌kind,max_concretize,trace,verbose,unroll(prog)=(𝗍𝗍,𝗇𝗂𝗅) and a behavior of the C#minor semantics on input trace 𝑡𝑟 is 𝖦𝗈𝖾𝗌_𝗐𝗋𝗈𝗇𝗀(𝑡𝑟), then false follows. Thus an empty alarm list excludes run-time error for every input trace represented by that semantics.
Referenced from 2 locations
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 𝐢𝐟 𝑥=0 𝐭𝐡𝐞𝐧 𝑦:=0 𝐞𝐥𝐬𝐞 𝑦:=1;𝐢𝐟 𝑦=0 𝐭𝐡𝐞𝐧𝐚𝐬𝐬𝐞𝐫𝐭 𝑥=0 𝐞𝐥𝐬𝐞 𝐬𝐤𝐢𝐩. 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 𝑥 ≠0 with the later then edge 𝑦 =0 is syntactically describable but semantically infeasible: the first edge assigns 𝑦 =1.
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.
Referenced from 2 locations
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.
Referenced from 2 locations
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 𝑥 ↦[ −∞, +∞] and 𝑦 ↦[0,1]; filtering the second then edge leaves 𝑥 unconstrained, so an interval analysis cannot prove its assertion. Every semantic trace taking that edge came from the first then branch and has 𝑥 =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.
★★☆ 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.
Referenced from 3 locations
A source-gated probabilistic application
The interval-trace semantics of Beutner, Ong, and Zaiser assigns each finite interval trace 𝒕 =⟨[𝑎1,𝑏1],…,[𝑎𝑛,𝑏𝑛]⟩ a volume vol(𝒕) =∏𝑖(𝑏𝑖 −𝑎𝑖), an interval weight 𝗐𝗍𝐼𝑃(𝒕), and an interval result 𝗏𝖺𝗅𝐼𝑃(𝒕). 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 𝑈, define 𝗅𝗈𝗐𝖾𝗋𝖡𝖽T𝑃(𝑈)=∑𝒕∈Tvol(𝒕)min𝗐𝗍𝐼𝑃(𝒕)[𝗏𝖺𝗅𝐼𝑃(𝒕)⊆𝑈],𝗎𝗉𝗉𝖾𝗋𝖡𝖽T𝑃(𝑈)=∑𝒕∈Tvol(𝒕)sup𝗐𝗍𝐼𝑃(𝒕)[𝗏𝖺𝗅𝐼𝑃(𝒕)∩𝑈≠∅]. The brackets are (0/1) indicators.
For the paper’s typed recursive probabilistic language:
if T is countable and compatible, then 𝗅𝗈𝗐𝖾𝗋𝖡𝖽T𝑃≤[[𝑃]];
if T is countable and exhaustive, then [[𝑃]]≤𝗎𝗉𝗉𝖾𝗋𝖡𝖽T𝑃.
The inequalities are pointwise on measurable result sets. The middle term is the program’s unnormalized measure, not its normalized posterior.
Referenced from 2 locations
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 𝑥 ≤𝑦 pointwise, and rejects a nonnegative-subtraction claim at 0 −1. 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.
★★☆ For interval addition, calculate 𝛼𝗂(+(𝛾𝗂[1,3]×𝛾𝗂[−2,4])) and recover the endpoint formula as the best correct approximation. Give a sound but less precise result and prove the pointwise comparison.
Referenced from 4 locations
★★★ 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.
Referenced from 4 locations
★★★ Calculate the first three DBM loop-head iterates for 𝖢𝗈𝗎𝗇𝗍𝖽𝗈𝗐𝗇. Apply entrywise widening, show that 𝑦 −𝑥 is dropped while 𝑥 −𝑦 ≤0 is retained, and verify the resulting pre-fixed-point inequality.
Referenced from 3 locations
★★☆ 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.
Referenced from 3 locations
★★★ 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 [𝑙1𝑙2,𝑢1𝑢2]: 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 𝖲𝗍𝖺𝗍𝖾(4,3) to the relational fixture: the unchanged 𝑥 ≤𝑦 oracle must fail. State the strengthened input invariant needed to restore the five original passes and the new multiplication and threshold passes.
Referenced from 5 locations