In this lesson, you will learn how to declare type parameters using angle brackets and how their lexical scope limits where those types can be used within your code.
The Syntax of Generics
When you want a struct or a function to work with different data types, you introduce a type parameter using angle brackets (<T>). Think of T as a placeholder or a "blank" that the compiler will fill in later.
To use this, you must declare the parameter immediately after the name of the struct or function:
struct Container<T> {
value: T,
}
fn reveal<T>(item: T) {
// ...
}
The T inside the brackets tells Rust: "I am defining a generic entity, and T is the name I am using for the unknown type."
Lexical Scope
The scope of a type parameter is strictly limited to the block where it is defined.
- Functions: The scope of
Tstarts at the opening angle bracket and ends at the closing brace of the function body. You can useTfor parameters, return types, and local variables. However, thatTis invisible to other functions. - Structs: When you declare
struct Container<T>, thatTis part of the type's identity. If you want to use thatTin animplblock, you must redeclare it:impl<T> Container<T> { ... }.
Crucially, you cannot use a type parameter defined in a struct's impl block inside a standalone function unless that function also defines its own type parameter. The compiler treats them as entirely separate "slots" for types.
Why it Matters
By being explicit with your angle brackets, you help the compiler perform monomorphization. When you call reveal(5), the compiler creates a specific version of reveal where T is i32. When you call reveal("hello"), it creates another version for &str. The scope ensures that you don't accidentally mix up these types in ways that would break type safety.
Key Takeaway: Type parameters must be declared in angle brackets at the point of definition, and their scope is strictly confined to the structure or function where they are introduced.