use antigen::{antigen, presents};
#[antigen(
name = "panic-in-drop",
category = AntigenCategory::FunctionalCorrectness,
fingerprint = r#"all_of([item = impl, impl_of_trait("Drop"), any_of([body_calls("unwrap"), body_calls("expect"), body_contains_macro("panic"), body_contains_macro("unreachable"), body_contains_macro("todo"), body_contains_macro("unimplemented")])])"#,
family = "drop-and-panic-discipline",
summary = "A real Drop impl whose body reaches a panic source (.unwrap()/.expect() or panic!/...). Panic-during-unwind aborts the process.",
references = ["https://doc.rust-lang.org/std/ops/trait.Drop.html#panics"],
)]
pub struct PanicInDrop;
struct PanickyGuard {
pending: Option<String>,
}
#[presents(PanicInDrop)]
impl Drop for PanickyGuard {
fn drop(&mut self) {
let _flushed = self.pending.take().unwrap();
}
}
struct SafeGuard {
pending: Option<String>,
}
#[presents(PanicInDrop)]
impl Drop for SafeGuard {
fn drop(&mut self) {
if let Some(_pending) = self.pending.take() {
}
}
}
struct NotReallyDrop {
pending: Option<String>,
}
impl NotReallyDrop {
fn drop(&mut self) {
let _ = self.pending.take().unwrap();
}
}
fn main() {
println!(
"antigen drop-panic example: see source for the affinity-pair + the inherent-drop spare."
);
println!(
"The bad Drop and the safe Drop are both #[presents]-marked (audit lists both; the safe one is FINGERPRINT-spared); the un-marked inherent `NotReallyDrop` is genuinely absent from scan. To read the bind/spare side by side, see antigen/tests/stdlib_family_fingerprints.rs."
);
let g = PanickyGuard {
pending: Some("data".to_string()),
};
drop(g);
let s = SafeGuard { pending: None };
drop(s);
let mut n = NotReallyDrop {
pending: Some("x".to_string()),
};
n.drop();
}