ruk·si

🦀 Rust
Generics

Updated at 2024-01-04 06:26

Structs and functions can be generic.

struct Pair<T> {
    a: T,
    b: T,
}

fn foobar<T>(arg: T) {
    todo!();
}

Generic types can have trait constraints.

fn print<T: Display + Debug>(value: T) {
    println!("value = {}", value);
}

You can specify the default generic type in many contexts.

<PlaceholderType=ConcreteType>

You can force method implementation of certain traits to be called.

<Dog as Animal>::vocalize()

Functions will work only on types that have a known size at compile time. However, you can use ?Sized to relax this restriction.

Might be useful if you are working with traits by reference.

// note that we are still taking a reference through `&T`
fn generic<T: ?Sized>(t: &T)

Return-position Impl Trait (RPIT)

You can return a type that implements a trait.

fn make_adder(a: i32) -> impl Fn(i32) -> i32 {
    move |b| a + b
}

fn player_names(players: &[Player]) -> impl Iterator<Item = &String> {
    players.iter().map(|p| &p.name)
}

Useful with e.g., function closures and iterators.

Return-position Impl Trait In Trait (RPITIT)

You can also use RPIT in trait definitions.

trait Container {
    fn items(&self) -> impl Iterator<Item = Widget>;
}

Sources