Skip to content

← Generics and Traits step 1 of 24

Easy Primitives

Traits as shared behaviour

A trait is a named set of behaviour that many different types can promise to provide. It is the single organising idea of Rust’s type system: generics, dynamic dispatch, operator overloading, conversions, iteration, formatting and comparison are all traits. Learn this shape once and a large part of the standard library stops being mysterious.

Here is the whole idea in three lines:

pub trait Shape {
    fn area(&self) -> f64;
}

That declares a promise — “whoever implements me can be asked for an area” — and nothing else. There is no data, no constructor, no inheritance. A concrete type keeps its own fields and then separately opts in:

impl Shape for Circle {
    fn area(&self) -> f64 { /* ... */ }
}

Notice that the impl Shape for Circle block is not inside Circle. In Rust the type and its behaviours are declared independently, which is why you can add a trait to a type you did not write.

Your task

pub fn areas(specs: Vec<(String, Vec<f64>)>) -> Vec<f64>

Each spec is a tag plus its parameters:

  • ("circle", [r]) — a circle of radius r, area π · r²
  • ("rect", [w, h]) — a rectangle, area w · h
  • anything else — including a known tag with the wrong number of parameters — contributes 0.0

The output has one entry per input, in order.

The starter already contains impl Shape for Circle {} and impl Shape for Rect {} with empty bodies. Compile it before you change anything. You will get:

error[E0046]: not all trait items implemented, missing: `area`

E0046 is the most common first error a Rust learner meets when writing traits, and it is one of the friendliest: it names exactly what is missing. Get used to reading it as a checklist rather than as a rejection.

Two errors are worth causing on purpose while you are here.

  • Rename your method to fn are(&self) inside the impl block. You now get E0407 — “method are is not a member of trait Shape“ — and E0046 for the still-missing area. Almost every real E0407 is a typo, and the two errors arriving together is the tell.
  • Call c.perimeter() on a Circle. E0599: no method found. A trait only gives you the methods it declares.

Why the signature looks like that

A trait-object Box<dyn Shape> cannot be turned into JSON, so a learner-defined type can never appear in the entry point’s signature. The tag-plus-parameters encoding used here — a String naming the variant plus a Vec<f64> of its numbers — is how every problem in this track smuggles your own types across that boundary. You build them inside the function and hand back plain data.

Remember the grade is compile + tests + clippy -D warnings.