Writing Generic Code in Rust
Learn to write functions and data structures that work with multiple types, enhancing code reusability without sacrificing type safety.
Writing Generic Code in Rust is a free Learn Rust Coding lesson on CoddyKit — lesson 1 of 3. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Learn Rust Coding learning path, one of 3 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Why Write Generic Code?
Imagine you need a function that finds the largest item in a list. What if you need it for numbers, and then for characters, and then for custom objects?
Without generics, you'd write a separate function for each type, leading to lots of duplicated code. This is where generics come in!
Introducing Generics
Generics allow you to write code that works with multiple types, without repeating yourself. They are a way to write flexible and reusable functions or data structures.
Think of it as a blueprint that can be adapted for different materials.
Your First Generic Function
To make a function generic, we declare type parameters in angle brackets <> after the function name. A common type parameter name is T (for Type).
This print_anything function can now print any type!
fn print_anything<T>(item: T) {
println!("The item is: {}", item);
}
pub fn main() {
print_anything(5);
print_anything("hello");
print_anything(true);
}Type Parameters Explained
The <T> in fn print_anything<T>(item: T) means T is a placeholder for a type. When you call the function with an i32, T becomes i32.
- Type Parameters: Generic types are usually named with uppercase letters, like
T,U,V. - Flexibility: The compiler figures out the concrete type at compile time.
Adding Behavior: Trait Bounds
Sometimes, your generic function needs its type parameter T to have specific behaviors. For example, if you want to compare two Ts, T must be comparable.
We add trait bounds to specify these requirements. Here, T: PartialOrd + Copy means T must implement the PartialOrd (partial ordering for comparison) and Copy traits.
fn largest<T: PartialOrd + Copy>(list: &[T]) -> T {
let mut largest = list[0];
for &item in list.iter() {
if item > largest {
largest = item;
}
}
largest
}
pub fn main() {
let number_list = vec![34, 50, 25, 100, 65];
println!("Largest number: {}", largest(&number_list));
let char_list = vec!['y', 'm', 'a', 'q'];
println!("Largest char: {}", largest(&char_list));
}Multiple Trait Bounds Syntax
You can require multiple traits for a generic type by using the + syntax, like T: TraitA + TraitB.
For complex bounds, you can also use a where clause after the function signature, which can make the signature cleaner:
fn some_function<T, U>(t: T, u: U) -> i32 where T: Display + Clone, U: Clone + Debug { /* ... */ }
Generic Structs
Just like functions, you can define structs to be generic over one or more type parameters. This allows your data structures to hold data of any specified type.
The Point<T> struct can hold coordinates of any type T (e.g., i32, f64).
struct Point<T> {
x: T,
y: T,
}
pub fn main() {
let integer_point = Point {
x: 5,
y: 10
};
let float_point = Point {
x: 1.0,
y: 4.0
};
println!("Int Point: ({}, {})",
integer_point.x, integer_point.y);
println!("Float Point: ({}, {})",
float_point.x, float_point.y);
}Implementing Methods on Generic Structs
When implementing methods for a generic struct, you need to specify the generic type parameter(s) after impl.
You can also add trait bounds to methods if a method specifically requires certain behavior from its generic types.
struct Point<T> {
x: T,
y: T,
}
impl<T> Point<T> {
fn x(&self) -> &T {
&self.x
}
}
pub fn main() {
let p = Point {
x: 5,
y: 10
};
println!("p.x = {}", p.x());
}Generics and Performance
One of Rust's strengths is that generics are a zero-cost abstraction. This means using generics doesn't incur any runtime performance penalty.
Rust achieves this through monomorphization: at compile time, the compiler generates specialized versions of your generic code for each concrete type it's used with. So, largest<i32> and largest<char> become two distinct, optimized functions.
Test Your Knowledge
Which of the following statements about Rust generics are TRUE?
Recap: The Power of Generics
In this lesson, you've learned the fundamentals of writing generic code in Rust:
- What they are: A way to write flexible, reusable code.
- Generic functions: Using
<T>for type parameters. - Trait bounds: Specifying required behaviors with
T: Trait. - Generic structs: Creating data structures that hold generic types.
- Zero-cost: Rust's generics compile to specific code, ensuring no runtime penalty.
Generics are a cornerstone of idiomatic Rust, enabling powerful, type-safe abstractions!
Frequently asked questions
Is the “Writing Generic Code in Rust” lesson free?
Yes — the full text of “Writing Generic Code in Rust” is free to read here on the web, and the Learn Rust Coding course includes 3 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Learn Rust Coding course, upgrade to CoddyKit PRO.
What will I learn in “Writing Generic Code in Rust”?
Learn to write functions and data structures that work with multiple types, enhancing code reusability without sacrificing type safety. You practise Learn Rust Coding with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Learn Rust Coding?
No prior experience is required. Learn Rust Coding on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 3, so you can start here or from the beginning and move at your own pace.
How long does the “Writing Generic Code in Rust” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Learn Rust Coding lesson?
Yes. Every Learn Rust Coding lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Writing Generic Code in Rust
- Defining and Implementing Traits
- Advanced Trait Usage: Associated Types