a trait and trait bound
Suppose you want to write one function that can print anything 'printable', or sort anything 'comparable', without caring whether it is a number, a string, or your own struct. You need a way to say 'this type supports these operations' as a contract that many different types can satisfy. A trait is Rust's name for that contract: a named set of method signatures (and sometimes associated types or constants) that a type can declare it implements. It is the same idea as an interface in Java or a concept in C++ — a promise about what a type can do, separate from how it does it.
You define a trait with the methods it requires, for example trait Summary { fn summarize(&self) -> String; }. A type then implements it with an impl block: impl Summary for Article { fn summarize(&self) -> String { ... } }. Now Article satisfies the Summary contract. A trait bound is how you USE that contract in generic code: it constrains a type parameter to only those types that implement a given trait. Written fn notify<T: Summary>(item: &T), it reads 'for any type T that implements Summary, here is notify'; inside the body you may call item.summarize() because the bound guarantees the method exists. When the constraints get long you move them into a where clause, where T: Summary + Clone, Wrapped: Display, which says the same thing more readably. The bound is checked at compile time: try to call notify with a type that does not implement Summary and the program does not compile, naming exactly which trait is missing.
Why this matters: traits plus trait bounds are how Rust does polymorphism without inheritance. They let you write one generic function that works for every type satisfying a contract, with the satisfaction proven at compile time and zero runtime check. The honest subtlety is the distinction between defining (impl Trait for Type, declaring a type fulfils the contract) and constraining (T: Trait, demanding a contract from a type parameter) — they use related syntax but do opposite jobs. Traits underpin almost everything else in this field: dispatch, generics, Send/Sync, Drop, and closures are all traits.
trait Summary { // the contract fn summarize(&self) -> String; } struct Article { title: String } impl Summary for Article { // Article fulfils it fn summarize(&self) -> String { format!("Article: {}", self.title) } } // Trait BOUND: T must implement Summary. fn notify<T: Summary>(item: &T) { println!("News! {}", item.summarize()); } // notify(&5); // error: i32 does not implement Summary
A trait names a contract; impl fulfils it for a type; a trait bound demands it from a generic parameter — all checked at compile time.
Defining and constraining look similar but differ: impl Trait for Type says a type satisfies the contract; T: Trait demands the contract from a parameter. Confusing the two is the most common early trait mistake.