liveBook · Manning

Marker trait

As explained in Idiomatic Rust

A marker trait is a Rust trait that conveys compile-time information about a type without necessarily defining methods or other behavior.

A marker trait indicates an attribute of a Rust type without necessarily adding behavior. It is often empty: its purpose is to let other code require a property at compile time. This is a specialized technique, useful when a named constraint makes code clearer than repeating trait bounds. section 7.5 section 7.0

Listing 7.2 Full-featured marker trait
#[derive(
    Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
struct KitchenSink;               #1

trait FullFeatured {}             #2

impl<T> FullFeatured for T where  #3
    T: Clone
        + Copy
        + std::fmt::Debug
        + Default
        + Eq
        + std::hash::Hash
        + Ord
        + PartialEq
        + PartialOrd
{
}

`FullFeatured` has no methods. Its blanket implementation marks every type that satisfies the listed bounds; the derived `KitchenSink` type satisfies them without an explicit `impl FullFeatured`. section 7.5

Require the marker in a generic type

`struct Container<T: FullFeatured> { t: T }` requires its element type to meet the marker’s bounds. With the blanket implementation above, `Container { t: KitchenSink {} }` is valid. The marker gives the constraint a name instead of repeating its list of traits at each use. section 7.5

Keep the distinction between marking and behavior clear. `Send` and `Sync` are marker traits without methods, but implementing either manually requires `unsafe`; only the compiler can do so safely. A supertrait declaration such as `trait CloneAndDebug: Clone + Debug {}` expresses required traits directly. Although a trait with methods can also be treated as a marker, an empty trait is generally less confusing. `PhantomData` is different: it is a marker struct used to represent a generic parameter without storing a value of that type. section 7.5 section 2.1.5

How Idiomatic Rust covers it

How deep it goes
Works through an empty trait, blanket implementation, derived type, and generic bound; offers no single prescribed use case.
Examples
Uses a derived unit struct, an empty `FullFeatured` trait, its blanket implementation, and a generic container constrained by that trait.
What it assumes
Assumes familiarity with Rust traits, generic bounds, and derives while introducing the marker-trait idiom itself.
What you can do after
Build it from scratch with an empty trait and blanket implementation, then use it as a generic bound.
How it connects
Connects blanket implementations, trait bounds, supertraits, Send, and Sync; distinguishes marker traits from PhantomData marker structs.

Also explained in

Compare how 2 books explain marker trait →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Idiomatic Rust. The section links point to the parts of the book it draws on.