2

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)
    }
}
Fabian Knorr
  • 3,134
  • 3
  • 20
  • 32
  • https://play.rust-lang.org/?gist=c9834097a07ece7b0d1dff6d5bebe44e&version=stable&mode=debug&edition=2015 this seems to work with your example. but I think you cannot call `.into_box()` on unsized types then. edit: oh I just see your additional constraint with the `Box` to `Box` coercion. – belst Jul 21 '18 at 11:27
  • Hmm, if the `Box` -> `Box` conversion happens automatically, maybe I don't need that bound after all. – Fabian Knorr Jul 21 '18 at 12:06
  • you don't need to have `From` implemented if you want to convert a Boxed value to a Trait object. – belst Jul 21 '18 at 16:37
  • I believe your question is answered by the answers of [How can I define a function with a parameter that can be multiple kinds of trait objects?](https://stackoverflow.com/q/51247690/155423). If you disagree, please [edit] your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Jul 21 '18 at 22:19
  • Edited, the solution does not work in the generic case. – Fabian Knorr Jul 23 '18 at 05:09
  • Yes, it **cannot** be solved in the generic case because they are overlapping. There is no solution to that, it is a hard constraint of the Rust compiler. It has nothing to do with your specific code. – Shepmaster Jul 23 '18 at 12:50
  • You're right. I believe there _might_ exist a solution though if the standard library implemented `From> for Box where U: Unsize`. – Fabian Knorr Jul 23 '18 at 15:22

0 Answers0