From 5485642c4bf7f30e8e94b7b2bba29a3da3b7227e Mon Sep 17 00:00:00 2001 From: tanglearncode Date: Mon, 14 Sep 2026 02:42:37 +0800 Subject: [PATCH] Test signatures for functions that only accept 'static borrows Since the signature check change, a safe mock! or replace! signature cannot declare a 'static borrowed input, even for a function that only accepts 'static borrows; such functions use an unsafe fn signature. Only mock! had a test for that form, and neither macro documented the rejection. Two compile_fail doctests now show that a safe fn(&'static str) signature is rejected for such a function, one for mock! and one for replace!. tests/replacement.rs gains a test that replaces one through unsafe fn(&'static str) -> usize and checks that the replacement kept its 'static argument. --- src/lib.rs | 12 ++++++++++++ tests/replacement.rs | 24 ++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 6d75ed8..9350b4e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -429,6 +429,12 @@ impl Drop for Session { /// type Input = &'static str; /// shimforge::mock!(session, source, fn(Input) -> usize); /// ``` +/// A function that only accepts `'static` borrows needs an `unsafe fn` signature: +/// ```compile_fail +/// let mut session = shimforge::Session::new_global(); +/// fn source(value: &'static str) -> usize { value.len() } +/// shimforge::mock!(session, source, fn(&'static str) -> usize); +/// ``` /// A static result cannot become a shorter borrow: /// ```compile_fail /// let mut session = shimforge::Session::new_global(); @@ -559,6 +565,12 @@ fn finish(result: Result<(), Error>, fatal: fn() -> !) { /// fn source(value: &mut usize) { *value += 1; } /// shimforge::replace!(session, source => |_| (), fn(&'static mut usize)); /// ``` +/// A function that only accepts `'static` borrows needs an `unsafe fn` signature: +/// ```compile_fail +/// let mut session = shimforge::Session::new_global(); +/// fn source(value: &'static str) -> usize { value.len() } +/// shimforge::replace!(session, source => |value| value.len(), fn(&'static str) -> usize); +/// ``` /// A static result cannot become a shorter borrow: /// ```compile_fail /// let mut session = shimforge::Session::new_global(); diff --git a/tests/replacement.rs b/tests/replacement.rs index dc6a0ca..809b511 100644 --- a/tests/replacement.rs +++ b/tests/replacement.rs @@ -357,6 +357,30 @@ fn replacement_preserves_the_borrowed_argument_lifetime() { assert_eq!(borrowed(owned.as_str()), "b"); } +fn static_label(value: &'static str) -> usize { + value.len() +} + +static REMEMBERED_LABEL: Mutex> = Mutex::new(None); + +fn remember_label(value: &'static str) -> usize { + *REMEMBERED_LABEL.lock().unwrap() = Some(value); + 7 +} + +#[test] +fn static_only_inputs_are_replaced_through_an_unsafe_signature() { + let _serial = serial_test(); + let mut session = Session::new_global(); + // A safe signature is rejected for a function that only accepts 'static borrows, + // so it is declared unsafe, and the replacement may keep its argument. + replace!(session, static_label => remember_label, unsafe fn(&'static str) -> usize); + assert_eq!(static_label("kept"), 7); + assert_eq!(*REMEMBERED_LABEL.lock().unwrap(), Some("kept")); + session.restore(); + assert_eq!(static_label("kept"), 4); +} + struct Counter { value: i64, }