What is the Rust type keyword?

Rust type keyword

The type keyword in rust has a different meaning in the 2 places it can be used:

  1. Type alias: Just another name for the same type.
  2. Associated types: this occurs within traits and trait impl blocks. Associated types are used to define a trait that uses some type(s) without needing to know exactly what those types are until the trait is implemented.

Associated types are different from generics because (Following copied from docs):

  • When a trait has a generic parameter, it can be implemented for a type multiple times, changing the concrete types of the generic type parameters each time.
  • With associated types, we don’t need to annotate types because we can’t implement a trait on a type multiple times

Example:

fn main() {
    // Type alias, Nr is an alias for u32
    type Nr = u32;
    let number: Nr = 34;

    let test = Test { nr: 9 };
    println!(" {} ", test.add_one()); // prints 10
}

struct Test {
    nr: i32,
}

pub trait Hi {
    // Associated type
    type Item;

    fn add_one(&self) -> Self::Item;
}

impl Hi for Test {
    // Associated type Item will be type i64
    type Item = i64;

    fn add_one(&self) -> Self::Item {
        (self.nr + 1) as i64
    }
}

A simple type Foo = Bar; outside of an impl defines a type alias, and is documented in The Book. There's a generic version type Foo<T> = ... but if you understand generics in general then this is an obvious extension.

type in an impl defines an associated type. They are documented in The Book, but I've already written a short summary, so you get that too:

When you have a trait like Add, you want to abstract not only over what types of things can be added, but also over the type of their sum. Adding integers results in integers, adding floats results in floats. But you don't want the result type to be a parameter of Add as in Add<ThingToAdd, ResultType>, for reasons that I'll skim over here.

Therefore, the trait comes with a type that's associated with the impl. Given any implementation of Add, e.g., impl Add<Foo> for Bar, the type of the addition result is already determined. This is declared in the trait like this:

trait Add<Rhs> {
    type Result;
    // ...
}

And then all implementations define what the type of their result is:

impl Add<Foo> for Bar {
    type Result = BarPlusFoo;
    // ...
}

Tags:

Rust