I have the following code:
use std::ops::Div;
use std::ops::Mul;
#[derive(Debug)]
struct Foo<T> {
bar: T,
}
impl<T> Foo<T>
where
T: Div<Output = T> + Copy,
{
fn new(bar: T) -> Foo<T> {
let baz = Foo::baz(bar);
Foo { bar: bar / baz }
}
fn baz(bar: T) -> T {
unimplemented!();
}
}
impl<T> Mul for Foo<T>
where
T: Mul<Output = T>,
{
type Output = Foo<T>;
fn mul(self, other: Foo<T>) -> Foo<T> {
Foo::new(self.bar * other.bar)
}
}
However, the compiler complains:
error[E0277]: cannot divide `T` by `T`
--> src/main.rs:29:9
|
29 | Foo::new(self.bar * other.bar)
| ^^^^^^^^ no implementation for `T / T`
|
= help: the trait `std::ops::Div` is not implemented for `T`
= help: consider adding a `where T: std::ops::Div` bound
note: required by `<Foo<T>>::new`
--> src/main.rs:13:5
|
13 | fn new(bar: T) -> Foo<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
--> src/main.rs:29:9
|
29 | Foo::new(self.bar * other.bar)
| ^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
= help: consider adding a `where T: std::marker::Copy` bound
note: required by `<Foo<T>>::new`
--> src/main.rs:13:5
|
13 | fn new(bar: T) -> Foo<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^
This can be fixed with this modification:
impl<T> Mul for Foo<T>
where
T: Mul<Output = T> + Div<Output = T> + Copy,
Why do I need to add Div<Output = T>
and Copy
to Mul for Foo<T>
? Shouldn't Foo<T>
already satisfy the bounds because of:
impl<T> Foo<T>
where
T: Div<Output = T> + Copy,
Each impl
block is completely distinct from each other, including their trait bounds — the fact that one impl
block has a constraint means nothing to the others.
In this case, your impl
block for the trait Mul
doesn't really need the Div
trait, as it could construct the Foo
directly:
impl<T> Mul for Foo<T>
where
T: Mul<Output = T>,
{
type Output = Foo<T>;
fn mul(self, other: Foo<T>) -> Foo<T> {
Foo { bar: self.bar * other.bar }
}
}
It is only because you have chosen to call Foo::new
(which has the Div
and Copy
requirements) that your original version of Mul
will not compile. This is conceptually the same problem as this plain function which also doesn't need Copy
or Div
:
fn x<T>(a: T) -> Foo<T> {
Foo::new(a)
}
Note that I've said "impl
block", not "inherent impl
block" or "trait impl
block". You can have multiple inherent impl
blocks with different bounds:
impl<T> Vec<T> {
pub fn new() -> Vec<T> { /* ... */ }
}
impl<T> Vec<T>
where
T: Clone,
{
pub fn resize(&mut self, new_len: usize, value: T) { /* ... */ }
}
This allows a type to have functions that only apply when certain conditions are met.
See also: