-2

I want to work with DST's and having the following scenario

I have the following trait which has ability to take Box and return new Trait Object outside:

pub trait MyTrait {
    fn create_from_box(boxed: Box<Self>) -> Self
    where
        Self: Sized;
}

I have following to different structs which are implementing MyTrait struct FirstStruct;

impl MyTrait for FirstStruct {
    fn create_from_box(boxed: Box<FirstStruct>) -> FirstStruct {
        FirstStruct // Build another struct with some logic and boxed struct values
    }
}

struct SecondStruct;

impl MyTrait for SecondStruct {
    fn create_from_box(boxed: Box<SecondStruct>) -> SecondStruct {
        SecondStruct // Build another struct with some logic and boxed struct values
    }
}

I have a function which gets my trait object in some conditional logic

fn get_my_trait_object() -> Box<MyTrait> {
    let condition = true; // Retrieved via some logic .

    match condition {
        true => Box::new(FirstStruct),
        false => Box::new(SecondStruct),
    }
}    

Then I have the following function which gets my trait object as boxed value and then passes it into MyTrait static method.

And then it tries to create a new MyTrait object which will used later on.

pub fn main() {
    let boxed = get_my_trait_object();
    let desired_trait_object = MyTrait::create_from_box(boxed);
}

The main problem here is, when I executed the code I get following two different errors:

  • The size for values of type dyn MyTrait cannot be known at compilation time
  • All local variables must have a statically known size

How can I solve these errors and achieve what I am trying to do?

Playground

Akiner Alkan
  • 6,145
  • 3
  • 32
  • 68
  • 1
    I don't understand what you are trying to do. `create_from_box` does not attempt to return a trait object, but a concrete type (and that's impossible because the concrete type of `boxed` is not known at compile time). – Boiethios Jan 07 '19 at 10:17
  • I am trying to generate a new concrete type regarding to dynamic boxed type. I do not know that is possible but if that is not possible, how can I achieve this need? – Akiner Alkan Jan 07 '19 at 10:26
  • Possible duplicate of [How to get a reference to a concrete type from a trait object?](https://stackoverflow.com/questions/33687447/how-to-get-a-reference-to-a-concrete-type-from-a-trait-object) – Boiethios Jan 07 '19 at 10:32
  • @Boiethios, Do I really need to use `as_any()` and `downcast_ref()`? Since this workaround is upcasting the trait first and downcasting manually, I thought that there may be better solution to the problem. – Akiner Alkan Jan 07 '19 at 10:37
  • Yes, or read the implementation and implement your own downcasting trait: give a unique id to each concrete type, and when you want to downcast to a type `T`, compare the id of `T` and the id of your trait object. If they are the same, do an unsafe `transmute`. – Boiethios Jan 07 '19 at 10:53
  • You cannot do what you want *as is* because downcasting is a compile-time operation in Rust, while a trait object is dynamic. – Boiethios Jan 07 '19 at 10:54
  • 1
    What type do you want `desired_trait_object` to have? – Jmb Jan 07 '19 at 13:54
  • Just to chime in, I also don't understand what behavior you want from this code. You have two "versions" of `create_from_box`: one returns a `FirstStruct` and one returns a `SecondStruct`. Which one should `MyTrait::create_from_box(boxed)` call? There is no version of `create_from_box` that is available on trait objects, because you can only use it when you know the concrete type (`Self`) it returns. – trent Jan 07 '19 at 14:22
  • You may be interested in [Why a function on a trait object cannot be called when bounded with `Self: Sized`?](https://stackoverflow.com/q/51822118/3650362) and [Traits as a return value from a function](https://stackoverflow.com/q/23437179/3650362) (which is a duplicate of [How do I return an instance of a trait from a method?](https://stackoverflow.com/q/30661046/3650362)). – trent Jan 07 '19 at 14:41
  • *How to create trait object from boxed trait?* — a ["boxed trait" **is** a trait object](https://stackoverflow.com/questions/27567849/what-makes-something-a-trait-object) – Shepmaster Jan 07 '19 at 16:54

1 Answers1

1

You can use self even if your type is boxed (see into_vec), so your solution could be.

pub trait CreateFromBox {
    fn create_from_box(self: Box<Self>) -> Self;
}

#[derive(Debug, Clone)]
struct Foo(u32);
impl CreateFromBox for Foo {
    fn create_from_box(self: Box<Self>) -> Self {
        Self(self.0 + 1)
    }
}

fn main() {
    let a: Box<Foo> = Box::new(Foo(3));
    let tmp = a.clone();
    let b: Foo = tmp.create_from_box();

    println!("{:?} {:?}", a, b);
}
hellow
  • 12,430
  • 7
  • 56
  • 79
  • Something like this? I think your main problem is your `get_my_trait_object` which doesn't work in the way you think you want it. It looks like you want to implement the factory pattern, which doesn't work well with rust. – hellow Jan 07 '19 at 10:44
  • That's not what the OP wants, if I understand well. He wants to downcast from a trait object. – Boiethios Jan 07 '19 at 10:50
  • @Boiethios, This is more like I am seeking to, Trying to implement it accordingly on my side. Let you know if I could. – Akiner Alkan Jan 07 '19 at 10:54
  • @hellow, This was close to my intention but the problem here is we are working on fully over concrete objects like `Box`, I need the inference from trait types like `Box` which seems not applicable in Rust I guess. – Akiner Alkan Jan 07 '19 at 11:47