Menu
Coddy logo textTech

Multiple Bounds

Part of the Object Oriented Programming section of Coddy's Rust journey — lesson 41 of 61.

Sometimes a single trait bound isn't enough. You might need a generic type that can both be printed and provide a summary. Rust lets you require multiple traits using the + syntax.

Here's how to specify that a type must implement two traits:

use std::fmt::Display;

trait Summary {
    fn summarize(&self) -> String;
}

fn announce<T: Display + Summary>(item: T) {
    println!("Breaking news: {}", item);
    println!("Summary: {}", item.summarize());
}

The bound T: Display + Summary means "T must implement both Display and Summary." Inside the function, you can use capabilities from both traits—printing with {} (from Display) and calling summarize() (from Summary).

You can chain as many traits as needed:

fn process<T: Display + Summary + Clone>(item: T) {
    // Can print, summarize, AND clone
}

This pattern is essential when your function relies on multiple behaviors. Rather than accepting any type and hoping it works, you explicitly declare exactly what capabilities are required—and the compiler enforces it at compile time.

challenge icon

Challenge

Easy

Let's build a product inspection system that requires items to have multiple capabilities! You'll create a generic function that only accepts types implementing both a custom trait and a standard trait, demonstrating how the + syntax combines multiple bounds.

You'll organize your code across two files:

  • product.rs: Define a public Inspectable trait with a method called inspect that takes &self and returns a String containing inspection details. Then create a public Gadget struct with public name (String) and serial (u32) fields. Your Gadget should implement both Inspectable (returning Inspecting: {name}) and std::fmt::Display (formatting as {name} (SN: {serial})). Finally, create a public generic function called full_report that accepts any type T implementing both Display and Inspectable. This function should print two lines: first the item using the {} formatter, then the result of calling inspect().
  • main.rs: Bring in your product module and create a Gadget instance using the inputs provided. Call full_report with your gadget to show that it satisfies both trait requirements.

The power of multiple bounds is that your full_report function can use capabilities from both traits—displaying the item nicely AND getting inspection details—all guaranteed at compile time.

Your output should show both the display format and the inspection result:

{name} (SN: {serial})
Inspecting: {name}

For example, with inputs Smartwatch and 98765:

Smartwatch (SN: 98765)
Inspecting: Smartwatch

You will receive two inputs: the gadget name and the serial number (parse as u32).

Cheat sheet

You can require multiple trait bounds on a generic type using the + syntax:

fn function_name<T: Trait1 + Trait2>(item: T) {
    // Can use capabilities from both traits
}

Example with Display and a custom trait:

use std::fmt::Display;

trait Summary {
    fn summarize(&self) -> String;
}

fn announce<T: Display + Summary>(item: T) {
    println!("Breaking news: {}", item);
    println!("Summary: {}", item.summarize());
}

You can chain multiple traits as needed:

fn process<T: Display + Summary + Clone>(item: T) {
    // Can print, summarize, AND clone
}

The compiler enforces that the type implements all specified traits at compile time.

Try it yourself

mod product;

use product::{Gadget, full_report};

fn main() {
    // Read inputs
    let mut name = String::new();
    std::io::stdin().read_line(&mut name).expect("Failed to read line");
    let name = name.trim().to_string();
    
    let mut serial_input = String::new();
    std::io::stdin().read_line(&mut serial_input).expect("Failed to read line");
    let serial: u32 = serial_input.trim().parse().expect("Failed to parse serial");
    
    // TODO: Create a Gadget instance with the name and serial
    
    // TODO: Call full_report with your gadget
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming