error[E0119]: conflicting implementations of trait `std::convert::From<std::boxed::Box<(dyn ATrait + 'static)>>` for type `std::boxed::Box<(dyn ATrait + 'static)>`:
--> box_from_clash.rs:7:1
|
7 | impl<T: ATrait> From<T> for Box<dyn ATrait> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: conflicting implementation in crate `core`:
- impl<T> std::convert::From<T> for T;
error: aborting due to previous error
but the from impl is converting between different types: it converts T to Box, which are definitely different. Is this a rustc bug, a rustc design choice, or a misunderstanding by me?
EDIT It’s worth noting that the code will compile with no problems if you remove the ?Sized bound.
let boxed: Box<dyn ATrait> = Box::new(SomethingThatImplementsATrait);
let boxed2: Box<dyn ATrait> = boxed.from();
In the second line the compiler needs to find an implementation for <Box<dyn ATrait> as From<Box<dyn ATrait>>>::from, it can either take the fully generic one from core, or, because Box<dyn ATrait>: ATrait, the one you have written.
I'm just confused because one is wrapped in a Box and the other isn't. Does the compiler consider Box<T> and T to be the same type, or more specifically Box<dyn Trait> and T: Trait?
In the from impl, what if you replace T with Box<dyn ATrait + 'a>, then you will have a conflicting impl with From<T> for T impl, so the compiler rejects your impl. This is correct and can be fixed by removing the ?Sized bounds because dyn Trait: Trait and is unsized (i.e. doesn’t impl Sized) like how @Ixrec said above. This means that it is guaranteed to that Box<dyn ATrait + 'a>: ATrait is false, which means it cannot conflict with From<T> for T due to the constraint on T (T: ATrait).
edit: code blocks for clarity
impl<U: ATrait + ?Sized> ATrait for Box<U> {}
// replace `T` with `Box<dyn ATrait + 'a>`
// this is valid because `Box<dyn ATrait + 'a>: ATrait` by the first impl
// oh no a conflict with `impl From<T> for T`
impl<'a> From<Box<dyn ATrait + 'a>> for Box<dyn ATrait + 'a> {}
impl<U: ATrait> ATrait for Box<U> {}
// replace `T` with `Box<dyn ATrait + 'a>`
// this is no longer valid because Box<dyn ATrait + 'a> doesn't implement ATrait,
// because `dyn ATrait` is not `Sized`, this means this impl doesn't even exist!
// yay no conflicts
// impl<'a> From<Box<dyn ATrait + 'a>> for Box<dyn ATrait + 'a> {}
I understand now. It’s a shame that these impls overlap, because they are both bigger than their intersection. This means that I can never implement impl<U: ATrait + ?Sized> ATrait for Box<U> {} even though it seems like a desirable thing to have. . Does specialization help with this?
I just saw the context of where you’re trying this out. Damn, that’s annoying. Unfortunately I don’t know whether specialization can help currently.