5.1 Keywords
Keywords are predefined, reserved words with special meanings in the Rust language. They form the building blocks of syntax and cannot be used as identifiers (like variable or function names) unless escaped using the raw identifier syntax (r#keyword
). Many Rust keywords overlap with C/C++, but Rust adds several unique ones to support features like ownership, borrowing, pattern matching, and concurrency.
5.1.1 Raw Identifiers
Occasionally, you might need to use an identifier that conflicts with a Rust keyword. This often happens when interfacing with C libraries or using older Rust code (crates) written before a word became a keyword in a newer Rust edition.
To resolve this, Rust provides raw identifiers: prefix the identifier with r#
. This tells the compiler to treat the following word strictly as an identifier, ignoring its keyword status.
For example, if a C library exports a function named try
(a reserved keyword in Rust), you would call it as r#try()
in your Rust code. Similarly, if Rust introduces a new keyword like gen
(as in the 2024 edition) that was used as a function or variable name in an older crate you depend on, you can use r#gen
to refer to the item from the old crate.
fn main() { // 'match' is a keyword, used for pattern matching. // To use it as a variable name, we need `r#`. let r#match = "Keyword used as identifier"; println!("{}", r#match); // 'type' is also a keyword. struct Example { r#type: i32, // Use raw identifier for field name } let instance = Example { r#type: 1 }; println!("Field value: {}", instance.r#type); // 'example' is NOT a keyword. Using r# is allowed but unnecessary. // Both 'example' and 'r#example' refer to the same identifier. let example = 5; let r#example = 10; // This shadows the previous 'example'. println!("Example: {}", example); // Prints 10 // Note: Inside format strings like println!, use the identifier *without* r#. // println!("{}", r#match); // This would be a compile error. }
While you can use r#
with non-keywords, it’s generally only needed for actual keyword conflicts or, rarely, for future-proofing if you suspect an identifier might become a keyword later.
5.1.2 Keyword Categories
Rust classifies keywords into three groups:
- Strict Keywords: Actively used by the language and always reserved.
- Reserved Keywords: Reserved for potential future language features; currently unused but cannot be identifiers.
- Weak Keywords: Have special meaning only in specific syntactic contexts; can be used as identifiers elsewhere.
5.1.3 Strict Keywords
These keywords have defined meanings and cannot be used as identifiers without r#
.
Keyword | Description | C/C++ Equivalent (Approximate) |
---|---|---|
as | Type casting, renaming imports (use path::item as new_name; ) | (type)value , static_cast |
async | Marks a function or block as asynchronous | C++20 co_await context |
await | Pauses execution until an async operation completes | C++20 co_await |
break | Exits a loop or block prematurely | break |
const | Declares compile-time constants | const |
continue | Skips the current loop iteration | continue |
crate | Refers to the current crate root | None |
dyn | Used with trait objects for dynamic dispatch | Virtual functions (indirectly) |
else | The alternative branch for an if or if let expression | else |
enum | Declares an enumeration (sum type) | enum |
extern | Links to external code (FFI), specifies ABI | extern "C" |
false | Boolean literal false | false (C++), 0 (C) |
fn | Declares a function | Function definition syntax |
for | Loops over an iterator | for , range-based for (C++) |
gen | Reserved (Rust 2024+, experimental generators) | C++20 coroutines |
if | Conditional expression | if |
impl | Implements methods or traits for a type | Class methods (C++), None (C) |
in | Part of for loop syntax (for item in iterator ) | Range-based for (C++) |
let | Introduces a variable declaration | Declaration syntax (no direct keyword) |
loop | Creates an unconditional, infinite loop | while(1) , for(;;) |
match | Pattern matching expression | switch (less powerful) |
mod | Declares a module | Namespaces (C++), None (C) |
move | Forces capture-by-value in closures | Lambda captures (C++) |
mut | Marks a variable or reference as mutable | No direct C equivalent (const is inverse) |
pub | Makes an item public (visible outside its module) | public: (C++ classes) |
ref | Binds by reference within a pattern | & in patterns (C++) |
return | Returns a value from a function early | return |
Self | Refers to the implementing type within impl or trait blocks | Current class type (C++) |
self | Refers to the instance in methods (&self , &mut self , self ) | this pointer (C++) |
static | Defines static items (global lifetime) or static lifetimes | static |
struct | Declares a structure (product type) | struct |
super | Refers to the parent module | .. in paths (conceptual) |
trait | Declares a trait (shared interface/behavior) | Abstract base class (C++), Interface (conceptual) |
true | Boolean literal true | true (C++), non-zero (C) |
type | Defines a type alias or associated type in traits | typedef , using (C++) |
unsafe | Marks a block or function with relaxed safety checks | C code is implicitly unsafe |
use | Imports items into the current scope | #include , using namespace |
where | Specifies constraints on generic types | requires (C++20 Concepts) |
while | Loops based on a condition | while |
5.1.4 Reserved Keywords (For Future Use)
These are currently unused but reserved for potential future syntax. Avoid using them as identifiers.
Reserved Keyword | Potential Use Area | C/C++ Equivalent (Possible) |
---|---|---|
abstract | Abstract types/methods | virtual ... = 0; (C++) |
become | Tail calls? | None |
box | Custom heap pointers | std::unique_ptr (concept) |
do | do-while loop? | do |
final | Prevent overriding | final (C++) |
macro | Alternative macro system? | #define (concept) |
override | Explicit method override | override (C++) |
priv | Private visibility? | private: (C++) |
try | Error handling syntax | try (C++) |
typeof | Type introspection? | typeof (GNU C), decltype (C++) |
unsized | Dynamically sized types | None |
virtual | Virtual dispatch | virtual (C++) |
yield | Generators/coroutines | co_yield (C++20) |
5.1.5 Weak Keywords
These words have special meaning only in specific contexts. Outside these contexts, they can be used as identifiers without r#
.
union
: Special meaning when defining aunion {}
type, otherwise usable as an identifier.'static
: Special meaning as a specific lifetime annotation, otherwise usable (though rare due to the leading'
).- Contextual Keywords (Examples): Words like
default
can have meaning within specificimpl
blocks but might be usable elsewhere.macro_rules
is primarily seen as the introducer for declarative macros.
5.1.6 Comparison with C/C++
While C programmers will recognize keywords like if
, else
, while
, for
, struct
, enum
, const
, and static
, Rust introduces many new ones. Keywords like let
, mut
, match
, mod
, crate
, use
, impl
, trait
, async
, await
, and unsafe
reflect Rust’s different approaches to variable declaration, mutability control, pattern matching, modularity, interfaces, asynchronous programming, and safety boundaries. The ownership system itself doesn’t have dedicated keywords but relies on how let
, mut
, fn
signatures, and lifetimes interact.