Week 6 - Traits, Coherence, and Monomorphization¶
6.1 Conceptual Core¶
- A trait is a named set of capabilities. Implementing a trait for a type is a claim that the type satisfies a contract-the contract is partly enforced by the compiler and partly by the implementor's discipline (e.g.,
HashandEqconsistency). - Coherence / orphan rule: an
impl Trait for Typeis allowed only if eitherTraitorTypeis local to the current crate. This is what prevents "two crates impl the same trait for the same type" diamond conflicts. - Monomorphization: every distinct type substitution at a generic call site produces a fresh compiled function in the binary.
Vec<u8>::pushandVec<i32>::pushare two different symbols. This is the dual edge of the language: zero-cost abstraction in exchange for binary bloat and compile time.
6.2 Mechanical Detail¶
- Static dispatch (
impl Trait, generics) vs dynamic dispatch (dyn Trait). The vtable layout ofdyn Trait: a fat pointer (data pointer + vtable pointer), where the vtable contains the destructor, size, alignment, and the trait method pointers. Inspect a real one withcargo asm. - Object safety / dyn compatibility: a trait is dyn-compatible if every method has a
Self: Sizedbound or takesselfby reference and does not returnSelfor useSelfin generic position. The 2024 edition formalized "dyn-compatible" terminology-use it. - Sealed traits: declare a private supertrait in a private module to prevent downstream impls. Used in
std::error::Errorhistorically, intokio::io::AsyncReadextensions, and in any API where future-compatibility demands closed extension. - Auto traits (
Send,Sync,Unpin,UnwindSafe,RefUnwindSafe): structural, opt-out via negative impl on nightly orPhantomData<*const ()>on stable.
6.3 Lab-"Bloat Forensics"¶
- Write a generic function
fn process<T: Display>(items: &[T]) -> Stringthat formats and concatenates. Instantiate it with five distinct types in a binary. - Run
cargo bloat --release --filter processand confirm there are five symbols. - Refactor to a
dyn Displayversion (&[&dyn Display]). Re-runcargo bloat. Document the binary-size delta and the codegen tradeoff. - Now read the disassembly of the dyn version with
cargo asmand identify the indirect call.
6.4 Idiomatic & Clippy Drill¶
clippy::needless_pass_by_value,clippy::trait_duplication_in_bounds,clippy::implicit_hasher. The last is subtle-explain why leakingRandomStateinto a public API is a SemVer hazard.
6.5 Production Hardening Slice¶
- Configure
[profile.release.package."*"] codegen-units = 1for maximum cross-function inlining, while keeping[profile.dev] codegen-units = 256for fast iteration. Document the build-time delta.