We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Generics and Traits step 8 of 24
Supertraits and default methods
A trait can require another trait:
pub trait Greet: Named {
fn greet(&self) -> String {
format!("hi {}", self.name())
}
}
Named is the supertrait. The colon looks like inheritance from a
class-based language and it is not: there is no shared data, no overriding,
and Greet is not a “kind of” Named. It is a bound — “to implement
Greet you must already implement Named“ — and in exchange, code inside
Greet (including the default body above) may call Named‘s methods on
self.
This is exactly how the standard library layers its own traits:
Copy: Clone, Eq: PartialEq, Ord: Eq + PartialOrd. Once you recognise the
pattern, those signatures stop looking like magic.
Default methods
greet above has a body. That makes it a default: an implementor may
accept it or replace it. And when every method of a trait has a default, this
is a complete, legal implementation:
impl Greet for Person {}
An empty block that nevertheless adds behaviour. It surprises people the first time, and it is the mechanism behind the extension-trait pattern you will meet later in this track.
Your task
pub trait Named { fn name(&self) -> String; }
pub trait Greet: Named { fn greet(&self) -> String { ... } }
pub struct Person(String);
pub struct Robot(String);
pub fn greet_all(specs: Vec<(String, String)>) -> Vec<String>
Each spec is (kind, name).
-
"robot"builds aRobot. Itsname()returns the name uppercased, and it overridesgreetto produce"BEEP HAL". -
anything else builds a
Person. Itsname()returns the name unchanged and it takes the defaultgreet, producing"hi ada".
The dispatch happens through Box<dyn Greet>, so both types are used through
the same trait object. Note that this compiles at all only because the
supertrait bound rides along: a dyn Greet is usable as a Named too.
The error you must meet
The starter implements Greet for both types and Named for neither.
Compile it:
error[E0277]: the trait bound `Person: Named` is not satisfied
|
16 | impl Greet for Person {}
| ^^^^^^ the trait `Named` is not implemented for `Person`
Read that twice. You wrote impl Greet and the compiler is complaining about
Named. That indirection is exactly what trips people up: the unmet
requirement is the supertrait, and the fix is in a different impl block from
the one you were editing. Expect it and it becomes obvious; meet it cold and
you will stare at Greet looking for the mistake.
A second, rarer code in the neighbourhood: E0038, “the trait cannot be
made into an object”. A supertrait bound propagates into dyn compatibility, so
if Named had a generic method or returned Self, Box<dyn Greet> would stop
compiling even though nothing about Greet changed.
One gate detail
Both traits stay pub. Under -D warnings rustc’s own dead_code lint is an
error, and a trait or method nothing reaches is dead code. Keep the visibility
the starter gives you.
Remember the grade is compile + tests + clippy -D warnings.
Stuck?
Rust reference solution
Sign in to attempt this problem and reveal the reference solution.