Skip to content

Migrate back to generic type parameter #336

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,7 @@ struct MyEqMatcher<T> {
expected: T,
}

impl<T: PartialEq + Debug> Matcher for MyEqMatcher<T> {
type ActualT = T;

impl<T: PartialEq + Debug> Matcher<T> for MyEqMatcher<T> {
fn matches(&self, actual: &Self::ActualT) -> MatcherResult {
(self.expected == *actual).into()
}
Expand All @@ -179,7 +177,7 @@ impl<T: PartialEq + Debug> Matcher for MyEqMatcher<T> {
It is recommended to expose a function which constructs the matcher:

```rust
pub fn eq_my_way<T: PartialEq + Debug>(expected: T) -> impl Matcher<ActualT = T> {
pub fn eq_my_way<T: PartialEq + Debug>(expected: T) -> impl Matcher<T> {
MyEqMatcher { expected }
}
```
Expand Down
22 changes: 8 additions & 14 deletions googletest/crate_docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,10 +216,8 @@ struct MyEqMatcher<T> {
expected: T,
}

impl<T: PartialEq + Debug> Matcher for MyEqMatcher<T> {
type ActualT = T;

fn matches(&self, actual: &Self::ActualT) -> MatcherResult {
impl<T: PartialEq + Debug> Matcher<T> for MyEqMatcher<T> {
fn matches<'a>(&self, actual: &'a T) -> MatcherResult where T: 'a{
if self.expected == *actual {
MatcherResult::Match
} else {
Expand Down Expand Up @@ -250,10 +248,8 @@ impl<T: PartialEq + Debug> Matcher for MyEqMatcher<T> {
# expected: T,
# }
#
# impl<T: PartialEq + Debug> Matcher for MyEqMatcher<T> {
# type ActualT = T;
#
# fn matches(&self, actual: &Self::ActualT) -> MatcherResult {
# impl<T: PartialEq + Debug> Matcher<T> for MyEqMatcher<T> {
# fn matches<'a>(&self, actual: &'a T) -> MatcherResult where T: 'a{
# if self.expected == *actual {
# MatcherResult::Match
# } else {
Expand All @@ -273,7 +269,7 @@ impl<T: PartialEq + Debug> Matcher for MyEqMatcher<T> {
# }
# }
#
pub fn eq_my_way<T: PartialEq + Debug>(expected: T) -> impl Matcher<ActualT = T> {
pub fn eq_my_way<T: PartialEq + Debug>(expected: T) -> impl Matcher<T> {
MyEqMatcher { expected }
}
```
Expand All @@ -289,10 +285,8 @@ impl<T: PartialEq + Debug> Matcher for MyEqMatcher<T> {
# expected: T,
# }
#
# impl<T: PartialEq + Debug> Matcher for MyEqMatcher<T> {
# type ActualT = T;
#
# fn matches(&self, actual: &Self::ActualT) -> MatcherResult {
# impl<T: PartialEq + Debug> Matcher<T> for MyEqMatcher<T> {
# fn matches<'a>(&self, actual: &'a T) -> MatcherResult where T: 'a{
# if self.expected == *actual {
# MatcherResult::Match
# } else {
Expand All @@ -312,7 +306,7 @@ impl<T: PartialEq + Debug> Matcher for MyEqMatcher<T> {
# }
# }
#
# pub fn eq_my_way<T: PartialEq + Debug>(expected: T) -> impl Matcher<ActualT = T> {
# pub fn eq_my_way<T: PartialEq + Debug>(expected: T) -> impl Matcher<T> {
# MyEqMatcher { expected }
# }
# /* The attribute macro would prevent the function from being compiled in a doctest.
Expand Down
2 changes: 1 addition & 1 deletion googletest/src/assertions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ pub mod internal {
#[must_use = "The assertion result must be evaluated to affect the test result."]
pub fn check_matcher<T: Debug + ?Sized>(
actual: &T,
expected: impl Matcher<ActualT = T>,
expected: impl Matcher<T>,
actual_expr: &'static str,
source_location: SourceLocation,
) -> Result<(), TestAssertionFailure> {
Expand Down
32 changes: 16 additions & 16 deletions googletest/src/matcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,16 @@ use crate::matchers::__internal_unstable_do_not_depend_on_these::DisjunctionMatc
use std::fmt::Debug;

/// An interface for checking an arbitrary condition on a datum.
pub trait Matcher {
/// The type against which this matcher matches.
type ActualT: Debug + ?Sized;

pub trait Matcher<ActualT: Debug + ?Sized> {
/// Returns whether the condition matches the datum `actual`.
///
/// The trait implementation defines what it means to "match". Often the
/// matching condition is based on data stored in the matcher. For example,
/// `eq` matches when its stored expected value is equal (in the sense of
/// the `==` operator) to the value `actual`.
fn matches(&self, actual: &Self::ActualT) -> MatcherResult;
fn matches<'a>(&self, actual: &'a ActualT) -> MatcherResult
where
ActualT: 'a;

/// Returns a description of `self` or a negative description if
/// `matcher_result` is `DoesNotMatch`.
Expand Down Expand Up @@ -128,7 +127,10 @@ pub trait Matcher {
/// format!("which points to a value {}", self.expected.explain_match(actual.deref()))
/// }
/// ```
fn explain_match(&self, actual: &Self::ActualT) -> String {
fn explain_match<'a>(&self, actual: &'a ActualT) -> String
where
ActualT: 'a,
{
format!("which {}", self.describe(self.matches(actual)))
}

Expand All @@ -155,10 +157,7 @@ pub trait Matcher {
// TODO(b/264518763): Replace the return type with impl Matcher and reduce
// visibility of ConjunctionMatcher once impl in return position in trait
// methods is stable.
fn and<Right: Matcher<ActualT = Self::ActualT>>(
self,
right: Right,
) -> ConjunctionMatcher<Self, Right>
fn and<Right: Matcher<ActualT>>(self, right: Right) -> ConjunctionMatcher<Self, Right>
where
Self: Sized,
{
Expand All @@ -185,10 +184,7 @@ pub trait Matcher {
// TODO(b/264518763): Replace the return type with impl Matcher and reduce
// visibility of DisjunctionMatcher once impl in return position in trait
// methods is stable.
fn or<Right: Matcher<ActualT = Self::ActualT>>(
self,
right: Right,
) -> DisjunctionMatcher<Self, Right>
fn or<Right: Matcher<ActualT>>(self, right: Right) -> DisjunctionMatcher<Self, Right>
where
Self: Sized,
{
Expand All @@ -206,7 +202,7 @@ const PRETTY_PRINT_LENGTH_THRESHOLD: usize = 60;
/// The parameter `actual_expr` contains the expression which was evaluated to
/// obtain `actual`.
pub(crate) fn create_assertion_failure<T: Debug + ?Sized>(
matcher: &impl Matcher<ActualT = T>,
matcher: &impl Matcher<T>,
actual: &T,
actual_expr: &'static str,
source_location: SourceLocation,
Expand Down Expand Up @@ -240,7 +236,11 @@ pub enum MatcherResult {

impl From<bool> for MatcherResult {
fn from(b: bool) -> Self {
if b { MatcherResult::Match } else { MatcherResult::NoMatch }
if b {
MatcherResult::Match
} else {
MatcherResult::NoMatch
}
}
}

Expand Down
20 changes: 10 additions & 10 deletions googletest/src/matcher_support/edit_distance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,8 +430,8 @@ mod tests {
}

#[test]
fn returns_common_part_plus_difference_plus_common_part_when_there_is_common_prefix_and_suffix()
-> Result<()> {
fn returns_common_part_plus_difference_plus_common_part_when_there_is_common_prefix_and_suffix(
) -> Result<()> {
let result = edit_list(
["Common part (1)", "Actual only", "Common part (2)"],
["Common part (1)", "Expected only", "Common part (2)"],
Expand All @@ -449,8 +449,8 @@ mod tests {
}

#[test]
fn returns_common_part_plus_extra_actual_plus_common_part_when_there_is_common_prefix_and_suffix()
-> Result<()> {
fn returns_common_part_plus_extra_actual_plus_common_part_when_there_is_common_prefix_and_suffix(
) -> Result<()> {
let result = edit_list(
["Common part (1)", "Actual only", "Common part (2)"],
["Common part (1)", "Common part (2)"],
Expand All @@ -467,8 +467,8 @@ mod tests {
}

#[test]
fn returns_common_part_plus_extra_expected_plus_common_part_when_there_is_common_prefix_and_suffix()
-> Result<()> {
fn returns_common_part_plus_extra_expected_plus_common_part_when_there_is_common_prefix_and_suffix(
) -> Result<()> {
let result = edit_list(
["Common part (1)", "Common part (2)"],
["Common part (1)", "Expected only", "Common part (2)"],
Expand Down Expand Up @@ -500,8 +500,8 @@ mod tests {
}

#[test]
fn does_not_skip_extra_parts_on_actual_in_prefix_mode_at_end_when_they_are_in_common()
-> Result<()> {
fn does_not_skip_extra_parts_on_actual_in_prefix_mode_at_end_when_they_are_in_common(
) -> Result<()> {
let result = edit_list(
["Actual only", "Common part"],
["Expected only", "Common part"],
Expand All @@ -518,8 +518,8 @@ mod tests {
}

#[test]
fn does_not_skip_corresponding_line_on_actual_when_actual_and_expected_differ_in_prefix_mode()
-> Result<()> {
fn does_not_skip_corresponding_line_on_actual_when_actual_and_expected_differ_in_prefix_mode(
) -> Result<()> {
let result = edit_list(["Actual only"], ["Expected only"], Mode::Prefix);
verify_that!(
result,
Expand Down
18 changes: 11 additions & 7 deletions googletest/src/matchers/all_matcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,22 +75,23 @@ pub mod internal {
/// For internal use only. API stablility is not guaranteed!
#[doc(hidden)]
pub struct AllMatcher<'a, T: Debug + ?Sized, const N: usize> {
components: [Box<dyn Matcher<ActualT = T> + 'a>; N],
components: [Box<dyn Matcher<T> + 'a>; N],
}

impl<'a, T: Debug + ?Sized, const N: usize> AllMatcher<'a, T, N> {
/// Constructs an [`AllMatcher`] with the given component matchers.
///
/// Intended for use only by the [`all`] macro.
pub fn new(components: [Box<dyn Matcher<ActualT = T> + 'a>; N]) -> Self {
pub fn new(components: [Box<dyn Matcher<T> + 'a>; N]) -> Self {
Self { components }
}
}

impl<'a, T: Debug + ?Sized, const N: usize> Matcher for AllMatcher<'a, T, N> {
type ActualT = T;

fn matches(&self, actual: &Self::ActualT) -> MatcherResult {
impl<'a, T: Debug + ?Sized, const N: usize> Matcher<T> for AllMatcher<'a, T, N> {
fn matches<'b>(&self, actual: &'b T) -> MatcherResult
where
T: 'b,
{
for component in &self.components {
match component.matches(actual) {
MatcherResult::NoMatch => {
Expand All @@ -102,7 +103,10 @@ pub mod internal {
MatcherResult::Match
}

fn explain_match(&self, actual: &Self::ActualT) -> String {
fn explain_match<'b>(&self, actual: &'b T) -> String
where
T: 'b,
{
match N {
0 => anything::<T>().explain_match(actual),
1 => self.components[0].explain_match(actual),
Expand Down
18 changes: 11 additions & 7 deletions googletest/src/matchers/any_matcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,26 +77,30 @@ pub mod internal {
/// For internal use only. API stablility is not guaranteed!
#[doc(hidden)]
pub struct AnyMatcher<'a, T: Debug + ?Sized, const N: usize> {
components: [Box<dyn Matcher<ActualT = T> + 'a>; N],
components: [Box<dyn Matcher<T> + 'a>; N],
}

impl<'a, T: Debug + ?Sized, const N: usize> AnyMatcher<'a, T, N> {
/// Constructs an [`AnyMatcher`] with the given component matchers.
///
/// Intended for use only by the [`all`] macro.
pub fn new(components: [Box<dyn Matcher<ActualT = T> + 'a>; N]) -> Self {
pub fn new(components: [Box<dyn Matcher<T> + 'a>; N]) -> Self {
Self { components }
}
}

impl<'a, T: Debug + ?Sized, const N: usize> Matcher for AnyMatcher<'a, T, N> {
type ActualT = T;

fn matches(&self, actual: &Self::ActualT) -> MatcherResult {
impl<'a, T: Debug + ?Sized, const N: usize> Matcher<T> for AnyMatcher<'a, T, N> {
fn matches<'b>(&self, actual: &'b T) -> MatcherResult
where
T: 'b,
{
MatcherResult::from(self.components.iter().any(|c| c.matches(actual).is_match()))
}

fn explain_match(&self, actual: &Self::ActualT) -> String {
fn explain_match<'b>(&self, actual: &'b T) -> String
where
T: 'b,
{
match N {
0 => format!("which {}", anything::<T>().describe(MatcherResult::NoMatch)),
1 => self.components[0].explain_match(actual),
Expand Down
17 changes: 9 additions & 8 deletions googletest/src/matchers/anything_matcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// limitations under the License.

use crate::matcher::{Matcher, MatcherResult};
use std::{fmt::Debug, marker::PhantomData};
use std::fmt::Debug;

/// Matches anything. This matcher always succeeds.
///
Expand All @@ -29,16 +29,17 @@ use std::{fmt::Debug, marker::PhantomData};
/// # }
/// # should_pass().unwrap();
/// ```
pub fn anything<T: Debug + ?Sized>() -> impl Matcher<ActualT = T> {
Anything::<T>(Default::default())
pub fn anything<T: Debug + ?Sized>() -> impl Matcher<T> {
Anything
}

struct Anything<T: ?Sized>(PhantomData<T>);
struct Anything;

impl<T: Debug + ?Sized> Matcher for Anything<T> {
type ActualT = T;

fn matches(&self, _: &T) -> MatcherResult {
impl<T: Debug + ?Sized> Matcher<T> for Anything {
fn matches<'a>(&self, _: &'a T) -> MatcherResult
where
T: 'a,
{
MatcherResult::Match
}

Expand Down
Loading