Saltar a contenido

Week 5 - Advanced Lifetimes, Variance, and HRTBs

5.1 Conceptual Core

  • Subtyping in Rust exists only among lifetimes. 'static <: 'a for 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 T is covariant in 'a and T.
  • &'a mut T is covariant in 'a, invariant in T.
  • fn(T) -> U is contravariant in T, covariant in U.
  • Cell<T>, *mut T, UnsafeCell<T> are invariant in T.
  • 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 a T for variance and Drop-checker purposes, even though no T is stored. Crucial for FFI wrappers and arena types.
  • 'static is not "lives forever"-it means "could live until program end if it wanted to." A &'static str is 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-checks to CI. Adding/removing a lifetime parameter to a public type is a SemVer-major change; the tool will catch it.

Comments