Patterns for Defensive Programming in Rust

https://news.ycombinator.com/rss Hits: 24
Summary

I have a hobby. Whenever I see the comment // this should never happen in code, I try to find out the exact conditions under which it could happen. And in 90% of cases, I find a way to do just that. More often than not, the developer just hasn鈥檛 considered all edge cases or future code changes. In fact, the reason why I like this comment so much is that it often marks the exact spot where strong guarantees fall apart. Often, violating implicit invariants that aren鈥檛 enforced by the compiler are the root cause. Yes, the compiler prevents memory safety issues, and the standard library is best-in-class. But even the standard library has its warts and bugs in business logic can still happen. All we can work with are hard-learned patterns to write more defensive Rust code, learned throughout years of shipping Rust code to production. I鈥檓 not talking about design patterns here, but rather small idioms, which are rarely documented, but make a big difference in the overall code quality. Here鈥檚 some innocent-looking code: if !matching_users.is_empty() { let existing_user = &matching_users[0]; } What if you refactor it and forget to keep the is_empty() check? The problem is that the vector indexing is decoupled from checking the length. So matching_users[0] can panic at runtime if the vector is empty. Checking the length and indexing are two separate operations, which can be changed independently. That鈥檚 our first implicit invariant that鈥檚 not enforced by the compiler. If we use slice pattern matching instead, we鈥檒l only get access to the element if the correct match arm is executed. match matching_users.as_slice() { [] => todo!("What to do if no users found!?"), [existing_user] => { } _ => Err(RepositoryError::DuplicateUsers) } Note how this automatically uncovered one more edge case: what if the list is empty? We hadn鈥檛 explicitly considered this case before. The compiler-enforced pattern matching requires us to think about all possible states! This is a common pattern in a...

First seen: 2025-12-05 18:17

Last seen: 2025-12-06 17:20