🎓 A1Learner
🔍

Rust Trait Aliases

A trait alias is one short name for a bundle of traits. Any type with the listed traits counts as the alias.

The pain: the bound repeats everywhere

Every function that needs the same bundle writes the whole list again:

use std::fmt::{Debug, Display};
fn show<T: Display + Debug + Clone>(value: &T) {
    println!("{} / {:?}", value, value);
}
fn main() {
    show(&42);
    show(&String::from("hi"));
}

The idea: one name for a bundle

On a nightly compiler with the feature switched on, an alias looks like this. It adds no methods and no requirements — it is only a name.

#![feature(trait_alias)]

trait Pretty = Display + Debug;

On stable Rust today: refused

The stable compiler rejects the feature flag itself, with error E0554: “#![feature] may not be used on the stable release channel” (checked with the compiler).

// rustc answers: error[E0554] — feature flags are nightly-only

The stable stand-in: supertrait plus blanket impl

An empty supertrait, handed to every qualifying type by one blanket impl, does the same job today.

trait Pretty: Display + Debug {}

impl<T: Display + Debug> Pretty for T {}

Example

use std::fmt::{Debug, Display};

// The stable stand-in for a trait alias:
// an empty supertrait, plus one blanket impl that hands it
// to every type that already has both parts.
trait Pretty: Display + Debug {}

impl<T: Display + Debug> Pretty for T {}

fn show<T: Pretty>(value: &T) {
    println!("{} / {:?}", value, value);
}

fn main() {
    show(&42);
    show(&String::from("hi"));
}

Key points

  • A trait alias is pure shorthand: any type with the listed traits counts, with nothing extra to implement
  • Status: proposed in RFC 1733 and available only behind #![feature(trait_alias)] on nightly — not stable, so published crates cannot use it
  • Difference from the stand-in: the supertrait trick creates a real new trait in your API.
  • Someone could also implement that trait by hand.
  • An alias would add no new trait at all.

In this example, Pretty itself is never implemented by hand. The blanket impl hands it to every type that is both Display and Debug. show asks only for T: Pretty, one short bound, yet inside it may print with {} (the Display half) and with {:?} (the Debug half). The number shows twice in the same style. The string shows plainly with {} and quoted with {:?}. Both halves of the bundle are at work. This is exactly the job a trait alias would do, spelled the stable way.

Note

Until aliases land, the supertrait-plus-blanket-impl bundle is the pattern to reach for.

Rust Where Clauses uses that same bundle to shorten bounds.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Rust Playground

Exercise

You need a short name for Display + Debug bounds in a published crate, today. What do you use?