Description
When implementing a trait with a member function (vs. one without), the compiler requires more information and takes much longer to compile.
Consider the following two implementations of addition over Peano numbers as types:
First, using std::ops::Add
: http://is.gd/7tO1cK
Second, using a custom trait for addition, AddPeano
, that has only an associated type and no member functions: http://is.gd/byhqSn
The key difference is here:
Using AddPeano
,
impl<Lhs: Peano + AddPeano<Rhs>, Rhs: Peano> AddPeano<Rhs> for Succ<Lhs> {
type Output = Succ<<Lhs as AddPeano<Rhs>>::Output>;
}
Using std::ops::Add
,
impl<Lhs: Peano + Add<Rhs>, Rhs: Peano> Add<Rhs> for Succ<Lhs> where <Lhs as Add<Rhs>>::Output: Peano {
type Output = Succ<<Lhs as Add<Rhs>>::Output>;
fn add(self, rhs: Rhs) -> Self::Output { unreachable!() }
}
Without the where
clause, the compiler gives the error
error: the trait `Peano` is not implemented for the type `<Lhs as core::ops::Add<Rhs>>::Output`
In main()
for both of those examples, the Add
traits are used for successive doubling until the number 32
is reached. Using AddPeano
, playpen finishes in moments, whereas using Add
it triggers playpen's timeout and fails to compile.
I have had similar results locally ... even using up 8 GB of ram in the case of the std::ops
version while the version without a function would compile virtually instantly.