Reputation: 22738
Why does this compile:
trait MyTrait {}
trait MyTraitFrom<'a, T> {
fn mytrait_from(value: &'a mut T) -> Self;
}
impl<'a, T: MyTrait> MyTraitFrom<'a, T> for &'a mut T {
fn mytrait_from(value: &'a mut T) -> Self {
value
}
}
impl<'a, T: MyTrait> MyTraitFrom<'a, &'a mut T> for &'a mut T {
fn mytrait_from(value: &'a mut &'a mut T) -> Self {
let value: &'a mut T = value;
value
}
}
but this doesn't:
trait MyTrait {}
trait MyTraitFrom<'a, T> {
fn mytrait_from(value: &'a mut T) -> Self;
}
impl<'a, T: MyTrait> MyTraitFrom<'a, T> for &'a mut dyn MyTrait {
fn mytrait_from(value: &'a mut T) -> Self {
value
}
}
impl<'a, T: MyTrait> MyTraitFrom<'a, &'a mut T> for &'a mut dyn MyTrait {
fn mytrait_from(value: &'a mut &'a mut T) -> Self {
let value: &'a mut T = value;
value
}
}
error[E0119]: conflicting implementations of trait `MyTraitFrom<'_, &mut _>` for type `&mut dyn MyTrait`
--> src/lib.rs:13:1
|
7 | impl<'a, T: MyTrait> MyTraitFrom<'a, T> for &'a mut dyn MyTrait {
| --------------------------------------------------------------- first implementation here
...
13 | impl<'a, T: MyTrait> MyTraitFrom<'a, &'a mut T> for &'a mut dyn MyTrait {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&mut dyn MyTrait`
|
= note: downstream crates may implement trait `MyTrait` for type `&mut _`
Isn't &'a mut T
more general than &'a mut dyn MyTrait
?
Upvotes: 1
Views: 51
Reputation: 71350
&'a mut T
is indeed more general than &'a mut dyn MyTrait
...
...if T
is not constrained somewhere else. Which it is here - the T
is the same for the generic parameter and the Self
type.
The more general code, which does not compile either, is:
impl<'a, T: MyTrait, U> MyTraitFrom<'a, T> for &'a mut U {
fn mytrait_from(value: &'a mut T) -> Self {
value
}
}
impl<'a, T: MyTrait, U> MyTraitFrom<'a, &'a mut T> for &'a mut U {
fn mytrait_from(value: &'a mut &'a mut T) -> Self {
let value: &'a mut T = value;
value
}
}
Think about it: we can list all generic parameters and Self
to obtain a unique identity for this implementation. If two identities conflict, their impl
s also do. For the dyn MyTrait
case, the identities (ignoring lifetimes) are (&'a mut dyn MyTrait
, T
) and (&'a mut dyn MyTrait
, &'a mut T
). As &'a mut T
is itself a T
, this clearly conflicts. The same also applies to the abovementioned example with U
. However, in your first case, the identitiers are (&'a mut T
, T
) and (&'a mut T
, &'a mut T
). These do not conflict, as when T
is &'a mut T
&'a mut T
becomes &'a mut &'a mut T
, and it is not the same as &'a mut T
anymore.
Upvotes: 1