Skip to content

Commit debf2d8

Browse files
committed
fix(API): Switch from Associated Types to Generics
The hope is that generics will also make implementing support for assert-rs#20 easier. So when to use each according to [The Book](https://doc.rust-lang.org/book/second-edition/ch19-03-advanced-traits.html#associated-types-versus-generics): Generics - Used when type is going to be function input - Can have multiple implementations of trait Associated types - Used when type is going to be a function output, like iterator - Avoids need to annotate type - Can only have one implementation of trait BREAKING CHANGE: The `Predicate` trait's API has changed.
1 parent 2529281 commit debf2d8

File tree

13 files changed

+118
-117
lines changed

13 files changed

+118
-117
lines changed

src/boolean.rs

Lines changed: 58 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,40 +8,48 @@
88

99
//! Definition of boolean logic combinators over `Predicate`s.
1010
11+
use std::marker::PhantomData;
12+
1113
use Predicate;
1214

1315
/// Predicate that combines two `Predicate`s, returning the AND of the results.
1416
///
1517
/// This is created by the `Predicate::and` function.
1618
#[derive(Debug)]
17-
pub struct AndPredicate<M1, M2>
19+
pub struct AndPredicate<M1, M2, Item>
1820
where
19-
M1: Predicate,
20-
M2: Predicate<Item = M1::Item>,
21+
M1: Predicate<Item>,
22+
M2: Predicate<Item>,
23+
Item: ?Sized,
2124
{
2225
a: M1,
2326
b: M2,
27+
_phantom: PhantomData<Item>,
2428
}
2529

26-
impl<M1, M2> AndPredicate<M1, M2>
30+
impl<M1, M2, Item> AndPredicate<M1, M2, Item>
2731
where
28-
M1: Predicate,
29-
M2: Predicate<Item = M1::Item>,
32+
M1: Predicate<Item>,
33+
M2: Predicate<Item>,
34+
Item: ?Sized,
3035
{
3136
/// Create a new `AndPredicate` over predicates `a` and `b`.
32-
pub fn new(a: M1, b: M2) -> AndPredicate<M1, M2> {
33-
AndPredicate { a: a, b: b }
37+
pub fn new(a: M1, b: M2) -> AndPredicate<M1, M2, Item> {
38+
AndPredicate {
39+
a: a,
40+
b: b,
41+
_phantom: PhantomData,
42+
}
3443
}
3544
}
3645

37-
impl<M1, M2> Predicate for AndPredicate<M1, M2>
46+
impl<M1, M2, Item> Predicate<Item> for AndPredicate<M1, M2, Item>
3847
where
39-
M1: Predicate,
40-
M2: Predicate<Item = M1::Item>,
48+
M1: Predicate<Item>,
49+
M2: Predicate<Item>,
50+
Item: ?Sized,
4151
{
42-
type Item = M1::Item;
43-
44-
fn eval(&self, item: &Self::Item) -> bool {
52+
fn eval(&self, item: &Item) -> bool {
4553
self.a.eval(item) && self.b.eval(item)
4654
}
4755
}
@@ -50,34 +58,40 @@ where
5058
///
5159
/// This is created by the `Predicate::or` function.
5260
#[derive(Debug)]
53-
pub struct OrPredicate<M1, M2>
61+
pub struct OrPredicate<M1, M2, Item>
5462
where
55-
M1: Predicate,
56-
M2: Predicate<Item = M1::Item>,
63+
M1: Predicate<Item>,
64+
M2: Predicate<Item>,
65+
Item: ?Sized,
5766
{
5867
a: M1,
5968
b: M2,
69+
_phantom: PhantomData<Item>,
6070
}
6171

62-
impl<M1, M2> OrPredicate<M1, M2>
72+
impl<M1, M2, Item> OrPredicate<M1, M2, Item>
6373
where
64-
M1: Predicate,
65-
M2: Predicate<Item = M1::Item>,
74+
M1: Predicate<Item>,
75+
M2: Predicate<Item>,
76+
Item: ?Sized,
6677
{
6778
/// Create a new `OrPredicate` over predicates `a` and `b`.
68-
pub fn new(a: M1, b: M2) -> OrPredicate<M1, M2> {
69-
OrPredicate { a: a, b: b }
79+
pub fn new(a: M1, b: M2) -> OrPredicate<M1, M2, Item> {
80+
OrPredicate {
81+
a: a,
82+
b: b,
83+
_phantom: PhantomData,
84+
}
7085
}
7186
}
7287

73-
impl<M1, M2> Predicate for OrPredicate<M1, M2>
88+
impl<M1, M2, Item> Predicate<Item> for OrPredicate<M1, M2, Item>
7489
where
75-
M1: Predicate,
76-
M2: Predicate<Item = M1::Item>,
90+
M1: Predicate<Item>,
91+
M2: Predicate<Item>,
92+
Item: ?Sized,
7793
{
78-
type Item = M1::Item;
79-
80-
fn eval(&self, item: &Self::Item) -> bool {
94+
fn eval(&self, item: &Item) -> bool {
8195
self.a.eval(item) || self.b.eval(item)
8296
}
8397
}
@@ -86,30 +100,35 @@ where
86100
///
87101
/// This is created by the `Predicate::not` function.
88102
#[derive(Debug)]
89-
pub struct NotPredicate<M>
103+
pub struct NotPredicate<M, Item>
90104
where
91-
M: Predicate,
105+
M: Predicate<Item>,
106+
Item: ?Sized,
92107
{
93108
inner: M,
109+
_phantom: PhantomData<Item>,
94110
}
95111

96-
impl<M> NotPredicate<M>
112+
impl<M, Item> NotPredicate<M, Item>
97113
where
98-
M: Predicate,
114+
M: Predicate<Item>,
115+
Item: ?Sized,
99116
{
100117
/// Create a new `NotPredicate` over predicate `inner`.
101-
pub fn new(inner: M) -> NotPredicate<M> {
102-
NotPredicate { inner: inner }
118+
pub fn new(inner: M) -> NotPredicate<M, Item> {
119+
NotPredicate {
120+
inner: inner,
121+
_phantom: PhantomData,
122+
}
103123
}
104124
}
105125

106-
impl<M> Predicate for NotPredicate<M>
126+
impl<M, Item> Predicate<Item> for NotPredicate<M, Item>
107127
where
108-
M: Predicate,
128+
M: Predicate<Item>,
129+
Item: ?Sized,
109130
{
110-
type Item = M::Item;
111-
112-
fn eval(&self, item: &Self::Item) -> bool {
131+
fn eval(&self, item: &Item) -> bool {
113132
!self.inner.eval(item)
114133
}
115134
}

src/boxed.rs

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,35 +15,45 @@ use Predicate;
1515

1616
/// `Predicate` that wraps another `Predicate` as a trait object, allowing
1717
/// sized storage of predicate types.
18-
pub struct BoxPredicate<T: ?Sized>(Box<Predicate<Item = T> + Send + Sync>);
18+
pub struct BoxPredicate<Item: ?Sized>(Box<Predicate<Item> + Send + Sync>);
1919

20-
impl<T> fmt::Debug for BoxPredicate<T> {
20+
impl<Item> BoxPredicate<Item>
21+
where
22+
Item: ?Sized,
23+
{
24+
/// Creates a new `BoxPredicate`, a wrapper around a dynamically-dispatched
25+
/// `Predicate` type with useful trait impls.
26+
pub fn new<P: Predicate<Item>>(inner: P) -> BoxPredicate<Item>
27+
where
28+
P: Send + Sync + 'static,
29+
{
30+
BoxPredicate(Box::new(inner))
31+
}
32+
}
33+
34+
impl<Item> fmt::Debug for BoxPredicate<Item>
35+
where
36+
Item: ?Sized,
37+
{
2138
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2239
f.debug_struct("BoxPredicate").finish()
2340
}
2441
}
2542

26-
impl<T> fmt::Display for BoxPredicate<T> {
43+
impl<Item> fmt::Display for BoxPredicate<Item>
44+
where
45+
Item: ?Sized,
46+
{
2747
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2848
write!(f, "BoxPredicate")
2949
}
3050
}
3151

32-
impl<T: ?Sized> Predicate for BoxPredicate<T> {
33-
type Item = T;
34-
35-
fn eval(&self, variable: &Self::Item) -> bool {
52+
impl<Item> Predicate<Item> for BoxPredicate<Item>
53+
where
54+
Item: ?Sized,
55+
{
56+
fn eval(&self, variable: &Item) -> bool {
3657
self.0.eval(variable)
3758
}
3859
}
39-
40-
impl<T: ?Sized> BoxPredicate<T> {
41-
/// Creates a new `BoxPredicate`, a wrapper around a dynamically-dispatched
42-
/// `Predicate` type with useful trait impls.
43-
pub fn new<P: Predicate<Item = T>>(inner: P) -> BoxPredicate<T>
44-
where
45-
P: Send + Sync + 'static,
46-
{
47-
BoxPredicate(Box::new(inner))
48-
}
49-
}

src/constant.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,13 @@ use Predicate;
1616
///
1717
/// This is created by the `predicate::always` and `predicate::never` functions.
1818
#[derive(Debug)]
19-
pub struct BooleanPredicate<T> {
19+
pub struct BooleanPredicate<Item> {
2020
retval: bool,
21-
_phantom: PhantomData<T>,
21+
_phantom: PhantomData<Item>,
2222
}
2323

24-
impl<T> Predicate for BooleanPredicate<T> {
25-
type Item = T;
26-
27-
fn eval(&self, _variable: &T) -> bool {
24+
impl<Item> Predicate<Item> for BooleanPredicate<Item> {
25+
fn eval(&self, _variable: &Item) -> bool {
2826
self.retval
2927
}
3028
}
@@ -43,7 +41,7 @@ impl<T> Predicate for BooleanPredicate<T> {
4341
/// // Won't work - Predicates can only operate on a single type
4442
/// // assert_eq!(true, predicate_fn.eval("hello"))
4543
/// ```
46-
pub fn always<T>() -> BooleanPredicate<T> {
44+
pub fn always<Item>() -> BooleanPredicate<Item> {
4745
BooleanPredicate {
4846
retval: true,
4947
_phantom: PhantomData,
@@ -64,7 +62,7 @@ pub fn always<T>() -> BooleanPredicate<T> {
6462
/// // Won't work - Predicates can only operate on a single type
6563
/// // assert_eq!(false, predicate_fn.eval("hello"))
6664
/// ```
67-
pub fn never<T>() -> BooleanPredicate<T> {
65+
pub fn never<Item>() -> BooleanPredicate<Item> {
6866
BooleanPredicate {
6967
retval: false,
7068
_phantom: PhantomData,

src/core.rs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,10 @@ use boxed::BoxPredicate;
1616
/// mean that the evaluated item is in some sort of pre-defined set. This is
1717
/// different from `Ord` and `Eq` in that an `item` will almost never be the
1818
/// same type as the implementing `Predicate` type.
19-
pub trait Predicate {
20-
/// The type that this `Predicate` will accept for evaluating.
21-
type Item: ?Sized;
22-
19+
pub trait Predicate<Item: ?Sized> {
2320
/// Execute this `Predicate` against `variable`, returning the resulting
2421
/// boolean.
25-
fn eval(&self, variable: &Self::Item) -> bool;
22+
fn eval(&self, variable: &Item) -> bool;
2623

2724
/// Compute the logical AND of two `Predicate` results, returning the result.
2825
///
@@ -35,9 +32,9 @@ pub trait Predicate {
3532
/// let predicate_fn2 = predicate::always().and(predicate::never());
3633
/// assert_eq!(true, predicate_fn1.eval(&4));
3734
/// assert_eq!(false, predicate_fn2.eval(&4));
38-
fn and<B>(self, other: B) -> AndPredicate<Self, B>
35+
fn and<B>(self, other: B) -> AndPredicate<Self, B, Item>
3936
where
40-
B: Predicate<Item = Self::Item>,
37+
B: Predicate<Item>,
4138
Self: Sized,
4239
{
4340
AndPredicate::new(self, other)
@@ -56,9 +53,9 @@ pub trait Predicate {
5653
/// assert_eq!(true, predicate_fn1.eval(&4));
5754
/// assert_eq!(true, predicate_fn2.eval(&4));
5855
/// assert_eq!(false, predicate_fn3.eval(&4));
59-
fn or<B>(self, other: B) -> OrPredicate<Self, B>
56+
fn or<B>(self, other: B) -> OrPredicate<Self, B, Item>
6057
where
61-
B: Predicate<Item = Self::Item>,
58+
B: Predicate<Item>,
6259
Self: Sized,
6360
{
6461
OrPredicate::new(self, other)
@@ -75,7 +72,7 @@ pub trait Predicate {
7572
/// let predicate_fn2 = predicate::never().not();
7673
/// assert_eq!(false, predicate_fn1.eval(&4));
7774
/// assert_eq!(true, predicate_fn2.eval(&4));
78-
fn not(self) -> NotPredicate<Self>
75+
fn not(self) -> NotPredicate<Self, Item>
7976
where
8077
Self: Sized,
8178
{
@@ -106,7 +103,7 @@ pub trait Predicate {
106103
/// assert_eq!(true, predicates[0].eval(&4));
107104
/// assert_eq!(false, predicates[1].eval(&4));
108105
/// ```
109-
fn boxed(self) -> BoxPredicate<Self::Item>
106+
fn boxed(self) -> BoxPredicate<Item>
110107
where
111108
Self: Sized + Send + Sync + 'static,
112109
{

src/float/close.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,7 @@ impl IsClosePredicate {
7878
}
7979
}
8080

81-
impl Predicate for IsClosePredicate {
82-
type Item = f64;
83-
81+
impl Predicate<f64> for IsClosePredicate {
8482
fn eval(&self, variable: &f64) -> bool {
8583
variable.approx_eq(&self.target, self.epsilon, self.ulps)
8684
}

src/function.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,10 @@ where
2323
_phantom: PhantomData<T>,
2424
}
2525

26-
impl<F, T> Predicate for FnPredicate<F, T>
26+
impl<F, T> Predicate<T> for FnPredicate<F, T>
2727
where
2828
F: Fn(&T) -> bool,
2929
{
30-
type Item = T;
31-
3230
fn eval(&self, variable: &T) -> bool {
3331
(self.function)(variable)
3432
}

src/lib.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,8 @@
6262
//! // returns a `bool`. Implementing a custom `Predicate` still allows all the
6363
//! // usual combinators of the `Predicate` trait to work!
6464
//! struct IsTheAnswer;
65-
//! impl Predicate for IsTheAnswer {
66-
//! type Item = i32;
67-
//! fn eval(&self, variable: &Self::Item) -> bool {
65+
//! impl Predicate<i32> for IsTheAnswer {
66+
//! fn eval(&self, variable: &i32) -> bool {
6867
//! *variable == 42
6968
//! }
7069
//! }

src/ord.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,11 @@ pub struct EqPredicate<T> {
2626
op: EqOps,
2727
}
2828

29-
impl<T> Predicate for EqPredicate<T>
29+
impl<T> Predicate<T> for EqPredicate<T>
3030
where
3131
T: PartialEq,
3232
{
33-
type Item = T;
34-
35-
fn eval(&self, variable: &Self::Item) -> bool {
33+
fn eval(&self, variable: &T) -> bool {
3634
match self.op {
3735
EqOps::Equal => variable.eq(&self.constant),
3836
EqOps::NotEqual => variable.ne(&self.constant),
@@ -102,13 +100,11 @@ pub struct OrdPredicate<T> {
102100
op: OrdOps,
103101
}
104102

105-
impl<T> Predicate for OrdPredicate<T>
103+
impl<T> Predicate<T> for OrdPredicate<T>
106104
where
107105
T: PartialOrd,
108106
{
109-
type Item = T;
110-
111-
fn eval(&self, variable: &Self::Item) -> bool {
107+
fn eval(&self, variable: &T) -> bool {
112108
match self.op {
113109
OrdOps::LessThan => variable.lt(&self.constant),
114110
OrdOps::LessThanOrEqual => variable.le(&self.constant),

0 commit comments

Comments
 (0)