diff --git a/src/lib.rs b/src/lib.rs index 8faf63e..21fe826 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(fn_traits, unboxed_closures)] +#![feature(fn_traits, unboxed_closures, tuple_trait)] //! Mocking framework for Rust (currently only nightly) //! diff --git a/src/mock_store.rs b/src/mock_store.rs index 22df3f0..58761ad 100644 --- a/src/mock_store.rs +++ b/src/mock_store.rs @@ -2,6 +2,7 @@ use crate::mocking::MockResult; use std::any::TypeId; use std::cell::RefCell; use std::collections::HashMap; +use std::marker::Tuple; use std::mem::transmute; use std::rc::Rc; @@ -44,7 +45,10 @@ impl MockStore { .add(id, mock); } - pub unsafe fn call(&self, id: TypeId, mut input: I) -> MockResult { + pub unsafe fn call(&self, id: TypeId, mut input: I) -> MockResult + where + I: Tuple, + { // Do not hold RefCell borrow while calling mock, it can try to modify mocks let layer_count = self.layers.borrow().len(); for layer_idx in (0..layer_count).rev() { @@ -118,7 +122,10 @@ struct ErasedStoredMock { } impl ErasedStoredMock { - unsafe fn call(self, input: I) -> MockLayerResult { + unsafe fn call(self, input: I) -> MockLayerResult + where + I: Tuple, + { let unerased: StoredMock = transmute(self.mock); unerased.call(input) } @@ -137,7 +144,10 @@ impl StoredMock { } } - fn call(&self, input: I) -> MockLayerResult { + fn call(&self, input: I) -> MockLayerResult + where + I: Tuple, + { match self.mock.try_borrow_mut() { Ok(mut mock) => MockLayerResult::Handled(mock.call_mut(input)), Err(_) => MockLayerResult::Unhandled(input), diff --git a/src/mocking.rs b/src/mocking.rs index f394a1e..c979276 100644 --- a/src/mocking.rs +++ b/src/mocking.rs @@ -1,6 +1,6 @@ use crate::mock_store::{MockLayer, MockStore}; use std::any::{Any, TypeId}; -use std::marker::PhantomData; +use std::marker::{PhantomData, Tuple}; use std::mem::transmute; /// Trait for setting up mocks @@ -42,7 +42,9 @@ pub trait Mockable { /// assert_eq!("mocked", get_string(&Context::default())); /// } /// ``` - unsafe fn mock_raw>>(&self, mock: M); + unsafe fn mock_raw>>(&self, mock: M) + where + T: Tuple; /// A safe variant of [mock_raw](#tymethod.mock_raw) for static closures /// @@ -62,7 +64,9 @@ pub trait Mockable { /// assert_eq!("mocked", get_string()); /// } /// ``` - fn mock_safe> + 'static>(&self, mock: M); + fn mock_safe> + 'static>(&self, mock: M) + where + T: Tuple; /// Stop mocking this function. /// @@ -97,7 +101,10 @@ pub fn clear_mocks() { MOCK_STORE.with(|mock_store| mock_store.clear()) } -impl> Mockable for F { +impl> Mockable for F +where + T: Tuple, +{ unsafe fn mock_raw>>(&self, mock: M) { let id = self.get_mock_id(); let boxed = Box::new(mock) as Box>; @@ -190,6 +197,7 @@ impl<'a> MockContext<'a> { where F: Mockable, M: FnMut> + 'a, + I: Tuple, { unsafe { self.mock_raw(mockable, mock) } } @@ -202,6 +210,7 @@ impl<'a> MockContext<'a> { where F: Mockable, M: FnMut>, + I: Tuple, { let mock_box = Box::new(mock) as Box>; let mock_box_static: Box> + 'static> = diff --git a/tests/injecting.rs b/tests/injecting.rs index 7767915..ba56594 100644 --- a/tests/injecting.rs +++ b/tests/injecting.rs @@ -1,4 +1,4 @@ -#![feature(const_fn, proc_macro_hygiene)] +#![feature(proc_macro_hygiene)] // Test if injecting works even if mocktopus is aliased extern crate mocktopus as mocktopus_aliased;