From ae57a8f973b8df1af108f59d230d8c4776c5138d Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Wed, 17 Apr 2024 11:29:34 +0300 Subject: [PATCH 1/3] Deprecate `as_mut()`, as using it invokes immediate UB --- src/mocking_utils.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/mocking_utils.rs b/src/mocking_utils.rs index d45f1cb..6504d52 100644 --- a/src/mocking_utils.rs +++ b/src/mocking_utils.rs @@ -1,3 +1,27 @@ +/// **This function is deprecated.** Using it invokes immediate undefined behavior, *even if the resulting reference is not used*. +/// If you need to convert `&` to `&mut`, use [`UnsafeCell`] instead. +/// +/// For example: +/// +/// ``` +/// #[mockable] +/// fn get_string(context: &mut Context) -> &mut String { +/// context.get_mut_string() +/// } +/// +/// #[test] +/// fn get_string_test() { +/// let mocked = std::cell::UnsafeCell::new("mocked".to_string()); +/// // MockResult::Return(&mut string) would fail +/// // SAFETY: We only call this function once, so there are no aliasing violations. +/// get_string.mock_raw(|_| MockResult::Return(unsafe { &mut *mocked.get() })); +/// +/// assert_eq!("mocked", get_string(&mut Context::default())); +/// } +/// ``` +/// +/// ----------------- +/// /// Converts non-mutable reference to a mutable one /// /// Allows creating multiple mutable references to a single item breaking Rust's safety policy. @@ -23,6 +47,10 @@ /// assert_eq!("mocked", get_string(&mut Context::default())); /// } /// ``` +/// +/// [`UnsafeCell`]: std::cell::UnsafeCell +#[deprecated = "this function invokes immediate undefined behavior and cannot be used correctly"] +#[allow(invalid_reference_casting)] pub unsafe fn as_mut(t_ref: &T) -> &mut T { &mut *(t_ref as *const T as *mut T) } From e6b009e9939b3d002abee00a68508fee08a16d5e Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Wed, 17 Apr 2024 12:28:21 +0300 Subject: [PATCH 2/3] Add a different, sound alternative to `as_mut()` `OnceMutCell` requires no unsafe code, and also does not invoke UB. --- src/mocking_utils.rs | 272 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 268 insertions(+), 4 deletions(-) diff --git a/src/mocking_utils.rs b/src/mocking_utils.rs index 6504d52..e65b8d7 100644 --- a/src/mocking_utils.rs +++ b/src/mocking_utils.rs @@ -1,5 +1,10 @@ +use std::cell::{Cell, UnsafeCell}; +use std::cmp::Ordering; +use std::error::Error; +use std::fmt; + /// **This function is deprecated.** Using it invokes immediate undefined behavior, *even if the resulting reference is not used*. -/// If you need to convert `&` to `&mut`, use [`UnsafeCell`] instead. +/// If you need to convert `&` to `&mut`, use [`OnceMutCell`] or [`UnsafeCell`] instead. /// /// For example: /// @@ -11,10 +16,9 @@ /// /// #[test] /// fn get_string_test() { -/// let mocked = std::cell::UnsafeCell::new("mocked".to_string()); +/// let mocked = OnceMutCell::new("mocked".to_string()); /// // MockResult::Return(&mut string) would fail -/// // SAFETY: We only call this function once, so there are no aliasing violations. -/// get_string.mock_raw(|_| MockResult::Return(unsafe { &mut *mocked.get() })); +/// get_string.mock_raw(|_| MockResult::Return(mocked.borrow())); /// /// assert_eq!("mocked", get_string(&mut Context::default())); /// } @@ -54,3 +58,263 @@ pub unsafe fn as_mut(t_ref: &T) -> &mut T { &mut *(t_ref as *const T as *mut T) } + +/// An error that is raised when you try to borrow a [`OnceMutCell`] that is already borrowed. +/// +/// If you have mutable access to the cell, call [`OnceMutCell::get_mut()`] instead. +/// +/// If you don't have mutable access to the cell at the borrow time but there is a time between the borrows +/// when you have mutable access to it, call [`OnceMutCell::reset()`] at that time. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +pub struct OnceMutCellBorrowedError; + +impl fmt::Display for OnceMutCellBorrowedError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + #[allow(deprecated)] + f.write_str(self.description()) + } +} + +impl std::error::Error for OnceMutCellBorrowedError { + #[inline] + fn description(&self) -> &str { + "`OnceMutCell` already borrowed" + } +} + +/// A cell that can be mutably borrowed, but only once. +/// +/// The cell can be borrowed more than once if you have a mutable access to it by [resetting] it. +/// +/// [resetting]: OnceMutCell::reset +/// +/// # Example +/// +/// ``` +/// # use mocktopus::mocking_utils::OnceMutCell; +/// let mut cell = OnceMutCell::new(123_i32); +/// +/// let v1: &mut i32 = cell.borrow(); +/// *v1 = 456; +/// +/// cell.reset(); +/// +/// let v2 = cell.borrow(); +/// assert_eq!(*v2, 456); +/// ``` +pub struct OnceMutCell { + borrowed: Cell, + value: UnsafeCell, +} + +impl OnceMutCell { + /// Creates a new `OnceMutCell` with the specified initial value. + #[inline] + pub const fn new(value: T) -> Self { + Self { + borrowed: Cell::new(false), + value: UnsafeCell::new(value), + } + } + + /// Consumes the cell, returning its value. + pub fn into_inner(self) -> T { + self.value.into_inner() + } +} + +impl OnceMutCell { + /// Gives an access to the cell's contents *when you have a mutable reference*. + /// + /// If you only have a shared reference, call [`borrow()`] instead. + /// + /// **Note:** Even though this takes a mutable reference (that serves as a proof there are no borrows of the cell), + /// this *does not* allow further `borrow()`s if the cell was borrowed already. If you need that, also call [`reset()`]. + /// + /// [`borrow()`]: OnceMutCell::borrow + /// [`reset()`]: OnceMutCell::reset + #[inline] + pub fn get_mut(&mut self) -> &mut T { + self.value.get_mut() + } + + /// Allows further borrows of the cell. + /// + /// This can be done safely since this method takes a mutable reference, which serves as a proof there are no + /// outstanding borrows. + #[inline] + pub fn reset(&mut self) { + self.borrowed.set(false); + } + + /// Tries to borrow the cell, returning an error if it is already borrowed. + /// + /// For a panicking version see [`borrow()`]. + /// + /// [`borrow()`]: OnceMutCell::borrow + #[inline] + pub fn try_borrow(&self) -> Result<&mut T, OnceMutCellBorrowedError> { + if self.borrowed.get() { + return Err(OnceMutCellBorrowedError); + } + + self.borrowed.set(true); + // SAFETY: We only allow one borrow (`self.borrowed` ensures that), and we can only get more borrows + // if we `reset()`, which requires a mutable reference to ensure there are no references to our value. + Ok(unsafe { &mut *self.value.get() }) + } + + /// Tries to borrow the cell, panicking if it is already borrowed. + /// + /// For a fallible version see [`try_borrow()`]. + /// + /// # Panics + /// + /// Panics if the cell is already borrowed. + /// + /// [`try_borrow()`]: OnceMutCell::try_borrow + #[inline] + #[track_caller] + pub fn borrow(&self) -> &mut T { + match self.try_borrow() { + Ok(value) => value, + Err(_) => panic_already_borrowed(), + } + } + + /// Tries to borrow the cell. If it succeeds, calls the callback and returns its return value. If it fails, returns an error. + /// After the callback has finished, resets the cell. + /// + /// This enables pattern that are impossible to express with [`try_borrow()`], since this essentially resets the cell with a shared + /// reference (but this is safe, since we set the cell as borrowed and we finished borrowing it). + /// + /// On the other hand, the closure's return value cannot borrow from the cell. + /// + /// For a panicking version see [`with()`]. + /// + /// [`try_borrow()`]: OnceMutCell::try_borrow + /// [`with()`]: OnceMutCell::with + #[inline] + pub fn try_with R>( + &self, + callback: F, + ) -> Result { + struct Guard<'a, T: ?Sized>(&'a OnceMutCell); + impl Drop for Guard<'_, T> { + #[inline] + fn drop(&mut self) { + self.0.borrowed.set(false); + } + } + + if self.borrowed.get() { + return Err(OnceMutCellBorrowedError); + } + + let guard = Guard(self); + guard.0.borrowed.set(true); + // SAFETY: We only allow one borrow (`self.borrowed` ensures that), and we can only get more borrows + // if we `reset()`, which requires a mutable reference to ensure there are no references to our value. + Ok(callback(unsafe { &mut *guard.0.value.get() })) + } + + /// Tries to borrow the cell. If it succeeds, calls the callback and returns its return value. If it fails, panics. + /// After the callback has finished, resets the cell. + /// + /// This enables pattern that are impossible to express with [`borrow()`], since this essentially resets the cell with a shared + /// reference (but this is safe, since we set the cell as borrowed and we finished borrowing it). + /// + /// On the other hand, the closure's return value cannot borrow from the cell. + /// + /// For a fallible version see [`try_with()`]. + /// + /// # Panics + /// + /// Panics if the cell is already borrowed. + /// + /// [`borrow()`]: OnceMutCell::borrow + /// [`try_with()`]: OnceMutCell::try_with + #[inline] + #[track_caller] + pub fn with R>(&self, callback: F) -> R { + match self.try_with(callback) { + Ok(result) => result, + Err(_) => panic_already_borrowed(), + } + } +} + +#[cold] +#[track_caller] +fn panic_already_borrowed() -> ! { + panic!("`OnceMutCell` already borrowed") +} + +impl Clone for OnceMutCell { + /// # Panics + /// + /// Panics if the cell is already borrowed. + #[inline] + #[track_caller] + fn clone(&self) -> Self { + Self::new(self.with(|v| v.clone())) + } +} + +impl Default for OnceMutCell { + #[inline] + fn default() -> Self { + Self::new(T::default()) + } +} + +impl From for OnceMutCell { + #[inline] + fn from(value: T) -> Self { + Self::new(value) + } +} + +impl PartialEq for OnceMutCell { + /// # Panics + /// + /// Panics if the cell is already borrowed. + #[inline] + #[track_caller] + fn eq(&self, other: &Self) -> bool { + self.with(|this| other.with(|other| this == other)) + } +} + +impl Eq for OnceMutCell {} + +impl PartialOrd for OnceMutCell { + /// # Panics + /// + /// Panics if the cell is already borrowed. + #[inline] + #[track_caller] + fn partial_cmp(&self, other: &Self) -> Option { + self.with(|this| other.with(|other| (*this).partial_cmp(&*other))) + } +} + +impl Ord for OnceMutCell { + /// # Panics + /// + /// Panics if the cell is already borrowed. + #[inline] + #[track_caller] + fn cmp(&self, other: &Self) -> Ordering { + self.with(|this| other.with(|other| (*this).cmp(&*other))) + } +} + +impl fmt::Debug for OnceMutCell { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.try_with(|value| f.debug_tuple("OnceMutCell").field(&value).finish()) { + Ok(result) => result, + Err(_) => f.pad("OnceMutCell()"), + } + } +} From c07999e526f56c2a48619d88d5283dd7550de7fc Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Wed, 17 Apr 2024 12:28:46 +0300 Subject: [PATCH 3/3] Use the new `OnceMutCell` instead of `as_mut()` in tests --- tests/mocking_methods/when_struct_generic_method_generic.rs | 6 +++--- tests/mocking_methods/when_struct_generic_method_regular.rs | 6 +++--- tests/mocking_methods/when_struct_regular_method_generic.rs | 6 +++--- tests/mocking_methods/when_struct_regular_method_regular.rs | 6 +++--- .../when_struct_generic_method_generic_async.rs | 6 +++--- .../when_struct_generic_method_regular_async.rs | 6 +++--- .../when_struct_regular_method_generic_async.rs | 6 +++--- .../when_struct_regular_method_regular_async.rs | 6 +++--- .../when_trait_generic_struct_generic_method_generic.rs | 6 +++--- .../when_trait_generic_struct_generic_method_regular.rs | 6 +++--- .../when_trait_generic_struct_regular_method_generic.rs | 6 +++--- .../when_trait_generic_struct_regular_method_regular.rs | 6 +++--- .../when_trait_regular_struct_generic_method_generic.rs | 6 +++--- .../when_trait_regular_struct_generic_method_regular.rs | 6 +++--- .../when_trait_regular_struct_regular_method_generic.rs | 6 +++--- .../when_trait_regular_struct_regular_method_regular.rs | 6 +++--- .../when_trait_generic_struct_generic_method_generic.rs | 6 +++--- .../when_trait_generic_struct_generic_method_regular.rs | 6 +++--- .../when_trait_generic_struct_regular_method_generic.rs | 6 +++--- .../when_trait_generic_struct_regular_method_regular.rs | 6 +++--- .../when_trait_regular_struct_generic_method_generic.rs | 6 +++--- .../when_trait_regular_struct_generic_method_regular.rs | 6 +++--- .../when_trait_regular_struct_regular_method_generic.rs | 6 +++--- .../when_trait_regular_struct_regular_method_regular.rs | 6 +++--- 24 files changed, 72 insertions(+), 72 deletions(-) diff --git a/tests/mocking_methods/when_struct_generic_method_generic.rs b/tests/mocking_methods/when_struct_generic_method_generic.rs index 7c90870..a8a36a5 100644 --- a/tests/mocking_methods/when_struct_generic_method_generic.rs +++ b/tests/mocking_methods/when_struct_generic_method_generic.rs @@ -117,17 +117,17 @@ mod and_method_is_ref_mut_method { #[test] fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2u8); - let struct_3 = Struct(3u8); + let mut struct_3 = OnceMutCell::new(Struct(3u8)); let mut struct_4 = Struct(4u8); let mut struct_str = Struct("abc"); unsafe { Struct::::ref_mut_method:: - .mock_raw(|_, b, c| MockResult::Continue((as_mut(&struct_3), !b, c + 1.))); + .mock_raw(|_, b, c| MockResult::Continue((struct_3.borrow(), !b, c + 1.))); } assert_eq!("0 false 2.5", struct_2.ref_mut_method(true, 1.5f32)); assert_eq!(2, struct_2.0); - assert_eq!(0, struct_3.0); + assert_eq!(0, struct_3.get_mut().0); assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc")); assert_eq!(0, struct_4.0); assert_eq!(" true 1.5", struct_str.ref_mut_method(true, 1.5)); diff --git a/tests/mocking_methods/when_struct_generic_method_regular.rs b/tests/mocking_methods/when_struct_generic_method_regular.rs index c340054..b372127 100644 --- a/tests/mocking_methods/when_struct_generic_method_regular.rs +++ b/tests/mocking_methods/when_struct_generic_method_regular.rs @@ -106,16 +106,16 @@ mod and_method_is_ref_mut_method { #[test] fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2u8); - let struct_3 = Struct(3u8); + let mut struct_3 = OnceMutCell::new(Struct(3u8)); let mut struct_str = Struct("str"); unsafe { Struct::::ref_mut_method - .mock_raw(|_, b| MockResult::Continue((as_mut(&struct_3), !b))); + .mock_raw(|_, b| MockResult::Continue((struct_3.borrow(), !b))); } assert_eq!("0 false", struct_2.ref_mut_method(true)); assert_eq!(2, struct_2.0); - assert_eq!(0, struct_3.0); + assert_eq!(0, struct_3.get_mut().0); assert_eq!(" true", struct_str.ref_mut_method(true)); assert_eq!("", struct_str.0); } diff --git a/tests/mocking_methods/when_struct_regular_method_generic.rs b/tests/mocking_methods/when_struct_regular_method_generic.rs index 97b6a0c..06771a6 100644 --- a/tests/mocking_methods/when_struct_regular_method_generic.rs +++ b/tests/mocking_methods/when_struct_regular_method_generic.rs @@ -108,16 +108,16 @@ mod and_method_is_ref_mut_method { #[test] fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2); - let struct_3 = Struct(3); + let mut struct_3 = OnceMutCell::new(Struct(3)); let mut struct_4 = Struct(4); unsafe { Struct::ref_mut_method:: - .mock_raw(|_, b, c| MockResult::Continue((as_mut(&struct_3), !b, c + 1.))); + .mock_raw(|_, b, c| MockResult::Continue((struct_3.borrow(), !b, c + 1.))); } assert_eq!("6 false 2.5", struct_2.ref_mut_method(true, 1.5f32)); assert_eq!(2, struct_2.0); - assert_eq!(6, struct_3.0); + assert_eq!(6, struct_3.get_mut().0); assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc")); assert_eq!(8, struct_4.0); } diff --git a/tests/mocking_methods/when_struct_regular_method_regular.rs b/tests/mocking_methods/when_struct_regular_method_regular.rs index 6c2b45a..af5cb28 100644 --- a/tests/mocking_methods/when_struct_regular_method_regular.rs +++ b/tests/mocking_methods/when_struct_regular_method_regular.rs @@ -96,14 +96,14 @@ mod and_method_is_ref_mut_method { #[test] fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2); - let struct_3 = Struct(3); + let mut struct_3 = OnceMutCell::new(Struct(3)); unsafe { - Struct::ref_mut_method.mock_raw(|_, b| MockResult::Continue((as_mut(&struct_3), !b))); + Struct::ref_mut_method.mock_raw(|_, b| MockResult::Continue((struct_3.borrow(), !b))); } assert_eq!("6 false", struct_2.ref_mut_method(true)); assert_eq!(2, struct_2.0); - assert_eq!(6, struct_3.0); + assert_eq!(6, struct_3.get_mut().0); } #[test] diff --git a/tests/mocking_methods_async/when_struct_generic_method_generic_async.rs b/tests/mocking_methods_async/when_struct_generic_method_generic_async.rs index a5b9e43..3624920 100644 --- a/tests/mocking_methods_async/when_struct_generic_method_generic_async.rs +++ b/tests/mocking_methods_async/when_struct_generic_method_generic_async.rs @@ -133,17 +133,17 @@ mod and_method_is_ref_mut_method { #[tokio::test] async fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2u8); - let struct_3 = Struct(3u8); + let mut struct_3 = OnceMutCell::new(Struct(3u8)); let mut struct_4 = Struct(4u8); let mut struct_str = Struct("abc"); unsafe { Struct::::ref_mut_method:: - .mock_raw(|_, b, c| MockResult::Continue((as_mut(&struct_3), !b, c + 1.))); + .mock_raw(|_, b, c| MockResult::Continue((struct_3.borrow(), !b, c + 1.))); } assert_eq!("0 false 2.5", struct_2.ref_mut_method(true, 1.5f32).await); assert_eq!(2, struct_2.0); - assert_eq!(0, struct_3.0); + assert_eq!(0, struct_3.get_mut().0); assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc").await); assert_eq!(0, struct_4.0); assert_eq!(" true 1.5", struct_str.ref_mut_method(true, 1.5).await); diff --git a/tests/mocking_methods_async/when_struct_generic_method_regular_async.rs b/tests/mocking_methods_async/when_struct_generic_method_regular_async.rs index ce66a9d..3b518e9 100644 --- a/tests/mocking_methods_async/when_struct_generic_method_regular_async.rs +++ b/tests/mocking_methods_async/when_struct_generic_method_regular_async.rs @@ -108,16 +108,16 @@ mod and_method_is_ref_mut_method { #[tokio::test] async fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2u8); - let struct_3 = Struct(3u8); + let mut struct_3 = OnceMutCell::new(Struct(3u8)); let mut struct_str = Struct("str"); unsafe { Struct::::ref_mut_method - .mock_raw(|_, b| MockResult::Continue((as_mut(&struct_3), !b))); + .mock_raw(|_, b| MockResult::Continue((struct_3.borrow(), !b))); } assert_eq!("0 false", struct_2.ref_mut_method(true).await); assert_eq!(2, struct_2.0); - assert_eq!(0, struct_3.0); + assert_eq!(0, struct_3.get_mut().0); assert_eq!(" true", struct_str.ref_mut_method(true).await); assert_eq!("", struct_str.0); } diff --git a/tests/mocking_methods_async/when_struct_regular_method_generic_async.rs b/tests/mocking_methods_async/when_struct_regular_method_generic_async.rs index 1a1f27c..a016e76 100644 --- a/tests/mocking_methods_async/when_struct_regular_method_generic_async.rs +++ b/tests/mocking_methods_async/when_struct_regular_method_generic_async.rs @@ -112,16 +112,16 @@ mod and_method_is_ref_mut_method { #[tokio::test] async fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2); - let struct_3 = Struct(3); + let mut struct_3 = OnceMutCell::new(Struct(3)); let mut struct_4 = Struct(4); unsafe { Struct::ref_mut_method:: - .mock_raw(|_, b, c| MockResult::Continue((as_mut(&struct_3), !b, c + 1.))); + .mock_raw(|_, b, c| MockResult::Continue((struct_3.borrow(), !b, c + 1.))); } assert_eq!("6 false 2.5", struct_2.ref_mut_method(true, 1.5f32).await); assert_eq!(2, struct_2.0); - assert_eq!(6, struct_3.0); + assert_eq!(6, struct_3.get_mut().0); assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc").await); assert_eq!(8, struct_4.0); } diff --git a/tests/mocking_methods_async/when_struct_regular_method_regular_async.rs b/tests/mocking_methods_async/when_struct_regular_method_regular_async.rs index 3eae79f..1f246cf 100644 --- a/tests/mocking_methods_async/when_struct_regular_method_regular_async.rs +++ b/tests/mocking_methods_async/when_struct_regular_method_regular_async.rs @@ -99,14 +99,14 @@ mod and_async_method_is_ref_mut_method { #[tokio::test] async fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2); - let struct_3 = Struct(3); + let mut struct_3 = OnceMutCell::new(Struct(3)); unsafe { - Struct::ref_mut_method.mock_raw(|_, b| MockResult::Continue((as_mut(&struct_3), !b))); + Struct::ref_mut_method.mock_raw(|_, b| MockResult::Continue((struct_3.borrow(), !b))); } assert_eq!("6 false", struct_2.ref_mut_method(true).await); assert_eq!(2, struct_2.0); - assert_eq!(6, struct_3.0); + assert_eq!(6, struct_3.get_mut().0); } #[tokio::test] diff --git a/tests/mocking_trait_defaults/when_trait_generic_struct_generic_method_generic.rs b/tests/mocking_trait_defaults/when_trait_generic_struct_generic_method_generic.rs index 76a0a9e..a546dfc 100644 --- a/tests/mocking_trait_defaults/when_trait_generic_struct_generic_method_generic.rs +++ b/tests/mocking_trait_defaults/when_trait_generic_struct_generic_method_generic.rs @@ -213,19 +213,19 @@ mod and_method_is_ref_mut_method { #[test] fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2u8); - let struct_3 = Struct(3u8); + let mut struct_3 = OnceMutCell::new(Struct(3u8)); let mut struct_4 = Struct(4u8); let mut struct_str = Struct("abc"); let mut struct_5 = Struct(5u8); unsafe { as Trait>::ref_mut_method::.mock_raw(|_, b, c, d| { - MockResult::Continue((as_mut(&struct_3), !b, c + 1., d.to_ascii_uppercase())) + MockResult::Continue((struct_3.borrow(), !b, c + 1., d.to_ascii_uppercase())) }); } assert_eq!("0 false 2.5 A", struct_2.ref_mut_method(true, 1.5f32, 'a')); assert_eq!(2, struct_2.0); - assert_eq!(0, struct_3.0); + assert_eq!(0, struct_3.get_mut().0); assert_eq!("0 true abc a", struct_4.ref_mut_method(true, "abc", 'a')); assert_eq!(0, struct_4.0); assert_eq!(" true 1.5 a", struct_str.ref_mut_method(true, 1.5, 'a')); diff --git a/tests/mocking_trait_defaults/when_trait_generic_struct_generic_method_regular.rs b/tests/mocking_trait_defaults/when_trait_generic_struct_generic_method_regular.rs index 586ccce..1f79dcb 100644 --- a/tests/mocking_trait_defaults/when_trait_generic_struct_generic_method_regular.rs +++ b/tests/mocking_trait_defaults/when_trait_generic_struct_generic_method_regular.rs @@ -131,18 +131,18 @@ mod and_method_is_ref_mut_method { #[test] fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2u8); - let struct_3 = Struct(3u8); + let mut struct_3 = OnceMutCell::new(Struct(3u8)); let mut struct_str = Struct("str"); let mut struct_4 = Struct(4u8); unsafe { as Trait>::ref_mut_method.mock_raw(|_, b, c| { - MockResult::Continue((as_mut(&struct_3), !b, c.to_ascii_uppercase())) + MockResult::Continue((struct_3.borrow(), !b, c.to_ascii_uppercase())) }); } assert_eq!("0 false A", struct_2.ref_mut_method(true, 'a')); assert_eq!(2, struct_2.0); - assert_eq!(0, struct_3.0); + assert_eq!(0, struct_3.get_mut().0); assert_eq!(" true a", struct_str.ref_mut_method(true, 'a')); assert_eq!("", struct_str.0); assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc")); diff --git a/tests/mocking_trait_defaults/when_trait_generic_struct_regular_method_generic.rs b/tests/mocking_trait_defaults/when_trait_generic_struct_regular_method_generic.rs index 2372f23..2d13fee 100644 --- a/tests/mocking_trait_defaults/when_trait_generic_struct_regular_method_generic.rs +++ b/tests/mocking_trait_defaults/when_trait_generic_struct_regular_method_generic.rs @@ -165,18 +165,18 @@ mod and_method_is_ref_mut_method { #[test] fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2); - let struct_3 = Struct(3); + let mut struct_3 = OnceMutCell::new(Struct(3)); let mut struct_4 = Struct(4); let mut struct_5 = Struct(5); unsafe { >::ref_mut_method::.mock_raw(|_, b, c, d| { - MockResult::Continue((as_mut(&struct_3), !b, c + 1., d.to_ascii_uppercase())) + MockResult::Continue((struct_3.borrow(), !b, c + 1., d.to_ascii_uppercase())) }); } assert_eq!("6 false 2.5 A", struct_2.ref_mut_method(true, 1.5f32, 'a')); assert_eq!(2, struct_2.0); - assert_eq!(6, struct_3.0); + assert_eq!(6, struct_3.get_mut().0); assert_eq!("8 true abc a", struct_4.ref_mut_method(true, "abc", 'a')); assert_eq!(8, struct_4.0); assert_eq!( diff --git a/tests/mocking_trait_defaults/when_trait_generic_struct_regular_method_regular.rs b/tests/mocking_trait_defaults/when_trait_generic_struct_regular_method_regular.rs index d10595d..b55a283 100644 --- a/tests/mocking_trait_defaults/when_trait_generic_struct_regular_method_regular.rs +++ b/tests/mocking_trait_defaults/when_trait_generic_struct_regular_method_regular.rs @@ -122,17 +122,17 @@ mod and_method_is_ref_mut_method { #[test] fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2); - let struct_3 = Struct(3); + let mut struct_3 = OnceMutCell::new(Struct(3)); let mut struct_4 = Struct(4); unsafe { >::ref_mut_method.mock_raw(|_, b, c| { - MockResult::Continue((as_mut(&struct_3), !b, c.to_ascii_uppercase())) + MockResult::Continue((struct_3.borrow(), !b, c.to_ascii_uppercase())) }); } assert_eq!("6 false A", struct_2.ref_mut_method(true, 'a')); assert_eq!(2, struct_2.0); - assert_eq!(6, struct_3.0); + assert_eq!(6, struct_3.get_mut().0); assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc")); assert_eq!(8, struct_4.0); } diff --git a/tests/mocking_trait_defaults/when_trait_regular_struct_generic_method_generic.rs b/tests/mocking_trait_defaults/when_trait_regular_struct_generic_method_generic.rs index ccb843b..d49d572 100644 --- a/tests/mocking_trait_defaults/when_trait_regular_struct_generic_method_generic.rs +++ b/tests/mocking_trait_defaults/when_trait_regular_struct_generic_method_generic.rs @@ -130,17 +130,17 @@ mod and_method_is_ref_mut_method { #[test] fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2u8); - let struct_3 = Struct(3u8); + let mut struct_3 = OnceMutCell::new(Struct(3u8)); let mut struct_4 = Struct(4u8); let mut struct_str = Struct("abc"); unsafe { Struct::::ref_mut_method:: - .mock_raw(|_, b, c| MockResult::Continue((as_mut(&struct_3), !b, c + 1.))); + .mock_raw(|_, b, c| MockResult::Continue((struct_3.borrow(), !b, c + 1.))); } assert_eq!("0 false 2.5", struct_2.ref_mut_method(true, 1.5f32)); assert_eq!(2, struct_2.0); - assert_eq!(0, struct_3.0); + assert_eq!(0, struct_3.get_mut().0); assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc")); assert_eq!(0, struct_4.0); assert_eq!(" true 1.5", struct_str.ref_mut_method(true, 1.5)); diff --git a/tests/mocking_trait_defaults/when_trait_regular_struct_generic_method_regular.rs b/tests/mocking_trait_defaults/when_trait_regular_struct_generic_method_regular.rs index 6660ab4..4eb7549 100644 --- a/tests/mocking_trait_defaults/when_trait_regular_struct_generic_method_regular.rs +++ b/tests/mocking_trait_defaults/when_trait_regular_struct_generic_method_regular.rs @@ -119,16 +119,16 @@ mod and_method_is_ref_mut_method { #[test] fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2u8); - let struct_3 = Struct(3u8); + let mut struct_3 = OnceMutCell::new(Struct(3u8)); let mut struct_str = Struct("str"); unsafe { Struct::::ref_mut_method - .mock_raw(|_, b| MockResult::Continue((as_mut(&struct_3), !b))); + .mock_raw(|_, b| MockResult::Continue((struct_3.borrow(), !b))); } assert_eq!("0 false", struct_2.ref_mut_method(true)); assert_eq!(2, struct_2.0); - assert_eq!(0, struct_3.0); + assert_eq!(0, struct_3.get_mut().0); assert_eq!(" true", struct_str.ref_mut_method(true)); assert_eq!("", struct_str.0); } diff --git a/tests/mocking_trait_defaults/when_trait_regular_struct_regular_method_generic.rs b/tests/mocking_trait_defaults/when_trait_regular_struct_regular_method_generic.rs index 93776f6..b16cb00 100644 --- a/tests/mocking_trait_defaults/when_trait_regular_struct_regular_method_generic.rs +++ b/tests/mocking_trait_defaults/when_trait_regular_struct_regular_method_generic.rs @@ -121,16 +121,16 @@ mod and_method_is_ref_mut_method { #[test] fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2); - let struct_3 = Struct(3); + let mut struct_3 = OnceMutCell::new(Struct(3)); let mut struct_4 = Struct(4); unsafe { Struct::ref_mut_method:: - .mock_raw(|_, b, c| MockResult::Continue((as_mut(&struct_3), !b, c + 1.))); + .mock_raw(|_, b, c| MockResult::Continue((struct_3.borrow(), !b, c + 1.))); } assert_eq!("6 false 2.5", struct_2.ref_mut_method(true, 1.5f32)); assert_eq!(2, struct_2.0); - assert_eq!(6, struct_3.0); + assert_eq!(6, struct_3.get_mut().0); assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc")); assert_eq!(8, struct_4.0); } diff --git a/tests/mocking_trait_defaults/when_trait_regular_struct_regular_method_regular.rs b/tests/mocking_trait_defaults/when_trait_regular_struct_regular_method_regular.rs index 97fff1a..51cb362 100644 --- a/tests/mocking_trait_defaults/when_trait_regular_struct_regular_method_regular.rs +++ b/tests/mocking_trait_defaults/when_trait_regular_struct_regular_method_regular.rs @@ -109,14 +109,14 @@ mod and_method_is_ref_mut_method { #[test] fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2); - let struct_3 = Struct(3); + let mut struct_3 = OnceMutCell::new(Struct(3)); unsafe { - Struct::ref_mut_method.mock_raw(|_, b| MockResult::Continue((as_mut(&struct_3), !b))); + Struct::ref_mut_method.mock_raw(|_, b| MockResult::Continue((struct_3.borrow(), !b))); } assert_eq!("6 false", struct_2.ref_mut_method(true)); assert_eq!(2, struct_2.0); - assert_eq!(6, struct_3.0); + assert_eq!(6, struct_3.get_mut().0); } #[test] diff --git a/tests/mocking_traits/when_trait_generic_struct_generic_method_generic.rs b/tests/mocking_traits/when_trait_generic_struct_generic_method_generic.rs index 6165fa2..75bbc29 100644 --- a/tests/mocking_traits/when_trait_generic_struct_generic_method_generic.rs +++ b/tests/mocking_traits/when_trait_generic_struct_generic_method_generic.rs @@ -194,19 +194,19 @@ mod and_method_is_ref_mut_method { #[test] fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2u8); - let struct_3 = Struct(3u8); + let mut struct_3 = OnceMutCell::new(Struct(3u8)); let mut struct_4 = Struct(4u8); let mut struct_str = Struct("abc"); let mut struct_5 = Struct(5u8); unsafe { as Trait>::ref_mut_method::.mock_raw(|_, b, c, d| { - MockResult::Continue((as_mut(&struct_3), !b, c + 1., d.to_ascii_uppercase())) + MockResult::Continue((struct_3.borrow(), !b, c + 1., d.to_ascii_uppercase())) }); } assert_eq!("0 false 2.5 A", struct_2.ref_mut_method(true, 1.5f32, 'a')); assert_eq!(2, struct_2.0); - assert_eq!(0, struct_3.0); + assert_eq!(0, struct_3.get_mut().0); assert_eq!("0 true abc a", struct_4.ref_mut_method(true, "abc", 'a')); assert_eq!(0, struct_4.0); assert_eq!(" true 1.5 a", struct_str.ref_mut_method(true, 1.5, 'a')); diff --git a/tests/mocking_traits/when_trait_generic_struct_generic_method_regular.rs b/tests/mocking_traits/when_trait_generic_struct_generic_method_regular.rs index ac48f0a..7a6a6e6 100644 --- a/tests/mocking_traits/when_trait_generic_struct_generic_method_regular.rs +++ b/tests/mocking_traits/when_trait_generic_struct_generic_method_regular.rs @@ -125,18 +125,18 @@ mod and_method_is_ref_mut_method { #[test] fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2u8); - let struct_3 = Struct(3u8); + let mut struct_3 = OnceMutCell::new(Struct(3u8)); let mut struct_str = Struct("str"); let mut struct_4 = Struct(4u8); unsafe { as Trait>::ref_mut_method.mock_raw(|_, b, c| { - MockResult::Continue((as_mut(&struct_3), !b, c.to_ascii_uppercase())) + MockResult::Continue((struct_3.borrow(), !b, c.to_ascii_uppercase())) }); } assert_eq!("0 false A", struct_2.ref_mut_method(true, 'a')); assert_eq!(2, struct_2.0); - assert_eq!(0, struct_3.0); + assert_eq!(0, struct_3.get_mut().0); assert_eq!(" true a", struct_str.ref_mut_method(true, 'a')); assert_eq!("", struct_str.0); assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc")); diff --git a/tests/mocking_traits/when_trait_generic_struct_regular_method_generic.rs b/tests/mocking_traits/when_trait_generic_struct_regular_method_generic.rs index 2fc8530..690bfdb 100644 --- a/tests/mocking_traits/when_trait_generic_struct_regular_method_generic.rs +++ b/tests/mocking_traits/when_trait_generic_struct_regular_method_generic.rs @@ -146,18 +146,18 @@ mod and_method_is_ref_mut_method { #[test] fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2); - let struct_3 = Struct(3); + let mut struct_3 = OnceMutCell::new(Struct(3)); let mut struct_4 = Struct(4); let mut struct_5 = Struct(5); unsafe { >::ref_mut_method::.mock_raw(|_, b, c, d| { - MockResult::Continue((as_mut(&struct_3), !b, c + 1., d.to_ascii_uppercase())) + MockResult::Continue((struct_3.borrow(), !b, c + 1., d.to_ascii_uppercase())) }); } assert_eq!("6 false 2.5 A", struct_2.ref_mut_method(true, 1.5f32, 'a')); assert_eq!(2, struct_2.0); - assert_eq!(6, struct_3.0); + assert_eq!(6, struct_3.get_mut().0); assert_eq!("8 true abc a", struct_4.ref_mut_method(true, "abc", 'a')); assert_eq!(8, struct_4.0); assert_eq!( diff --git a/tests/mocking_traits/when_trait_generic_struct_regular_method_regular.rs b/tests/mocking_traits/when_trait_generic_struct_regular_method_regular.rs index b89129a..5d619b7 100644 --- a/tests/mocking_traits/when_trait_generic_struct_regular_method_regular.rs +++ b/tests/mocking_traits/when_trait_generic_struct_regular_method_regular.rs @@ -116,17 +116,17 @@ mod and_method_is_ref_mut_method { #[test] fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2); - let struct_3 = Struct(3); + let mut struct_3 = OnceMutCell::new(Struct(3)); let mut struct_4 = Struct(4); unsafe { >::ref_mut_method.mock_raw(|_, b, c| { - MockResult::Continue((as_mut(&struct_3), !b, c.to_ascii_uppercase())) + MockResult::Continue((struct_3.borrow(), !b, c.to_ascii_uppercase())) }); } assert_eq!("6 false A", struct_2.ref_mut_method(true, 'a')); assert_eq!(2, struct_2.0); - assert_eq!(6, struct_3.0); + assert_eq!(6, struct_3.get_mut().0); assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc")); assert_eq!(8, struct_4.0); } diff --git a/tests/mocking_traits/when_trait_regular_struct_generic_method_generic.rs b/tests/mocking_traits/when_trait_regular_struct_generic_method_generic.rs index 9158a9f..41efbd4 100644 --- a/tests/mocking_traits/when_trait_regular_struct_generic_method_generic.rs +++ b/tests/mocking_traits/when_trait_regular_struct_generic_method_generic.rs @@ -124,17 +124,17 @@ mod and_method_is_ref_mut_method { #[test] fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2u8); - let struct_3 = Struct(3u8); + let mut struct_3 = OnceMutCell::new(Struct(3u8)); let mut struct_4 = Struct(4u8); let mut struct_str = Struct("abc"); unsafe { Struct::::ref_mut_method:: - .mock_raw(|_, b, c| MockResult::Continue((as_mut(&struct_3), !b, c + 1.))); + .mock_raw(|_, b, c| MockResult::Continue((struct_3.borrow(), !b, c + 1.))); } assert_eq!("0 false 2.5", struct_2.ref_mut_method(true, 1.5f32)); assert_eq!(2, struct_2.0); - assert_eq!(0, struct_3.0); + assert_eq!(0, struct_3.get_mut().0); assert_eq!("0 true abc", struct_4.ref_mut_method(true, "abc")); assert_eq!(0, struct_4.0); assert_eq!(" true 1.5", struct_str.ref_mut_method(true, 1.5)); diff --git a/tests/mocking_traits/when_trait_regular_struct_generic_method_regular.rs b/tests/mocking_traits/when_trait_regular_struct_generic_method_regular.rs index 86472ca..a6be7b2 100644 --- a/tests/mocking_traits/when_trait_regular_struct_generic_method_regular.rs +++ b/tests/mocking_traits/when_trait_regular_struct_generic_method_regular.rs @@ -113,16 +113,16 @@ mod and_method_is_ref_mut_method { #[test] fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2u8); - let struct_3 = Struct(3u8); + let mut struct_3 = OnceMutCell::new(Struct(3u8)); let mut struct_str = Struct("str"); unsafe { Struct::::ref_mut_method - .mock_raw(|_, b| MockResult::Continue((as_mut(&struct_3), !b))); + .mock_raw(|_, b| MockResult::Continue((struct_3.borrow(), !b))); } assert_eq!("0 false", struct_2.ref_mut_method(true)); assert_eq!(2, struct_2.0); - assert_eq!(0, struct_3.0); + assert_eq!(0, struct_3.get_mut().0); assert_eq!(" true", struct_str.ref_mut_method(true)); assert_eq!("", struct_str.0); } diff --git a/tests/mocking_traits/when_trait_regular_struct_regular_method_generic.rs b/tests/mocking_traits/when_trait_regular_struct_regular_method_generic.rs index 7b48832..8371c12 100644 --- a/tests/mocking_traits/when_trait_regular_struct_regular_method_generic.rs +++ b/tests/mocking_traits/when_trait_regular_struct_regular_method_generic.rs @@ -115,16 +115,16 @@ mod and_method_is_ref_mut_method { #[test] fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2); - let struct_3 = Struct(3); + let mut struct_3 = OnceMutCell::new(Struct(3)); let mut struct_4 = Struct(4); unsafe { Struct::ref_mut_method:: - .mock_raw(|_, b, c| MockResult::Continue((as_mut(&struct_3), !b, c + 1.))); + .mock_raw(|_, b, c| MockResult::Continue((struct_3.borrow(), !b, c + 1.))); } assert_eq!("6 false 2.5", struct_2.ref_mut_method(true, 1.5f32)); assert_eq!(2, struct_2.0); - assert_eq!(6, struct_3.0); + assert_eq!(6, struct_3.get_mut().0); assert_eq!("8 true abc", struct_4.ref_mut_method(true, "abc")); assert_eq!(8, struct_4.0); } diff --git a/tests/mocking_traits/when_trait_regular_struct_regular_method_regular.rs b/tests/mocking_traits/when_trait_regular_struct_regular_method_regular.rs index e1250d6..477d447 100644 --- a/tests/mocking_traits/when_trait_regular_struct_regular_method_regular.rs +++ b/tests/mocking_traits/when_trait_regular_struct_regular_method_regular.rs @@ -103,14 +103,14 @@ mod and_method_is_ref_mut_method { #[test] fn and_continue_mocked_then_runs_with_modified_args() { let mut struct_2 = Struct(2); - let struct_3 = Struct(3); + let mut struct_3 = OnceMutCell::new(Struct(3)); unsafe { - Struct::ref_mut_method.mock_raw(|_, b| MockResult::Continue((as_mut(&struct_3), !b))); + Struct::ref_mut_method.mock_raw(|_, b| MockResult::Continue((struct_3.borrow(), !b))); } assert_eq!("6 false", struct_2.ref_mut_method(true)); assert_eq!(2, struct_2.0); - assert_eq!(6, struct_3.0); + assert_eq!(6, struct_3.get_mut().0); } #[test]