RustGlossary

Rust Glossary

A reference guide to Rust terminology — from core concepts to advanced topics — arranged alphabetically. Each entry gives a concise definition and, where helpful, a short code example.

Arc

Arc<T> (Atomically Reference Counted) is a smart pointer that allows multiple owners to share the same heap-allocated value across threads. Unlike Rc<T>, it uses atomic operations to update the reference count, making it safe to clone() and send to another thread. It is always immutable on its own; pair it with Mutex<T> or RwLock<T> for shared mutable state.

RUST
use std::sync::Arc;
let shared = Arc::new(vec![1, 2, 3]);
let clone  = Arc::clone(&shared);
std::thread::spawn(move || println!("{:?}", clone)).join().unwrap();
Borrow Checker

The borrow checker is the part of the Rust compiler that enforces ownership and borrowing rules at compile time. It tracks every reference in your program and rejects code that would cause a use-after-free, a data race, or an invalidated reference. If your code compiles, the borrow checker has verified that none of these memory safety bugs can occur at runtime.

Box

Box<T> is the simplest heap-allocating smart pointer. It moves a value of type T onto the heap and keeps a single owning pointer to it on the stack. When the Box is dropped the heap memory is freed automatically. Common uses are recursive data structures (e.g. linked lists), large values you want to avoid copying, and returning trait objects (Box<dyn Trait>).

RUST
let b = Box::new(5);
println!("b = {}", b); // dereferences automatically via Deref
Cargo

Cargo is Rust's official build system and package manager. It handles compiling crates, managing dependencies declared in Cargo.toml, running tests, formatting code, generating documentation, and publishing packages to crates.io. Almost every Rust project is a Cargo project; the commands cargo build, cargo test, and cargo run are the daily workhorses.

Clone

Clone is a trait that allows a type to produce an explicit deep copy of itself via the .clone() method. Unlike Copy, cloning is always explicit and may be expensive (e.g. copying a heap-allocated String or Vec). You can derive it automatically with #[derive(Clone)] if all fields are Clone.

RUST
let s1 = String::from("hello");
let s2 = s1.clone(); // explicit deep copy — both are valid
Closure

A closure is an anonymous function that can capture variables from its enclosing scope. Rust closures implement one or more of the Fn, FnMut, and FnOnce traits depending on how they use captured variables. They are written with pipe delimiters: |params| body. Closures are the backbone of Rust's iterator API and are used extensively for callbacks and higher-order functions.

RUST
let offset = 10;
let add_offset = |x| x + offset;
println!("{}", add_offset(5)); // 15
Copy

Copy is a marker trait for types whose values are duplicated bit-for-bit automatically when assigned or passed to a function, rather than moved. All primitive types (i32, f64, bool, char) and tuples/arrays of Copy types implement Copy. A type cannot implement Copy if it owns heap-allocated memory, because that would create two owners of the same data.

Crate

A crate is the smallest compilation unit in Rust. There are two kinds: a binary crate (produces an executable, has a main function) and a library crate (produces a .rlib that other crates can depend on). Each crate has a crate root — src/main.rs for binaries and src/lib.rs for libraries. A package can contain multiple crates.

Deref Coercion

Deref coercion is a convenience feature that automatically converts a reference to one type into a reference to another when the Deref trait is implemented. For example, &String automatically coerces to &str, and &Vec<T> coerces to &[T]. This means you can pass a &String to a function that expects &str without explicit conversion.

RUST
fn greet(s: &str) { println!("Hello, {}!", s); }
let name = String::from("Alice");
greet(&name);  // &String coerced to &str automatically
Drop

The Drop trait lets you specify code to run when a value goes out of scope. Rust calls drop() automatically — you never need to free memory manually. Types like String, Vec, Box, and Mutex all implement Drop to release their resources. You can implement Drop on your own types to clean up files, network connections, or other resources deterministically.

DST (Dynamically Sized Type)

A dynamically sized type (DST) is a type whose size is not known at compile time. The two most common DSTs are str (a string slice without a length baked in) and trait objects (dyn Trait). Because the compiler cannot put a DST directly on the stack, you always use them behind a reference (&str, &dyn Trait) or behind a pointer (Box<dyn Trait>).

Enum

An enum (enumeration) is a type that can be exactly one of several named variants. Rust enums are much more powerful than in most languages: each variant can hold different data, making them algebraic data types. The standard library's Option<T> and Result<T, E> are both enums. Enums are typically consumed with match or if let.

RUST
enum Shape {
    Circle(f64),
    Rectangle(f64, f64),
    Triangle { base: f64, height: f64 },
}
let area = match Shape::Circle(3.0) {
    Shape::Circle(r)                    => std::f64::consts::PI * r * r,
    Shape::Rectangle(w, h)             => w * h,
    Shape::Triangle { base, height }   => 0.5 * base * height,
};
Fearless Concurrency

"Fearless concurrency" is Rust's promise that its ownership and type system eliminate entire classes of concurrency bugs — data races, use-after-free across threads, and unsynchronised mutation — at compile time. The Send and Sync marker traits encode thread-safety requirements, and the compiler refuses code that would violate them. You can write concurrent code without fear of the most common bugs.

FFI (Foreign Function Interface)

The FFI allows Rust code to call functions written in C (and other languages that expose a C ABI) and to expose Rust functions to C. You declare external functions inside an extern "C" block. All FFI calls are inherently unsafe because Rust cannot verify the safety guarantees of foreign code.

RUST
extern "C" {
    fn abs(x: i32) -> i32;
}
fn main() {
    unsafe { println!("{}", abs(-5)); }
}
Future

A Future is a value that represents an asynchronous computation that will produce a result at some point. Futures are lazy — they do no work until polled by an async runtime (such as Tokio). The async fn syntax sugar desugars into a function returning impl Future. You drive a future to completion by .await-ing it inside another async context.

Generic

Generics allow you to write functions, structs, enums, and impl blocks that are parameterised over one or more types. The compiler performs monomorphization — generating a concrete copy for each distinct type used — so generics have zero runtime overhead. Trait bounds constrain which types are acceptable, e.g. fn largest<T: PartialOrd>(list: &[T]) -> &T.

impl Trait

impl Trait is a concise syntax for expressing a generic parameter or return type that implements a given trait, without naming the concrete type. In parameter position (fn f(x: impl Display)) it is equivalent to a generic bound. In return position (fn f() -> impl Iterator) it tells callers the concrete type implements the trait without revealing what it actually is.

Interior Mutability

Interior mutability is a design pattern that lets you mutate data through a shared (immutable) reference, bypassing the usual borrow rules. Rust provides Cell<T> and RefCell<T> for single-threaded interior mutability, and Mutex<T> / RwLock<T> for multi-threaded use. RefCell<T> enforces the borrow rules at runtime rather than compile time; a panic occurs if you violate them.

RUST
use std::cell::RefCell;
let data = RefCell::new(vec![1, 2, 3]);
data.borrow_mut().push(4);   // runtime borrow check
println!("{:?}", data.borrow());
Iterator

The Iterator trait defines a sequence of values produced one at a time via the next() -> Option<Self::Item> method. All collections in Rust expose iterators, and the trait provides dozens of default adaptor methods (.map(), .filter(), .fold(), etc.) that compose lazily. Iterators have zero overhead compared to hand-written loops because they are inlined by the compiler.

Lifetime

A lifetime is a compile-time label that describes how long a reference is valid. The borrow checker uses lifetimes to prove that no reference outlives the data it points to. In most code lifetimes are inferred (elided). You write them explicitly ('a) only when the compiler cannot infer the relationship — most commonly in function signatures with multiple reference parameters or in structs that hold references.

RUST
// The returned reference lives at least as long as both inputs
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() { x } else { y }
}
Match

match is Rust's pattern-matching expression. It compares a value against a series of patterns and executes the arm whose pattern matches. The compiler enforces exhaustiveness — every possible value must be covered, either explicitly or with a wildcard. match can destructure enums, structs, tuples, and ranges, and can include match guards (if conditions on arms).

Module

Modules organise code into named namespaces and control visibility. You declare one with mod name { ... } or by creating a file name.rs (or name/mod.rs). Items inside a module are private by default; the pub keyword makes them accessible to code outside. Use use statements to bring paths into scope for shorter names.

Move Semantics

When you assign a value to a new variable or pass it to a function, Rust moves ownership to the destination. The original binding becomes invalid and the compiler will reject any subsequent use of it. Move semantics eliminate the need for a garbage collector by making ownership transfers explicit and statically verified. Types that implement Copy are an exception — they are copied instead of moved.

Mutex

A Mutex<T> (mutual exclusion lock) wraps a value and ensures that only one thread can access it at a time. You call .lock() to acquire the guard, which dereferences to &mut T, and the lock is automatically released when the guard is dropped. In Rust, Mutex is almost always used inside Arc so multiple threads can hold a reference to the same mutex.

Newtype Pattern

The newtype pattern wraps an existing type in a single-field tuple struct to create a distinct type with its own identity. This enforces type safety (a Metres cannot accidentally be added to a Seconds), enables implementing foreign traits on foreign types (working around the orphan rule), and can hide implementation details from callers.

RUST
struct Metres(f64);
struct Seconds(f64);
// fn foo(m: Metres, s: Seconds) — compiler prevents mixing them up
Option

Option<T> is Rust's replacement for null pointers. It is an enum with two variants: Some(T) when a value is present and None when it is absent. Because the compiler forces you to handle both cases, null-pointer dereferences are impossible. Rich combinator methods (.map(), .unwrap_or(), .and_then(), etc.) make working with Option ergonomic without verbose match expressions.

Orphan Rule

The orphan rule (also called the coherence rule) states that you can implement a trait for a type only if either the trait or the type is defined in your crate. This prevents two crates from providing conflicting implementations of the same trait for the same type. The newtype pattern is the standard workaround when you need to implement a foreign trait for a foreign type.

Ownership

Ownership is Rust's core memory management model. Every value has exactly one owner; when the owner goes out of scope the value is automatically dropped (freed). Ownership can be transferred (moved) but not shared without borrowing. These three rules — single owner, scope-based drop, explicit transfer — enable memory safety without a garbage collector and are enforced entirely at compile time.

Package

A package is one or more crates grouped together by a Cargo.toml file. It must contain at most one library crate (src/lib.rs) but may contain multiple binary crates (in src/bin/). The Cargo.toml defines the package name, version, edition, and all dependencies. Packages are the unit of publication to crates.io.

Panic

A panic is an unrecoverable error that causes the current thread to unwind (or abort, depending on configuration) and print a backtrace. Panics are triggered by panic!("message"), out-of-bounds indexing, .unwrap() on None or Err, and integer overflow in debug builds. For recoverable errors, return Result instead. Panics can be caught across thread boundaries with std::panic::catch_unwind.

Pattern Matching

Pattern matching is the ability to test a value against a structure and simultaneously bind its parts to variables. Rust supports it in match expressions, if let, while let, let else, and even plain let bindings. Patterns can match literals, ranges, enum variants, struct fields, tuple elements, and can be combined with guards. The compiler ensures match arms are exhaustive.

Rc

Rc<T> (Reference Counted) is a single-threaded smart pointer for shared ownership. Multiple Rc clones can point to the same heap allocation; the data is dropped only when the last clone is dropped. Because it is not thread-safe, the compiler prevents sending an Rc across a thread boundary. For multi-threaded shared ownership, use Arc<T>.

Reference

A reference is a non-owning pointer to a value, written &T (shared/immutable) or &mut T (exclusive/mutable). References are guaranteed by the borrow checker to always point to valid data. You can have many &T references simultaneously, or exactly one &mut T reference — but not both at the same time. References implement Deref, so they coerce to inner types automatically.

Result

Result<T, E> is an enum for recoverable errors with two variants: Ok(T) on success and Err(E) on failure. Functions that can fail should return Result rather than panicking. The ? operator propagates errors automatically, and a rich combinator API (.map(), .and_then(), .unwrap_or_else(), etc.) makes composition ergonomic.

Send

Send is a marker trait that indicates a type is safe to transfer ownership to another thread. The compiler automatically implements Send for most types. Raw pointers and Rc<T> are the main exceptions because they are not thread-safe. If a type contains any !Send field, it is automatically !Send too. The compiler uses this to prevent you from accidentally sending unsafe values across threads.

Slice

A slice is a dynamically-sized view into a contiguous sequence of elements in memory. Written &[T] for element slices and &str for string slices. Slices carry both a pointer and a length, so they know their own size without owning the data. They are obtained from arrays (&arr[1..3]), Vecs (&v[..]), or Strings (&s[0..5]).

Smart Pointer

A smart pointer is a data structure that acts like a pointer but provides additional capabilities such as automatic memory management or extra metadata. Rust's smart pointers implement the Deref and Drop traits. The most common ones are Box<T> (heap allocation), Rc<T> / Arc<T> (shared ownership), and RefCell<T> / Mutex<T> (interior mutability).

Struct

A struct is a custom data type that groups named fields together. Rust has three kinds: named structs (struct Point { x: f64, y: f64 }), tuple structs (struct Color(u8, u8, u8)), and unit structs (struct Marker). Methods and associated functions are defined in impl blocks. Structs can derive common traits like Debug, Clone, and PartialEq.

Sync

Sync is a marker trait that indicates it is safe to share a reference to a type across threads (i.e. &T can be sent to another thread). A type is Sync if and only if &T is Send. Types with interior mutability that is not thread-safe, like RefCell<T> and Cell<T>, are !Sync. Mutex<T> is Sync because it protects its data.

Trait

A trait defines a shared interface — a set of method signatures that types can implement. Traits are similar to interfaces in other languages but more powerful: they support default implementations, associated types, and blanket implementations (impl<T: Foo> Bar for T). The compiler uses trait bounds to verify that a generic type supports the operations you need.

Trait Bound

A trait bound constrains a generic type parameter to only accept types that implement a given trait. Written as T: Trait in angle brackets or after a where keyword. Multiple bounds are combined with +: T: Clone + Debug. Trait bounds are checked by the compiler at every call site, providing both safety and zero-cost monomorphized code.

Trait Object

A trait object (dyn Trait) is a fat pointer to a heap- or stack-allocated value plus a vtable that holds pointers to the value's trait method implementations. Unlike generics (monomorphized at compile time), trait objects enable runtime polymorphism — the concrete type is not known until runtime. They are used as &dyn Trait or Box<dyn Trait> because they are DSTs.

Unit Type

The unit type () is a zero-sized type with exactly one value: the empty tuple (). Functions that do not return a meaningful value implicitly return (). Result<(), E> is the canonical type for fallible operations that succeed with no output. Unit structs are a closely related concept — they too are zero-sized.

Unsafe

The unsafe keyword marks a block or function as opting out of some of Rust's compile-time safety guarantees. Inside an unsafe block you can dereference raw pointers, call unsafe functions, access mutable statics, implement unsafe traits, and access union fields. Unsafe code is not inherently wrong, but the programmer takes responsibility for upholding the invariants the compiler can no longer check.

Vec

Vec<T> is the standard growable, heap-allocated array. It stores elements contiguously in memory and resizes automatically when capacity is exceeded. The three key fields are a pointer to the heap buffer, a length (number of elements), and a capacity (allocated slots). Vec implements Deref<Target = [T]> so slice methods work on it directly.

RUST
let mut v: Vec<i32> = Vec::new();
v.push(1); v.push(2); v.push(3);
let third = v[2];
let slice: &[i32] = &v[1..];
Zero-Cost Abstraction

A zero-cost abstraction is a high-level language feature that compiles to the same machine code you would write by hand in C — it adds no runtime overhead. Rust's iterators, generics (via monomorphization), closures, and async/await are all zero-cost abstractions. The principle is: "What you don't use, you don't pay for. What you do use, you couldn't hand-code any better."

Success
Refer back to this glossary whenever you encounter an unfamiliar Rust term. Each concept links to a dedicated tutorial page in the sidebar for a full explanation with worked examples.