Rusty thoughts on "Parse, don't validate"
Eli Bendersky explores Alexis King's 'Parse, don't validate' pattern in Rust, showing how types like NonEmpty and AbsPathBuf encode invariants at compile time.
read it It provides clear, practical Rust code examples demonstrating how type refinement eliminates redundant runtime checks.
summary
The article reviews Alexis King's 'Parse, don't validate' design pattern using practical Rust examples. It contrasts standard types like Vec and PathBuf, which require repeated runtime checks, with refined types such as NonEmpty, AbsPathBuf, and NonZero. By transforming data into these specific types at system boundaries, developers can enforce domain invariants and make illegal states unrepresentable. This approach simplifies downstream code and shifts validation errors to compile time.
key points
- Standard collections like Vec force developers to handle empty states repeatedly, even when invariants guarantee data exists.
- Refined types such as NonEmpty and AbsPathBuf capture state proofs during parsing, eliminating the need for downstream validation.
- Standard library types like NonZero leverage niche optimizations to provide safety guarantees without performance overhead.
who should read it
Rust developers and software engineers interested in type-driven design and correctness.
discussion warm
consensus
Commenters largely embrace the pattern while expanding on it, noting that 'Parse, don't validate' is a specific application of the broader principle 'Make Illegal States Unrepresentable'.
pushback
A minority argues that custom wrapper types introduce unnecessary boilerplate and that standard collections paired with unwrap() are often pragmatic enough for typical applications.
I prefer a slightly more general rule: Make Illegal States Unrepresentable. The "Parse, don't validate" rule is a special case of MISU.
What's the difference? MISU applies even when there's no parsing-like transformation happening. For example, if you have a variable that represents the current state of a network connection, and let's say it can be Disconnected, or Connected to some IP address (this is an oversimplification).
Then one way to do it would be
struct { connected: bool, peer_ip: int32 }
The trouble is that this allows us to represent an illegal/meaningless state: we're …
It broadens the discussion by connecting the article's core thesis to the more general principle of making illegal states unrepresentable using sum types.
Generated by an LLM from the article and thread. Check the sources before relying on it.