Skip to main content

oxilean_std/static_analysis/
functions.rs

1//! Auto-generated module
2//!
3//! šŸ¤– Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
6use std::collections::{BTreeSet, HashSet, VecDeque};
7
8use super::types::{
9    AndersenPTA, ConstPropState, EraserState, FixpointSolver, IFCTracker, Interval, NullTracker,
10    Nullability, PDGraph, SecurityLevel, Sign, TaintState, TypestateAutomaton,
11};
12
13pub fn app(f: Expr, a: Expr) -> Expr {
14    Expr::App(Box::new(f), Box::new(a))
15}
16pub fn app2(f: Expr, a: Expr, b: Expr) -> Expr {
17    app(app(f, a), b)
18}
19pub fn app3(f: Expr, a: Expr, b: Expr, c: Expr) -> Expr {
20    app(app2(f, a, b), c)
21}
22pub fn cst(s: &str) -> Expr {
23    Expr::Const(Name::str(s), vec![])
24}
25pub fn prop() -> Expr {
26    Expr::Sort(Level::zero())
27}
28pub fn type0() -> Expr {
29    Expr::Sort(Level::succ(Level::zero()))
30}
31pub fn pi(bi: BinderInfo, name: &str, dom: Expr, body: Expr) -> Expr {
32    Expr::Pi(bi, Name::str(name), Box::new(dom), Box::new(body))
33}
34pub fn arrow(a: Expr, b: Expr) -> Expr {
35    pi(BinderInfo::Default, "_", a, b)
36}
37pub fn bvar(n: u32) -> Expr {
38    Expr::BVar(n)
39}
40pub fn nat_ty() -> Expr {
41    cst("Nat")
42}
43pub fn bool_ty() -> Expr {
44    cst("Bool")
45}
46pub fn string_ty() -> Expr {
47    cst("String")
48}
49pub fn list_ty(elem: Expr) -> Expr {
50    app(cst("List"), elem)
51}
52pub fn option_ty(elem: Expr) -> Expr {
53    app(cst("Option"), elem)
54}
55pub fn set_ty(elem: Expr) -> Expr {
56    app(cst("Set"), elem)
57}
58pub fn pair_ty(a: Expr, b: Expr) -> Expr {
59    app2(cst("Prod"), a, b)
60}
61/// `Lattice : Type → Type` — A complete lattice on a carrier type.
62pub fn lattice_ty() -> Expr {
63    arrow(type0(), type0())
64}
65/// `LatticeBottom : āˆ€ L, Lattice L → L` — Bottom element ⊄.
66pub fn lattice_bottom_ty() -> Expr {
67    pi(
68        BinderInfo::Default,
69        "L",
70        type0(),
71        arrow(app(cst("Lattice"), bvar(0)), bvar(1)),
72    )
73}
74/// `LatticeTop : āˆ€ L, Lattice L → L` — Top element ⊤.
75pub fn lattice_top_ty() -> Expr {
76    pi(
77        BinderInfo::Default,
78        "L",
79        type0(),
80        arrow(app(cst("Lattice"), bvar(0)), bvar(1)),
81    )
82}
83/// `LatticeJoin : āˆ€ L, Lattice L → L → L → L` — Join operator āŠ”.
84pub fn lattice_join_ty() -> Expr {
85    pi(
86        BinderInfo::Default,
87        "L",
88        type0(),
89        arrow(
90            app(cst("Lattice"), bvar(0)),
91            arrow(bvar(1), arrow(bvar(2), bvar(3))),
92        ),
93    )
94}
95/// `LatticeMeet : āˆ€ L, Lattice L → L → L → L` — Meet operator āŠ“.
96pub fn lattice_meet_ty() -> Expr {
97    pi(
98        BinderInfo::Default,
99        "L",
100        type0(),
101        arrow(
102            app(cst("Lattice"), bvar(0)),
103            arrow(bvar(1), arrow(bvar(2), bvar(3))),
104        ),
105    )
106}
107/// `LatticeLeq : āˆ€ L, Lattice L → L → L → Prop` — Partial order āŠ‘.
108pub fn lattice_leq_ty() -> Expr {
109    pi(
110        BinderInfo::Default,
111        "L",
112        type0(),
113        arrow(
114            app(cst("Lattice"), bvar(0)),
115            arrow(bvar(1), arrow(bvar(2), prop())),
116        ),
117    )
118}
119/// `MooreFamily : Set (Set A) → Prop` — Closed under arbitrary intersection.
120pub fn moore_family_ty() -> Expr {
121    pi(
122        BinderInfo::Default,
123        "A",
124        type0(),
125        arrow(set_ty(set_ty(bvar(0))), prop()),
126    )
127}
128/// `CompleteLattice_GaloisConnection : every Galois connection yields a complete lattice`
129pub fn complete_lattice_galois_ty() -> Expr {
130    pi(
131        BinderInfo::Default,
132        "L",
133        type0(),
134        arrow(
135            app(cst("GaloisConn"), bvar(0)),
136            app(cst("CompleteLattice"), bvar(1)),
137        ),
138    )
139}
140/// `ConcreteSemantics : Program → Set State` — Collecting semantics.
141pub fn concrete_semantics_ty() -> Expr {
142    arrow(cst("Program"), set_ty(cst("ConcreteState")))
143}
144/// `AbstractSemantics : Program → AbsDom` — Abstract semantics over an abstract domain.
145pub fn abstract_semantics_ty() -> Expr {
146    arrow(cst("Program"), cst("AbsDom"))
147}
148/// `GaloisConnection : (C → A) Ɨ (A → C) → Prop`
149/// (α, γ) form a Galois connection: α(c) āŠ‘ a ↔ c āŠ† γ(a).
150pub fn galois_connection_ty() -> Expr {
151    pair_ty(
152        arrow(cst("ConcreteState"), cst("AbsDom")),
153        arrow(cst("AbsDom"), cst("ConcreteState")),
154    )
155}
156/// `Abstraction : ConcreteSemantics → AbsDom` — Abstraction function α.
157pub fn abstraction_ty() -> Expr {
158    arrow(concrete_semantics_ty(), cst("AbsDom"))
159}
160/// `Concretization : AbsDom → ConcreteSemantics` — Concretization function γ.
161pub fn concretization_ty() -> Expr {
162    arrow(cst("AbsDom"), concrete_semantics_ty())
163}
164/// `GaloisInsertion : GaloisConnection → Prop` — α∘γ = id (optimal abstraction).
165pub fn galois_insertion_ty() -> Expr {
166    arrow(galois_connection_ty(), prop())
167}
168/// `Widening : AbsDom → AbsDom → AbsDom` — Widening operator ā–½.
169pub fn widening_ty() -> Expr {
170    arrow(cst("AbsDom"), arrow(cst("AbsDom"), cst("AbsDom")))
171}
172/// `Narrowing : AbsDom → AbsDom → AbsDom` — Narrowing operator ā–³.
173pub fn narrowing_ty() -> Expr {
174    arrow(cst("AbsDom"), arrow(cst("AbsDom"), cst("AbsDom")))
175}
176/// `Widening_Terminates : widening guarantees termination of iteration`
177pub fn widening_terminates_ty() -> Expr {
178    pi(
179        BinderInfo::Default,
180        "f",
181        arrow(cst("AbsDom"), cst("AbsDom")),
182        app(
183            cst("Terminates"),
184            app2(cst("fixpoint_widen"), bvar(0), cst("Widening")),
185        ),
186    )
187}
188/// `AbstractInterp_Sound : āˆ€ prog, α(collect prog) āŠ‘ abs_semantics prog`
189pub fn abstract_interp_sound_ty() -> Expr {
190    pi(
191        BinderInfo::Default,
192        "prog",
193        cst("Program"),
194        app(
195            app(cst("Leq"), app(cst("α"), app(cst("collect"), bvar(0)))),
196            app(cst("abs_semantics"), bvar(0)),
197        ),
198    )
199}
200/// `Narrowing_RefinesPost : āˆ€ x y, y āŠ‘ x → y ā–³ (f x) āŠ‘ x`
201pub fn narrowing_refines_post_ty() -> Expr {
202    pi(
203        BinderInfo::Default,
204        "x",
205        cst("AbsDom"),
206        pi(
207            BinderInfo::Default,
208            "y",
209            cst("AbsDom"),
210            arrow(
211                app2(cst("Leq"), bvar(0), bvar(1)),
212                app(
213                    app(
214                        cst("Leq"),
215                        app2(cst("Narrowing"), bvar(1), app(cst("f"), bvar(2))),
216                    ),
217                    bvar(2),
218                ),
219            ),
220        ),
221    )
222}
223/// `HeapGraph : Type` — A shape graph: nodes are abstract heap cells.
224pub fn heap_graph_ty() -> Expr {
225    type0()
226}
227/// `HeapNode : Type` — An abstract heap node (summary or concrete).
228pub fn heap_node_ty() -> Expr {
229    type0()
230}
231/// `SharingPred : HeapGraph → HeapNode → HeapNode → Prop`
232/// May-sharing: two nodes may alias through some path.
233pub fn sharing_pred_ty() -> Expr {
234    arrow(
235        heap_graph_ty(),
236        arrow(heap_node_ty(), arrow(heap_node_ty(), prop())),
237    )
238}
239/// `CyclicPred : HeapGraph → HeapNode → Prop`
240/// A node may be part of a cyclic structure.
241pub fn cyclic_pred_ty() -> Expr {
242    arrow(heap_graph_ty(), arrow(heap_node_ty(), prop()))
243}
244/// `ShapeDescriptor : Type` — An abstract shape: tree, dag, list, cyclic-list, graph.
245pub fn shape_descriptor_ty() -> Expr {
246    type0()
247}
248/// `shape_join : ShapeDescriptor → ShapeDescriptor → ShapeDescriptor`
249pub fn shape_join_ty() -> Expr {
250    arrow(
251        shape_descriptor_ty(),
252        arrow(shape_descriptor_ty(), shape_descriptor_ty()),
253    )
254}
255/// `shape_transfer : HeapOp → ShapeDescriptor → ShapeDescriptor`
256pub fn shape_transfer_ty() -> Expr {
257    arrow(
258        cst("HeapOp"),
259        arrow(shape_descriptor_ty(), shape_descriptor_ty()),
260    )
261}
262/// `ShapeSound : āˆ€ op s, shape_transfer op s over-approximates concrete shapes`
263pub fn shape_sound_ty() -> Expr {
264    pi(
265        BinderInfo::Default,
266        "op",
267        cst("HeapOp"),
268        pi(
269            BinderInfo::Default,
270            "s",
271            shape_descriptor_ty(),
272            app(
273                cst("OverApprox"),
274                app2(cst("shape_transfer"), bvar(1), bvar(0)),
275            ),
276        ),
277    )
278}
279/// `ThreeValued : Type` — Three-valued logic {True, False, Maybe} for must/may.
280pub fn three_valued_ty() -> Expr {
281    type0()
282}
283/// `MustAlias : HeapGraph → HeapNode → HeapNode → ThreeValued`
284pub fn must_alias_ty() -> Expr {
285    arrow(
286        heap_graph_ty(),
287        arrow(heap_node_ty(), arrow(heap_node_ty(), three_valued_ty())),
288    )
289}
290/// `AllocSite : Type` — An allocation site (abstract heap location).
291pub fn alloc_site_ty() -> Expr {
292    nat_ty()
293}
294/// `PointsTo : Var → Set AllocSite` — Points-to set for a variable.
295pub fn points_to_ty() -> Expr {
296    arrow(cst("Var"), set_ty(alloc_site_ty()))
297}
298/// `AndersenAnalysis : Program → PointsTo` — Andersen inclusion-based pointer analysis.
299pub fn andersen_analysis_ty() -> Expr {
300    arrow(cst("Program"), points_to_ty())
301}
302/// `SteensgaardAnalysis : Program → (Var → Var)` — Steensgaard unification-based analysis.
303/// Returns equivalence classes (union-find representative).
304pub fn steensgaard_analysis_ty() -> Expr {
305    arrow(cst("Program"), arrow(cst("Var"), cst("Var")))
306}
307/// `Andersen_Sound : āˆ€ prog, andersen is a sound over-approximation`
308pub fn andersen_sound_ty() -> Expr {
309    pi(
310        BinderInfo::Default,
311        "prog",
312        cst("Program"),
313        app(cst("Sound"), app(cst("AndersenAnalysis"), bvar(0))),
314    )
315}
316/// `Steensgaard_SubAndersen : Steensgaard āŠ‘ Andersen (less precise but O(n α(n)))`
317pub fn steensgaard_sub_andersen_ty() -> Expr {
318    pi(
319        BinderInfo::Default,
320        "prog",
321        cst("Program"),
322        app(
323            app(cst("Leq"), app(cst("SteensgaardAnalysis"), bvar(0))),
324            app(cst("AndersenAnalysis"), bvar(0)),
325        ),
326    )
327}
328/// `Andersen_Cubic : Andersen analysis is O(n³) in the worst case`
329pub fn andersen_cubic_ty() -> Expr {
330    app(
331        cst("TimeComplexity"),
332        app(cst("CubicN"), cst("AndersenAnalysis")),
333    )
334}
335/// `Steensgaard_AlmostLinear : Steensgaard is nearly O(n) via union-find`
336pub fn steensgaard_almost_linear_ty() -> Expr {
337    app(
338        cst("TimeComplexity"),
339        app(cst("InvAckermann"), cst("SteensgaardAnalysis")),
340    )
341}
342/// `AliasResult : Var → Var → Prop` — Two variables may alias.
343pub fn alias_result_ty() -> Expr {
344    arrow(cst("Var"), arrow(cst("Var"), prop()))
345}
346/// `MayAlias : Program → Var → Var → Bool`
347pub fn may_alias_ty() -> Expr {
348    arrow(
349        cst("Program"),
350        arrow(cst("Var"), arrow(cst("Var"), bool_ty())),
351    )
352}
353/// `MustAliasPair : Program → Var → Var → Bool`
354pub fn must_alias_pair_ty() -> Expr {
355    arrow(
356        cst("Program"),
357        arrow(cst("Var"), arrow(cst("Var"), bool_ty())),
358    )
359}
360/// `TypeBasedAlias : Type → Type → Bool` — TBAA: types determine alias potential.
361pub fn type_based_alias_ty() -> Expr {
362    arrow(cst("IRType"), arrow(cst("IRType"), bool_ty()))
363}
364/// `NoAlias : Var → Var → Prop` — Two variables definitely do not alias.
365pub fn no_alias_ty() -> Expr {
366    arrow(cst("Var"), arrow(cst("Var"), prop()))
367}
368/// `Alias_Undecidable : alias analysis is undecidable in general`
369pub fn alias_undecidable_ty() -> Expr {
370    app(cst("Undecidable"), cst("ExactAliasAnalysis"))
371}
372/// `SoftType : Type` — A soft type: a type that may be violated at runtime.
373pub fn soft_type_ty() -> Expr {
374    type0()
375}
376/// `SoftTypeCheck : Program → SoftType → Bool`
377pub fn soft_type_check_ty() -> Expr {
378    arrow(cst("Program"), arrow(soft_type_ty(), bool_ty()))
379}
380/// `RefinementType : Type → Pred → Type` — `{x : T | P(x)}`.
381pub fn refinement_type_ty() -> Expr {
382    arrow(type0(), arrow(arrow(bvar(0), prop()), type0()))
383}
384/// `EffectType : Type → EffectSet → Type` — A type annotated with an effect.
385pub fn effect_type_ty() -> Expr {
386    arrow(type0(), arrow(cst("EffectSet"), type0()))
387}
388/// `EffectSubtype : EffectType → EffectType → Prop` — Subtyping with effects.
389pub fn effect_subtype_ty() -> Expr {
390    arrow(effect_type_ty(), arrow(effect_type_ty(), prop()))
391}
392/// `Liquid_Haskell_Sound : āˆ€ prog, liquid_type_check prog → no_runtime_type_errors prog`
393pub fn liquid_haskell_sound_ty() -> Expr {
394    pi(
395        BinderInfo::Default,
396        "prog",
397        cst("Program"),
398        arrow(
399            app(cst("liquid_type_check"), bvar(0)),
400            app(cst("no_runtime_errors"), bvar(1)),
401        ),
402    )
403}
404/// `CallSite : Type` — A call site in the program.
405pub fn call_site_ty() -> Expr {
406    nat_ty()
407}
408/// `AbstractClosure : Type` — An abstract closure: (lambda, env).
409pub fn abstract_closure_ty() -> Expr {
410    type0()
411}
412/// `ZeroCFA : Program → CallSite → Set AbstractClosure`
413/// 0-CFA: context-insensitive closure analysis.
414pub fn zero_cfa_ty() -> Expr {
415    arrow(
416        cst("Program"),
417        arrow(call_site_ty(), set_ty(abstract_closure_ty())),
418    )
419}
420/// `KCFA : Nat → Program → (CallSite Ɨ List CallSite) → Set AbstractClosure`
421/// k-CFA: context-sensitive with call-string depth k.
422pub fn k_cfa_ty() -> Expr {
423    arrow(
424        nat_ty(),
425        arrow(
426            cst("Program"),
427            arrow(
428                pair_ty(call_site_ty(), list_ty(call_site_ty())),
429                set_ty(abstract_closure_ty()),
430            ),
431        ),
432    )
433}
434/// `CFA_Overapprox : āˆ€ k prog, k_cfa k prog āŠ‡ actual call targets`
435pub fn cfa_overapprox_ty() -> Expr {
436    pi(
437        BinderInfo::Default,
438        "k",
439        nat_ty(),
440        pi(
441            BinderInfo::Default,
442            "prog",
443            cst("Program"),
444            app(cst("Overapproximates"), app2(cst("KCFA"), bvar(1), bvar(0))),
445        ),
446    )
447}
448/// `CFA_Monotone_in_k : 0-CFA āŠ‘ 1-CFA āŠ‘ 2-CFA āŠ‘ …`
449pub fn cfa_monotone_k_ty() -> Expr {
450    pi(
451        BinderInfo::Default,
452        "k",
453        nat_ty(),
454        app(
455            app(cst("Leq"), app2(cst("KCFA"), bvar(0), cst("prog"))),
456            app2(cst("KCFA"), app(cst("Succ"), bvar(0)), cst("prog")),
457        ),
458    )
459}
460/// `KCFA_Complexity : k-CFA is EXPTIME-complete for k ≄ 1`
461pub fn k_cfa_complexity_ty() -> Expr {
462    pi(
463        BinderInfo::Default,
464        "k",
465        nat_ty(),
466        arrow(
467            app(cst("Ge"), app2(cst("Ge"), bvar(0), nat_ty())),
468            app(cst("EXPTIMEComplete"), app(cst("KCFA"), bvar(1))),
469        ),
470    )
471}
472/// `Effect : Type` — An abstract program effect (read, write, alloc, throw, io).
473pub fn effect_ty() -> Expr {
474    type0()
475}
476/// `EffectSet : Type` — A set of effects annotating an expression or function.
477pub fn effect_set_ty() -> Expr {
478    set_ty(effect_ty())
479}
480/// `ReadEffect : Var → Effect` — Reading from variable.
481pub fn read_effect_ty() -> Expr {
482    arrow(cst("Var"), effect_ty())
483}
484/// `WriteEffect : Var → Effect` — Writing to variable.
485pub fn write_effect_ty() -> Expr {
486    arrow(cst("Var"), effect_ty())
487}
488/// `ExnEffect : ExnType → Effect` — Raising an exception.
489pub fn exn_effect_ty() -> Expr {
490    arrow(cst("ExnType"), effect_ty())
491}
492/// `infer_effects : Program → EffectMap` — Effect inference over a whole program.
493pub fn infer_effects_ty() -> Expr {
494    arrow(cst("Program"), cst("EffectMap"))
495}
496/// `EffectSound : āˆ€ prog, infer_effects prog āŠ‡ actual_effects prog`
497pub fn effect_sound_ty() -> Expr {
498    pi(
499        BinderInfo::Default,
500        "prog",
501        cst("Program"),
502        app(
503            app(cst("Superset"), app(cst("infer_effects"), bvar(0))),
504            app(cst("actual_effects"), bvar(0)),
505        ),
506    )
507}
508/// `PureFunction : Expr → Prop` — A function with empty effect set.
509pub fn pure_function_ty() -> Expr {
510    arrow(cst("Expr"), prop())
511}
512/// `ResourceType : Type` — A linear/affine resource type.
513pub fn resource_type_ty() -> Expr {
514    type0()
515}
516/// `UsageAnnotation : Type` — Usage count: 0, 1, or ω (unrestricted).
517pub fn usage_annotation_ty() -> Expr {
518    type0()
519}
520/// `LinearType : ResourceType → Prop` — Resource must be used exactly once.
521pub fn linear_type_ty() -> Expr {
522    arrow(resource_type_ty(), prop())
523}
524/// `AffineType : ResourceType → Prop` — Resource used at most once.
525pub fn affine_type_ty() -> Expr {
526    arrow(resource_type_ty(), prop())
527}
528/// `ResourceUsageAnalysis : Program → Var → UsageAnnotation`
529/// Infers usage count (0, 1, ω) for each variable.
530pub fn resource_usage_analysis_ty() -> Expr {
531    arrow(cst("Program"), arrow(cst("Var"), usage_annotation_ty()))
532}
533/// `LeakFreedom : Program → Prop` — All acquired resources are released.
534pub fn leak_freedom_ty() -> Expr {
535    arrow(cst("Program"), prop())
536}
537/// `LinearType_LeakFree : āˆ€ prog, well_typed_linear prog → LeakFreedom prog`
538pub fn linear_type_leak_free_ty() -> Expr {
539    pi(
540        BinderInfo::Default,
541        "prog",
542        cst("Program"),
543        arrow(
544            app(cst("WellTypedLinear"), bvar(0)),
545            app(cst("LeakFreedom"), bvar(1)),
546        ),
547    )
548}
549/// `UsageCount_Sound : usage analysis is a sound over-approximation of actual usage`
550pub fn usage_count_sound_ty() -> Expr {
551    pi(
552        BinderInfo::Default,
553        "prog",
554        cst("Program"),
555        app(cst("Sound"), app(cst("ResourceUsageAnalysis"), bvar(0))),
556    )
557}
558/// `Thread : Type` — An abstract thread identifier.
559pub fn thread_ty() -> Expr {
560    nat_ty()
561}
562/// `LockSet : Type` — The set of locks held by a thread.
563pub fn lock_set_ty() -> Expr {
564    set_ty(nat_ty())
565}
566/// `HappensBefore : Event → Event → Prop` — The happens-before partial order.
567pub fn happens_before_ty() -> Expr {
568    arrow(cst("Event"), arrow(cst("Event"), prop()))
569}
570/// `DataRace : Event → Event → Prop`
571/// Two events form a data race if they access the same location, at least
572/// one is a write, they are from different threads, and not ordered by HB.
573pub fn data_race_ty() -> Expr {
574    arrow(cst("Event"), arrow(cst("Event"), prop()))
575}
576/// `EraserLockSet : Thread → MemLoc → Set Lock`
577/// Eraser algorithm: track C(v) = intersection of lock sets for variable v.
578pub fn eraser_lock_set_ty() -> Expr {
579    arrow(thread_ty(), arrow(cst("MemLoc"), lock_set_ty()))
580}
581/// `Eraser_Invariant : C(v) ≠ āˆ… → no data race on v`
582pub fn eraser_invariant_ty() -> Expr {
583    pi(
584        BinderInfo::Default,
585        "v",
586        cst("MemLoc"),
587        arrow(
588            app(cst("NonEmpty"), app(cst("C"), bvar(0))),
589            app(cst("NoRace"), bvar(1)),
590        ),
591    )
592}
593/// `TSan_Sound : ThreadSanitizer reports all races`
594pub fn tsan_sound_ty() -> Expr {
595    pi(
596        BinderInfo::Default,
597        "prog",
598        cst("Program"),
599        arrow(
600            app(cst("HasRace"), bvar(0)),
601            app(cst("TSanReports"), bvar(1)),
602        ),
603    )
604}
605/// `DataRaceFreedom : Program → Prop` — No data races in the program.
606pub fn data_race_freedom_ty() -> Expr {
607    arrow(cst("Program"), prop())
608}
609/// `DRF_Sequential : āˆ€ prog, DRF prog → sequential_consistent prog`
610pub fn drf_sequential_ty() -> Expr {
611    pi(
612        BinderInfo::Default,
613        "prog",
614        cst("Program"),
615        arrow(
616            app(cst("DataRaceFreedom"), bvar(0)),
617            app(cst("SeqConsistent"), bvar(1)),
618        ),
619    )
620}
621/// `TaintSource : Type` — A source of tainted data (user input, env vars, etc.).
622pub fn taint_source_ty() -> Expr {
623    type0()
624}
625/// `TaintSink : Type` — A sink that must not receive tainted data (SQL query, shell cmd).
626pub fn taint_sink_ty() -> Expr {
627    type0()
628}
629/// `Sanitizer : Type` — A function that removes taint (e.g., HTML-escape).
630pub fn sanitizer_ty() -> Expr {
631    type0()
632}
633/// `TaintLabel : Var → Bool` — Is a variable tainted?
634pub fn taint_label_ty() -> Expr {
635    arrow(cst("Var"), bool_ty())
636}
637/// `TaintPropagation : Program → TaintLabel → TaintLabel`
638/// Propagate taint through the program.
639pub fn taint_propagation_ty() -> Expr {
640    arrow(cst("Program"), arrow(taint_label_ty(), taint_label_ty()))
641}
642/// `TaintViolation : Program → TaintLabel → Set (Var Ɨ TaintSink) → Prop`
643/// A taint violation: tainted variable reaches a sink without sanitization.
644pub fn taint_violation_ty() -> Expr {
645    arrow(
646        cst("Program"),
647        arrow(
648            taint_label_ty(),
649            arrow(set_ty(pair_ty(cst("Var"), taint_sink_ty())), prop()),
650        ),
651    )
652}
653/// `Taint_Sound : āˆ€ prog, taint_propagation over-approximates actual taint flow`
654pub fn taint_sound_ty() -> Expr {
655    pi(
656        BinderInfo::Default,
657        "prog",
658        cst("Program"),
659        app(cst("Sound"), app(cst("TaintPropagation"), bvar(0))),
660    )
661}
662/// `Taint_NoFalseNegatives : all real taint violations are reported`
663pub fn taint_no_false_neg_ty() -> Expr {
664    pi(
665        BinderInfo::Default,
666        "prog",
667        cst("Program"),
668        arrow(
669            app(cst("RealViolation"), bvar(0)),
670            app(cst("Reported"), bvar(1)),
671        ),
672    )
673}
674/// `SepLogicHeap : Type` — A heap in separation logic (finite partial map Addr → Val).
675pub fn sep_logic_heap_ty() -> Expr {
676    arrow(cst("Addr"), option_ty(cst("Val")))
677}
678/// `SepConj : SepPred → SepPred → SepPred` — Separating conjunction P * Q.
679pub fn sep_conj_ty() -> Expr {
680    arrow(
681        arrow(sep_logic_heap_ty(), prop()),
682        arrow(
683            arrow(sep_logic_heap_ty(), prop()),
684            arrow(sep_logic_heap_ty(), prop()),
685        ),
686    )
687}
688/// `SepImp : SepPred → SepPred → SepPred` — Magic wand P āˆ’āˆ— Q.
689pub fn sep_imp_ty() -> Expr {
690    arrow(
691        arrow(sep_logic_heap_ty(), prop()),
692        arrow(
693            arrow(sep_logic_heap_ty(), prop()),
694            arrow(sep_logic_heap_ty(), prop()),
695        ),
696    )
697}
698/// `PointsToCell : Addr → Val → SepPred` — Singleton heap cell l ↦ v.
699pub fn points_to_cell_ty() -> Expr {
700    arrow(
701        cst("Addr"),
702        arrow(cst("Val"), arrow(sep_logic_heap_ty(), prop())),
703    )
704}
705/// `FrameRule : āˆ€ prog P Q R, {P} prog {Q} → {P * R} prog {Q * R}` — Frame rule.
706pub fn frame_rule_ty() -> Expr {
707    pi(
708        BinderInfo::Default,
709        "P",
710        arrow(sep_logic_heap_ty(), prop()),
711        pi(
712            BinderInfo::Default,
713            "Q",
714            arrow(sep_logic_heap_ty(), prop()),
715            pi(
716                BinderInfo::Default,
717                "R",
718                arrow(sep_logic_heap_ty(), prop()),
719                arrow(
720                    app3(cst("HoareTriple"), bvar(2), cst("prog"), bvar(1)),
721                    app3(
722                        cst("HoareTriple"),
723                        app2(cst("SepConj"), bvar(2), bvar(0)),
724                        cst("prog"),
725                        app2(cst("SepConj"), bvar(1), bvar(0)),
726                    ),
727                ),
728            ),
729        ),
730    )
731}
732/// `HeapShape_TreePred : HeapNode → SepPred` — Predicate for an acyclic linked list.
733pub fn heap_shape_tree_pred_ty() -> Expr {
734    arrow(heap_node_ty(), arrow(sep_logic_heap_ty(), prop()))
735}
736/// `MemorySafety : Program → SepPred → Prop` — No out-of-bounds or dangling access.
737pub fn memory_safety_ty() -> Expr {
738    arrow(
739        cst("Program"),
740        arrow(arrow(sep_logic_heap_ty(), prop()), prop()),
741    )
742}
743/// `OwnershipTransfer : SepPred → SepPred → Prop`
744/// Ownership transfer from pre to post (move semantics).
745pub fn ownership_transfer_ty() -> Expr {
746    arrow(
747        arrow(sep_logic_heap_ty(), prop()),
748        arrow(arrow(sep_logic_heap_ty(), prop()), prop()),
749    )
750}
751/// `Typestate : Type` — A typestate: a type annotated with a protocol state.
752pub fn typestate_ty() -> Expr {
753    type0()
754}
755/// `TypestateProtocol : Type` — A resource usage protocol (e.g. Opened/Closed file).
756pub fn typestate_protocol_ty() -> Expr {
757    arrow(typestate_ty(), set_ty(typestate_ty()))
758}
759/// `TypestateTransition : Typestate → Op → Typestate → Prop`
760/// Specifies valid state transitions under operations.
761pub fn typestate_transition_ty() -> Expr {
762    arrow(
763        typestate_ty(),
764        arrow(cst("Op"), arrow(typestate_ty(), prop())),
765    )
766}
767/// `TypestateCheck : Program → TypestateProtocol → Prop`
768/// Program respects the resource usage protocol.
769pub fn typestate_check_ty() -> Expr {
770    arrow(cst("Program"), arrow(typestate_protocol_ty(), prop()))
771}
772/// `MustUseResource : Typestate → Prop` — Resource in this state must be consumed.
773pub fn must_use_resource_ty() -> Expr {
774    arrow(typestate_ty(), prop())
775}
776/// `TypestateSound : typestate analysis is a sound approximation of runtime states`
777pub fn typestate_sound_ty() -> Expr {
778    pi(
779        BinderInfo::Default,
780        "prog",
781        cst("Program"),
782        arrow(
783            app(cst("TypestateCheck"), bvar(0)),
784            app(cst("NoProtocolViolation"), bvar(1)),
785        ),
786    )
787}
788/// `Region : Type` — A memory region (stack frame, heap generation, etc.).
789pub fn region_ty() -> Expr {
790    nat_ty()
791}
792/// `RegionAnnotation : Expr → Region` — Maps an expression to its allocation region.
793pub fn region_annotation_ty() -> Expr {
794    arrow(cst("Expr"), region_ty())
795}
796/// `EscapeAnalysis : Program → Var → Bool`
797/// Returns true if a variable's value may escape its defining scope.
798pub fn escape_analysis_ty() -> Expr {
799    arrow(cst("Program"), arrow(cst("Var"), bool_ty()))
800}
801/// `RegionInference : Program → RegionAnnotation`
802/// Infer allocation regions to enable stack allocation of non-escaping values.
803pub fn region_inference_ty() -> Expr {
804    arrow(cst("Program"), region_annotation_ty())
805}
806/// `Escape_Sound : āˆ€ prog v, ¬escape prog v → stack_allocated prog v`
807pub fn escape_sound_ty() -> Expr {
808    pi(
809        BinderInfo::Default,
810        "prog",
811        cst("Program"),
812        pi(
813            BinderInfo::Default,
814            "v",
815            cst("Var"),
816            arrow(
817                app(
818                    app(cst("Not"), app2(cst("EscapeAnalysis"), bvar(1), bvar(0))),
819                    nat_ty(),
820                ),
821                app2(cst("StackAllocated"), bvar(1), bvar(0)),
822            ),
823        ),
824    )
825}
826/// `RegionSubtyping : Region → Region → Prop` — Lifetime/region containment.
827pub fn region_subtyping_ty() -> Expr {
828    arrow(region_ty(), arrow(region_ty(), prop()))
829}
830/// `MonadicEffect : Type → EffectSet → Type`
831/// A computation of type T with effects E (monadic encoding).
832pub fn monadic_effect_ty() -> Expr {
833    arrow(type0(), arrow(effect_set_ty(), type0()))
834}
835/// `GradedMonad : (EffectSet → Type → Type) → Prop`
836/// A graded monad indexed by effect sets.
837pub fn graded_monad_ty() -> Expr {
838    arrow(arrow(effect_set_ty(), arrow(type0(), type0())), prop())
839}
840/// `CapabilitySet : Type` — A set of capabilities (permissions) held at a program point.
841pub fn capability_set_ty() -> Expr {
842    set_ty(cst("Capability"))
843}
844/// `CapabilityJudgment : Context → Expr → EffectType → Prop`
845/// Typing judgment: in context Ī“ with capabilities C, expression e has effect type T.
846pub fn capability_judgment_ty() -> Expr {
847    arrow(
848        cst("Context"),
849        arrow(cst("Expr"), arrow(effect_type_ty(), prop())),
850    )
851}
852/// `EffectPolymorphism : āˆ€ e f, e : T!{f} → e : T!{f ∪ g}` — Effect weakening.
853pub fn effect_polymorphism_ty() -> Expr {
854    pi(
855        BinderInfo::Default,
856        "f",
857        effect_set_ty(),
858        pi(
859            BinderInfo::Default,
860            "g",
861            effect_set_ty(),
862            pi(
863                BinderInfo::Default,
864                "T",
865                type0(),
866                arrow(
867                    app2(cst("HasEffectType"), bvar(0), bvar(2)),
868                    app2(
869                        cst("HasEffectType"),
870                        bvar(0),
871                        app2(cst("EffectUnion"), bvar(2), bvar(1)),
872                    ),
873                ),
874            ),
875        ),
876    )
877}
878/// `AlgebraicEffectHandler : EffectSet → Type → Type`
879/// Handler type that handles a set of algebraic effects.
880pub fn algebraic_effect_handler_ty() -> Expr {
881    arrow(effect_set_ty(), arrow(type0(), type0()))
882}
883/// `GradualType : Type` — A gradual type (may contain the unknown type ?).
884pub fn gradual_type_ty() -> Expr {
885    type0()
886}
887/// `UnknownType : GradualType` — The dynamic unknown type ?.
888pub fn unknown_type_ty() -> Expr {
889    gradual_type_ty()
890}
891/// `ConsistencyRel : GradualType → GradualType → Prop` — Type consistency (~).
892pub fn consistency_rel_ty() -> Expr {
893    arrow(gradual_type_ty(), arrow(gradual_type_ty(), prop()))
894}
895/// `CastInsertion : GradualExpr → StaticExpr` — Elaborates gradual to casted static code.
896pub fn cast_insertion_ty() -> Expr {
897    arrow(cst("GradualExpr"), cst("StaticExpr"))
898}
899/// `CastCorrectness : āˆ€ e, eval (cast_insert e) = gradual_eval e`
900/// Cast insertion preserves semantics.
901pub fn cast_correctness_ty() -> Expr {
902    pi(
903        BinderInfo::Default,
904        "e",
905        cst("GradualExpr"),
906        app(
907            app(
908                cst("Eq"),
909                app(cst("eval"), app(cst("CastInsertion"), bvar(0))),
910            ),
911            app(cst("gradual_eval"), bvar(0)),
912        ),
913    )
914}
915/// `Blame_Theorem : dynamic cast failures are attributed to correct source location`
916pub fn blame_theorem_ty() -> Expr {
917    pi(
918        BinderInfo::Default,
919        "e",
920        cst("GradualExpr"),
921        arrow(
922            app(cst("CastFails"), bvar(0)),
923            app(cst("BlameCorrect"), bvar(1)),
924        ),
925    )
926}
927/// `LiquidType : BaseType → Qualifier → RefinementType`
928/// A liquid type `{v : B | Q(v)}` with a qualifier drawn from a template set.
929pub fn liquid_type_ty() -> Expr {
930    arrow(
931        cst("BaseType"),
932        arrow(cst("Qualifier"), cst("RefinementType")),
933    )
934}
935/// `QualifierInstantiation : Template → Substitution → Qualifier`
936/// A qualifier instantiated from a Liquid Haskell template.
937pub fn qualifier_instantiation_ty() -> Expr {
938    arrow(
939        cst("Template"),
940        arrow(cst("Substitution"), cst("Qualifier")),
941    )
942}
943/// `SubtypingRefinement : RefinementType → RefinementType → Prop`
944/// `{v : B | P} <: {v : B | Q}` iff P ⊢ Q.
945pub fn subtyping_refinement_ty() -> Expr {
946    arrow(cst("RefinementType"), arrow(cst("RefinementType"), prop()))
947}
948/// `RefinementInference : Program → Var → RefinementType`
949/// Automatically infer strongest safe refinement types.
950pub fn refinement_inference_ty() -> Expr {
951    arrow(cst("Program"), arrow(cst("Var"), cst("RefinementType")))
952}
953/// `LiquidType_Complete : liquid type inference is complete for the qualifier set`
954pub fn liquid_type_complete_ty() -> Expr {
955    pi(
956        BinderInfo::Default,
957        "prog",
958        cst("Program"),
959        arrow(
960            app(cst("QualifierSetFinite"), bvar(0)),
961            app(cst("RefinementInferenceComplete"), bvar(1)),
962        ),
963    )
964}
965/// `SecurityLabel : Type` — A security lattice element (e.g. Low, High, Secret).
966pub fn security_label_ty() -> Expr {
967    type0()
968}
969/// `SecrecyLattice : SecurityLabel → SecurityLabel → Prop` — Label ordering āŠ‘.
970pub fn secrecy_lattice_ty() -> Expr {
971    arrow(security_label_ty(), arrow(security_label_ty(), prop()))
972}
973/// `LabelEnv : Var → SecurityLabel` — Security label environment.
974pub fn label_env_ty() -> Expr {
975    arrow(cst("Var"), security_label_ty())
976}
977/// `NonInterference : Program → LabelEnv → Prop`
978/// Low-equivalent inputs produce low-equivalent outputs.
979pub fn non_interference_ty() -> Expr {
980    arrow(cst("Program"), arrow(label_env_ty(), prop()))
981}
982/// `Declassification : Expr → SecurityLabel → SecurityLabel → Prop`
983/// Explicit declassification from high to low label.
984pub fn declassification_ty() -> Expr {
985    arrow(
986        cst("Expr"),
987        arrow(security_label_ty(), arrow(security_label_ty(), prop())),
988    )
989}
990/// `IFCTypeSystem : Context → Expr → LabeledType → Prop`
991/// Information flow control typing judgment.
992pub fn ifc_type_system_ty() -> Expr {
993    arrow(
994        cst("Context"),
995        arrow(cst("Expr"), arrow(cst("LabeledType"), prop())),
996    )
997}
998/// `NI_Theorem : āˆ€ prog env, IFC_typed prog env → NonInterference prog env`
999pub fn ni_theorem_ty() -> Expr {
1000    pi(
1001        BinderInfo::Default,
1002        "prog",
1003        cst("Program"),
1004        pi(
1005            BinderInfo::Default,
1006            "env",
1007            label_env_ty(),
1008            arrow(
1009                app2(cst("IFC_typed"), bvar(1), bvar(0)),
1010                app2(cst("NonInterference"), bvar(2), bvar(1)),
1011            ),
1012        ),
1013    )
1014}
1015/// `ConstantFolding : Expr → Expr` — Evaluate constant sub-expressions at compile time.
1016pub fn constant_folding_ty() -> Expr {
1017    arrow(cst("Expr"), cst("Expr"))
1018}
1019/// `ConstantPropagation : Program → Var → Option Val`
1020/// Statically determine the value of a variable if it is constant.
1021pub fn constant_propagation_ty() -> Expr {
1022    arrow(cst("Program"), arrow(cst("Var"), option_ty(cst("Val"))))
1023}
1024/// `ConstFold_Correct : āˆ€ e, eval (const_fold e) = eval e`
1025pub fn const_fold_correct_ty() -> Expr {
1026    pi(
1027        BinderInfo::Default,
1028        "e",
1029        cst("Expr"),
1030        app(
1031            app(
1032                cst("Eq"),
1033                app(cst("eval"), app(cst("ConstantFolding"), bvar(0))),
1034            ),
1035            app(cst("eval"), bvar(0)),
1036        ),
1037    )
1038}
1039/// `IntervalDomain : Type` — Abstract domain for value range analysis (intervals).
1040pub fn interval_domain_ty() -> Expr {
1041    type0()
1042}
1043/// `BitfieldDomain : Type` — Abstract domain tracking known/unknown bits.
1044pub fn bitfield_domain_ty() -> Expr {
1045    type0()
1046}
1047/// `ValueRangeAnalysis : Program → Var → IntervalDomain`
1048/// Compute abstract value ranges for all variables.
1049pub fn value_range_analysis_ty() -> Expr {
1050    arrow(cst("Program"), arrow(cst("Var"), interval_domain_ty()))
1051}
1052/// `VRA_Sound : āˆ€ prog, value_range_analysis over-approximates concrete values`
1053pub fn vra_sound_ty() -> Expr {
1054    pi(
1055        BinderInfo::Default,
1056        "prog",
1057        cst("Program"),
1058        app(cst("Sound"), app(cst("ValueRangeAnalysis"), bvar(0))),
1059    )
1060}
1061/// `NullabilityAnnotation : Type → Bool → Type`
1062/// Type annotated with nullability: T? vs T!.
1063pub fn nullability_annotation_ty() -> Expr {
1064    arrow(type0(), arrow(bool_ty(), type0()))
1065}
1066/// `NullPointerAnalysis : Program → Var → ThreeValued`
1067/// Three-valued result: definitely null / definitely non-null / maybe null.
1068pub fn null_pointer_analysis_ty() -> Expr {
1069    arrow(cst("Program"), arrow(cst("Var"), three_valued_ty()))
1070}
1071/// `DefiniteAssignment : Program → Var → Prop`
1072/// Every use of a variable is preceded by a definition.
1073pub fn definite_assignment_ty() -> Expr {
1074    arrow(cst("Program"), arrow(cst("Var"), prop()))
1075}
1076/// `NullSafety : Program → Prop` — No null dereferences occur.
1077pub fn null_safety_ty() -> Expr {
1078    arrow(cst("Program"), prop())
1079}
1080/// `NullAnalysis_Sound : āˆ€ prog, null_pointer_analysis is sound`
1081pub fn null_analysis_sound_ty() -> Expr {
1082    pi(
1083        BinderInfo::Default,
1084        "prog",
1085        cst("Program"),
1086        app(cst("Sound"), app(cst("NullPointerAnalysis"), bvar(0))),
1087    )
1088}
1089/// `LockOrder : Lock → Lock → Prop` — A consistent lock acquisition order.
1090pub fn lock_order_ty() -> Expr {
1091    arrow(cst("Lock"), arrow(cst("Lock"), prop()))
1092}
1093/// `DeadlockFreedom : Program → Prop` — No circular lock dependencies.
1094pub fn deadlock_freedom_ty() -> Expr {
1095    arrow(cst("Program"), prop())
1096}
1097/// `LockOrder_Acyclic : āˆ€ prog, acyclic_lock_order prog → DeadlockFreedom prog`
1098pub fn lock_order_acyclic_ty() -> Expr {
1099    pi(
1100        BinderInfo::Default,
1101        "prog",
1102        cst("Program"),
1103        arrow(
1104            app(cst("AcyclicLockOrder"), bvar(0)),
1105            app(cst("DeadlockFreedom"), bvar(1)),
1106        ),
1107    )
1108}
1109/// `AtomicBlock : Program → Stmt → Prop`
1110/// A statement executes atomically with respect to all other threads.
1111pub fn atomic_block_ty() -> Expr {
1112    arrow(cst("Program"), arrow(cst("Stmt"), prop()))
1113}
1114/// `Atomicity_Serializability : āˆ€ prog s, Atomic prog s → serializable_execution prog s`
1115pub fn atomicity_serializability_ty() -> Expr {
1116    pi(
1117        BinderInfo::Default,
1118        "prog",
1119        cst("Program"),
1120        pi(
1121            BinderInfo::Default,
1122            "s",
1123            cst("Stmt"),
1124            arrow(
1125                app2(cst("AtomicBlock"), bvar(1), bvar(0)),
1126                app2(cst("SerializableExec"), bvar(2), bvar(1)),
1127            ),
1128        ),
1129    )
1130}
1131/// `LockSetAnalysis : Program → Thread → MemLoc → LockSet`
1132/// Compute the set of locks held by thread t when accessing loc.
1133pub fn lock_set_analysis_ty() -> Expr {
1134    arrow(
1135        cst("Program"),
1136        arrow(thread_ty(), arrow(cst("MemLoc"), lock_set_ty())),
1137    )
1138}
1139/// `OwnershipType : Type` — A type carrying ownership (unique, shared, borrowed).
1140pub fn ownership_type_ty() -> Expr {
1141    type0()
1142}
1143/// `BorrowKind : Type` — Borrow flavor: immutable (&) or mutable (&mut).
1144pub fn borrow_kind_ty() -> Expr {
1145    type0()
1146}
1147/// `Lifetime : Type` — A lifetime region for borrow validity.
1148pub fn lifetime_ty() -> Expr {
1149    nat_ty()
1150}
1151/// `BorrowCheck : Program → Prop` — Rust-like borrow checker soundness.
1152pub fn borrow_check_ty() -> Expr {
1153    arrow(cst("Program"), prop())
1154}
1155/// `OwnershipUnique : OwnershipType → Prop` — At most one owner at any time.
1156pub fn ownership_unique_ty() -> Expr {
1157    arrow(ownership_type_ty(), prop())
1158}
1159/// `BorrowCheck_MemSafe : āˆ€ prog, borrow_check prog → memory_safe prog`
1160pub fn borrow_check_mem_safe_ty() -> Expr {
1161    pi(
1162        BinderInfo::Default,
1163        "prog",
1164        cst("Program"),
1165        arrow(
1166            app(cst("BorrowCheck"), bvar(0)),
1167            app(cst("MemorySafe"), bvar(1)),
1168        ),
1169    )
1170}
1171/// `LifetimeSubtyping : Lifetime → Lifetime → Prop` — 'a: 'b (a outlives b).
1172pub fn lifetime_subtyping_ty() -> Expr {
1173    arrow(lifetime_ty(), arrow(lifetime_ty(), prop()))
1174}
1175/// `NonLexicalLifetime : Program → LifetimeAnnotation`
1176/// Non-lexical lifetime inference for precise scope analysis.
1177pub fn non_lexical_lifetime_ty() -> Expr {
1178    arrow(cst("Program"), cst("LifetimeAnnotation"))
1179}
1180/// `DataDependence : Stmt → Stmt → Prop` — def-use data dependence edge.
1181pub fn data_dependence_ty() -> Expr {
1182    arrow(cst("Stmt"), arrow(cst("Stmt"), prop()))
1183}
1184/// `ControlDependence : Stmt → Stmt → Prop` — Control dependence edge.
1185pub fn control_dependence_ty() -> Expr {
1186    arrow(cst("Stmt"), arrow(cst("Stmt"), prop()))
1187}
1188/// `ProgramDependenceGraph : Program → PDG`
1189/// Build the program dependence graph combining data and control edges.
1190pub fn program_dependence_graph_ty() -> Expr {
1191    arrow(cst("Program"), cst("PDG"))
1192}
1193/// `BackwardSlice : PDG → SliceCriterion → Set Stmt`
1194/// Backward slice: all statements that can affect the criterion.
1195pub fn backward_slice_ty() -> Expr {
1196    arrow(
1197        cst("PDG"),
1198        arrow(cst("SliceCriterion"), set_ty(cst("Stmt"))),
1199    )
1200}
1201/// `ForwardSlice : PDG → SliceCriterion → Set Stmt`
1202/// Forward slice: all statements that the criterion can affect.
1203pub fn forward_slice_ty() -> Expr {
1204    arrow(
1205        cst("PDG"),
1206        arrow(cst("SliceCriterion"), set_ty(cst("Stmt"))),
1207    )
1208}
1209/// `Slice_Correct : āˆ€ prog c, backward_slice preserves criterion semantics`
1210pub fn slice_correct_ty() -> Expr {
1211    pi(
1212        BinderInfo::Default,
1213        "prog",
1214        cst("Program"),
1215        pi(
1216            BinderInfo::Default,
1217            "c",
1218            cst("SliceCriterion"),
1219            app(
1220                cst("PreservesSemantics"),
1221                app2(
1222                    cst("BackwardSlice"),
1223                    app(cst("ProgramDependenceGraph"), bvar(1)),
1224                    bvar(0),
1225                ),
1226            ),
1227        ),
1228    )
1229}
1230/// Populate an OxiLean kernel `Environment` with all static-analysis axioms.
1231pub fn build_static_analysis_env() -> Environment {
1232    let mut env = Environment::new();
1233    let axioms: &[(&str, Expr)] = &[
1234        ("Lattice", lattice_ty()),
1235        ("LatticeBottom", lattice_bottom_ty()),
1236        ("LatticeTop", lattice_top_ty()),
1237        ("LatticeJoin", lattice_join_ty()),
1238        ("LatticeMeet", lattice_meet_ty()),
1239        ("LatticeLeq", lattice_leq_ty()),
1240        ("MooreFamily", moore_family_ty()),
1241        ("CompleteLattice_GaloisConn", complete_lattice_galois_ty()),
1242        ("ConcreteSemantics", concrete_semantics_ty()),
1243        ("AbstractSemantics", abstract_semantics_ty()),
1244        ("GaloisConnection", galois_connection_ty()),
1245        ("Abstraction", abstraction_ty()),
1246        ("Concretization", concretization_ty()),
1247        ("GaloisInsertion", galois_insertion_ty()),
1248        ("Widening", widening_ty()),
1249        ("Narrowing", narrowing_ty()),
1250        ("Widening_Terminates", widening_terminates_ty()),
1251        ("AbstractInterp_Sound", abstract_interp_sound_ty()),
1252        ("Narrowing_RefinesPost", narrowing_refines_post_ty()),
1253        ("HeapGraph", heap_graph_ty()),
1254        ("HeapNode", heap_node_ty()),
1255        ("SharingPred", sharing_pred_ty()),
1256        ("CyclicPred", cyclic_pred_ty()),
1257        ("ShapeDescriptor", shape_descriptor_ty()),
1258        ("shape_join", shape_join_ty()),
1259        ("shape_transfer", shape_transfer_ty()),
1260        ("ShapeSound", shape_sound_ty()),
1261        ("ThreeValued", three_valued_ty()),
1262        ("MustAlias", must_alias_ty()),
1263        ("AllocSite", alloc_site_ty()),
1264        ("PointsTo", points_to_ty()),
1265        ("AndersenAnalysis", andersen_analysis_ty()),
1266        ("SteensgaardAnalysis", steensgaard_analysis_ty()),
1267        ("Andersen_Sound", andersen_sound_ty()),
1268        ("Steensgaard_SubAndersen", steensgaard_sub_andersen_ty()),
1269        ("Andersen_Cubic", andersen_cubic_ty()),
1270        ("Steensgaard_AlmostLinear", steensgaard_almost_linear_ty()),
1271        ("AliasResult", alias_result_ty()),
1272        ("MayAlias", may_alias_ty()),
1273        ("MustAliasPair", must_alias_pair_ty()),
1274        ("TypeBasedAlias", type_based_alias_ty()),
1275        ("NoAlias", no_alias_ty()),
1276        ("Alias_Undecidable", alias_undecidable_ty()),
1277        ("SoftType", soft_type_ty()),
1278        ("SoftTypeCheck", soft_type_check_ty()),
1279        ("RefinementType", refinement_type_ty()),
1280        ("EffectType", effect_type_ty()),
1281        ("EffectSubtype", effect_subtype_ty()),
1282        ("Liquid_Haskell_Sound", liquid_haskell_sound_ty()),
1283        ("CallSite", call_site_ty()),
1284        ("AbstractClosure", abstract_closure_ty()),
1285        ("ZeroCFA", zero_cfa_ty()),
1286        ("KCFA", k_cfa_ty()),
1287        ("CFA_Overapprox", cfa_overapprox_ty()),
1288        ("CFA_Monotone_in_k", cfa_monotone_k_ty()),
1289        ("KCFA_Complexity", k_cfa_complexity_ty()),
1290        ("Effect", effect_ty()),
1291        ("EffectSet", effect_set_ty()),
1292        ("ReadEffect", read_effect_ty()),
1293        ("WriteEffect", write_effect_ty()),
1294        ("ExnEffect", exn_effect_ty()),
1295        ("infer_effects", infer_effects_ty()),
1296        ("EffectSound", effect_sound_ty()),
1297        ("PureFunction", pure_function_ty()),
1298        ("ResourceType", resource_type_ty()),
1299        ("UsageAnnotation", usage_annotation_ty()),
1300        ("LinearType", linear_type_ty()),
1301        ("AffineType", affine_type_ty()),
1302        ("ResourceUsageAnalysis", resource_usage_analysis_ty()),
1303        ("LeakFreedom", leak_freedom_ty()),
1304        ("LinearType_LeakFree", linear_type_leak_free_ty()),
1305        ("UsageCount_Sound", usage_count_sound_ty()),
1306        ("Thread", thread_ty()),
1307        ("LockSet", lock_set_ty()),
1308        ("HappensBefore", happens_before_ty()),
1309        ("DataRace", data_race_ty()),
1310        ("EraserLockSet", eraser_lock_set_ty()),
1311        ("Eraser_Invariant", eraser_invariant_ty()),
1312        ("TSan_Sound", tsan_sound_ty()),
1313        ("DataRaceFreedom", data_race_freedom_ty()),
1314        ("DRF_Sequential", drf_sequential_ty()),
1315        ("TaintSource", taint_source_ty()),
1316        ("TaintSink", taint_sink_ty()),
1317        ("Sanitizer", sanitizer_ty()),
1318        ("TaintLabel", taint_label_ty()),
1319        ("TaintPropagation", taint_propagation_ty()),
1320        ("TaintViolation", taint_violation_ty()),
1321        ("Taint_Sound", taint_sound_ty()),
1322        ("Taint_NoFalseNegatives", taint_no_false_neg_ty()),
1323        ("SepLogicHeap", sep_logic_heap_ty()),
1324        ("SepConj", sep_conj_ty()),
1325        ("SepImp", sep_imp_ty()),
1326        ("PointsToCell", points_to_cell_ty()),
1327        ("FrameRule", frame_rule_ty()),
1328        ("HeapShape_TreePred", heap_shape_tree_pred_ty()),
1329        ("MemorySafety", memory_safety_ty()),
1330        ("OwnershipTransfer", ownership_transfer_ty()),
1331        ("Typestate", typestate_ty()),
1332        ("TypestateProtocol", typestate_protocol_ty()),
1333        ("TypestateTransition", typestate_transition_ty()),
1334        ("TypestateCheck", typestate_check_ty()),
1335        ("MustUseResource", must_use_resource_ty()),
1336        ("TypestateSound", typestate_sound_ty()),
1337        ("Region", region_ty()),
1338        ("RegionAnnotation", region_annotation_ty()),
1339        ("EscapeAnalysis", escape_analysis_ty()),
1340        ("RegionInference", region_inference_ty()),
1341        ("Escape_Sound", escape_sound_ty()),
1342        ("RegionSubtyping", region_subtyping_ty()),
1343        ("MonadicEffect", monadic_effect_ty()),
1344        ("GradedMonad", graded_monad_ty()),
1345        ("CapabilitySet", capability_set_ty()),
1346        ("CapabilityJudgment", capability_judgment_ty()),
1347        ("EffectPolymorphism", effect_polymorphism_ty()),
1348        ("AlgebraicEffectHandler", algebraic_effect_handler_ty()),
1349        ("GradualType", gradual_type_ty()),
1350        ("UnknownType", unknown_type_ty()),
1351        ("ConsistencyRel", consistency_rel_ty()),
1352        ("CastInsertion", cast_insertion_ty()),
1353        ("CastCorrectness", cast_correctness_ty()),
1354        ("Blame_Theorem", blame_theorem_ty()),
1355        ("LiquidType", liquid_type_ty()),
1356        ("QualifierInstantiation", qualifier_instantiation_ty()),
1357        ("SubtypingRefinement", subtyping_refinement_ty()),
1358        ("RefinementInference", refinement_inference_ty()),
1359        ("LiquidType_Complete", liquid_type_complete_ty()),
1360        ("SecurityLabel", security_label_ty()),
1361        ("SecrecyLattice", secrecy_lattice_ty()),
1362        ("LabelEnv", label_env_ty()),
1363        ("NonInterference", non_interference_ty()),
1364        ("Declassification", declassification_ty()),
1365        ("IFCTypeSystem", ifc_type_system_ty()),
1366        ("NI_Theorem", ni_theorem_ty()),
1367        ("ConstantFolding", constant_folding_ty()),
1368        ("ConstantPropagation", constant_propagation_ty()),
1369        ("ConstFold_Correct", const_fold_correct_ty()),
1370        ("IntervalDomain", interval_domain_ty()),
1371        ("BitfieldDomain", bitfield_domain_ty()),
1372        ("ValueRangeAnalysis", value_range_analysis_ty()),
1373        ("VRA_Sound", vra_sound_ty()),
1374        ("NullabilityAnnotation", nullability_annotation_ty()),
1375        ("NullPointerAnalysis", null_pointer_analysis_ty()),
1376        ("DefiniteAssignment", definite_assignment_ty()),
1377        ("NullSafety", null_safety_ty()),
1378        ("NullAnalysis_Sound", null_analysis_sound_ty()),
1379        ("LockOrder", lock_order_ty()),
1380        ("DeadlockFreedom", deadlock_freedom_ty()),
1381        ("LockOrder_Acyclic", lock_order_acyclic_ty()),
1382        ("AtomicBlock", atomic_block_ty()),
1383        ("Atomicity_Serializability", atomicity_serializability_ty()),
1384        ("LockSetAnalysis", lock_set_analysis_ty()),
1385        ("OwnershipType", ownership_type_ty()),
1386        ("BorrowKind", borrow_kind_ty()),
1387        ("Lifetime", lifetime_ty()),
1388        ("BorrowCheck", borrow_check_ty()),
1389        ("OwnershipUnique", ownership_unique_ty()),
1390        ("BorrowCheck_MemSafe", borrow_check_mem_safe_ty()),
1391        ("LifetimeSubtyping", lifetime_subtyping_ty()),
1392        ("NonLexicalLifetime", non_lexical_lifetime_ty()),
1393        ("DataDependence", data_dependence_ty()),
1394        ("ControlDependence", control_dependence_ty()),
1395        ("ProgramDependenceGraph", program_dependence_graph_ty()),
1396        ("BackwardSlice", backward_slice_ty()),
1397        ("ForwardSlice", forward_slice_ty()),
1398        ("Slice_Correct", slice_correct_ty()),
1399    ];
1400    for (name, ty) in axioms {
1401        env.add(Declaration::Axiom {
1402            name: Name::str(*name),
1403            univ_params: vec![],
1404            ty: ty.clone(),
1405        })
1406        .ok();
1407    }
1408    env
1409}
1410#[cfg(test)]
1411mod tests {
1412    use super::*;
1413    /// Smoke test: build env produces expected axioms.
1414    #[test]
1415    fn test_build_env_nonempty() {
1416        let env = build_static_analysis_env();
1417        let names = [
1418            "Lattice",
1419            "GaloisConnection",
1420            "Widening",
1421            "Narrowing",
1422            "AndersenAnalysis",
1423            "HappensBefore",
1424            "TaintPropagation",
1425            "ShapeDescriptor",
1426            "KCFA",
1427            "DataRaceFreedom",
1428        ];
1429        let count = names
1430            .iter()
1431            .filter(|&&n| env.get(&Name::str(n)).is_some())
1432            .count();
1433        assert_eq!(count, 10);
1434    }
1435    /// Interval lattice: join, meet, order.
1436    #[test]
1437    fn test_interval_lattice() {
1438        let a = Interval::Range(1, 5);
1439        let b = Interval::Range(3, 8);
1440        assert_eq!(a.join(&b), Interval::Range(1, 8));
1441        assert_eq!(a.meet(&b), Interval::Range(3, 5));
1442        assert!(Interval::Bottom.leq(&a));
1443        assert!(a.leq(&Interval::top()));
1444        assert!(!b.leq(&a));
1445    }
1446    /// Interval widening drives to ⊤.
1447    #[test]
1448    fn test_interval_widening() {
1449        let mut x = Interval::Range(0, 0);
1450        for _ in 0..5 {
1451            let next = x.add(&Interval::single(1));
1452            x = x.widen(&next);
1453        }
1454        assert_eq!(x, Interval::Range(0, i64::MAX));
1455    }
1456    /// Sign domain: join and add.
1457    #[test]
1458    fn test_sign_domain() {
1459        assert_eq!(Sign::of(3), Sign::Pos);
1460        assert_eq!(Sign::of(-2), Sign::Neg);
1461        assert_eq!(Sign::of(0), Sign::Zero);
1462        assert_eq!(Sign::Pos.join(&Sign::Neg), Sign::Top);
1463        assert_eq!(Sign::Pos.add(&Sign::Zero), Sign::Pos);
1464        assert_eq!(Sign::Neg.neg(), Sign::Pos);
1465    }
1466    /// Andersen PTA: simple copy chain.
1467    #[test]
1468    fn test_andersen_copy_chain() {
1469        let mut pta = AndersenPTA::new(3);
1470        pta.add_alloc(0, 0);
1471        pta.add_copy(0, 1);
1472        pta.add_copy(1, 2);
1473        pta.solve();
1474        assert!(pta.pts[0].contains(&0));
1475        assert!(pta.pts[1].contains(&0));
1476        assert!(pta.pts[2].contains(&0));
1477        assert!(pta.may_alias(0, 1));
1478        assert!(pta.may_alias(1, 2));
1479    }
1480    /// Taint propagation: source → propagation → sink.
1481    #[test]
1482    fn test_taint_propagation() {
1483        let mut ts = TaintState::new();
1484        ts.add_source("user_input");
1485        ts.propagate("x", &["user_input"]);
1486        ts.propagate("y", &["x", "const"]);
1487        assert!(ts.violates("x"));
1488        assert!(ts.violates("y"));
1489        ts.sanitize("x");
1490        assert!(!ts.violates("x"));
1491        assert!(ts.violates("y"));
1492    }
1493    /// Eraser race detection: two threads, no common lock → race.
1494    #[test]
1495    fn test_eraser_race_detected() {
1496        let mut state = EraserState::new();
1497        let locks_t1: BTreeSet<usize> = vec![1].into_iter().collect();
1498        let locks_t2: BTreeSet<usize> = vec![2].into_iter().collect();
1499        state.observe_access(0, &locks_t1, true);
1500        state.observe_access(1, &locks_t2, true);
1501        assert!(state.has_race());
1502    }
1503    /// Eraser: same lock on both accesses → no race.
1504    #[test]
1505    fn test_eraser_no_race() {
1506        let mut state = EraserState::new();
1507        let locks: BTreeSet<usize> = vec![42].into_iter().collect();
1508        state.observe_access(0, &locks, true);
1509        state.observe_access(1, &locks, false);
1510        assert!(!state.has_race());
1511    }
1512    /// Fixpoint solver: reachability over a 3-node chain.
1513    #[test]
1514    fn test_fixpoint_reachability() {
1515        let edges = vec![vec![1], vec![2], vec![]];
1516        let mut solver = FixpointSolver::new(
1517            3,
1518            edges,
1519            false,
1520            |a: &bool, b: &bool| *a || *b,
1521            |n, v| if n == 0 { true } else { *v },
1522        );
1523        solver.values[0] = true;
1524        solver.solve();
1525        assert!(solver.values[1]);
1526        assert!(solver.values[2]);
1527    }
1528    /// New axioms are registered in the environment.
1529    #[test]
1530    fn test_new_axioms_registered() {
1531        let env = build_static_analysis_env();
1532        let names = [
1533            "SepConj",
1534            "FrameRule",
1535            "TypestateSound",
1536            "EscapeAnalysis",
1537            "GradedMonad",
1538            "CastCorrectness",
1539            "LiquidType",
1540            "NonInterference",
1541            "ConstantFolding",
1542            "NullSafety",
1543            "DeadlockFreedom",
1544            "BorrowCheck",
1545            "BackwardSlice",
1546        ];
1547        let count = names
1548            .iter()
1549            .filter(|&&n| env.get(&Name::str(n)).is_some())
1550            .count();
1551        assert_eq!(count, names.len());
1552    }
1553    /// TypestateAutomaton: file open/close protocol.
1554    #[test]
1555    fn test_typestate_automaton_file() {
1556        let mut aut = TypestateAutomaton::new(2, 0);
1557        aut.add_transition(0, "open", 1);
1558        aut.add_transition(1, "read", 1);
1559        aut.add_transition(1, "close", 0);
1560        aut.set_accepting(0);
1561        assert!(aut.accepts(&["open", "read", "close"]));
1562        assert!(!aut.accepts(&["open", "read"]));
1563        assert!(aut.violates(&["open", "open"]));
1564    }
1565    /// IFCTracker: high-labeled data must not flow to low sink.
1566    #[test]
1567    fn test_ifc_tracker_violation() {
1568        let mut tracker = IFCTracker::new();
1569        tracker.assign("password", SecurityLevel::High);
1570        tracker.assign("user_id", SecurityLevel::Low);
1571        tracker.propagate("derived", &["password", "user_id"]);
1572        assert_eq!(tracker.label_of("derived"), SecurityLevel::High);
1573        tracker.check_flow("derived", &SecurityLevel::Low);
1574        assert!(tracker.has_violation());
1575    }
1576    /// IFCTracker: low-labeled data can flow to high sink.
1577    #[test]
1578    fn test_ifc_tracker_ok() {
1579        let mut tracker = IFCTracker::new();
1580        tracker.assign("public_id", SecurityLevel::Low);
1581        tracker.check_flow("public_id", &SecurityLevel::High);
1582        assert!(!tracker.has_violation());
1583    }
1584    /// ConstPropState: basic folding and join.
1585    #[test]
1586    fn test_const_prop_state() {
1587        let mut s1 = ConstPropState::new();
1588        s1.set_const("x", 10);
1589        s1.set_const("y", 5);
1590        assert_eq!(s1.fold_add("x", "y"), Some(15));
1591        let mut s2 = ConstPropState::new();
1592        s2.set_const("x", 10);
1593        s2.set_top("y");
1594        let joined = s1.join(&s2);
1595        assert_eq!(joined.get("x"), Some(10));
1596        assert_eq!(joined.get("y"), None);
1597    }
1598    /// PDGraph: backward and forward slicing.
1599    #[test]
1600    fn test_pd_graph_slicing() {
1601        let mut pdg = PDGraph::new(4);
1602        pdg.add_data_edge(0, 1);
1603        pdg.add_data_edge(1, 3);
1604        let bwd = pdg.backward_slice(3);
1605        assert!(bwd.contains(&3));
1606        assert!(bwd.contains(&1));
1607        assert!(bwd.contains(&0));
1608        assert!(!bwd.contains(&2));
1609        let fwd = pdg.forward_slice(0);
1610        assert!(fwd.contains(&0));
1611        assert!(fwd.contains(&1));
1612        assert!(fwd.contains(&3));
1613    }
1614    /// NullTracker: alarm on dereference of maybe-null variable.
1615    #[test]
1616    fn test_null_tracker_alarm() {
1617        let mut tracker = NullTracker::new();
1618        tracker.declare_maybe_null("ptr");
1619        tracker.dereference("ptr");
1620        assert!(tracker.has_alarm());
1621    }
1622    /// NullTracker: no alarm on definitely non-null variable.
1623    #[test]
1624    fn test_null_tracker_no_alarm() {
1625        let mut tracker = NullTracker::new();
1626        tracker.declare_non_null("safe_ptr");
1627        tracker.dereference("safe_ptr");
1628        assert!(!tracker.has_alarm());
1629    }
1630    /// NullTracker: join merges states correctly.
1631    #[test]
1632    fn test_null_tracker_join() {
1633        let mut t1 = NullTracker::new();
1634        t1.declare_non_null("p");
1635        let mut t2 = NullTracker::new();
1636        t2.declare_null("p");
1637        let merged = t1.join(&t2);
1638        assert_eq!(merged.get("p"), &Nullability::MaybeNull);
1639    }
1640}