I'm trying to write an extension trait that allows me to move any value of type T
into any Box<B>
, where Box<T>
can be coerced into Box<B>
. My first attempt is the following:
trait IntoBox<B: ?Sized> {
fn into_box(self) -> Box<B>;
}
impl<T, B: ?Sized> IntoBox<B> for T
where
Box<T>: Into<Box<B>>,
{
fn into_box(self) -> Box<B> {
Box::new(self).into()
}
}
fn main() {
// Ok
let _: Box<u32> = 42.into_box();
// Error: the trait bound `std::boxed::Box<std::fmt::Display>:
// std::convert::From<std::boxed::Box<&str>>` is not satisfied
let _: Box<std::fmt::Display> = "Hello World".into_box();
}
This code works for regular boxes, but not trait objects. I suspect Into
is the wrong bound here. What should I use instead?
Edit: As explained in the answer to this question, this problem can be solved with respect to any number of concrete types T
by providing a blanket impl for T: Unsize<U>
. However this does not work in the generic case because the impls would be conflicting:
impl<T, B> IntoBox<B> for T
where
Box<T>: Into<Box<B>>,
{
fn into_box(self) -> Box<B> {
Box::new(self).into()
}
}
impl<T, B: ?Sized> IntoBox<B> for T
where
B: std::marker::Unsize<T>
{
fn into_box(self) -> Box<B> {
Box::new(self)
}
}