Rust MCQ
Test your Rust knowledge with 100 multiple choice questions covering fundamentals to advanced concepts, with instant feedback and explanations.
How This Practice Test Works
Every question below expands right on this page — click a question to reveal its four options, pick the one you think is correct, and you'll get instant feedback along with the correct answer and a short explanation of the reasoning. Questions are grouped by difficulty, so start with the 40 beginner questions to confirm your fundamentals, work through the 40 intermediate ones, and finish with the 20 advanced questions that mirror what exams and technical screenings actually ask. There's no sign-up, no timer, and no limit — retake the test as often as you like.
Curated by Tech Baithak Editorial Team · Last updated: June 2026
1
Which organization develops the Rust programming language?
Correct Answer
Mozilla (now the Rust Foundation)
Explanation
Rust was created by Graydon Hoare at Mozilla in 2006. The Rust Foundation was established in 2021 to steward the project.
2
What is Rust's primary memory safety guarantee?
Correct Answer
Ownership and borrowing rules enforced at compile time, eliminating dangling pointers and data races without a GC
Explanation
Rust's ownership system ensures memory safety at compile time with no runtime garbage collector. The borrow checker prevents use-after-free and data races.
3
What is ownership in Rust?
Correct Answer
A set of rules governing when memory is allocated and freed: each value has exactly one owner; the value is dropped when the owner goes out of scope
Explanation
Rust's ownership model: each value has one owner. When the owner goes out of scope, the value is dropped (memory freed). Ownership can be moved but not copied by default.
4
What is a move in Rust?
Correct Answer
Transferring ownership of a value to another variable, making the original variable invalid
Explanation
let s1 = String::from("hello"); let s2 = s1; — s1 is moved into s2. Using s1 after this is a compile error.
5
What is the Copy trait?
Correct Answer
A marker trait for types that can be bitwise-copied on assignment, so the original remains valid
Explanation
Types like i32, bool, char, and tuples of Copy types implement Copy. let x = 5; let y = x; — x is still valid because integers are Copy.
6
What is a reference in Rust?
Correct Answer
A pointer to a value that does not own the data, allowing access without taking ownership
Explanation
&T is an immutable reference; &mut T is a mutable reference. References are guaranteed to be valid (non-dangling) by the borrow checker.
7
What is borrowing in Rust?
Correct Answer
Creating a reference to a value without taking ownership
Explanation
fn print(s: &String) borrows s without taking ownership. The original owner retains ownership after the function returns.
8
What are Rust's borrowing rules?
Correct Answer
Either one mutable reference OR any number of immutable references — never both at the same time
Explanation
The borrow checker enforces: at most one &mut T, or any number of &T at a time. This prevents data races at compile time.
9
What is a slice in Rust?
Correct Answer
A reference to a contiguous subsequence of elements in a collection
Explanation
&str is a string slice; &[i32] is an integer slice. Slices hold a pointer and a length without owning the data.
10
What is the difference between &str and String?
Correct Answer
&str is a borrowed reference to string data (string slice); String is an owned, heap-allocated, growable string
Explanation
&str is a view into string data (can point to a String or string literal). String owns its data and can grow. Use &str for function parameters accepting both.
11
What is an enum in Rust?
Correct Answer
A type that can be one of several variants, each optionally holding data
Explanation
enum Message { Quit, Move { x: i32, y: i32 }, Write(String) } — Rust enums are algebraic data types, far more powerful than C enums.
12
What is Option<T> used for?
Correct Answer
Representing a value that may or may not exist: Some(T) or None
Explanation
Option<T> replaces null pointers. You must handle both Some(x) and None, preventing null pointer dereferences.
13
What is Result<T, E>?
Correct Answer
A type representing either success Ok(T) or failure Err(E)
Explanation
Result is used for operations that can fail: fn open(path: &str) -> Result<File, io::Error>. Callers must handle both Ok and Err cases.
14
What does the ? operator do in Rust?
Correct Answer
Unwraps a Result, returning early with Err if the operation failed
Explanation
let file = File::open("path")?; returns the Err to the caller if it fails, otherwise unwraps the Ok value. Replaces verbose match expressions.
15
What is a struct in Rust?
Correct Answer
A custom data type grouping related named fields
Explanation
struct Point { x: f64, y: f64 } defines a named group of values. Structs are value types stored on the stack unless boxed.
16
What is a trait in Rust?
Correct Answer
A collection of methods that types can implement to share behavior
Explanation
Traits (like Java interfaces or Haskell typeclasses) define shared behavior. trait Area { fn area(&self) -> f64; } implemented by Circle, Rectangle, etc.
17
What is a lifetime in Rust?
Correct Answer
An annotation describing how long a reference is valid, ensuring references do not outlive the data they point to
Explanation
Lifetime annotations ('a) on references let the compiler verify references don't outlive their data: fn longest<'a>(x: &'a str, y: &'a str) -> &'a str.
18
What is the borrow checker?
Correct Answer
A compile-time analysis that enforces ownership and borrowing rules to prevent use-after-free, dangling references, and data races
Explanation
The borrow checker is part of the Rust compiler. It checks that references are valid and that mutability rules are respected — all at compile time.
19
What is pattern matching in Rust?
Correct Answer
The match expression that destructures and matches against patterns like enum variants, literals, tuples, and structs
Explanation
match coin { Coin::Penny => 1, Coin::Nickel => 5, _ => 0 } is exhaustive — all cases must be handled.
20
What does panic! do?
Correct Answer
Terminates the current thread with an error message (optionally unwinds the stack)
Explanation
panic!("message") crashes the program (or thread). It's for unrecoverable errors. Use Result for recoverable errors.
21
What is Box<T>?
Correct Answer
A heap-allocated smart pointer providing unique ownership of a value
Explanation
Box<T> puts T on the heap. Use Box when you need a heap allocation, a trait object (Box<dyn Trait>), or a recursive data type.
22
What is Rc<T>?
Correct Answer
Reference-counted smart pointer enabling multiple owners of the same heap data in single-threaded contexts
Explanation
Rc<T> (Reference Counted) allows multiple owners. The data is freed when the last Rc is dropped. Not Send/Sync — use Arc for multithreading.
23
What is Arc<T>?
Correct Answer
An Atomically Reference Counted smart pointer safe for sharing across threads
Explanation
Arc<T> is the thread-safe version of Rc<T>, using atomic operations for the reference count. Use with Mutex<T> for shared mutable state across threads.
24
What is Cell<T> and RefCell<T>?
Correct Answer
Types providing interior mutability: Cell<T> for Copy types, RefCell<T> for runtime-checked borrows
Explanation
Interior mutability allows mutation through an immutable reference. RefCell<T> enforces borrow rules at runtime, panicking on violations.
25
What is the use keyword in Rust?
Correct Answer
Brings a path into scope to avoid repeating long module paths
Explanation
use std::collections::HashMap; allows using HashMap directly instead of the full path.
26
What is cargo in Rust?
Correct Answer
Rust's package manager and build system
Explanation
Cargo handles dependencies (Cargo.toml), building (cargo build), testing (cargo test), documentation (cargo doc), and publishing to crates.io.
27
What is a crate in Rust?
Correct Answer
The smallest unit of compilation — a binary or library package
Explanation
A crate is a binary (has main) or a library. crates.io is the package registry. Cargo.toml specifies crate dependencies.
28
What does the derive attribute do?
Correct Answer
Automatically implements specified traits (Debug, Clone, PartialEq, etc.) for a type using procedural macros
Explanation
#[derive(Debug, Clone, PartialEq)] auto-generates the implementations of those traits for the struct or enum.
29
What is the println! macro?
Correct Answer
A macro that formats and prints a string followed by a newline to stdout
Explanation
println!("Value: {}", x) formats and prints to stdout with a newline. {} uses the Display trait; {:?} uses the Debug trait.
30
What is a vector Vec<T> in Rust?
Correct Answer
A heap-allocated, growable, type-safe array
Explanation
Vec<T> grows dynamically. vec![1,2,3] or Vec::new() with push(). Elements are stored contiguously on the heap.
31
What is an iterator in Rust?
Correct Answer
A trait (Iterator) with a next() method, enabling lazy consumption of sequences with adaptors like map, filter, and collect
Explanation
v.iter().filter(|x| *x > 2).map(|x| x * 2).collect::<Vec<_>>() chains lazy iterator adaptors, executing only on collect().
32
What is the difference between iter(), iter_mut(), and into_iter()?
Correct Answer
iter() yields &T; iter_mut() yields &mut T; into_iter() consumes the collection yielding T
Explanation
Use iter() for read-only access, iter_mut() for mutation, into_iter() when you want to consume and transform the collection.
33
What is the Drop trait?
Correct Answer
A trait with fn drop(&mut self) called automatically when a value goes out of scope, for custom cleanup
Explanation
impl Drop for MyResource { fn drop(&mut self) { /* cleanup */ } } runs when the value goes out of scope, implementing RAII.
34
What is an impl block?
Correct Answer
A block defining methods and associated functions for a struct or enum
Explanation
impl Point { fn new(x: f64, y: f64) -> Self { ... } fn distance(&self) -> f64 { ... } } defines methods on Point.
35
What is a closure in Rust?
Correct Answer
An anonymous function that captures variables from its environment using |params| expression syntax
Explanation
let double = |x| x * 2; captures no environment. Closures can capture by reference (&), mutable reference (&mut), or by value (move).
36
What is the Fn, FnMut, FnOnce trait hierarchy?
Correct Answer
FnOnce consumes captured vars (called once); FnMut mutates them (called repeatedly); Fn only borrows (called any number of times)
Explanation
FnOnce ⊇ FnMut ⊇ Fn. A function accepting Fn can be passed any closure. Closures implement the most specific trait based on how they capture.
37
What does the move keyword do in a closure?
Correct Answer
Forces the closure to take ownership of all captured variables rather than borrowing them
Explanation
move || { use_data(data) } moves data into the closure. Required when passing closures to threads where the outer scope may not outlive the thread.
38
What are generics in Rust?
Correct Answer
Type parameters (<T>) that allow writing functions, structs, and enums that work with multiple types while maintaining type safety
Explanation
fn largest<T: PartialOrd>(list: &[T]) -> T works for any type T that implements PartialOrd. Rust monomorphizes generics at compile time.
39
What is monomorphization?
Correct Answer
The compiler generating concrete implementations of generic code for each concrete type used
Explanation
When you use Vec<i32> and Vec<String>, Rust compiles two separate Vec implementations. This makes generics zero-cost but can increase binary size.
40
What is a Rust lifetime elision rule?
Correct Answer
Compiler rules that infer lifetime annotations in common patterns so they don't need to be written explicitly
Explanation
Three elision rules: (1) each input ref gets its own lifetime; (2) one input → output gets same; (3) self method → output gets self's lifetime.
1
What is a trait object (dyn Trait)?
Correct Answer
A runtime-dispatched reference to any type implementing a trait, enabling dynamic polymorphism via a vtable
Explanation
Box<dyn Animal> or &dyn Animal is a fat pointer (data ptr + vtable ptr) that can hold any Animal implementor. Use when concrete types aren't known at compile time.
2
What is the difference between static dispatch (generics) and dynamic dispatch (dyn Trait)?
Correct Answer
Static dispatch inlines/monomorphizes for each concrete type (faster); dynamic dispatch uses vtable (slower but smaller binary, enables heterogeneous collections)
Explanation
fn f<T: Display>(x: T) is statically dispatched. fn g(x: &dyn Display) is dynamically dispatched via vtable indirection.
3
What is the Send trait?
Correct Answer
A marker trait indicating ownership of the type can be transferred across thread boundaries
Explanation
Types are Send if sending them to another thread is safe. Most types are Send. Rc<T> is not Send (non-atomic reference counting).
4
What is the Sync trait?
Correct Answer
A marker trait indicating it is safe for multiple threads to hold shared references (&T) to the type simultaneously
Explanation
T: Sync means &T: Send. Mutex<T> is Sync even if T is not, because it serializes access.
5
What is the Mutex<T> in Rust?
Correct Answer
A mutual exclusion primitive that provides safe mutable access to T across threads, returning a MutexGuard when locked
Explanation
let data = Arc::new(Mutex::new(5)); let guard = data.lock().unwrap(); *guard += 1; — the guard releases the lock when dropped.
6
What is async/await in Rust?
Correct Answer
A zero-cost asynchronous programming model where async functions return futures, driven by an executor (tokio, async-std)
Explanation
async fn fetch() -> Result<...> { let resp = client.get(url).await?; } Futures are lazy state machines. Executors like tokio::main drive them.
7
What is a Future in Rust?
Correct Answer
A lazy computation represented as a state machine that produces a value when polled to completion
Explanation
Futures implement trait Future { type Output; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>; }. They do nothing until polled by an executor.
8
What is unsafe Rust?
Correct Answer
Code in an unsafe block that opts out of some borrow checker guarantees, enabling raw pointer dereference, calling unsafe functions, etc.
Explanation
unsafe { *raw_ptr } allows raw pointer dereference. Use unsafe for FFI, performance-critical code, and implementing safe abstractions. The programmer assumes correctness.
9
What is a raw pointer in Rust?
Correct Answer
*const T or *mut T — pointers without lifetime or aliasing guarantees, usable only in unsafe blocks
Explanation
Raw pointers (*const T) don't guarantee non-null or valid memory. Creating them is safe; dereferencing requires unsafe.
10
What is the From/Into trait?
Correct Answer
Conversion traits: From<T> for infallible conversions; Into<T> is the reciprocal (implementing From auto-implements Into)
Explanation
impl From<i32> for MyType { fn from(x: i32) -> Self { ... } } then i32::from(x) or x.into() both work.
11
What is the Display trait?
Correct Answer
A trait requiring fmt::Display implementation, enabling {} formatting with println!
Explanation
impl fmt::Display for Point { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "({},{})", self.x, self.y) } }
12
What is a macro in Rust?
Correct Answer
Code that generates code during compilation — declarative macros (macro_rules!) or procedural macros (#[derive], attribute, function-like)
Explanation
Macros avoid code duplication. macro_rules! my_macro { ... } is declarative. proc macros (like serde's #[derive(Serialize)]) use the Rust compiler API.
13
What is the newtype pattern?
Correct Answer
Using a tuple struct of one field to create a distinct named type for type safety
Explanation
struct Meters(f64); and struct Kilograms(f64) are distinct types despite holding f64. Prevents accidental mixing of units while having zero runtime cost.
14
What is the purpose of PhantomData<T>?
Correct Answer
A zero-sized type used to make the type system aware of an unused generic parameter for lifetime or type variance purposes
Explanation
struct Iter<'a, T> { ptr: *const T, _phantom: PhantomData<&'a T> } tells the compiler the Iter borrows T with lifetime 'a, enabling proper variance.
15
What is Pin<T> used for?
Correct Answer
Preventing a value from being moved in memory, required for self-referential structs and async futures
Explanation
Pin<P> guarantees the pointee won't be moved after pinning. Async/await creates self-referential state machines that would be invalidated by moves, so futures require Pin.
16
What is the Deref coercion?
Correct Answer
Implicit conversion when passing a &T where &U is expected, if T implements Deref<Target=U>
Explanation
Box<String> coerces to &String which coerces to &str. String::from("hello") can be passed as &str. This chain is performed automatically.
17
What is the difference between clone() and copy?
Correct Answer
Copy is an implicit bitwise copy for simple types; clone() is an explicit deep copy for complex types like String
Explanation
Integers implement Copy — assignment copies automatically. String does not implement Copy; you must call .clone() to create a deep copy.
18
What is a type alias (type) in Rust?
Correct Answer
An alternate name for an existing type with no additional safety guarantees: type Result<T> = Result<T, io::Error>
Explanation
type Thunk = Box<dyn Fn() + Send + 'static>; is a type alias. Unlike struct Newtype(T), a type alias IS the same type.
19
What is the ? Sized bound?
Correct Answer
Relaxing the default Sized constraint on a generic parameter to allow dynamically-sized types (DSTs) like str and [T]
Explanation
fn f<T: ?Sized>(x: &T) allows passing str and [T] as well as Sized types. fn f<T>(x: &T) implicitly requires T: Sized.
20
What is Rust's impl Trait syntax in function arguments?
Correct Answer
Shorthand for a generic type parameter constrained by a trait: fn f(x: impl Display) is equivalent to fn f<T: Display>(x: T)
Explanation
fn double_and_print(x: impl Display + Debug) is cleaner than generics for simple cases. It's static dispatch — the compiler generates a concrete implementation.
21
What is the purpose of Cow<'a, B> (Clone on Write)?
Correct Answer
A smart pointer holding either a borrowed reference or an owned value, only cloning when mutation is needed
Explanation
Cow::Borrowed(&str) avoids allocation; Cow::Owned(String) owns data. Cow::to_mut() clones only when mutation is needed. Useful for APIs accepting both &str and String.
22
What is the BufReader and BufWriter purpose in Rust?
Correct Answer
Wrappers adding buffering to any Reader/Writer, reducing the number of system calls for small reads/writes
Explanation
BufReader<R> buffers reads from R into a 8KB buffer by default. Instead of one syscall per byte, you get one syscall per 8KB. Use flush() on BufWriter before dropping.
23
What is Rust's type inference limitations?
Correct Answer
Rust cannot infer type parameters that don't appear in method arguments; use turbofish ::<> syntax or annotate the variable
Explanation
let v = Vec::new() fails (can't infer T). let v: Vec<i32> = Vec::new() or Vec::<i32>::new() works. Iterator collect() often needs type annotation.
24
What is the turbofish operator ::<> in Rust?
Correct Answer
Syntax for specifying generic type parameters explicitly at the call site when inference fails: "hello".parse::<i32>()
Explanation
"42".parse::<i32>().unwrap() or Vec::<i32>::new() uses turbofish when the compiler can't infer the type from context.
25
What is Rust's RwLock<T>?
Correct Answer
A synchronization primitive allowing multiple concurrent readers or one exclusive writer
Explanation
RwLock.read() can be held by many threads simultaneously. RwLock.write() requires exclusive access. Use when reads are frequent and writes are rare.
26
What are proc macros in Rust?
Correct Answer
Macros implemented as Rust functions that operate on token streams, enabling powerful code generation like #[derive(Serialize)]
Explanation
Procedural macros are separate crates (proc-macro = true) that receive TokenStream and return TokenStream. Used by serde, tokio, thiserror, and async-trait.
27
What is the thiserror crate used for?
Correct Answer
A derive macro that generates error boilerplate (Display, Error, From) for custom error types
Explanation
#[derive(Error)] #[error("file {path} not found")] struct FileNotFound { path: String } generates Display and std::error::Error implementation.
28
What is the anyhow crate?
Correct Answer
A crate providing anyhow::Error (a type-erased error) for application code where error type doesn't matter, using context() to add messages
Explanation
fn main() -> anyhow::Result<()> with ? on any error. file.read_to_string().context("reading config") adds context. Use thiserror for library errors, anyhow for apps.
29
What is Rust's cfg! macro and #[cfg] attribute?
Correct Answer
Compile-time conditional compilation based on platform, features, or custom flags
Explanation
#[cfg(target_os = "linux")] fn platform_func() compiles only on Linux. cfg!(debug_assertions) is a bool constant. Used for platform-specific code and feature gates.
30
What is Rust's const generics?
Correct Answer
Generic parameters that can be compile-time constant values (not just types), like array length: struct FixedArray<T, const N: usize>
Explanation
fn zeros<const N: usize>() -> [i32; N] { [0; N] } creates zero arrays of any size. [T; N] arrays are const-generic over N in std.
31
What is the std::mem::discriminant function?
Correct Answer
Returns an opaque value representing which enum variant is active, useful for comparing variants without caring about associated values
Explanation
discriminant(&MyEnum::Foo) == discriminant(&MyEnum::Foo) is true. Lets you compare variant identity without destructuring, even when associated values differ.
32
What is Rust's std::hint::black_box?
Correct Answer
A function that prevents the compiler from optimizing away computations in benchmarks
Explanation
criterion benchmarks use black_box(input) to prevent the optimizer from constant-folding the benchmark away, ensuring accurate measurements.
33
What is the From<&str> for String vs Into<String> pattern?
Correct Answer
String::from("hello") uses From; "hello".to_string() and "hello".into() (when context is String) use Into. All are zero-overhead allocations
Explanation
Because From<T> for U is implemented, U: Into<T> is auto-implemented. Function parameters using impl Into<String> accept both String and &str without explicit conversion.
34
What is Rust's once_cell crate and how is it now in std?
Correct Answer
A crate providing OnceCell<T> and OnceLock<T> for lazy one-time initialization; stabilized as std::cell::OnceLock and std::sync::OnceLock in Rust 1.70
Explanation
static LOG: OnceLock<Logger> = OnceLock::new(); LOG.get_or_init(|| Logger::new()) initializes exactly once across all threads. Replaces lazy_static! macro.
35
What is std::sync::mpsc?
Correct Answer
Multi-producer, single-consumer channel for message passing
Explanation
std::sync::mpsc (multi-producer, single-consumer) provides channel::<T>() returning (Sender<T>, Receiver<T>). Sender can be cloned for multiple producers.
36
What is Rust's associated const in a trait?
Correct Answer
A trait item that is a compile-time constant value each implementing type must provide
Explanation
trait HasMax { const MAX: u32; } impl HasMax for u8 { const MAX: u32 = 255; } provides a per-type compile-time constant.
37
What does the std::mem::forget function do?
Correct Answer
Consumes a value without running its destructor, leaking any resources it owns
Explanation
mem::forget(value) is safe but leaks resources. Used when transferring ownership to C code (ManuallyDrop is preferred), or implementing FFI handshakes.
38
What is the difference between String::new() and String::with_capacity(n)?
Correct Answer
String::new() allocates no heap memory initially; with_capacity(n) pre-allocates n bytes, avoiding reallocations when building strings incrementally
Explanation
Pre-allocating with String::with_capacity(100) avoids multiple reallocations when pushing chars or appending substrings in a loop.
39
What is the Entry API for HashMap in Rust?
Correct Answer
A way to insert or modify a value only if the key is absent or present, avoiding redundant lookups via map.entry(key).or_insert(default)
Explanation
counts.entry(word).and_modify(|c| *c += 1).or_insert(1) increments if present, inserts 1 if absent — all in one lookup.
40
What is the difference between map() and and_then() on Option/Result?
Correct Answer
map() transforms the inner value, wrapping the result back; and_then() (flatMap) passes the inner value to a closure that returns Option/Result itself, avoiding double wrapping
Explanation
opt.map(|x| x + 1) returns Option<i32>. opt.and_then(|x| if x > 0 { Some(x) } else { None }) flattens Option<Option<i32>> into Option<i32>.
1
What is the Non-Lexical Lifetimes (NLL) improvement?
Correct Answer
The borrow checker analyzing actual live ranges of borrows rather than lexical scopes, reducing false-positive borrow errors
Explanation
NLL allows let x = v[0]; v.push(y); to compile — x's borrow ends before the push. Prior to NLL, any &v reference blocked mutation for the entire lexical scope.
2
What is variance in Rust lifetimes?
Correct Answer
Whether substituting a subtype for a type parameter is allowed: covariant (safe to substitute longer), contravariant (shorter), or invariant (exact)
Explanation
&'a T is covariant over 'a and T. &'a mut T is covariant over 'a but invariant over T (to prevent unsound mutations). PhantomData affects variance.
3
What is the difference between associated types and generic type parameters in traits?
Correct Answer
Associated types (type Output) bind one type per implementation (cleaner API); generics (T) allow multiple implementations per type for different T
Explanation
Iterator has type Item (one per impl). If it were generic Iterator<Item>, you could implement multiple Iterators for the same type with different items.
4
What is the Higher-Ranked Trait Bound (HRTB) for<'a>?
Correct Answer
A bound meaning the trait must hold for all possible lifetimes: where F: for<'a> Fn(&'a str) -> &'a str
Explanation
HRTB are needed when a closure must work with any lifetime. fn apply<F: for<'a> Fn(&'a i32) -> &'a i32>(f: F) expresses that F is valid for any concrete lifetime 'a.
5
What is the Polonius borrow checker?
Correct Answer
A next-generation borrow checker based on Datalog queries that is more precise, accepting more valid programs than NLL
Explanation
Polonius models borrows as facts and uses Datalog to compute liveness. It accepts some patterns that NLL incorrectly rejects while maintaining soundness.
6
What is unsafe trait and unsafe impl?
Correct Answer
Unsafe traits (Send, Sync, GlobalAlloc) have safety invariants the compiler cannot check; unsafe impl promises the programmer upholds them
Explanation
unsafe trait Scary {} means implementing it is unsafe. unsafe impl Scary for MyType {} promises the programmer satisfies the contract. Send and Sync are unsafe traits.
7
What is the global allocator in Rust?
Correct Answer
A type implementing GlobalAlloc that replaces the default allocator for all heap allocations in the program
Explanation
#[global_allocator] static A: MyAllocator = MyAllocator; replaces the default allocator. Used for embedded systems, tracking allocations, or custom memory management.
8
What is specialization in Rust?
Correct Answer
An unstable feature allowing more specific trait implementations to override more general ones, enabling performance optimizations
Explanation
Specialization (RFC 1210, nightly-only) allows a blanket impl to be overridden by a more specific one. Used by the standard library (e.g., ToString being faster for types that impl Display).
9
What is the impact of Rust's zero-cost abstractions?
Correct Answer
High-level abstractions (iterators, closures, generics) compile to the same machine code as hand-written low-level equivalents, with no runtime overhead
Explanation
Rust's iterator chains, closures, and monomorphized generics are inlined and optimized to tight loops by LLVM, matching hand-optimized C performance.
10
What is async cancellation in Rust and why is it unique?
Correct Answer
Dropping a future cancels it — any awaited work is abandoned. This is synchronous and immediate but requires care for cleanup (select! cancellation safety)
Explanation
In Rust async, dropping a future stops it without any explicit cancel API. This is efficient but requires careful design around cancellation safety (e.g., don't cancel mid-transaction).
11
What is Rust's async runtime and why isn't one built-in?
Correct Answer
Rust intentionally leaves the async executor out of std to allow domain-specific runtimes (tokio, async-std, embassy) with different tradeoffs
Explanation
std only provides Future and async/await syntax. tokio is optimized for network I/O. embassy runs on embedded (no_std). smol is minimal. Different use cases need different executors.
12
What is the difference between tokio::spawn and std::thread::spawn in Rust?
Correct Answer
tokio::spawn creates a lightweight async task run on the tokio runtime; thread::spawn creates an OS thread with its own stack
Explanation
tokio::spawn creates Tasks — lightweight async work units. thread::spawn creates OS threads with ~8MB stack. You can run millions of Tasks; thousands of threads struggle.
13
What is the Miri interpreter for Rust?
Correct Answer
An interpreter for Rust MIR (Mid-level IR) that detects undefined behavior in unsafe code: use-after-free, out-of-bounds, invalid values
Explanation
cargo miri test runs tests under the Miri interpreter, catching UB that ASan/TSan might miss (invalid enum discriminants, uninitialized reads). Slow but thorough.
14
What is Rust's MIR (Mid-level Intermediate Representation)?
Correct Answer
A simplified control-flow graph representation used internally for borrow checking, optimization, and code generation before LLVM IR
Explanation
MIR is Rust's internal representation after type checking. The borrow checker runs on MIR. It's also used by Miri, cargo check optimizations, and constant evaluation.
15
What is soundness in Rust's type system?
Correct Answer
The property that safe Rust code can never cause undefined behavior; a library is sound if all valid uses of its public safe API cannot cause UB
Explanation
Soundness is Rust's core guarantee. A library with unsafe internals is sound if its safe interface cannot be misused to cause UB. Unsound APIs are bugs.
16
What is the Stacked Borrows memory model for Rust unsafe code?
Correct Answer
A formal operational model for memory accesses in Rust that defines when unsafe code causes undefined behavior via aliasing violations
Explanation
Stacked Borrows (Miri uses it) defines a stack of "borrows" per memory location. Accessing via an invalidated borrow or creating forbidden aliasing is UB.
17
What is the Rust portability lint and unsafe guidelines?
Correct Answer
The Unsafe Code Guidelines (UCG) define what unsafe Rust code may assume and is allowed to do, forming the basis of Rust's UB model
Explanation
The UCG (unstable, evolving) specifies allowed behaviors for unsafe code: layout guarantees, pointer provenance, aliasing. Violating UCG is UB even if it appears to work.
18
What is the difference between Arc<Mutex<T>> and Arc<RwLock<T>>?
Correct Answer
Arc<Mutex<T>> allows only one accessor at a time; Arc<RwLock<T>> allows concurrent reads but exclusive writes — better when reads are frequent
Explanation
RwLock has higher acquisition overhead than Mutex. For write-heavy or short-duration access, Mutex may outperform. Measure before switching.
19
What is the pinning contract and self-referential structs?
Correct Answer
Pin<P> guarantees the pointee won't move; self-referential structs (holding pointers to their own fields) require Pin because moving would invalidate the pointer
Explanation
Async state machines contain references to their own stack variables. Pin prevents moves after these references are created. unsafe impl Unpin on a self-referential type is unsound.
20
What is Rust's strict provenance model for raw pointers?
Correct Answer
Pointers carry provenance (metadata about their origin) beyond the address; casting integers to pointers may lose provenance, causing UB under strict models
Explanation
Strict provenance (ptr::from_exposed_addr, ptr.addr(), ptr.with_addr()) preserves pointer provenance information, making Rust's memory model compatible with address sanitizers and formal verification.