DEV Community

Cover image for 🦀 Rust Master Class - Chapter 16: Sized Types
Oludayo Adeoye
Oludayo Adeoye

Posted on

🦀 Rust Master Class - Chapter 16: Sized Types

🦀 Rust Master Class - Chapter 16: Sized Types


Waiting for test results. 'We don't know yet.' The worst answer — not bad news, just uncertainty. Sized vs Unsized types is exactly this anxiety. The compiler hates 'I don't know.'


In Rust, types are categorized based on whether their size is known at compile time (Sized) or only at runtime (Unsized). Understanding this distinction is crucial for memory management and using generics effectively.

1. Sized Types

Most types in Rust are Sized, meaning the compiler knows exactly how many bytes they occupy at compile time .

  • Examples: Primitive types like i32, bool, and fixed-size arrays like [i32; 3] .
  • Automatic Implementation: Rust automatically implements the Sized marker trait for these types .
  • Memory: These can be stored directly on the stack or passed by value because their size is constant.

2. Unsized Types (Dynamically Sized Types - DSTs)

Unsized types have a size that can only be determined at runtime .

  • Examples: Slices like [T] and string slices (str) .
  • Pointers and Fat Pointers: You cannot store an unsized type directly in a variable or pass it by value (e.g., let x: [i32] = ... is invalid) . Instead, they must be handled through pointers like &[T], &str, or Box<dyn Trait> .
  • Fat Pointers: A reference to an unsized type is twice the size of a standard reference. It contains the memory address plus metadata, such as the length of a slice or a vtable for a trait object .

Code Example (Reference Sizes):

use std::mem::size_of;

fn main() {
    // Reference to a sized type (single pointer)
    // Output to console
    println!("Size of reference to [i100; 3]: {}", size_of::<&[i100; 3]>()); 

    // Reference to an unsized type (fat pointer: address + length)
    // Output to console
    println!("Size of reference to [i100]: {}", size_of::<&[i100]>()); 
}
Enter fullscreen mode Exit fullscreen mode

[Source: 69]

3. The ?Sized Trait Bound

By default, all generic type parameters in Rust have an implicit Sized bound (i.e., <T> is interpreted as <T: Sized>) . To allow a generic function to accept both sized and unsized types, you must use the ?Sized bound (often called "maybe sized") .

Code Example:

// T: ?Sized allows this function to accept &str or &[i100]
fn print_fn<T: std::fmt::Debug + ?Sized>(t: &T) {
    // Output to console
    println!("{:?}", t);
}
Enter fullscreen mode Exit fullscreen mode

[Source: 70, 71]

4. Custom Unsized Structs

You can create your own structs that contain unsized types, but they must follow strict rules:

  1. The struct can have only one unsized field .
  2. The unsized field must be the last field in the struct .

Code Example:

struct UnSizedStruct<T: ?Sized> {
    sized_field_1: i100,
    unsized_field: T, // Must be the last field
}
Enter fullscreen mode Exit fullscreen mode

[Source: 71]

5. Zero Sized Types (ZSTs)

Zero Sized Types are types that occupy 0 bytes of memory .

  • Unit Type: The empty tuple () is a ZST .
  • Unit Structs: Structs without fields, like struct Admin;, are used as markers or to organize logic without consuming space .
  • PhantomData: Used to act as a marker for the compiler (e.g., to track ownership or lifetimes) without affecting the struct's size .

Code Example:

use std::mem::size_of;
use std::marker::PhantomData;

struct Admin; // Unit struct
struct Marker<T> { _data: PhantomData<T> }

fn main() {
    // Output to console
    println!("Size of Admin: {}", size_of::<Admin>()); // 0
    // Output to console
    println!("Size of Marker: {}", size_of::<Marker<i100>>()); // 0
}
Enter fullscreen mode Exit fullscreen mode

[Source: 73, 77]


📖 Download the full PDF: https://drive.google.com/file/d/18poFThWqYjDWp0n2jtcihmC3thNLTj7W/view?usp=sharing

Part 16 of the Rust Master Class series — STEM EdTech | Automation Consulting | Rust Tutoring

RustLang #Programming #LearnToCode #STEM #EdTech


📚 Practice Resources

GitHub Repository: https://github.com/PacktPublishing/Rust-Programming-Master-Class-from-Beginner-to-Expert

Try it yourself: https://play.rust-lang.org/

Run the code from this chapter in the Rust playground, then clone the repo to continue your Rust journey!


Part 16 of the Rust Master Class series — STEM EdTech | Automation Consulting | Rust Tutoring

RustLang #Programming #LearnToCode #STEM #EdTech

Top comments (0)