Pimp My IDE / Garage dispatch
Back to garage
September 27, 2026 | Rust / types / input boundaries

Stop checking the same promise twice.

Validation rejects bad input. Parsing can do more. It can return a value whose shape makes the rejected case impossible downstream.

The take. Put the proof in the returned type. A successful boundary should narrow what later code can represent, not hand back the same loose container with a comment attached.

A checked vector is still a vector.

Eli Bendersky starts with a configuration function that reads a comma-separated environment variable into a Rust Vec<PathBuf>. The function rejects an empty vector. Its caller still receives a type that permits emptiness, so asking for the first item returns an Option and forces another branch.[1]

The check happened. The returned value did not retain what the check proved. Later code must trust control flow, a comment, or an unreachable! claim.

If success proves a fact, return a value that remembers the fact.

Parsing moves the boundary.

A non-empty collection stores a head and a possibly empty tail. There is no constructor for zero elements. Conversion from Vec can fail once. After it succeeds, first() returns an element instead of another question.[1]

Alexis King's original essay describes the same move as strengthening the input type. The caller stops carrying an impossible branch because the parser has changed the representation, not merely inspected it.[2]

Refine values in steps.

Bendersky points to rust-analyzer's absolute path type. A regular path can first become a UTF-8 path, then an absolute UTF-8 path. Each conversion establishes one fact. Code that receives the refined type does not need to ask those questions again.[1]

This is useful beyond Rust. Agent tools ingest paths, tool arguments, policy files, model output, and remote payloads. Convert each loose input into a smaller, named state before granting the next capability. Keep syntax, structural, semantic, and authority failures distinct.

Errors belong to the conversion.

Serde's documentation separates format errors such as unexpected input or trailing characters from errors raised while constructing a target value, such as a missing required field.[3] That distinction gives operators a repairable answer. The bytes may be malformed, the shape may be wrong, or the value may violate a rule.

Do not erase those failures into one "invalid config" message. Name the stage, the rejected field, and the expected form. Then return the refined value only after that stage passes.

Interactive makeover / input validation

Invariant stamp press

Traditional purpose replaced: validate a text box, then let every caller wonder what passed. Better version: choose the value contract, run one visible conversion, and copy a handoff that names the facts still unproved.

Load the raw stock

Enter one illustrative POSIX path per line. The selected die controls which facts the browser checks.

Returned value contract

Changes wait in the raw tray until you press the machine.

NonEmpty<AbsPath> die2 parsed items

Conversion passed. Two unique absolute paths are represented by the teaching value.

Print the boundary handoff

A parsed path string does not prove that the path exists, is safe to access, or belongs to the caller. Those checks remain explicit.

Sources read, not vibes

Open the source log
  1. Eli Bendersky, "Rusty thoughts on Parse, don't validate", published September 26, 2026 and read September 27, 2026. This is the source for the Rust NonEmpty, rust-analyzer path refinement, NonZero, and Serde examples.
  2. Alexis King, "Parse, don't validate", published November 5, 2019 and read September 27, 2026. This is the original type-driven design argument and the source for strengthening an input type rather than repeating partial checks.
  3. Serde documentation, "Error handling", read September 27, 2026. It documents format-specific deserialization errors and custom errors raised while constructing data structures.
  4. Hacker News discussion 49864743, verified through the Hacker News API and page on September 27, 2026. It is the discovery route. At reading time it had no substantive comments, so it supports no technical claim.

Source boundary. The article applies the cited type-design pattern to agent and tool inputs as editorial advice. The browser press recognizes only trimmed lines, a leading slash, and duplicate strings. It does not resolve paths, inspect a filesystem, compile Rust, or grant authority.