iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Quiz

Six Rust questions that come up in code review. Try first.

Six Rust design questions

EXAMPLE
// ============================================================
// Q1) Why does this fail to compile?
// ============================================================
// let s = String::from("hi");
// let r = &s;
// drop(s);
// println!("{r}");
//
// ANSWER: r borrows s; dropping s while r still lives is a use-after-free
// that the borrow checker prevents. The print line MUST come before drop(s).

// ============================================================
// Q2) When to use String vs &str?
// ============================================================
// ANSWER:
// - &str:   borrowed view; cheap to pass; default function parameter type
// - String: owned, heap-allocated; needed when you mutate or return it
// Functions usually take &str; types usually own String fields.

// ============================================================
// Q3) Vec<T> vs &[T] in function signatures?
// ============================================================
// ANSWER: prefer &[T] when you only read. Callers can pass &Vec<T>, &[T; N],
// or any slice. Only take Vec<T> if you take ownership or mutate via push.

// ============================================================
// Q4) Why does this not compile?
// ============================================================
// fn double(x: i32) -> i32 { x * 2 }
// let xs = vec![1, 2, 3];
// let doubled: Vec<_> = xs.iter().map(double).collect();
//
// ANSWER: xs.iter() yields &i32, not i32. Either map(|&x| x * 2) or
// xs.iter().copied().map(double).collect().

// ============================================================
// Q5) Result<T, E> chain ergonomics
// ============================================================
// ANSWER: ? propagates errors. Use it on EVERY fallible call inside a
// function that itself returns Result. anyhow/thiserror give richer error
// messages without ceremony.

// ============================================================
// Q6) When is .clone() acceptable?
// ============================================================
// ANSWER:
// - Tests and one-off scripts where ergonomics > perf
// - Small types where clone is cheap (i32, String of fewer chars)
// - When you genuinely need a separate owned value
// Cloning in hot loops to satisfy the borrow checker is a code smell — refactor
// to borrow, use Rc/Arc for shared ownership, or restructure the data flow.

// ============================================================
// Bonus — async vs threaded?
// ============================================================
// ANSWER:
// - Many concurrent I/O tasks:  async (tokio)
// - CPU-bound parallelism:       std::thread + rayon
// Do not run CPU-bound work inside async without spawn_blocking; you stall
// the executor.

// ============================================================
// Scoring
// ============================================================
// 6 / 6 -> ship to production Rust
// 4 / 6 -> bookmark rust/cheatsheet
// < 4   -> The Rust Book + the rustlings exercises

Why it matters

When you reach for `.clone()` to "appease the borrow checker", pause and ask if borrowing or restructuring would work instead. Clones in hot loops are silent perf killers; in cold code paths they are fine. The mental check is the difference between idiomatic Rust and "Rust that compiles but throws away the language guarantees".

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// 3 questions per lesson.
Try it Yourself »

Discussion

Loading…