In Rust, trait bounds serve as constraints on types rather than just interfaces. When definnig a trait with bounds, we're actually specifying that any implementing type must also satisfy other trait requirements.
Basic Implementation Example
use std::fmt;
struct Coordinate {
x: i32,
y: i32,
}
trait Duplicate {
fn duplicate(&self) -> Self;
}
trait Formatter: fmt::Display + Duplicate {
fn format_output(&self) {
let text = self.to_string();
let length = text.len();
println!("{}", "*".repeat(length + 4));
println!("*{}*", " ".repeat(length + 2));
println!("* {text} *");
println!("*{}*", " ".repeat(length + 2));
println!("{}", "*".repeat(length + 4));
}
}
impl Formatter for Coordinate {}
impl fmt::Display for Coordinate {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
impl Duplicate for Coordinate {
fn duplicate(&self) -> Self {
Coordinate { x: self.x, y: self.y }
}
}
fn main() {
let coord = Coordinate { x: 15, y: 25 };
coord.format_output();
let dup = coord.duplicate();
dup.format_output();
}
Method-Level Constraints
use std::fmt;
struct Position {
x: i32,
y: i32,
}
trait Replicate {
fn replicate(&self) -> Self;
}
trait OutputFormatter: fmt::Display + Replicate + Sized {
fn display_formatted(&self) {
let cloned = self.replicate();
let content = cloned.to_string();
let width = content.len();
println!("{}", "*".repeat(width + 4));
println!("*{}*", " ".repeat(width + 2));
println!("* {content} *");
println!("*{}*", " ".repeat(width + 2));
println!("{}", "*".repeat(width + 4));
}
}
impl OutputFormatter for Position {}
impl fmt::Display for Position {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
impl Replicate for Position {
fn replicate(&self) -> Self {
Position { x: self.x, y: self.y }
}
}
fn main() {
let pos = Position { x: 30, y: 40 };
pos.display_formatted();
}
Function Parameter Constraints
trait CustomFormatter {
fn custom_format(&self)
where
Self: fmt::Display + Replicate + Sized,
{
let replica = self.replicate();
let text = replica.to_string();
let len = text.len();
println!("{}", "*".repeat(len + 4));
println!("*{}*", " ".repeat(len + 2));
println!("* {text} *");
println!("*{}*", " ".repeat(len + 2));
println!("{}", "*".repeat(len + 4));
}
}