?Sized
Every type in Rust must have a statically known sized. So every type is implemented Sized
trait automatically. However there are sometime you need a DST(Dynamic Size Type), so you can use the special keyword ?Sized
to indicate that you accept a DST type: T: ?Sized
.
Rust will automatically called destructors of all type, most of the time, we don’t have to implement Drop
in most cases. When we implemented a Drop trait, rust will called the Drop::drop
method first, then drop the variable.
There are a cases that need to be remembered: when a value is drop with custom code, it means that the Drop::drop
method is called. However the Drop::drop
method take parameter &mut self
, so there might be some lifetime conflict for customized destructor.
The reason that Rust don’t accept a child trait to be accepted in function which needs parent trait is the subtyping will lead to undefined behavior.
trait Animal {
fn snuggle(&self);
fn eat(&mut self);
}
trait Cat: Animal {
fn meow(&self);
}
trait Dog: Animal {
fn bark(&self);
}
fn love(pet: Animal) {
pet.snuggle();
}
// This should be acceptable....?
let mr_snuggles: Cat = ...;
love(mr_snuggles);
//----------
fn evil_feeder(pet: &mut Animal) {
let spike: Dog = ...;
// `pet` is an Animal, and Dog is a subtype of Animal,
// so this should be fine, right..?
*pet = spike;
}
// No it is not acceptable
let mut mr_snuggles: Cat = ...;
evil_feeder(&mut mr_snuggles); // Replaces mr_snuggles with a Dog
mr_snuggles.meow();
The most usual way to use subtyping is lifetime. When lifetime 'b
contains lifetime 'a
, we can say 'b
is a subtype of the lifetime 'a
. To understand this rule, think of this sentence: “object live in lifetime 'a
live in lifetime 'b
too. This can also be understood by the above relationship that represented by Cat
Dog
Animal
. Also it is important to note that 'static
is a subtype for every lifetime.