diff --git a/CHANGELOG.md b/CHANGELOG.md index a664b660..8c371eba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [ Unreleased ] - ReleaseDate + +## Fixed + +- Fix mocking trait methods whose return values have lifetime parameters, a + regression sine v0.10.0. + ([#301](https://github.com/asomers/mockall/pull/301)) + ## [ 0.10.0 ] - 2021-06-27 ### Added diff --git a/mockall/tests/mock_generic_method_returning_nonstatic.rs b/mockall/tests/mock_generic_method_returning_nonstatic.rs index 865e2862..5fc5fe3f 100644 --- a/mockall/tests/mock_generic_method_returning_nonstatic.rs +++ b/mockall/tests/mock_generic_method_returning_nonstatic.rs @@ -10,6 +10,11 @@ use mockall::*; #[derive(Clone)] struct X<'a>(&'a u32); +trait Bong { + fn trait_foo<'a>(&self) -> X<'a>; + fn trait_baz<'a>(&self) -> &X<'a>; +} + mock! { Thing { fn foo<'a>(&self) -> X<'a>; @@ -29,6 +34,11 @@ mock! { // std::any::Any, which means they must be 'static. //fn bean<'a, T: 'static>(&self, t: T) -> X<'a>; } + // The same types of methods should work if they are Trait methods. + impl Bong for Thing { + fn trait_foo<'a>(&self) -> X<'a>; + fn trait_baz<'a>(&self) -> &X<'a>; + } } #[test] @@ -67,3 +77,41 @@ fn return_nonstatic() { assert_eq!(42u32, *thing.foo().0); } + +mod trait_methods { + use super::*; + + #[test] + fn return_static() { + const D: u32 = 42; + let x = X(&D); + let mut thing = MockThing::new(); + thing.expect_trait_foo() + .return_const(x); + + assert_eq!(42u32, *thing.trait_foo().0); + } + + #[test] + fn return_static_ref() { + const D: u32 = 42; + let x = X(&D); + let mut thing = MockThing::new(); + thing.expect_trait_baz() + .return_const(x); + + assert_eq!(42u32, *(*thing.trait_baz()).0); + } + + #[test] + fn return_nonstatic() { + let d = 42u32; + let x = X(&d); + let xstatic: X<'static> = unsafe{ std::mem::transmute(x) }; + let mut thing = MockThing::new(); + thing.expect_trait_foo() + .returning(move || xstatic.clone()); + + assert_eq!(42u32, *thing.trait_foo().0); + } +} diff --git a/mockall_derive/src/mock_function.rs b/mockall_derive/src/mock_function.rs index 25755429..849ddbb2 100644 --- a/mockall_derive/src/mock_function.rs +++ b/mockall_derive/src/mock_function.rs @@ -619,10 +619,10 @@ impl MockFunction { -> impl ToTokens { let inner_mod_ident = self.inner_mod_ident(); - if let Some(sa) = self_args { + if let Some(PathArguments::AngleBracketed(abga)) = self_args { assert!(!self.is_method_generic(), "specific impls with generic methods are TODO"); - quote!(#inner_mod_ident::Expectation #sa) + quote!(#inner_mod_ident::Expectation #abga) } else { // staticize any lifetimes. This is necessary for methods that // return non-static types, because the Expectation itself must be