Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A supertrait in Rust is a trait that must be implemented by a type before that type is allowed to implement a dependent trait (the subtrait). It establishes a strict trait bound on Self, enforcing a structural requirement where the subtrait relies on the guarantees, methods, or associated items defined in the supertrait.

Syntax and Desugaring

The relationship is defined using the : operator after the subtrait’s name.
trait Supertrait {
    fn super_method(&self);
}

trait Subtrait: Supertrait {
    fn sub_method(&self);
}
Under the hood, this syntax is entirely equivalent to adding a where clause bounding Self. The compiler desugars the above definition to:
trait Subtrait where Self: Supertrait {
    fn sub_method(&self);
}

Implementation Mechanics

Unlike object-oriented inheritance, a subtrait does not inherit the implementations of the supertrait. Instead, it enforces a contract on the implementing type. Rust requires explicit, separate impl blocks for both the supertrait and the subtrait. If a type attempts to implement the subtrait without first implementing the supertrait, the compiler will emit an E0277 error (the trait bound is not satisfied).
struct ConcreteType;

// 1. The supertrait must be explicitly implemented.
impl Supertrait for ConcreteType {
    fn super_method(&self) {
        // Implementation details
    }
}

// 2. The subtrait can now be implemented.
impl Subtrait for ConcreteType {
    fn sub_method(&self) {
        // Implementation details
        
        // The subtrait's methods can freely call the supertrait's methods
        // because the compiler guarantees `Self` implements `Supertrait`.
        self.super_method(); 
    }
}

Multiple Supertraits

A subtrait can require multiple supertraits by chaining them with the + operator. The implementing type must satisfy all listed trait bounds.
trait SuperA {}
trait SuperB {}

trait Subtrait: SuperA + SuperB {}

Trait Objects and Vtables

When working with dynamic dispatch (dyn Subtrait), the vtable generated for the subtrait automatically includes the function pointers for all methods defined in its supertraits. This means a trait object of the subtrait can directly invoke supertrait methods without needing to be explicitly cast or upcast.
fn dynamic_dispatch(obj: &dyn Subtrait) {
    obj.sub_method();   // Resolved via Subtrait vtable
    obj.super_method(); // Resolved via the same vtable, inherited from Supertrait requirements
}

Key Technical Distinctions

  1. No Method Overriding: A subtrait cannot override a method defined in a supertrait. The methods belong to distinct traits and are resolved based on the trait in scope.
  2. No Automatic Implementation: Implementing Subtrait does not automatically generate an implementation for Supertrait. Both must be manually implemented by the developer.
  3. Associated Types: If a supertrait defines an associated type, the subtrait can reference that associated type directly via <Self as Supertrait>::AssociatedTypeName, or simply Self::AssociatedTypeName if there is no ambiguity.
Master Rust with Deep Grasping Methodology!Learn More