Skip to content

Commit ee05df3

Browse files
authored
[rust_verify] fix: skip codegen when --compile is not set (#2509)
1 parent 5dd6d83 commit ee05df3

3 files changed

Lines changed: 93 additions & 1 deletion

File tree

source/rust_verify/src/driver.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ This would avoid the complex interleaving above and avoid needing to use lifetim
115115
for all functions (it would only be needed for functions with tracked data in proof code).
116116
*/
117117
struct CompilerCallbacksEraseMacro {
118+
pub do_compile: bool,
118119
pub override_stability: bool,
119120
}
120121

@@ -136,6 +137,18 @@ impl rustc_driver::Callbacks for CompilerCallbacksEraseMacro {
136137
});
137138
}
138139
}
140+
141+
fn after_analysis<'tcx>(
142+
&mut self,
143+
_compiler: &rustc_interface::interface::Compiler,
144+
_tcx: TyCtxt<'tcx>,
145+
) -> rustc_driver::Compilation {
146+
if self.do_compile {
147+
rustc_driver::Compilation::Continue
148+
} else {
149+
rustc_driver::Compilation::Stop
150+
}
151+
}
139152
}
140153

141154
/// Captures the verification and compilation time
@@ -153,9 +166,11 @@ pub struct Stats {
153166

154167
pub(crate) fn run_with_erase_macro_compile(
155168
mut rustc_args: Vec<String>,
169+
do_compile: bool,
156170
vstd: Vstd,
157171
) -> Result<(), ()> {
158172
let mut callbacks = CompilerCallbacksEraseMacro {
173+
do_compile,
159174
override_stability: matches!(vstd, Vstd::IsCore | Vstd::ImportedViaCore),
160175
};
161176
rustc_args.extend(["--cfg", "verus_only", "--cfg", "verus_keep_ghost"].map(|s| s.to_string()));
@@ -320,7 +335,8 @@ pub fn run(
320335
if !verifier.compile && (verifier.args.no_erasure_check || verifier.args.no_lifetime) {
321336
Ok(())
322337
} else {
323-
run_with_erase_macro_compile(rustc_args, verifier.args.vstd)
338+
let do_compile = verifier.compile || verifier.via_cargo_args.is_some();
339+
run_with_erase_macro_compile(rustc_args, do_compile, verifier.args.vstd)
324340
};
325341

326342
let time2 = Instant::now();

source/rust_verify_test/tests/common/mod.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,50 @@ pub fn run_verus(
443443
run
444444
}
445445

446+
pub fn run_verus_raw(args: &[&str], dir: &std::path::Path) -> std::process::Output {
447+
if std::env::var("VERUS_IN_VARGO").is_err() {
448+
panic!("not running in vargo, read the README for instructions");
449+
}
450+
let exe = if cfg!(target_os = "windows") { ".exe" } else { "" };
451+
452+
let current_exe = std::env::current_exe().unwrap();
453+
let deps_path = current_exe.parent().unwrap();
454+
let target_path = deps_path.parent().unwrap();
455+
let profile = target_path.file_name().unwrap().to_str().unwrap();
456+
let verus_target_path = target_path
457+
.ancestors()
458+
.nth(2)
459+
.expect("expected path to have at least two parents")
460+
.join("target-verus")
461+
.join(profile);
462+
let bin = verus_target_path.join(format!("rust_verify{exe}"));
463+
464+
let z3 = std::env::var("VERUS_Z3_PATH")
465+
.map(|p| {
466+
let p = std::path::PathBuf::from(p);
467+
if p.is_relative() { std::path::PathBuf::from("..").join(p) } else { p }
468+
})
469+
.unwrap_or({
470+
if cfg!(target_os = "windows") {
471+
std::path::PathBuf::from("..\\z3.exe")
472+
} else {
473+
std::path::PathBuf::from("../z3")
474+
}
475+
});
476+
let z3 = path::absolute(z3).expect("Failed to find absolute path for Z3 executable");
477+
478+
std::process::Command::new(bin)
479+
.current_dir(dir)
480+
.env("VERUS_Z3_PATH", z3)
481+
.args(args)
482+
.stdout(std::process::Stdio::piped())
483+
.stderr(std::process::Stdio::piped())
484+
.spawn()
485+
.expect("could not execute verus")
486+
.wait_with_output()
487+
.expect("raw verus wait failed")
488+
}
489+
446490
pub fn run_cargo_verus(args: &[&str], dir: &std::path::Path) -> std::process::Output {
447491
run_cargo_verus_with_target(args, dir, &dir.join("target"))
448492
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#![feature(rustc_private)]
2+
#[macro_use]
3+
mod common;
4+
use common::*;
5+
6+
use tempfile::TempDir;
7+
8+
#[test]
9+
fn compile_flag_produces_binary() {
10+
let tempdir = TempDir::new().expect("temp dir");
11+
let entry_file = tempdir.path().join("test.rs");
12+
let code = format!("{}\n{}\nverus! {{ fn main() {{}} }}\n", FEATURE_PRELUDE, USE_PRELUDE);
13+
std::fs::write(&entry_file, code).expect("write source file");
14+
15+
let output = run_verus_raw(&["--compile", entry_file.to_str().unwrap()], tempdir.path());
16+
let exe_name = if cfg!(target_os = "windows") { "test.exe" } else { "test" };
17+
assert!(output.status.success(), "verus failed:\n{}", String::from_utf8_lossy(&output.stderr));
18+
assert!(tempdir.path().join(exe_name).exists());
19+
}
20+
21+
#[test]
22+
fn no_compile_flag_does_not_produce_binary() {
23+
let tempdir = TempDir::new().expect("temp dir");
24+
let entry_file = tempdir.path().join("test.rs");
25+
let code = format!("{}\n{}\nverus! {{ fn main() {{}} }}\n", FEATURE_PRELUDE, USE_PRELUDE);
26+
std::fs::write(&entry_file, code).expect("write source file");
27+
28+
let output = run_verus_raw(&[entry_file.to_str().unwrap()], tempdir.path());
29+
let exe_name = if cfg!(target_os = "windows") { "test.exe" } else { "test" };
30+
assert!(output.status.success(), "verus failed:\n{}", String::from_utf8_lossy(&output.stderr));
31+
assert!(!tempdir.path().join(exe_name).exists());
32+
}

0 commit comments

Comments
 (0)