How to solve the problem with the transfer of an object belonging to a trait?

Hello everyone. I want to pass certain objects to the "OtherStructure" structure. Approximate implementation from below:

struct JustStructure(u8);

impl SpecialTrait for JustStructure {
    
}

impl SimpleTrait for JustStructure {
    
}

trait SpecialTrait: SimpleTrait {
    
}

trait SimpleTrait: AsSimple {
    
}

trait AsSimple {
    fn as_simple(&self) -> &dyn SimpleTrait;
}

impl<T: SimpleTrait> AsSimple for T {
    fn as_simple(&self) -> &dyn SimpleTrait {
        self
    }
}

struct OtherStructure {
    object1: Box::<dyn SimpleTrait>,
    object2: Box::<dyn SimpleTrait>,
}

impl OtherStructure {
    fn new(object1: Box<dyn SimpleTrait>, object2: Box<dyn SimpleTrait>) -> Self {
        OtherStructure {
            object1,
            object2,
        }
    }
}

fn main() {
    let object1: JustStructure = JustStructure(255);
    let object2: JustStructure = JustStructure(254);
    let vec_objects: Vec<Box<dyn SpecialTrait>> = vec![Box::new(object1), 
                                                       Box::new(object2)];
    
    let object3: OtherStructure = OtherStructure::new(Box::new(vec_objects[0].as_simple()), vec_objects[1].as_simple());
}

The compiler throws this error:

error[E0277]: the trait bound `&dyn SimpleTrait: SimpleTrait` is not satisfied
  --> src/main.rs:49:55
   |
49 |     let object3: OtherStructure = OtherStructure::new(Box::new(vec_objects[0].as_simple()), vec_objects[1].as_simple());
   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `SimpleTrait` is not implemented for `&dyn SimpleTrait`
   |
   = help: the trait `SimpleTrait` is implemented for `JustStructure`
   = note: required for the cast to the object type `dyn SimpleTrait`

error[E0308]: mismatched types
  --> src/main.rs:49:93
   |
49 |     let object3: OtherStructure = OtherStructure::new(Box::new(vec_objects[0].as_simple()), vec_objects[1].as_simple());
   |                                                                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Box`, found `&dyn SimpleTrait`
   |
   = note: expected struct `Box<(dyn SimpleTrait + 'static)>`
           found reference `&dyn SimpleTrait`

Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `playground` due to 2 previous errors

I've also tried passing objects through links, but I'm having problems with lifetimes(

How can this problem be solved? And how to solve it more correctly through links or box?

vec_objects[0].as_simple() returns a &dyn SimpleTrait and you want to box it. This can be done, but the resulting Box will need to be of type Box<dyn SimpleTrait + 'a> and will also need to implement impl SimpleTrait for &dyn SimpleTrait.

As far as I understand, downcasting of trait objects is not yet supported in Rust, so doing this is quite problematic.

Here is an example of implementation

1 Like

By "through links" do you mean by reference?

If &'a dyn SimpleTrait gave you lifetime trouble, Box<dyn SimpleTrait + 'a> probably will. [1] Are you looking for the ability to effectively clone an owned Box<dyn SimpleTrait> from a borrowed &dyn SimpleTrait?


  1. Also, &dyn Trait and Box<dyn Trait> don't automatically implement Trait like dyn Trait generally does, so you may have to supply that implementation. ↩ī¸Ž

I'm 99% sure topicstarter does mistake #6.a and tries to find a way to convert OOP-heavy design into Rust.

Although, to be far, this one is a bit less crazy than others since downcasting of traits is not inherently dangerous (like implementation inheritance) and it works on nightly.

1 Like

Yes.

Ideally, I want to pass the object to the structure so that the structure performs logical operations on the object. And vec_objects will be used constantly with already changed data. So I want to copy objects.

For various technical reasons, Clone can't be implemented for trait objects. You can, however, write a method that will return a boxed clone:

trait SimpleTrait: CloneAsSimple {
    
}

trait CloneAsSimple {
    fn as_simple(&self) -> Box<dyn SimpleTrait>;
}

impl<T: SimpleTrait + Clone + 'static> CloneAsSimple for T {
    fn as_simple(&self)->Box<dyn SimpleTrait> {
        Box::new(self.clone())
    }
}

impl CloneAsSimple for Box<dyn SimpleTrait> {
    fn as_simple(&self)->Box<dyn SimpleTrait> {
        (*self).as_simple()
    }
}

impl SimpleTrait for Box<dyn SimpleTrait> {}
1 Like

Pretty much echoing @2e71828:

-trait SimpleTrait: AsSimple {}
+trait SimpleTrait: AsSimple + CloneSimple {}
+
+trait CloneSimple {
+    fn into_boxed_simple(&self) -> Box<dyn SimpleTrait>;
+}
+
+impl CloneSimple for JustStructure {
+    fn into_boxed_simple(&self) -> Box<dyn SimpleTrait> {
+        // Probably more typically: Box::new(self.clone())
+        Box::new(JustStructure(self.0))
+    }
+}

 fn main() {
     // ...
     let object3: OtherStructure = OtherStructure::new(
-        Box::new(vec_objects[0].as_simple()),
-        vec_objects[1].as_simple(),
+        vec_objects[0].into_boxed_simple(),
+        vec_objects[1].into_boxed_simple()
     );
 }

Playground with some other formulations.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.