Skip to content

Commit 585e479

Browse files
authored
Merge pull request #19 from os-checker/tests-diff
Fix: ensures hash is unchanged when unrelated contracts and proofs are added
2 parents 045af65 + 255c4fc commit 585e479

18 files changed

+5079
-1058
lines changed

Cargo.lock

Lines changed: 23 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ tracing-error = "0.2"
2121
[dev-dependencies]
2222
assert_cmd = "2.0.16"
2323
expect-test = "1.5.1"
24+
pretty_assertions = "1.4.1"
2425

2526
[lints.rust]
2627
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(kani)'] }

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Distributed and resource-efficient verification for verify-rust-std
2+
3+
Context: [Distributed and resource-efficient verification][distributed], GSoC Rust 2025
4+
5+
[distributed]: https://github.com/rust-lang/google-summer-of-code/tree/45141d74c28d91e114cf621d2d56aea6c3f82547?tab=readme-ov-file#distributed-and-resource-efficient-verification
6+
7+
## Steps
8+
9+
The list in very incomplete at the moment.
10+
11+
- [ ] Analyze kani's proofs and contracts
12+
- [x] Rust Compiler Driver
13+
- [x] Reuse reachability code from kani
14+
- [x] Traverse calls starting from proofs and contracts
15+
- [ ] Generate proofs that need to rerun
16+
- [ ] Compute difference
17+
- [ ] Emit JSON
18+
- [ ] CI setup
19+
- [ ] Run kani
20+
- [ ] Run ESBMC ??

src/functions/mod.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use stable_mir::{
99
mir::mono::{Instance, MonoItem},
1010
ty::{FnDef, RigidTy, Ty, TyKind},
1111
};
12+
use std::cmp::Ordering;
1213

1314
mod kani;
1415
mod serialization;
@@ -81,6 +82,7 @@ impl Function {
8182

8283
let mut callees = IndexSet::new();
8384
callgraph.recursive_callees(item, &mut callees);
85+
callees.sort_by(|a, b| cmp_callees(a, b, tcx, src_map));
8486

8587
let func = source_code_with(body.span, tcx, src_map);
8688
info!(" - {:?} ({span:?}): {func}", inst_def.name());
@@ -119,3 +121,20 @@ fn source_code_with(
119121
let span = internal(tcx, stable_mir_span);
120122
source_code(span, src_map)
121123
}
124+
125+
fn source_code_of_body(inst: &Instance, tcx: TyCtxt, src_map: &SourceMap) -> Option<String> {
126+
inst.body().map(|body| source_code_with(body.span, tcx, src_map))
127+
}
128+
129+
fn cmp_callees(a: &Instance, b: &Instance, tcx: TyCtxt, src_map: &SourceMap) -> Ordering {
130+
let filename_a = a.def.span().get_filename();
131+
let filename_b = b.def.span().get_filename();
132+
match filename_a.cmp(&filename_b) {
133+
Ordering::Equal => (),
134+
ord => return ord,
135+
}
136+
137+
let body_a = source_code_of_body(a, tcx, src_map);
138+
let body_b = source_code_of_body(b, tcx, src_map);
139+
body_a.cmp(&body_b)
140+
}

src/functions/serialization.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,7 @@ impl Callee {
7676
let inst_def = &inst.def;
7777
let def_id = format_def_id(&inst_def.def_id());
7878
let file = inst_def.span().get_filename();
79-
let func = inst
80-
.body()
81-
.map(|body| super::source_code_with(body.span, tcx, src_map))
82-
.unwrap_or_default();
79+
let func = super::source_code_of_body(inst, tcx, src_map).unwrap_or_default();
8380
Callee { def_id, file, func }
8481
}
8582
}

src/lib.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use serde::{Deserialize, Serialize};
2+
3+
/// A Rust funtion with its file source, attributes, and raw function content.
4+
#[derive(Debug, Serialize, Deserialize)]
5+
pub struct SerFunction {
6+
pub hash: String,
7+
/// DefId in stable_mir.
8+
pub def_id: String,
9+
/// Every funtion must be declared in a specific file, even for those
10+
/// generated by macros.
11+
pub file: String,
12+
/// Attributes are attached the function, but it seems that attributes
13+
/// and function must be separated to query.
14+
pub attrs: Vec<String>,
15+
/// Raw function string, including name, signature, and body.
16+
pub func: String,
17+
/// Recursive fnction calls inside the body.
18+
pub callees: Vec<Callee>,
19+
}
20+
21+
#[derive(Debug, Serialize, Deserialize)]
22+
pub struct Callee {
23+
pub def_id: String,
24+
pub file: String,
25+
pub func: String,
26+
}
27+
28+
impl SerFunction {
29+
/// Even though callees are in insertion order, to make them easy to check,
30+
/// sort by file and function.
31+
pub fn callee_sorted_by_file_func(&self) -> Vec<[&str; 2]> {
32+
let mut callees: Vec<_> = self.callees.iter().collect();
33+
callees.sort_by(|a, b| (&a.file, &a.func).cmp(&(&b.file, &b.func)));
34+
callees.into_iter().map(|c| [&*c.file, &*c.func]).collect()
35+
}
36+
}

tests/compare/contract1.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#[cfg(kani)]
2+
mod verify {
3+
#[kani::requires(a > 0)]
4+
pub fn contract(a: u8) {}
5+
6+
#[kani::proof]
7+
pub fn f() {
8+
contract(0);
9+
}
10+
}

tests/compare/contract2.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#[cfg(kani)]
2+
mod verify {
3+
#[kani::requires(a > 0)]
4+
pub fn contract(a: u8) {}
5+
6+
#[kani::proof]
7+
pub fn f() {
8+
contract(0);
9+
}
10+
11+
#[kani::requires(a > 0)]
12+
pub fn g(a: u8) {}
13+
}

tests/compare/proof1.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#[cfg(kani)]
2+
mod verify {
3+
#[kani::proof]
4+
pub fn f() {
5+
let a = 1;
6+
assert_eq!(a + 1, 2);
7+
}
8+
}

tests/compare/proof2.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#[cfg(kani)]
2+
mod verify {
3+
#[kani::proof]
4+
pub fn f() {
5+
let a = 1;
6+
assert_eq!(a + 1, 2);
7+
}
8+
9+
#[kani::proof]
10+
pub fn g() {
11+
let a = 1;
12+
assert_eq!(a + 1, 2);
13+
}
14+
}

0 commit comments

Comments
 (0)