Skip to main content

bb_runtime/
fallible.rs

1//! Fallible `Vec::try_reserve_exact` wrapper used at engine
2//! ingress boundaries per
3//! `docs/internal/superpowers/specs/2026-06-24-engine-boundary-fallibility-and-backend-owned-tensors.md`
4//! §1 (Principle 1) + §2.1 sites S4 / S5.
5//!
6//! Production code calls `Vec::try_reserve_exact` directly through
7//! this single wrapper so the test harness can intercept the call
8//! and force a `TryReserveError` without monkey-patching the global
9//! allocator — keeps the `peak_alloc` / `dhat` test infrastructure
10//! free of conflicts.
11//!
12//! At runtime the wrapper is a zero-cost forward to
13//! `Vec::try_reserve_exact`; the `cfg(any(test, feature =
14//! "test-components"))` arm threads the injection state through a
15//! thread-local `Cell` so integration tests in the facade crate can
16//! drive the seam through the same one-shot fault primitive the
17//! crate-internal tests use.
18//!
19//! Hot path: one branch + one fn call (LLVM inlines the
20//! non-test arm).
21
22use std::collections::TryReserveError;
23
24/// Fallibly reserve `additional` slots in `vec`. Wraps
25/// `Vec::try_reserve_exact` so the boundary callers route through
26/// a single seam.
27///
28/// Under `cfg(any(test, feature = "test-components"))` callers may
29/// install a thread-local fault via [`testing::FailOnce`] which
30/// forces the next invocation to return a synthetic
31/// `TryReserveError`. Production builds (no test-components
32/// feature) never pay for the test branch — the function is
33/// `#[inline]` and the non-test arm is a direct delegate.
34#[inline]
35pub(crate) fn try_reserve_exact<T>(
36    vec: &mut Vec<T>,
37    additional: usize,
38) -> Result<(), TryReserveError> {
39    #[cfg(any(test, feature = "test-components"))]
40    {
41        if let Some(err) = testing::take_pending_fault() {
42            return Err(err);
43        }
44    }
45    vec.try_reserve_exact(additional)
46}
47
48#[cfg(any(test, feature = "test-components"))]
49pub mod testing {
50    //! Thread-local one-shot fault for the `try_reserve_exact` seam
51    //! in the enclosing module. Reachable under
52    //! `cfg(any(test, feature = "test-components"))` so integration
53    //! tests in the facade crate can drive the same seam the
54    //! crate-internal sibling tests use. `FailOnce::install` returns
55    //! an RAII guard that clears the thread-local on drop so a
56    //! panicking assertion does not poison the next test on the
57    //! thread.
58    //!
59    //! `try_reserve_exact` against `Vec<()>` is the canonical way to
60    //! mint a real `TryReserveError` without unsafe.
61    use std::cell::Cell;
62    use std::collections::TryReserveError;
63
64    thread_local! {
65        static PENDING_FAULT: Cell<Option<TryReserveError>> = const { Cell::new(None) };
66    }
67
68    /// Replace the thread-local fault with `Some(err)`. The next
69    /// `try_reserve_exact` call consumes it and returns `Err`.
70    pub fn arm_fault(err: TryReserveError) {
71        PENDING_FAULT.with(|cell| cell.set(Some(err)));
72    }
73
74    /// Read-and-clear the pending fault, if any. Internal to
75    /// `super::try_reserve_exact`.
76    pub(super) fn take_pending_fault() -> Option<TryReserveError> {
77        PENDING_FAULT.with(|cell| cell.take())
78    }
79
80    /// Synthesize a real `TryReserveError`. Asking for `usize::MAX`
81    /// elements of a 32-byte type overflows the allocation-size
82    /// computation in `Vec::try_reserve_exact` and returns
83    /// `Err(CapacityOverflow)` without actually touching the
84    /// allocator.
85    pub fn synthetic_err() -> TryReserveError {
86        // Sized payload so `additional * size_of::<T>()` overflows
87        // and the CapacityOverflow branch fires before any alloc.
88        let mut v: Vec<[u8; 32]> = Vec::new();
89        v.try_reserve_exact(usize::MAX)
90            .expect_err("usize::MAX reserve overflows TryReserveError")
91    }
92
93    /// RAII guard that arms a fault on construction and clears it
94    /// on drop. Use when a test might panic between arming and
95    /// consuming the fault.
96    pub struct FailOnce {
97        // No state needed; presence on stack guarantees drop runs.
98        _private: (),
99    }
100
101    impl FailOnce {
102        /// Install a one-shot fault. Returns the guard.
103        pub fn install() -> Self {
104            arm_fault(synthetic_err());
105            Self { _private: () }
106        }
107    }
108
109    impl Drop for FailOnce {
110        fn drop(&mut self) {
111            // Clear any uncon­sumed fault so leftover state does not
112            // poison the next test on this thread.
113            PENDING_FAULT.with(|cell| cell.set(None));
114        }
115    }
116}