-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Could we remove the Copy
requirement of ActualT
type parameter in Matcher
trait?
#542
Comments
Can you share more details why this is not valid anymore? There are a few playgrounds in the #323. I noticed that I did not add a regression test to demonstrate this. I will try to add them in the future.
Custom matchers are something that is supported, but has not been the main focus of our devex effort. I would like to improve on that. Can you share the difficulty you are facing there? |
Sorry for the late reply
For example, when I tried to implement a matcher that takes a use googletest::{description::Description, matcher::MatcherResult, prelude::*};
#[derive(MatcherBase)]
struct MyMatcher {
children: Vec<Box<dyn for<'a> Matcher<&'a i32>>>,
}
impl<'a> Matcher<&'a [i32]> for MyMatcher {
fn matches(&self, actual: &'a [i32]) -> MatcherResult {
if actual.len() != self.children.len() {
return MatcherResult::NoMatch;
}
for (x, m) in actual.iter().zip(self.children.iter()) {
if m.matches(x).is_no_match() {
return MatcherResult::NoMatch;
}
}
MatcherResult::Match
}
fn describe(
&self,
matcher_result: MatcherResult,
) -> Description {
todo!()
}
}
fn main() {
let m = MyMatcher {
children: vec![Box::new(points_to(eq(3)))],
};
let x = vec![1, 2, 3];
let x = &*x;
expect_that!(x, m);
} If the |
Or put it another way, if I define the new trait that takes reference in trait MyMatcherTrait<T: std::fmt::Debug> {
fn matches(&self, actual: &T) -> MatcherResult;
fn describe(&self, matcher_result: MatcherResult) -> Description;
} Then the following blanket implementation can be applied to any type that implements the current impl<T, ActualT> MyMatcherTrait<ActualT> for T
where
T: Matcher<ActualT>,
ActualT: std::fmt::Debug + Copy,
{
fn matches(&self, actual: &ActualT) -> MatcherResult {
Matcher::matches(self, *actual)
}
fn describe(&self, matcher_result: MatcherResult) -> Description {
todo!()
}
} Which means that we don't really lose anything if we switched to the new trait. |
I've been trying to migrate from 0.11 to 0.13, and I stumbled on this new requirement pretty much throughout all my code, as my assertions were built all with owned values. For example, I have a looot of assertion methods that looks like these:
And now I can't really implement them anymore:
as obviously:
Essentially taking ownership in the matchers of the "expected" values was super handy to create these methods, which now is not really possible anymore. And yes I know this specific case I could nest a |
In 471d4a2, the
ActualT
changed from an associated type to a type parameter. I think it is a good change, but isActualT: Copy
still required? In #323, there was some discussions about lifetime problems, but I don't think that is still valid now because the lifetime of the object being matched is not tied to the matcher anymore.The comment in the code mentioned:
But
Copy
in rust is generally considered cheap (if object is so large that memcpy is expensive, then the type probably shouldn't implement Copy in the first place), so there is no harm to takeactual: &ActualT
instead. IfActualT
isCopy
, the implementer can dereference it by themselves. This simplify a lot of lifetime problems when implementing custom matchers.The text was updated successfully, but these errors were encountered: