If you can answer these without flipping back, you've internalised more Rust than you think.
Twenty multiple-choice questions covering the ground we've walked
together: ownership and borrowing, Option and Result, lifetimes,
traits, enums, modules. Pick an answer to lock it in and reveal the
explanations — not just for the right answer, but for every
distractor too, because the wrong answers are usually where the
learning lives.
No grade, no time limit, no record kept. Skim the explanations even for the ones you got right — sometimes the why is more interesting than the what.
What happens when you pass a String to a function in Rust?
Think about ownership rules.
String by value transfers ownership; the caller can't use it again unless the function returns it.&String (or &str). Bare String means a move.Which of these creates a mutable variable in Rust?
var keyword.mut keyword opts a binding into mutability.const is for compile-time constants and is never mutable.What is Option<T> for?
Think about what other languages reach for null to express.
as, From/Into, or try_from.Some(value) when the value is present, None when it isn't. No nulls needed.Result<T, E>. Option only models absence, not failure.How do you borrow a value immutably?
.borrow() is a RefCell method, not the general way to take a reference.* dereferences a reference; it doesn't create one.& operator produces a shared, immutable reference.Which statement about Rust's ownership is correct?
Copy, so they're duplicated on assignment, no manual management.SharedPtr is a C++ thing. Rust uses Rc<T> (single-threaded) or Arc<T> (across threads).Rc/Arc only for shared handles).What's the difference between String and &str?
"...") are baked into the binary as &'static str, but String values are very much runtime.String owns its bytes; &str is a view into bytes owned by somebody else (a String, a literal, etc.).String can be made mutable with let mut, but the headline difference is ownership.What does #[derive(Debug)] do?
#[warn(...)], #[deny(...)]).Debug is implemented you can format the value with {:?} or {:#?}.What does the ? operator do on a Result<T, E>?
It collapses a very common match pattern.
? returns early, it doesn't unwind.? only operates on Result (and Option).match res { Ok(v) => v, Err(e) => return Err(e.into()) }..ok(), .err()), but ? is not one of them.Which of these creates an empty Vec?
new keyword. Constructors are just associated functions: Vec::new().vec! macro with no elements gives you an empty vector.Vec, not Vector.What happens if you call HashMap::get for a key that doesn't exist?
Rust prefers types over panics for expected absence.
entry API, not the default behaviour of get.entry().or_default() is opt-in.)get never panics. Indexing (map["key"]) does, but get returns an Option.Option<&V>, so missing keys are part of the API.How do you create an owned String from a string literal?
to_string(), from the ToString trait.new keyword in Rust.String::from("hello").to_owned() clones the &str into a heap-allocated String. String::from("hello") and "hello".to_string() also work.Which of these is true of Rust enums?
Rust enums are closer to algebraic data types than to C-style enums.
Enum trait.Option, Result, and many parser ASTs are enums.match instead, and == only works if the enum derives PartialEq.What does the lifetime in this signature say?
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str
'a is the shorter of x's and y's lifetimes.
'a says "at least as long as", not "strictly less than".'a adds.'a as the shorter of the two and unifies via subtyping.'a is the intersection of the two input lifetimes, and the return reference is valid for that whole window.What does .clone() typically do?
clone() produces a second value alongside the original.String, clone() allocates fresh memory and copies the contents in.&value. .clone() creates a new value.Clone impls are deep; they duplicate owned heap data so the new value is fully independent.What is match primarily for?
match on the variants.String/str methods, not in control flow.regex crate. Not built into the language.When is a value's drop method called?
Same answer that explains why Rust doesn't need a garbage collector.
drop() is one way to force early dropping, but normal end-of-scope drops happen automatically.Drop::drop directly. Use std::mem::drop if you need to drop early.drop call at the end of the value's scope.What does the 'static lifetime mean?
'static says nothing about where the memory lives, only how long.'static references are either to data baked into the binary (string literals, const data) or to leaked heap allocations.Sized trait, which is unrelated.'static is about lifetime, not mutability. A static mut is 'static and mutable (but unsafe to touch).What is a trait in Rust?
Send, Sync, Copy, …) are a kind of trait, but traits in general aren't about memory management.How do you make an item visible from outside its module?
statics still default to private; they need pub static to escape the module.global keyword.extern is for FFI bindings, not module visibility.pub opens up cross-module visibility; you can also scope it with pub(crate) or pub(super).Which of these does not create a reference?
* is the dereference operator.
*x dereferences x and (for Copy types) gives you the value. r is a value, not a reference.AsRef::as_ref returns a reference.