What this round is for
Rust interviews are unusually focused. Ownership, borrowing and lifetimes account for most of the round, because they account for most of the language - everything else follows from the question of who owns this data and how long it lives.
The second theme is cost. Interviewers want to know whether you can say what the guarantee buys, what it costs, and when another language would be the better choice.
The questions
Answer each one out loud before you open it. An answer you have read is not an answer you can
give under pressure, which is the only kind that counts.
Q1
What is ownership?
Show the answer
Hide the answer
Every value has one owner, and the value is freed when the owner goes out of scope.
No garbage collector decides when, and no programmer has to remember. Single ownership is what makes a double free impossible by construction.
What it is really testing.
Whether you connect it to the absence of a garbage collector and of double frees.
Q2
What is a move?
Show the answer
Hide the answer
Assigning a non-Copy value transfers ownership, and the original binding becomes unusable.
Using it afterwards is a compile error rather than a run-time surprise, which is the whole point of tracking ownership statically.
What it is really testing.
Whether you know the original binding becomes unusable, and why that is checked.
Q3
What is the Copy trait?
Show the answer
Hide the answer
It marks types cheap enough to duplicate implicitly, so assignment copies rather than moves.
Integers, booleans and other simple types are Copy. For anything else you ask for a clone explicitly, so the cost is written down.
What it is really testing.
Whether you know why clone must be explicit for everything else.
Q4
What are the borrowing rules?
Show the answer
Hide the answer
Any number of immutable references, or exactly one mutable reference, never both at once.
That single rule prevents iterator invalidation, unexpected mutation and data races, all without run-time cost.
What it is really testing.
Whether you can state the rule precisely. It is the foundation of everything else.
Q5
How do borrowing rules eliminate data races?
Show the answer
Hide the answer
A race needs two accesses to the same data with at least one writing - which the rule forbids.
If concurrent Rust compiles, it has no data race. That is a narrow and genuine claim, not marketing.
What it is really testing.
Whether you can explain the mechanism rather than repeating fearless concurrency.
Q6
What are lifetimes?
Show the answer
Hide the answer
Annotations telling the compiler how long a reference is valid, so it can refuse a dangling one.
Most of the time they are inferred. They appear where the relationship between an input and an output reference is genuinely ambiguous.
What it is really testing.
Whether you know they are mostly inferred rather than always written.
Q7
What is non-lexical lifetime?
Show the answer
Hide the answer
A borrow ends at its last use rather than at the end of the block.
It made a large class of previously rejected but obviously correct programs compile, which removed much of the early frustration.
What it is really testing.
Whether you know borrows end at last use, which modern Rust relies on.
Q8
How does Rust handle absence instead of null?
Show the answer
Hide the answer
Option, with Some and None - so a missing value cannot be used by accident.
You must unwrap it, and unwrapping forces you to handle the empty case. The null reference is simply not expressible.
What it is really testing.
Whether you connect it to the billion-dollar mistake being unexpressible.
Q9
How does Rust handle failure instead of exceptions?
Show the answer
Hide the answer
Result, with Ok and Err, returned from any function that can fail.
The caller must deal with it, and the question-mark operator propagates an error upward in one character while keeping the handling visible.
What it is really testing.
Whether you know the caller is forced to deal with it.
Q10
What does the question-mark operator do?
Show the answer
Hide the answer
It returns early with the error if a Result is Err, otherwise unwraps the Ok value.
It keeps explicit error handling without the ceremony, which is why Rust code is less repetitive than Go despite the same philosophy.
What it is really testing.
Whether you know it keeps handling visible while removing the ceremony.
Q11
When is unwrap acceptable?
Show the answer
Hide the answer
In tests, prototypes, and where you can prove the value is present.
In production code it is a panic waiting for an unexpected input. expect with a message is better, because the panic then explains itself.
What it is really testing.
Whether you prefer expect so the panic explains itself.
Q12
What is pattern matching and why is exhaustiveness valuable?
Show the answer
Hide the answer
Destructuring a value and handling every case, with the compiler checking none is missed.
Add a variant a year later and every incomplete match fails to compile, handing you the list of places to update.
What it is really testing.
Whether you value the compile error when a variant is added later.
Q13
What is a trait?
Show the answer
Hide the answer
A set of methods a type can implement, similar to an interface.
Traits can have default methods, and generic code can accept any type implementing one, which is how abstraction works in Rust.
What it is really testing.
Whether you know traits can carry default methods.
Q14
What is the difference between static and dynamic dispatch?
Show the answer
Hide the answer
Generic code is specialised per type at compile time; dyn Trait looks the method up at run time.
Static dispatch has no run-time cost - that is what zero-cost abstraction means. Dynamic dispatch is opt-in and visible.
What it is really testing.
Whether you know dynamic dispatch is opt-in and visible in the type.
Q15
What does zero-cost abstraction mean?
Show the answer
Hide the answer
Expressive code compiles to the same machine code you would have written by hand.
An iterator chain typically produces the same assembly as the equivalent loop, with no intermediate collections allocated.
What it is really testing.
Whether you can give the iterator example rather than repeating the phrase.
Q16
What is Box and when do you need it?
Show the answer
Hide the answer
A pointer to heap data with a single owner, needed for recursive types and for dyn Trait.
A recursive enum has no known size at compile time, so the recursive field must be behind a pointer.
What it is really testing.
Whether you know why a recursive type needs one.
Q17
What is Rc and when would you use it?
Show the answer
Hide the answer
A reference-counted pointer allowing several owners of immutable data, freed when the last goes away.
It is single-threaded only. Arc is the atomic version for sharing across threads, at the cost of atomic operations.
What it is really testing.
Whether you know Rc is single-threaded and Arc is the atomic version.
Q18
What is interior mutability?
Show the answer
Hide the answer
Mutating through a shared reference, with the borrow rule enforced at run time instead of compile time.
RefCell panics if the rule is violated, which is a loud reproducible failure rather than silent corruption.
What it is really testing.
Whether you know the check moves to run time rather than disappearing.
Q19
How do you share mutable state between threads?
Show the answer
Hide the answer
Arc<Mutex<T>> - shared ownership with a lock guarding the data.
The lock returns a guard, and the data is only reachable through it, so forgetting to lock is not possible.
What it is really testing.
Whether you know the guard makes forgetting to lock impossible.
Q20
What are Send and Sync?
Show the answer
Hide the answer
Send means a type can move between threads; Sync means a reference can be shared between them.
They are automatic for most types and are what let the compiler reject unsound concurrent code without you writing anything.
What it is really testing.
Whether you know they are automatic and what they let the compiler reject.
Q21
What is the difference between String and &str?
Show the answer
Hide the answer
String owns its data and can grow; &str is a borrowed view of string data.
Taking &str as a parameter accepts both, which is why it is the idiomatic argument type.
What it is really testing.
Whether you know &str is the idiomatic parameter type and why.
Q22
What is the difference between Vec and a slice?
Show the answer
Hide the answer
Vec owns a growable buffer; a slice is a borrowed view of part of one.
Functions should usually take a slice so they work with arrays and vectors alike without forcing an allocation.
What it is really testing.
Whether you take slices rather than forcing callers to allocate.
Q23
Why are iterators lazy and does it matter?
Show the answer
Hide the answer
Nothing runs until something consumes the chain, so no step materialises an intermediate collection.
That is what lets a long pipeline over a huge sequence run without allocating, and why it compiles to the same code as a loop.
What it is really testing.
Whether you connect laziness to the absence of intermediate allocations.
Q24
What is the difference between iter, into_iter and iter_mut?
Show the answer
Hide the answer
iter borrows, iter_mut borrows mutably, into_iter takes ownership and consumes the collection.
Choosing into_iter when you still need the collection afterwards is a common early mistake.
What it is really testing.
Whether you know into_iter consumes the collection.
Q25
What is the difference between a struct and an enum in Rust?
Show the answer
Hide the answer
A struct holds all its fields; an enum is exactly one of several variants, each able to carry data.
Enums with data are far more powerful than enums in most languages, and they are how state is modelled correctly.
What it is really testing.
Whether you know Rust enums carry data, unlike most languages.
Q26
How do you model a state machine in Rust?
Show the answer
Hide the answer
An enum of states, each carrying only the data valid in that state, matched exhaustively.
Invalid combinations become unrepresentable rather than merely discouraged, which is a stronger guarantee than a convention.
What it is really testing.
Whether you make invalid states unrepresentable rather than merely checked.
Q27
What is the Drop trait?
Show the answer
Hide the answer
Code that runs when a value goes out of scope, used to release resources.
Because ownership is tracked, cleanup is deterministic - there is no collector deciding later, which C++ programmers will recognise as RAII.
What it is really testing.
Whether you know cleanup is deterministic rather than collector-driven.
Q28
What does unsafe actually allow?
Show the answer
Hide the answer
Dereferencing raw pointers, calling foreign functions, and a few other operations the compiler cannot verify.
It does not turn off the borrow checker. It narrows where the rules relax and makes those regions searchable and auditable.
What it is really testing.
Whether you know it does not disable the borrow checker.
Q29
What is a macro in Rust and why are there two kinds?
Show the answer
Hide the answer
Declarative macros match patterns; procedural macros run code to generate code at compile time.
Derive macros are the common case - one attribute generates an implementation that would be tedious and error-prone by hand.
What it is really testing.
Whether you know derive macros are the common everyday case.
Q30
What is Cargo and what comes with it?
Show the answer
Hide the answer
The build tool and package manager, with testing, benchmarking, documentation and publishing built in.
Doc comments are compiled and run as tests, so published examples cannot silently rot.
What it is really testing.
Whether you know doc examples are compiled and tested.
Q31
How does async work in Rust?
Show the answer
Hide the answer
Futures are lazy state machines that do nothing until polled by an executor.
The language provides the syntax and no runtime, so you choose an executor - which is unusual and occasionally surprising.
What it is really testing.
Whether you know futures are lazy and the runtime is not built in.
Q32
What is the difference between async in Rust and in other languages?
Show the answer
Hide the answer
Rust futures do nothing until awaited, and there is no built-in runtime.
Creating a future and dropping it performs no work at all, where in most languages the operation would already have started.
What it is really testing.
Whether you know dropping a future performs no work at all.
Q33
What is a lifetime elision rule?
Show the answer
Hide the answer
A convention letting the compiler infer lifetimes in common signatures so you do not annotate them.
It is why most functions need no annotations, and why the ones that do are genuinely ambiguous cases.
What it is really testing.
Whether you know why most signatures need no annotation.
Q34
What is the orphan rule?
Show the answer
Hide the answer
You may implement a trait for a type only if you own one of the two.
It prevents two crates defining conflicting implementations. The newtype pattern is the standard way around it.
What it is really testing.
Whether you know what it prevents and how the newtype pattern works around it.
Q35
What is the newtype pattern?
Show the answer
Hide the answer
Wrapping a type in a single-field struct to give it a distinct identity.
It enables trait implementations the orphan rule forbids, and it stops a user id and an order id being interchangeable.
What it is really testing.
Whether you can name a use beyond trait implementations.
Q36
How do you handle errors in a library versus an application?
Show the answer
Hide the answer
A library defines its own error type; an application can use a boxed or aggregated error.
Returning a concrete error type lets callers match on specific cases, which a boxed error prevents.
What it is really testing.
Whether you know a boxed error prevents callers matching on cases.
Q37
What is the difference between panic and a Result error?
Show the answer
Hide the answer
A panic is an unrecoverable bug; a Result is an anticipated failure the caller should handle.
Panics can be configured to abort or unwind, and a library that panics on bad input is making a decision for its caller.
What it is really testing.
Whether you know a panicking library decides for its caller.
Q38
Why are compile times slow and what helps?
Show the answer
Hide the answer
The compiler does a great deal of analysis and monomorphises generics for each concrete type.
Splitting into crates, reducing generic instantiation and using a faster linker all help; incremental builds help most.
What it is really testing.
Whether you know monomorphisation is a major contributor.
Q39
What makes some data structures awkward in Rust?
Show the answer
Hide the answer
Anything with shared mutable references or cycles - a doubly linked list, a graph.
They need reference counting, interior mutability or arena allocation. It is the honest cost of the ownership guarantee.
What it is really testing.
Whether you can be honest about the cost rather than defending the language.
Q40
Where is Rust the right choice and where is it not?
Show the answer
Hide the answer
Right where failure is expensive and performance matters; wrong for exploratory work that changes hourly.
Choosing it for a prototype means arguing with the compiler about the lifetimes of code you are going to delete.
What it is really testing.
Whether you can name where it is the wrong tool.