Rust Trait object conversion

后端 未结 2 1476
醉梦人生
醉梦人生 2020-12-11 19:02

The following code won\'t compile due to two instances of this error:

error[E0277]: the trait bound Self: std::marker::Sized is not satis

2条回答
  •  一生所求
    2020-12-11 19:21

    Dynamically sized types can also implement traits. In particular, when you define an object-safe trait, the compiler also defines a dynamically sized type with the same name as the trait, which lets you use object types such as &Component.

    Object types such as &Component or &Any are not just ordinary pointers; they're fat pointers. A fat pointer combines a pointer to the data and another piece of data: for object types, it's a pointer to the vtable; for slices, it's the length of the slice.

    When casting from a regular pointer (e.g. a &Button) to an object type, the compiler statically knows which vtable to put in the fat pointer (e.g. Button's vtable for Any). On the other hand, Rust doesn't support casting from an object type to another object type (e.g. from &Component to &Any), because there's not enough data in an object to initialize the new fat pointer. This is why the compiler adds this note to the error message:

    = note: required for the cast to the object type `std::any::Any + 'static`
    

    There are two ways to fix this:

    1. Require that all types implementing Component be Sized:

      trait Component: Any + Sized {
          fn as_any(&self) -> &Any {
              self
          }
      
          fn as_any_mut(&mut self) -> &mut Any {
              self
          }
      }
      

      This has the consequence that you will not be able to use object types such as &Component or Box at all.

    2. Make the as_any and as_any_mut methods only available when Self is Sized:

      trait Component: Any {
          fn as_any(&self) -> &Any
              where Self: Sized
          {
              self
          }
      
          fn as_any_mut(&mut self) -> &mut Any
              where Self: Sized
          {
              self
          }
      }
      

      This way, you can still use object types for the trait, but you will not be able to call as_any and as_any_mut on them.

提交回复
热议问题