Skip to content

Commit

Permalink
run-make-support: add drop bomb module
Browse files Browse the repository at this point in the history
  • Loading branch information
jieyouxu committed Jun 11, 2024
1 parent 7255c28 commit a3feeb3
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 0 deletions.
50 changes: 50 additions & 0 deletions src/tools/run-make-support/src/drop_bomb/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//! This module implements "drop bombs" intended for use by command wrappers to ensure that the
//! constructed commands are *eventually* executed. This is exactly like `rustc_errors::Diag` where
//! we force every `Diag` to be consumed or we emit a bug, but we panic instead.
//!
//! This is adapted from <https://docs.rs/drop_bomb/latest/drop_bomb/> and simplified for our
//! purposes.

use std::ffi::{OsStr, OsString};
use std::panic;

#[cfg(test)]
mod tests;

#[derive(Debug)]
pub(crate) struct DropBomb {
command: OsString,
defused: bool,
armed_line: u32,
}

impl DropBomb {
/// Arm a [`DropBomb`]. If the value is dropped without being [`defused`][Self::defused], then
/// it will panic. It is expected that the command wrapper uses `#[track_caller]` to help
/// propagate the caller info from rmake.rs.
#[track_caller]
pub(crate) fn arm<S: AsRef<OsStr>>(command: S) -> DropBomb {
DropBomb {
command: command.as_ref().into(),
defused: false,
armed_line: panic::Location::caller().line(),
}
}

/// Defuse the [`DropBomb`]. This will prevent the drop bomb from panicking when dropped.
pub(crate) fn defuse(&mut self) {
self.defused = true;
}
}

impl Drop for DropBomb {
fn drop(&mut self) {
if !self.defused && !std::thread::panicking() {
panic!(
"command constructed but not executed at line {}: `{}`",
self.armed_line,
self.command.to_string_lossy()
)
}
}
}
15 changes: 15 additions & 0 deletions src/tools/run-make-support/src/drop_bomb/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use super::DropBomb;

#[test]
#[should_panic]
fn test_arm() {
let bomb = DropBomb::arm("hi :3");
drop(bomb); // <- armed bomb should explode when not defused
}

#[test]
fn test_defuse() {
let mut bomb = DropBomb::arm("hi :3");
bomb.defuse();
drop(bomb); // <- defused bomb should not explode
}
1 change: 1 addition & 0 deletions src/tools/run-make-support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod cc;
pub mod clang;
mod command;
pub mod diff;
mod drop_bomb;
pub mod llvm_readobj;
pub mod run;
pub mod rustc;
Expand Down

0 comments on commit a3feeb3

Please sign in to comment.