Member-only story
🦀 Variance in Rust Explained
The hidden rules of type substitution
Rust’s type system enforces rules you never explicitly write. When you pass a reference to a function, the compiler silently decides whether a longer lifetime can substitute for a shorter one. When you use a generic type, it determines whether Container<&'long T> can become Container<&'short T>. These decisions follow a system called variance, and understanding it transforms confusing compiler errors into predictable behavior.
Most Rust programmers encounter variance indirectly. They write code that seems reasonable, the compiler rejects it, and they add lifetime annotations until it works. This trial-and-error approach obscures something elegant: a small set of rules governs all these behaviors. Learn the rules, and you’ll predict what the compiler accepts before you write the code.
Variance answers a deceptively simple question: when can one type substitute for another? The answer depends on where that type appears. A type that works as a function argument might fail as a return value. A type safe in an immutable reference becomes dangerous in a mutable one. The rules aren’t arbitrary. They prevent real bugs.









