rapx/verify/report.rs
1//! Diagnostics and summaries for the staged verifier pipeline.
2//!
3//! The driver and later checking stages report their per-path property results
4//! through the types in this module. Keeping these types here leaves the driver
5//! focused on orchestration.
6
7use rustc_hir::def_id::DefId;
8
9use super::{contract::Property, helpers::CheckpointLocation};
10
11/// Verification status for one required property on one path.
12#[derive(Clone, Debug)]
13pub enum CheckResult {
14 /// The property has been proved for this path.
15 Proved,
16 /// The verifier found a possible violation for this path.
17 Failed,
18 /// The verifier has not implemented or completed the proof for this path.
19 Unknown,
20}
21
22/// Result for one required property along one path to a checkpoint.
23#[derive(Clone, Debug)]
24pub struct PropertyCheckResult<'tcx> {
25 /// Unsafe checkpoint being checked.
26 pub checkpoint: CheckpointLocation,
27 /// Index of the checkpoint in the function-level checkpoint list.
28 pub checkpoint_index: usize,
29 /// Index of the path in the checkpoint path set.
30 pub path_index: usize,
31 /// Index of the property in the checkpoint-level property list.
32 pub property_index: usize,
33 /// Required property checked on this path.
34 pub property: Property<'tcx>,
35 /// Current verification status.
36 pub result: CheckResult,
37 /// Optional path-local diagnostics generated by the staged visitors.
38 pub diagnostics: Option<VisitDiagnostics>,
39 /// Human-readable path description.
40 pub path_description: String,
41 /// Callee name for this checkpoint.
42 pub callee_name: String,
43}
44
45/// Human-readable diagnostics emitted for one path/property check.
46#[derive(Clone, Debug)]
47pub struct VisitDiagnostics {
48 /// Backward visit summary for relevant MIR items.
49 pub backward: String,
50 /// Forward visit summary for abstract facts collected from those items.
51 pub forward: String,
52}
53
54impl VisitDiagnostics {
55 /// Create diagnostics from backward and forward visitor summaries.
56 pub fn new(backward: String, forward: String) -> Self {
57 Self { backward, forward }
58 }
59}
60
61/// Verification report for one function target.
62#[derive(Clone, Debug)]
63pub struct VerificationReport<'tcx> {
64 /// Function that was verified.
65 pub function: DefId,
66 /// Per-path property results emitted by the verifier.
67 pub results: Vec<PropertyCheckResult<'tcx>>,
68}
69
70impl<'tcx> VerificationReport<'tcx> {
71 /// Create an empty report for a function target.
72 pub fn new(function: DefId) -> Self {
73 Self {
74 function,
75 results: Vec::new(),
76 }
77 }
78
79 /// Add one path/property check result to this report.
80 pub fn push(&mut self, result: PropertyCheckResult<'tcx>) {
81 self.results.push(result);
82 }
83
84 /// Return the number of check results in this report.
85 pub fn len(&self) -> usize {
86 self.results.len()
87 }
88
89 /// Return true when this report contains no check results.
90 pub fn is_empty(&self) -> bool {
91 self.results.is_empty()
92 }
93
94 /// Render the whole report as a readable multi-line diagnostic.
95 pub fn describe(&self) -> String {
96 let mut out = String::new();
97 out.push_str(&format!(
98 "[rapx::verify::diagnostics] function {:?}: {} check item(s)\n",
99 self.function,
100 self.results.len()
101 ));
102
103 for (index, result) in self.results.iter().enumerate() {
104 out.push_str(&format!(
105 " check #{index}: checkpoint #{}, bb{}, path #{}, property #{} {:?}, result {:?}\n",
106 result.checkpoint_index,
107 result.checkpoint.block.as_usize(),
108 result.path_index,
109 result.property_index,
110 result.property.kind,
111 result.result
112 ));
113
114 if let Some(diagnostics) = &result.diagnostics {
115 out.push_str(&diagnostics.backward);
116 if !diagnostics.backward.ends_with('\n') {
117 out.push('\n');
118 }
119 out.push_str(&diagnostics.forward);
120 if !diagnostics.forward.ends_with('\n') {
121 out.push('\n');
122 }
123 }
124 }
125
126 out
127 }
128}