Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Generics and Trait Boundaries

uv’s internal crates use generics to specialize hot, strongly typed pipelines.

Preparer<'a, Context: BuildContext> borrows tags, cache, hashing policy, and a DistributionDatabase parameterized by the build context. Resolver fetching is generic over Provider: ResolverProvider. PEP 508 parsing is generic over a Pep508Url representation. Associated types keep errors and domain values connected to their provider.

Trait objects appear where optional runtime substitution is genuinely useful. Option<Arc<dyn Reporter>> lets CLI progress implementations observe the same pipeline without parameterizing every enclosing command. Errors are frequently boxed at domain boundaries to keep large recursive error enums manageable.

Enums carry closed domain variation: Dist::Built | Source, cache buckets, lock modes, link modes, and resolution outcomes. These are not trait objects because exhaustive policy decisions are valuable.

The pattern is: generics for compile-time collaborators in core algorithms, enums for closed protocol/domain states, and trait objects for leaf observers or heterogeneous errors whose exact type no longer affects control flow.