740-phantom-variance-control — Phantom Variance Control
Tutorial Video
Text description (accessibility)
This video demonstrates the "740-phantom-variance-control — Phantom Variance Control" functional Rust example. Difficulty level: Advanced. Key concepts covered: Functional Programming. Variance describes how subtyping relationships propagate through generic type constructors. Key difference from OCaml: 1. **Syntax**: OCaml uses `+'a` / `
Tutorial
The Problem
Variance describes how subtyping relationships propagate through generic type constructors. In Rust, lifetimes and types can be covariant, contravariant, or invariant in a type parameter. Getting variance wrong leads to unsound code: a Cell<&'static str> being treated as Cell<&'short str> would allow writing a short-lived reference into a long-lived cell. PhantomData is the tool for explicitly setting variance when the compiler cannot infer it correctly from the struct fields, especially when raw pointers are involved.
🎯 Learning Outcomes
PhantomData<T> for covariance (acts like owning a T)PhantomData<fn(T)> for contravariance (acts like a function consuming T)PhantomData<Cell<T>> or PhantomData<*mut T> for invarianceCode Example
#![allow(clippy::all)]
//! # Phantom Variance Control
pub fn placeholder() -> &'static str {
"phantom-variance-control implementation"
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_placeholder() {
assert!(!placeholder().is_empty());
}
}Key Differences
+'a / -'a variance annotations directly; Rust encodes variance through the type of the PhantomData field.PhantomData<fn(T)> for contravariance is a non-obvious idiom requiring documentation.OCaml Approach
OCaml uses variance annotations directly on type parameters: type +'a t (covariant), type -'a t (contravariant), and type 'a t (invariant by default). The compiler verifies that the annotation matches the actual usage. OCaml's explicit variance annotations are more readable than Rust's PhantomData trick. The Base library's Container types use precise variance annotations to enable safe covariant use.
Full Source
#![allow(clippy::all)]
//! # Phantom Variance Control
pub fn placeholder() -> &'static str {
"phantom-variance-control implementation"
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_placeholder() {
assert!(!placeholder().is_empty());
}
}#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_placeholder() {
assert!(!placeholder().is_empty());
}
}
Deep Comparison
Variance Control
See example files for comparison.
Exercises
Writer<T> type that is contravariant in T — it accepts a T but produces nothing — and verify that Writer<&'short str> can be used as Writer<&'static str>.Buffer<T> type that must be invariant in T because it both reads and writes T. Use PhantomData<Cell<T>> and explain why invariance is required.Producer<T> (covariant) and Consumer<T> (contravariant) and combine them into a Channel<T> that is invariant, demonstrating variance composition.