Challenge 3: Why Rust Makes This a Compile Error and C Doesn't — Possible Solution ==================================================================== In C, `pthread_mutex_t lock` and `int counter` are two ENTIRELY SEPARATE variables, with no relationship between them that the language itself is aware of. The compiler has no concept of "counter is the data lock protects" -- that association exists only in the programmer's own understanding, or at best in a comment. Because of this, the compiler has absolutely no basis on which to reject code that reads or writes counter without first locking lock -- from the compiler's perspective, counter is just an ordinary int, freely readable and writable from anywhere, including from inside a thread function that never touches lock at all. The mistake compiles cleanly and runs; whether it actually causes a visible problem depends entirely on thread timing/scheduling, which is why the consequences are only SOMETIMES visible -- exactly Challenge 1's own non-deterministic counter values. Rust's Mutex takes a fundamentally different structural approach: the protected data lives INSIDE the Mutex itself as its own field -- there is no separate, independently-accessible "counter" variable that exists outside the Mutex's control at all. The ONLY way to obtain a reference to the inner data is by calling `.lock()`, which returns a MutexGuard -- and Rust's borrow checker enforces that no code anywhere in the program can name or access the inner value except through that guard. This means attempting to read or write the protected data WITHOUT first calling `.lock()` isn't merely bad practice in Rust -- it's not even syntactically possible, because there is no variable name in scope that would let the code refer to the data directly. The compiler doesn't need special-case logic to "detect" an unprotected access; the language's own scoping and ownership rules make an unprotected access impossible to even write, which is why it becomes a compile error (specifically, a "cannot find value" or ownership-related error) rather than a runtime risk. WHY THIS WORKS AS AN ANSWER ------------------------------ This identifies the structural root cause -- data and lock as two unrelated variables in C (nothing for the compiler to check) versus data living INSIDE the Mutex type in Rust (nothing to access without going through the lock) -- rather than describing the difference as merely "Rust checks more thoroughly," and explains why C's failure mode is specifically non-deterministic (dependent on thread timing) in a way Rust's compile-time rejection simply cannot be.