Sized
There's more to &str than meets the eye, even after having
investigated deref coercion.
From our previous discussion on memory layouts,
it would have been reasonable to expect &str to be represented as a single usize on
the stack, a pointer. That's not the case though. &str stores some metadata next
to the pointer: the length of the slice it points to. Going back to the example from
a previous section:
let mut s = String::with_capacity(5);
s.push_str("Hello");
// Create a string slice reference from the `String`, 
// skipping the first byte.
let slice: &str = &s[1..];In memory, we get:
                    s                              slice
      +---------+--------+----------+      +---------+--------+
Stack | pointer | length | capacity |      | pointer | length |
      |    |    |   5    |    5     |      |    |    |   4    |
      +----|----+--------+----------+      +----|----+--------+
           |        s                           |  
           |                                    |
           v                                    | 
         +---+---+---+---+---+                  |
Heap:    | H | e | l | l | o |                  |
         +---+---+---+---+---+                  |
               ^                                |
               |                                |
               +--------------------------------+
What's going on?
Dynamically sized types
str is a dynamically sized type (DST).
A DST is a type whose size is not known at compile time. Whenever you have a
reference to a DST, like &str, it has to include additional
information about the data it points to. It is a fat pointer.
In the case of &str, it stores the length of the slice it points to.
We'll see more examples of DSTs in the rest of the course.
The Sized trait
Rust's std library defines a trait called Sized.
pub trait Sized {
    // This is an empty trait, no methods to implement.
}A type is Sized if its size is known at compile time. In other words, it's not a DST.
Marker traits
Sized is your first example of a marker trait.
A marker trait is a trait that doesn't require any methods to be implemented. It doesn't define any behavior.
It only serves to mark a type as having certain properties.
The mark is then leveraged by the compiler to enable certain behaviors or optimizations.
Auto traits
In particular, Sized is also an auto trait.
You don't need to implement it explicitly; the compiler implements it automatically for you
based on the type's definition.
Examples
All the types we've seen so far are Sized: u32, String, bool, etc.
str, as we just saw, is not Sized.
&str is Sized though! We know its size at compile time: two usizes, one for the pointer
and one for the length.
Exercise
The exercise for this section is located in 04_traits/08_sized