Conditional Method Implementations
// Copyright 2025 Google LLC
// SPDX-License-Identifier: Apache-2.0
// No trait bounds on the type definition.
pub struct Value<T>(T);
// Instead bounds are put on the implementations for the type.
impl<T: std::fmt::Display> Value<T> {
fn log(&self) {
println!("{}", self.0);
}
}
// alternatively
impl<T> Value<T> {
// Specifies the trait bound in a where expression
fn log_error(&self)
where
T: std::error::Error,
{
eprintln!("{}", self.0);
}
}
-
When authoring a type with generic parameters, we can write implementations for that type that depend on what the parameters are or what traits they implement.
-
These methods are only available when the type meets those conditions.
-
For things like ordered sets, where you’d want the inner type to always be
Ord, this is the preferred way of putting a trait bound on a parameter of a type.We don’t put the definition on the type itself as this would cause downstream issues for everywhere the type is mentioned with a generic parameter.
We can maintain invariants just fine with conditional method implementations.