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(¤t);
}
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"