Advanced Traits

Trait Aliases and Their Stability Status

A trait alias is a shorthand name for a recurring combination of traits (such as Debug + Clone + Send + Sync + 'static). Because the dedicated syntax trait MyAlias = TraitA + TraitB; (#![feature(trait_alias)]) remains unstable on nightly Rust, stable Rust libraries use the supertrait + universal blanket implementation pattern to create zero-cost trait aliases today.

Stability Status of trait Alias = ...

Feature Syntax Current Status
Native trait alias syntax pub trait ServiceBound = Send + Sync + Clone + 'static; Unstable (#![feature(trait_alias)], RFC 1733)
Supertrait + blanket impl idiom pub trait ServiceBound: Send + Sync + Clone + 'static {} + impl<T: ...> ServiceBound for T {} 100% Stable (works in all Rust editions)

Implementing a Trait Alias in Stable Rust

By defining an empty trait whose supertraits are the desired bound combination and immediately adding a blanket implementation for all types T satisfying those supertraits, any type that implements the underlying traits automatically implements the alias—without requiring downstream types to write an impl block:

Stable Trait Alias Pattern:

  1. Define supertrait bundle:
     `pub trait ThreadSafeValue: Clone + Debug + Send + Sync + 'static {}`

  2. Add universal blanket impl:
     `impl<T: Clone + Debug + Send + Sync + 'static> ThreadSafeValue for T {}`

  Result: Every `T` satisfying the 5 bounds automatically implements `ThreadSafeValue`!
use std::fmt::Debug;

// 1. Declare the trait alias as a trait with supertrait bounds:
pub trait MessagePayload: Clone + Debug + Send + Sync + 'static {}

// 2. Automatically implement it for every type satisfying those bounds:
impl<T> MessagePayload for T where T: Clone + Debug + Send + Sync + 'static {}

// Generic structs and functions now use the single concise bound `M: MessagePayload`:
struct Envelope<M: MessagePayload> {
    id: u64,
    payload: M,
}

fn broadcast<M: MessagePayload>(env: &Envelope<M>) -> Envelope<M> {
    println!("broadcasting envelope #{}: {:?}", env.id, env.payload);
    Envelope {
        id: env.id + 1,
        payload: env.payload.clone(),
    }
}

fn main() {
    // `String` satisfies `Clone + Debug + Send + Sync + 'static`, so it
    // automatically implements `MessagePayload` with zero boilerplate!
    let msg = Envelope {
        id: 1,
        payload: String::from("cluster-heartbeat"),
    };
    let forwarded = broadcast(&msg);
    println!("forwarded id: {}", forwarded.id);
}
broadcasting envelope #1: "cluster-heartbeat"
forwarded id: 2

Trait Aliases with Associated Type Constraints

The supertrait + blanket-impl pattern also supports aliasing traits with associated type constraints or Higher-Ranked Trait Bounds (such as aliasing Fn(&Request) -> Response + Send + Sync + 'static):

pub trait StringTransform: Fn(&str) -> String + Send + Sync + 'static {}

impl<F> StringTransform for F where F: Fn(&str) -> String + Send + Sync + 'static {}

fn apply_all(input: &str, transforms: &[Box<dyn StringTransform>]) -> String {
    let mut current = input.to_string();
    for t in transforms {
        current = t(&current);
    }
    current
}

fn main() {
    let pipeline: Vec<Box<dyn StringTransform>> = vec![
        Box::new(|s: &str| s.trim().to_string()),
        Box::new(|s: &str| s.to_uppercase()),
    ];

    println!("result: {:?}", apply_all("  rust traits  ", &pipeline));
}
result: "RUST TRAITS"