Hello. I have a problem. I'm writing a physics engine, which is where the problem happened. I am currently working on object collision and I have 2 traits: ObjectInterface and MoveInterface: ObjectInterface. In the MoveInterface: ObjectInterface trait, I have the function fn sat(&self, object: &dyn ObjectInterface) -> Option<(f32, Vec2D, Vec2D)>. And here the actual problem is that the compiler complains that I use ObjectInterface in the function. My idea is that a moving object can collide with both a moving object and a standing object. How can this be fixed?
Error:
error[E0658]: trait upcasting coercion is experimental
--> src/physics_engine/map.rs:34:65
|
34 | println!("{:?}", (*self.dyn_objects[i]).sat(&(*self.dyn_objects[j])));
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
then it will accept an &dyn MoveInterface. However, that only works if sat() can be generic, which it can't if it going to be used on a trait object, so this basic technique doesn't apply to your situation.
Another possibility is to do the explicit upcasting trick that is often used with dyn Any:
trait MoveInterface: ObjectInterface {
fn as_object(&self) -> &dyn ObjectInterface;
// ...
}
// then in each of your implementations...
impl MoveInterface for SomeType {
fn as_object(&self) -> &dyn ObjectInterface { self }
// ...
}
// then use it like this:
println!("{:?}", (*self.dyn_objects[i]).sat(self.dyn_objects[j].as_object()));
This is essentially an explicit version of the trait upcasting the compiler doesn't currently support: by implementing the as_object() method, we insert into the MoveInterface vtable a function that can return an ObjectInterface vtable pointer.
The catch is that you have to write fn as_object(&self) in every impl. (It cannot be a default method.)