Project 1: Ownership Visualizer (See the Borrow Checker’s Mind)

A CLI tool that takes Rust code snippets and outputs a visual ASCII diagram showing ownership transfers, borrows, and lifetimes—like seeing through the compiler’s eyes.

Quick Reference

Attribute Value
Primary Language Rust
Alternative Languages None (this is Rust-specific)
Difficulty Level 1: Beginner
Time Estimate 1-2 weeks
Knowledge Area Ownership / Borrowing / Compiler Internals
Tooling Rust Compiler, cargo
Prerequisites Basic programming knowledge, understand what memory allocation means conceptually

What You Will Build

A CLI tool that takes Rust code snippets and outputs a visual ASCII diagram showing ownership transfers, borrows, and lifetimes—like seeing through the compiler’s eyes.

Why It Matters

This project builds core skills that appear repeatedly in real-world systems and tooling.

Core Challenges

  • Parsing Rust code to identify variable bindings → maps to understanding let, mut, and move semantics
  • Tracking when ownership moves vs. borrows → maps to the core ownership model
  • Identifying lifetime scopes → maps to understanding when values are dropped
  • Detecting borrow checker violations → maps to the rules the compiler enforces

Key Concepts

  • Ownership fundamentals: “The Rust Programming Language” Chapter 4 - Steve Klabnik
  • Move semantics: “Programming Rust, 2nd Edition” Chapter 4 - Jim Blandy
  • The Drop trait: “Rust for Rustaceans” Chapter 1 - Jon Gjengset
  • Parsing with nom or pest: “Command-Line Rust” Chapter 8 - Ken Youens-Clark

Real-World Outcome

$ cargo run -- analyze snippet.rs
Analyzing: snippet.rs

fn main() {
    let s1 = String::from("hello");  // s1 OWNS "hello"let s2 = s1;                      // ownership MOVES to s2
    │                                 // s1 is now INVALID
    │   ╭──────────╮
    │   │ s1: ──X  │ (moved out)
    │   │ s2: ───● │ (now owns)
    │   ╰──────────╯
    │
    println!("{}", s2);               // OK: s2 is valid
    // println!("{}", s1);            // ERROR: s1 was moved!
}

Ownership Timeline:
[0] s1 created (owns String)
[1] s1 moved to s2 (s1 invalidated)
[2] s2 used in println!
[3] s2 dropped (String freed)

Implementation Guide

  1. Reproduce the simplest happy-path scenario.
  2. Build the smallest working version of the core feature.
  3. Add input validation and error handling.
  4. Add instrumentation/logging to confirm behavior.
  5. Refactor into clean modules with tests.

Milestones

  • Milestone 1: Minimal working program that runs end-to-end.
  • Milestone 2: Correct outputs for typical inputs.
  • Milestone 3: Robust handling of edge cases.
  • Milestone 4: Clean structure and documented usage.

Validation Checklist

  • Output matches the real-world outcome example
  • Handles invalid inputs safely
  • Provides clear errors and exit codes
  • Repeatable results across runs

References

  • Main guide: LEARN_RUST_DEEP_DIVE.md
  • “The Rust Programming Language” by Steve Klabnik and Carol Nichols