DEV Community

Subesh Yadav
Subesh Yadav

Posted on • Edited on

Day 17 of #100DaysOfRust – Introduction to Generics, Traits, and Lifetimes in Rust

Welcome to Day 17 of my #100DaysOfRust journey! Today was all about stepping into Generics, a powerful feature in Rust that helps us write flexible, reusable, and clean code. We also began peeking into Traits and Lifetimes, both of which are key pillars of Rust's type system.

Let’s break it all down.


📅 Removing Duplication with Functions

We began by solving a simple problem: finding the largest number in a list. Here’s a basic implementation:

fn main() {
    let number_list = vec![34, 50, 25, 100, 65];

    let mut largest = &number_list[0];

    for number in &number_list {
        if number > largest {
            largest = number;
        }
    }

    println!("The largest number is {largest}");
}
Enter fullscreen mode Exit fullscreen mode

Duplicating this code for multiple lists becomes tedious. So we extracted a function:

fn largest(list: &[i32]) -> &i32 {
    let mut largest = &list[0];

    for item in list {
        if item > largest {
            largest = item;
        }
    }

    largest
}
Enter fullscreen mode Exit fullscreen mode

Clean and reusable!


🧰 Introducing Generics in Functions

But what if we wanted the same function to work on characters?

fn largest_char(list: &[char]) -> &char {
    let mut largest = &list[0];

    for item in list {
        if item > largest {
            largest = item;
        }
    }

    largest
}
Enter fullscreen mode Exit fullscreen mode

Still duplication! So we introduce Generics:

fn largest<T: PartialOrd + Copy>(list: &[T]) -> T {
    let mut largest = list[0];

    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }

    largest
}
Enter fullscreen mode Exit fullscreen mode
  • T is a generic type.
  • PartialOrd ensures we can compare values.
  • Copy ensures we can duplicate values safely.

🔹 Using Generics in Structs

struct Point<T> {
    x: T,
    y: T,
}

let integer = Point { x: 5, y: 10 };
let float = Point { x: 1.0, y: 4.0 };
Enter fullscreen mode Exit fullscreen mode

Or mix types:

struct Point<T, U> {
    x: T,
    y: U,
}

let mixed = Point { x: 5, y: 4.0 };
Enter fullscreen mode Exit fullscreen mode

🔠 Generics in Enums

Rust’s built-in enums like Option<T> and Result<T, E> use generics:

enum Option<T> {
    Some(T),
    None,
}

enum Result<T, E> {
    Ok(T),
    Err(E),
}
Enter fullscreen mode Exit fullscreen mode

We can define our own generic enums in a similar way.


💼 Generics in Methods

We can also define methods on generic types:

struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    fn x(&self) -> &T {
        &self.x
    }
}
Enter fullscreen mode Exit fullscreen mode

You can even specialize for specific types:

impl Point<f32> {
    fn distance_from_origin(&self) -> f32 {
        (self.x.powi(2) + self.y.powi(2)).sqrt()
    }
}
Enter fullscreen mode Exit fullscreen mode

🌐 Combining Generic Parameters

struct Point<X1, Y1> {
    x: X1,
    y: Y1,
}

impl<X1, Y1> Point<X1, Y1> {
    fn mixup<X2, Y2>(self, other: Point<X2, Y2>) -> Point<X1, Y2> {
        Point {
            x: self.x,
            y: other.y,
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Mix and match!


🧹 Monomorphization: Zero Runtime Cost

Rust uses a process called monomorphization to replace generic types with concrete types at compile time. This means:

  • No runtime performance cost.
  • You get the efficiency of handwritten type-specific code.

Example:

let integer = Some(5);
let float = Some(5.0);
Enter fullscreen mode Exit fullscreen mode

Compiles to:

enum Option_i32 { Some(i32), None }
enum Option_f64 { Some(f64), None }
Enter fullscreen mode Exit fullscreen mode

🔹 Summary

Today we covered:

  • Removing duplication with extracted functions
  • Introducing generics in functions, structs, enums, and methods
  • Trait bounds like PartialOrd, Copy
  • Specializing method implementations
  • Monomorphization for performance

Up next: Traits and Lifetimes!

Stay tuned as we go deeper into Rust's type system.

Top comments (0)