The following code won't compile due to two instances of this error:
error[E0277]: the trait bound
Self: std::marker::Sized
is not satisfied
I don't understand why Sized
is required in this instance as both &self
and &Any
are pointers and the operation does not require knowledge of the size of the structure that implements the trait, it only requires knowledge of the pointer itself and the type it is converting from and to, which it will have because &self
is generic when implemented inside a trait.
I think this may be an instance of the compiler enforcing unnecessary constraints and I've considered filing an issue with the rust-lang GitHub repo but I figured I should probably see if someone here knows something I don't before I go file an issue.
use std::any::Any;
trait Component: Any {
fn as_any(&self) -> &Any {
self
}
fn as_any_mut(&mut self) -> &mut Any {
self
}
}
The alternative to this is to make as_any()
and as_any_mut()
required functions for the structs that implement this trait, but for those structures the implementation would always be exactly as displayed here down to each individual character, resulting in several instances of identical boilerplate code.
A trait object is an opaque value of another type that implements a set of traits. The set of traits is made up of an object safe base trait plus any number of auto traits. Trait objects implement the base trait, its auto traits, and any supertraits of the base trait.
The Into trait is simply the reciprocal of the From trait. That is, if you have implemented the From trait for your type, Into will call it when necessary.
Implementing Intoalways use From . However, in most cases, people use Into to do the conversions, and this will allow that. In almost all cases, you should try to implement From , then fall back to Into if From can't be implemented.
Implementing Into for conversions to external types in old versions of Rust. It is important to understand that Into does not provide a From implementation (as From does with Into ). Therefore, you should always try to implement From and then fall back to Into if From can't be implemented.
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:
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<Component>
at all.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With