Associated Types and Advanced Traits

Supertraits

A supertrait is a prerequisite trait bound declared on another trait (trait Subtrait: Supertrait), requiring any type that implements Subtrait to also implement Supertrait and allowing default methods in Subtrait to call methods from Supertrait.

Declaring and Implementing Supertraits

use std::fmt;

// `OutlinePrint` requires `Self` to implement `fmt::Display`:
trait OutlinePrint: fmt::Display {
    fn outline_print(&self) {
        let output = self.to_string(); // Provided by Display
        let len = output.len();
        println!("{}", "*".repeat(len + 4));
        println!("* {output} *");
        println!("{}", "*".repeat(len + 4));
    }
}

struct Point {
    x: i32,
    y: i32,
}

impl fmt::Display for Point {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "({}, {})", self.x, self.y)
    }
}

impl OutlinePrint for Point {}

fn main() {
    let p = Point { x: 3, y: 7 };
    p.outline_print();
}
**********
* (3, 7) *
**********

Note that trait Sub: Super is syntactic sugar for trait Sub where Self: Super. Rust does not have class inheritance—implementing Sub does not automatically implement Super; you must write a separate impl Super for Type block (or #[derive(...)] it).

Missing Supertrait Implementation Error (E0277)

Attempting to implement a subtrait on a type that does not implement its supertrait fails with E0277:

// ❌ does not compile
trait Identifiable {
    fn id(&self) -> u64;
}

trait Auditable: Identifiable {
    fn audit_log(&self) -> String {
        format!("audited item #{}", self.id())
    }
}

struct Invoice;

impl Auditable for Invoice {}

fn main() {}
error[E0277]: the trait bound `Invoice: Identifiable` is not satisfied
  --> src/main.rs:14:20
   |
14 | impl Auditable for Invoice {}
   |                    ^^^^^^^ the trait `Identifiable` is not implemented for `Invoice`
   |
note: required by a bound in `Auditable`
  --> src/main.rs:6:18
   |
6  | trait Auditable: Identifiable {
   |                  ^^^^^^^^^^^^ required by this bound in `Auditable`

Trait Object Upcasting (&dyn Subtrait to &dyn Supertrait)

Starting in Rust 1.86 (and standard in the 2024 edition), a trait object for a dyn-compatible subtrait (&dyn Subtrait or Box<dyn Subtrait>) can be implicitly coerced (upcast) to a trait object of any of its dyn-compatible supertraits (&dyn Supertrait or Box<dyn Supertrait>):

trait Base {
    fn base_name(&self) -> &str;
}

trait Derived: Base {
    fn extra_info(&self) -> u32;
}

struct Service;

impl Base for Service {
    fn base_name(&self) -> &str {
        "auth-service"
    }
}

impl Derived for Service {
    fn extra_info(&self) -> u32 {
        200
    }
}

fn main() {
    let d: &dyn Derived = &Service;
    let b: &dyn Base = d; // Trait upcasting from &dyn Derived to &dyn Base
    println!("Base name: {}, extra: {}", b.base_name(), d.extra_info());
}
Base name: auth-service, extra: 200