I have the following minimal example:
use std::ops::{Deref, DerefMut};
trait Representation {
fn as_void_ptr(&self) -> *mut std::ffi::c_void {
self as *const Self as *mut _
}
}
impl Representation for f32 {}
pub trait PtrMut<T> {
fn ptr_mut(&mut self) -> &mut T;
}
struct MySlice<T> {
a: Vec<T>,
}
impl PtrMut<f32> for MySlice<f32> {
fn ptr_mut(&mut self) -> &mut f32 {
&mut self.a[0]
}
}
struct MyAsyncSlice<T> {
a: MySlice<T>,
ready: bool,
}
impl<T> Deref for MyAsyncSlice<T> {
type Target = MySlice<T>;
fn deref(&self) -> &Self::Target {
&self.a
}
}
impl<T> DerefMut for MyAsyncSlice<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.a
}
}
trait DoSomething {
fn do_something(&mut self);
}
When I write the following implementation, everything works as expected:
impl<D> DoSomething for D
where
D: DerefMut<Target: PtrMut<f32>>,
{
fn do_something(&mut self) {
todo!()
}
}
However, when I try to generalize it:
impl<T, D> DoSomething for D
where
D: DerefMut<Target: PtrMut<T>>,
T: Representation,
{
unsafe fn do_something(&mut self) {
todo!()
}
}
The compiler complains with the following error: error[E0207]: the type parameter
T is not constrained by the impl trait, self type, or predicates
I don’t understand why this happens. There can be only one implementation of DerefMut
for a given type, and it has a single associated Target
type. I am restricting DoSomething
to be implemented only for types whose Target
implements a specific generic trait, which I further constrain with T: Representation
. It seems that every generic parameter should be perfectly determined by these predicates, yet the compiler disagrees.
I think the following is related to this issue as well, when I do:
impl<D> DoSomething for D
where
D: DerefMut<Target: PtrMut<f32>>,
{
fn do_something(&mut self) {
todo!()
}
}
impl<D> DoSomething for D
where
D: DerefMut<Target: PtrMut<f64>>,
{
fn do_something(&mut self) {
todo!()
}
}
compiler complains that:
error[E0119]: conflicting implementations of trait `DoSomething`
--> src/test.rs:70:1
|
61 | / impl<D> DoSomething for D
62 | | where
63 | | D: DerefMut<Target: PtrMut<f32>>,
| |_____________________________________- first implementation here
...
70 | / impl<D> DoSomething for D
71 | | where
72 | | D: DerefMut<Target: PtrMut<f64>>,
| |_____________________________________^ conflicting implementation
I don't understand why those are conflicting implementation. These types can't overlap since one can't have multiple implementation of DerefMut trait for the same type.
Can someone explain what's going on here?
Rust playground link