Traits
Supertraits
A supertrait is a prerequisite trait declared on another trait (trait Sub: Super), requiring every type that implements Sub to also implement Super.
Declaring Single and Multiple Supertraits
List one or more supertraits after a colon (:) on the trait header, separated by + (or write where Self: SuperA + SuperB):
use std::fmt::Display;
trait Positioned {
fn coords(&self) -> (i32, i32);
}
// `MapMarker` has two supertraits: `Positioned` and `Display`
trait MapMarker: Positioned + Display {
fn render_pin(&self) -> String {
let (x, y) = self.coords();
format!("{self} @ ({x}, {y})")
}
}
struct Waypoint {
label: &'static str,
x: i32,
y: i32,
}
impl Positioned for Waypoint {
fn coords(&self) -> (i32, i32) {
(self.x, self.y)
}
}
impl Display for Waypoint {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "[{}]", self.label)
}
}
impl MapMarker for Waypoint {}
fn main() {
let wp = Waypoint {
label: "Summit",
x: 120,
y: -45,
};
println!("{}", wp.render_pin());
}
[Summit] @ (120, -45)
Missing Supertrait Implementation Error (E0277)
Attempting to implement a subtrait for a type that does not implement all of its supertraits fails at compile time with E0277:
// ❌ does not compile
trait Base {
fn id(&self) -> u32;
}
trait Derived: Base {}
struct Item;
impl Derived for Item {}
fn main() {}
error[E0277]: the trait bound `Item: Base` is not satisfied
--> src/main.rs:10:18
|
10 | impl Derived for Item {}
| ^^^^ the trait `Base` is not implemented for `Item`
|
note: required by a bound in `Derived`
--> src/main.rs:6:16
|
6 | trait Derived: Base {}
| ^^^^ required by this bound in `Derived`
Standard Library Supertrait Hierarchies
Many core traits in the standard library are linked by supertrait relationships:
| Subtrait | Supertrait(s) | Additional Guarantee or Capability |
|---|---|---|
Copy |
Clone |
Bitwise memcpy semantics in addition to explicit .clone() |
Eq |
PartialEq |
Reflexivity (a == a is always true) in addition to symmetric/transitive equality |
Ord |
Eq + PartialOrd |
Total ordering across all values of Self |
std::error::Error |
Debug + Display |
Human-readable and developer-readable formatting for every error |
Fn |
FnMut (which has supertrait FnOnce) |
Shared-reference invocation implies mutable-reference and by-value invocation |
ExactSizeIterator |
Iterator |
Known exact remaining length (len()) on an iterator |
Trait Object Upcasting (&dyn Sub to &dyn Super)
In modern stable Rust (since Rust 1.86 / 2024 edition), a trait object reference or smart pointer for a subtrait (&dyn Sub or Box<dyn Sub>) can be upcast directly to a trait object of any of its dyn-compatible supertraits (&dyn Super or Box<dyn Super>):
trait Device {
fn device_name(&self) -> &str;
}
trait NetworkDevice: Device {
fn ip_address(&self) -> &str;
}
struct Router;
impl Device for Router {
fn device_name(&self) -> &str {
"core-router-01"
}
}
impl NetworkDevice for Router {
fn ip_address(&self) -> &str {
"10.0.0.1"
}
}
fn inspect_device(dev: &dyn Device) {
println!("Device name: {}", dev.device_name());
}
fn main() {
let router = Router;
let net_dev: &dyn NetworkDevice = &router;
println!("IP: {}", net_dev.ip_address());
// Implicitly upcasts `&dyn NetworkDevice` to `&dyn Device`:
inspect_device(net_dev);
}
IP: 10.0.0.1
Device name: core-router-01