Skip to content

Commit a3feeb3

Browse files
committed
run-make-support: add drop bomb module
1 parent 7255c28 commit a3feeb3

File tree

3 files changed

+66
-0
lines changed

3 files changed

+66
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//! This module implements "drop bombs" intended for use by command wrappers to ensure that the
2+
//! constructed commands are *eventually* executed. This is exactly like `rustc_errors::Diag` where
3+
//! we force every `Diag` to be consumed or we emit a bug, but we panic instead.
4+
//!
5+
//! This is adapted from <https://docs.rs/drop_bomb/latest/drop_bomb/> and simplified for our
6+
//! purposes.
7+
8+
use std::ffi::{OsStr, OsString};
9+
use std::panic;
10+
11+
#[cfg(test)]
12+
mod tests;
13+
14+
#[derive(Debug)]
15+
pub(crate) struct DropBomb {
16+
command: OsString,
17+
defused: bool,
18+
armed_line: u32,
19+
}
20+
21+
impl DropBomb {
22+
/// Arm a [`DropBomb`]. If the value is dropped without being [`defused`][Self::defused], then
23+
/// it will panic. It is expected that the command wrapper uses `#[track_caller]` to help
24+
/// propagate the caller info from rmake.rs.
25+
#[track_caller]
26+
pub(crate) fn arm<S: AsRef<OsStr>>(command: S) -> DropBomb {
27+
DropBomb {
28+
command: command.as_ref().into(),
29+
defused: false,
30+
armed_line: panic::Location::caller().line(),
31+
}
32+
}
33+
34+
/// Defuse the [`DropBomb`]. This will prevent the drop bomb from panicking when dropped.
35+
pub(crate) fn defuse(&mut self) {
36+
self.defused = true;
37+
}
38+
}
39+
40+
impl Drop for DropBomb {
41+
fn drop(&mut self) {
42+
if !self.defused && !std::thread::panicking() {
43+
panic!(
44+
"command constructed but not executed at line {}: `{}`",
45+
self.armed_line,
46+
self.command.to_string_lossy()
47+
)
48+
}
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
use super::DropBomb;
2+
3+
#[test]
4+
#[should_panic]
5+
fn test_arm() {
6+
let bomb = DropBomb::arm("hi :3");
7+
drop(bomb); // <- armed bomb should explode when not defused
8+
}
9+
10+
#[test]
11+
fn test_defuse() {
12+
let mut bomb = DropBomb::arm("hi :3");
13+
bomb.defuse();
14+
drop(bomb); // <- defused bomb should not explode
15+
}

src/tools/run-make-support/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pub mod cc;
77
pub mod clang;
88
mod command;
99
pub mod diff;
10+
mod drop_bomb;
1011
pub mod llvm_readobj;
1112
pub mod run;
1213
pub mod rustc;

0 commit comments

Comments
 (0)