Expert · Rust careers and interviews · topic 49 of 50 · 35 min
Interview questions: traits, errors, pointers and concurrency
Explanation
Q1. Generics versus trait objects?
Model answer: "Generics use static dispatch: the compiler makes a specialised copy for each type (monomorphization), so calls are fast and can be inlined, but binaries grow. Trait objects (dyn Trait behind a pointer) use dynamic dispatch through a vtable: one copy of the code, a small cost per call, and they allow mixing types in one collection or choosing the type at run time."
Q2. Option versus Result? When do you panic?
Model answer: "Option means a value may be absent; Result means an operation may fail and carries an error. I return Result for expected failures like bad input or I/O, and use ? to propagate errors. I panic only for bugs or impossible states, and in tests or prototypes. Libraries should rarely panic."
Q3. What does ? do exactly?
Model answer: "On Ok or Some it unwraps the value. On Err it converts the error with From::from and returns it from the current function; on None it returns None. It only works in functions whose return type can carry that early return."
Q4. Box, Rc, Arc, RefCell, Mutex: when each?
| Pointer | One-line answer |
|---|---|
| Box<T> | Single owner on the heap; recursive types and trait objects |
| Rc<T> | Shared ownership in one thread, read-only |
| Arc<T> | Shared ownership across threads (atomic count) |
| RefCell<T> | Interior mutability in one thread, borrow rules checked at run time |
| Mutex<T> / RwLock<T> | Interior mutability across threads, with locking |
Q5. What are Send and Sync?
Model answer: "Send means a value can be moved to another thread; Sync means a shared reference to it can be used from several threads. They are auto traits: the compiler derives them from a type's fields. Rc is neither, because its counter is not atomic; Arc<Mutex<T>> is both when T is Send."
Q6. Does Rust prevent deadlocks?
Model answer: "No. Safe Rust prevents data races, but deadlocks and logic bugs are still possible. I avoid them by keeping lock scopes short, never awaiting or calling unknown code while holding a lock, and taking multiple locks in a consistent order."
Q7. Threads or async?
Model answer: "Async suits many I/O-bound tasks, such as thousands of network connections, on a runtime like tokio with few threads. Threads suit CPU-bound work. Futures are lazy and need a runtime; blocking calls inside async code stall the runtime, so heavy work goes to spawn_blocking or a thread pool."
Q8. Quick-fire snippets
let v = vec![1, 2, 3];
let w = v;
println!("{}", v.len()); // does not compile: v was moved (E0382)
let x: Option<u32> = None;
println!("{}", x.unwrap_or(7)); // prints 7
let s = String::from("hi");
let t = &s;
let u = &s;
println!("{t}{u}"); // prints hihi: two shared borrows are fineA take-home assignment checklist
- Clear README: how to build, run and test; design decisions.
- cargo fmt, cargo clippy with no warnings, and passing tests.
- Errors handled with Result and good messages; no unwrap on user input.
- Small modules with clear names; logic in lib.rs.
- A few meaningful tests, including edge cases.
Common mistakes
- Saying RefCell makes code thread-safe. It does not; use Mutex or RwLock across threads.
- Claiming async is always faster. It is better for waiting, not for computing.
- Using unwrap everywhere in a take-home assignment. Reviewers notice immediately.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Interview questions: traits, errors, pointers and concurrency · 1/6
After ownership, interviews cover traits, errors, smart pointers, concurrency and async.
Prefer a video by a teacher? Find free videos on “rust interview questions traits smart pointers concurrency async” on YouTube ↗
In real life: A system-design follow-up
After the basics, an interviewer at a logistics company asks: "We need a service that tracks 50,000 delivery vans sending GPS pings every 5 seconds. How would you build it in Rust?" A strong answer: an axum service on tokio for the many connections, a bounded channel to a small pool of writer tasks for back-pressure, Arc-shared state for the latest positions (perhaps a RwLock or a concurrent map crate), batching database writes, and metrics and tracing for visibility. The answer connects language features to real constraints.
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
type Positions = Arc<RwLock<HashMap<u32, (f64, f64)>>>; // van id -> (lat, lon)
fn update(p: &Positions, van: u32, lat: f64, lon: f64) {
p.write().unwrap().insert(van, (lat, lon));
}
fn lookup(p: &Positions, van: u32) -> Option<(f64, f64)> {
p.read().unwrap().get(&van).copied()
}Practice (0/3 done)
Which pointer would you use for shared, changeable data across threads?
What does this print? let a: Result<u32, String> = Err("no".into()); println!("{}", a.unwrap_or(5) + 1);
Do a mock take-home in 3 hours: a CLI or small axum API that manages a library of books (add, list, search, borrow, return) with data saved to a JSON file. Apply the checklist from this topic, then ask a friend or online community to review it.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Portfolio, open source and a learning planRust careers and interviews · same module
- Where Rust is used and the job marketRust careers and interviews · same module
- Interview questions: KotlinKotlin and Android App Development · Android career path
- Rc, RefCell and WeakClosures, iterators and smart pointers
- Interview questions: DartFlutter and Dart · Flutter careers and interviews
- Interview questions: Android and ComposeKotlin and Android App Development · Android career path
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
What is monomorphization?
Answer: Generating specialised code for each concrete type used with a generic
It is why generics have no run-time cost.
Is RefCell<T> safe to share between threads?
Answer: No, it is not Sync
Use Mutex or RwLock across threads.
What happens if you call a blocking function inside a tokio task?
Answer: It can stall other tasks on that worker thread
Blocking work belongs in spawn_blocking.
Which is a good answer to "When do you panic?"
Answer: For bugs and impossible states; expected failures return Result
Panics are for programmer errors, not normal failures.
Which statement about Rust and deadlocks is true?Related
Answer: Deadlocks are still possible; avoid them by design
Rust prevents data races, not deadlocks.
Why does thread::spawn require 'static data?Related
Answer: The thread may outlive any borrowed local data
Spawned threads can run after the caller returns.
From Interview questions: ownership, borrowing and lifetimes
Which type should a ViewModel expose for screen state?Related
Why must dyn Trait be behind a pointer like Box?Related
Answer: Its size is not known at compile time
Different implementing types have different sizes.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 1 more topic in “Rust careers and interviews” before its exam: Portfolio, open source and a learning plan.
- Module 12 exam: Rust careers and interviews · 10 questions · 20 min, without help. 4 topics of this module still to finish first.
- 50 topics left in the course before the final exam.
← Previous: Interview questions: ownership, borrowing and lifetimes