ZST
- Rust course
- Expert
- Lesson 10/46
- 4 min
Learn zero-sized types (ZSTs) and their advantages.
ZSTs
Zero-sized types take no memory at all: (), structs without fields, [T; 0] and PhantomData<T>. The compiler erases them entirely; Vec<()> makes no allocation, and HashMap<K, ()> takes no more room than a HashSet:
size_of::<()>() // 0
size_of::<PhantomData<u64>>() // 0
let v: Vec<()> = vec![(); 1_000_000]; // allocates no memoryZSTs are ideal for carrying type-level information: marker types, state machines (typestate), unit systems.
Unit safety
Zero-cost unit tags separate values that carry the same number but must not be mixed up:
use std::marker::PhantomData;
struct Metre;
struct Saniye;
struct Olcu<B> {
deger: f64,
_birim: PhantomData<B>,
}
fn yol(m: Olcu<Metre>) -> f64 { m.deger }
// yol(Olcu::<Saniye> { .. }) // error: unit mismatchIn memory, Olcu<Metre> is just an f64.
Practice Zero-sized types
Write the Olcu<B> type above and the Metre unit. Print size_of::<()>(), size_of::<PhantomData<u64>>() and size_of::<Olcu<Metre>>() separated by spaces.
Starter code
use std::marker::PhantomData;
use std::mem::size_of;
fn main() {
// buraya yaz
}Sample solution
#![allow(dead_code)]
use std::marker::PhantomData;
use std::mem::size_of;
struct Metre;
struct Olcu<B> {
deger: f64,
_birim: PhantomData<B>,
}
fn main() {
println!("{} {} {}", size_of::<()>(), size_of::<PhantomData<u64>>(), size_of::<Olcu<Metre>>());
}Expected output
0 0 8
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 Why is <code>PhantomData<T></code> needed?
- To tell the compiler about an unused type parameter, "I own/depend on this type" Correct answer
- To allocate memory
- For speed
- It isn't needed
Explanation: An unused type parameter is a compile error (E0392); PhantomData also gives the right information for drop checking and variance.
2 Phantom type
struct Olcu<B> {
deger: f64,
_birim: ____<B>,
}
struct Olcu<B> {
deger: f64,
_birim: PhantomData<B>,
}
Explanation: PhantomData<B> is zero-sized but uses the type parameter B.
3 Type and size
| Term | Meaning |
|---|---|
() |
0 |
PhantomData<u64> |
0 bytes |
Olcu<Metre> |
8 |
[u8; 0] |
Zero (array) |