1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//! # Drop-and-Panic-Discipline Family — stdlib antigens (beta.2 voyage)
//!
//! Teardown footguns. The canonical one: a `Drop::drop` body that can panic. A
//! panic during `Drop` *while another panic is unwinding* aborts the process
//! (`panic=unwind`), and the destructor's own cleanup is skipped → leaked
//! resources even on the unwinding path. std got this wrong repeatedly.
//!
//! Biology cognate: **apoptosis gone wrong** — programmed cell death (`Drop`)
//! that itself triggers a catastrophic cascade (double-panic → abort) instead
//! of clean teardown.
//!
//! ## Antigen-category (ADR-028)
//!
//! `FunctionalCorrectness`: a panic in `Drop` produces a wrong *effect* (a
//! process abort / leaked resources during unwinding), not a wrong
//! representation.
//!
//! ## Relationship to the shipped `PanickingInDrop` example
//!
//! The `basic` example ships a `PanickingInDrop` antigen whose fingerprint is
//! `item = impl, any_of([body_contains_macro(...)])` — it over-fires on
//! non-`Drop` impls (its own comment flags "no operator for *this impl is for
//! the Drop trait* — that's a v2 enhancement") and misses `.unwrap()`-shaped
//! panics (macro-only). This member is that v2: `impl_of_trait("Drop")` for the
//! real-`Drop` precision + `body_calls` for the call-shaped panic coverage. The
//! example's shipped fingerprint is tightened in lock-step (the v2 tightening,
//! CHANGELOG'd).
use crateantigen;
// ============================================================================
// 1. PanicInDrop
// ============================================================================
/// A `Drop::drop` body that contains a reachable panic source — a process-abort
/// risk during unwinding.
///
/// **Where in the wild:** the canonical teardown footgun. A panic in `Drop`
/// during an in-flight unwind aborts the process; cleanup in the destructor is
/// then skipped → leaked resources even on `panic=unwind`.
///
/// **Tell:** an `impl Drop for T` (the real `Drop` trait, via `impl_of_trait("Drop")`
/// — NOT merely an inherent impl with a method named `drop`) whose body reaches a
/// panic source: a call-shaped `.unwrap()` / `.expect()` (`body_calls`) OR a
/// macro-shaped `panic!` / `unreachable!` / `todo!` / `unimplemented!`
/// (`body_contains_macro`). Covering both shapes is the point: a macro-only tell
/// (the shipped `PanickingInDrop`) silently misses the `.unwrap()` form, which is
/// the more common teardown panic.
///
/// **Tier:** **named** — the `impl_of_trait("Drop")` + reachable-panic-source
/// tell is precise, and the double-panic-on-unwind class is documented std
/// behaviour.
///
/// **Witness:** the drop body is panic-free, OR the risky op is wrapped to catch/
/// log, OR `std::thread::panicking()` is checked before the risky op (so the
/// destructor stays quiet during an in-flight unwind).
///
/// **Category:** `FunctionalCorrectness` — a panic in `Drop` produces a wrong
/// *effect* (a process abort / skipped cleanup during unwinding).
;