Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

Rust Dictionary

  1. Home
  2. Rust Dictionary
  3. Combining Generics and Trait Bounds

Combining Generics and Trait Bounds

A trait bound specifies, using a trait, the constraints that a generic type parameter must satisfy. This guarantees at compile time that a type has certain methods or capabilities.

Syntax

// Basic trait bound (trait name after :)
fn function_name<T: TraitName>(arg: T) { ... }

// Requiring multiple traits (combined with +)
fn function_name<T: Clone + Debug>(arg: T) { ... }

// where clause syntax (cleaner for complex bounds)
fn function_name<T, U>(a: T, b: U)
where
    T: Clone + Debug,
    U: Display + PartialOrd,
{ ... }

// impl Trait syntax (shorthand for arguments and return types)
fn function_name(arg: impl TraitName) -> impl TraitName { ... }

Syntax Reference

SyntaxDescription
<T: Trait>Specifies a trait bound on the type parameter T.
<T: A + B>Requires the type to implement multiple traits at once.
where T: TraitWrites the bound on a separate line using a where clause. Makes complex conditions easier to read.
impl TraitShorthand syntax usable as an argument or return type. Equivalent to an anonymous type parameter.
dyn TraitDynamic dispatch (trait object). Resolves methods at runtime.

Sample Code

use std::fmt::{Debug, Display};

// Multiple trait bounds: requires both Clone and Debug.
fn print_twice<T: Clone + Debug>(item: T) {
    let copy = item.clone();
    println!("{:?} / {:?}", item, copy);
}

// where clause: improves readability when there are two or more parameters.
fn compare_and_show<T, U>(a: T, b: U) -> String
where
    T: Display + PartialOrd,
    U: Display,
{
    format!("a={}, b={}", a, b)
}

// impl Trait syntax: returns a type that implements the trait.
fn make_adder(x: i32) -> impl Fn(i32) -> i32 {
    move |y| x + y
}

fn main() {
    print_twice(vec![1, 2, 3]); // [1, 2, 3] / [1, 2, 3]

    let result = compare_and_show(42, "hello");
    println!("{}", result); // a=42, b=hello

    let add5 = make_adder(5);
    println!("{}", add5(10)); // 15
}

Overview

Trait bounds let you guarantee at compile time that a generic type parameter supports certain methods. If you pass a type that does not satisfy the bounds, the compiler produces an error, preventing runtime failures.

When the number of bounds grows, function signatures can become hard to read. In that case, it is common practice to use a where clause to organize the bounds on separate lines.

When using impl Trait as a return type, the returned type must be a single, fixed type. If you need to return different types that implement a trait depending on a condition, use Box<dyn Trait> (dynamic dispatch) instead.

If you find any errors or copyright issues, please .