Generics

Rust is a systems programming language focused on speed, memory safety, and fearless concurrency — and generics let you write code that works over many types without giving up any of that speed.

Learn Generics in our free Rust course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.

Part of the free Rust course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

In this lesson you'll write generic functions and structs, add trait bounds, and see how Rust compiles them to specialized, zero-cost code.

What You'll Learn in This Lesson

1️⃣ Generic Functions and Trait Bounds

A generic function declares a type parameter in angle brackets, like <T> , then uses T in its signature. When the body needs an operation — comparing values, say — you add a trait bound like T: PartialOrd to require that capability.

One function handled integers, chars, and floats. The bound T: PartialOrd is what makes the > comparison legal — it promises every T can be ordered.

2️⃣ Generic Structs and Methods

Structs can be generic too. Point<T> holds two values of the same type; Pair<T, U> lets the fields differ. Methods go in an impl<T> block, optionally with their own bounds — here T: Display so we can print the fields.

This is exactly how the standard library is built: Vec<T> , Option<T> , and Result<T, E> are all generic types you've already been using.

Your turn. Fill in the blanks marked ___ , then run it.

Write a generic function that swaps the two elements of a same-typed tuple. Run it with cargo run .

📋 Quick Reference — Generics

Practice quiz

What main problem do generics solve?

  • Slower runtime
  • Memory leaks
  • Code duplication across types
  • Missing semicolons

Answer: Code duplication across types. Generics let one piece of code work over many types instead of duplicating it.

How do you declare a type parameter on a function?

  • fn f<T>(x: T)
  • fn f(T x)

Answer: fn f<T>(x: T). A type parameter goes in angle brackets, like fn f<T>(x: T).

What is a trait bound like T: PartialOrd?

  • A runtime check
  • A default value
  • A lifetime
  • A requirement that T implements a trait

Answer: A requirement that T implements a trait. It constrains T to types implementing the trait, here enabling comparisons.

Which bound lets you compare values with the > operator?

  • T: Display
  • T: PartialOrd
  • T: Clone
  • T: Copy

Answer: T: PartialOrd. PartialOrd provides ordering comparisons like > and <.

Do generics slow your program down at runtime?

  • No, they are zero-cost
  • Yes, significantly
  • Only with floats
  • Only in debug builds

Answer: No, they are zero-cost. Monomorphization makes generics zero-cost at runtime.

What is monomorphization?

  • Boxing every value
  • Garbage collection
  • Generating a specialized copy per concrete type at compile time
  • Runtime type checking

Answer: Generating a specialized copy per concrete type at compile time. The compiler creates a fully optimized copy for each concrete type used.

How do you write a struct generic over two types?

  • struct Pair<T, T>
  • struct Pair<T, U>

Answer: struct Pair<T, U>. Two independent parameters are written struct Pair<T, U>.

Where must the type parameter be declared for a generic impl block?

  • After the type name
  • Inside the method
  • It is inferred
  • After the impl keyword, as impl<T>

Answer: After the impl keyword, as impl<T>. Write impl<T> Point<T>; the parameter is declared after impl.

Which bound is needed to print a generic value with {}?

  • T: PartialOrd
  • T: std::fmt::Display
  • T: Iterator
  • T: Send

Answer: T: std::fmt::Display. Printing with {} requires the Display trait bound.

Which standard-library types are generic?

  • Only Vec
  • Only String
  • Vec<T>, Option<T>, and Result<T, E>
  • None of them

Answer: Vec<T>, Option<T>, and Result<T, E>. Vec, Option, and Result are all generic types built the same way.