Week 5 - Advanced Lifetimes, Variance, and HRTBs¶
5.1 Conceptual Core¶
- Subtyping in Rust exists only among lifetimes.
'static <: 'afor any'a. There is no Liskov-style subtyping for nominal types. - Variance describes how the subtyping of a generic parameter lifts to the type constructor:
&'a Tis covariant in'aandT.&'a mut Tis covariant in'a, invariant inT.fn(T) -> Uis contravariant inT, covariant inU.Cell<T>,*mut T,UnsafeCell<T>are invariant inT.- Higher-Ranked Trait Bounds (HRTBs):
for<'a> F: Fn(&'a str) -> &'a str - thefor<'a>quantifier means "for *every*'a` the caller might pick." Used pervasively in async closures and iterator combinators.
5.2 Mechanical Detail¶
- The lifetime-elision rules (three of them; memorize). Then write a function that elision cannot solve and observe the error.
PhantomData<T>: how to force a type to "act as if" it owned aTfor variance and Drop-checker purposes, even though noTis stored. Crucial for FFI wrappers and arena types.'staticis not "lives forever"-it means "could live until program end if it wanted to." A&'static stris an immutable reference whose region has no upper bound.- GATs (Generic Associated Types):
type Item<'a> where Self: 'a;. The pattern that finally unblocked lending iterators. Read RFC 1598 and the stabilization PR.
5.3 Lab-"A Lending Iterator"¶
Implement a WindowsMut lending iterator that yields overlapping &mut [T] windows over a slice. This requires GATs. Property-test it against a naive O(n²) reference implementation.
5.4 Idiomatic & Clippy Drill¶
clippy::needless_lifetimes,clippy::extra_unused_lifetimes,clippy::elidable_lifetime_names. Read RFC 2115 ("argument position impl Trait") and refactor a generic function to use APIT where the lifetime adds no information.
5.5 Production Hardening Slice¶
- Add
cargo-semver-checksto CI. Adding/removing a lifetime parameter to a public type is a SemVer-major change; the tool will catch it.