fix(params): a declared bool default was unreachable — absence read as false - #1
fix(params): a declared bool default was unreachable — absence read as false#1wengtytt wants to merge 1 commit into
bool default was unreachable — absence read as false#1Conversation
…s `false` Every typed route parameter reaches its declared default the same way: the macro emits `get_x(name).unwrap_or(default)`, and `get_x` returns `Err` when the parameter is missing because it goes through `require_scalar`. `bool` is the one type whose "missing" is itself a usable value, so `get_bool` answered `Ok(false)` rather than erroring — and `unwrap_or` unwrapped that `false`. THE DEFAULT WAS UNREACHABLE for every `param: bool = true`.⚠️ Found in a consumer: a cancellation route declared `at_period_end: bool = true` and documented the reversible, deferred form as its default. A client that omitted the parameter got the IMMEDIATE cancellation instead — the destructive direction, and the opposite of what the route promised. It stayed invisible because the route behaved correctly whenever the parameter WAS supplied. Adds `Extracted::get_bool_opt`, which distinguishes absent from `false`, and points the macro's defaulted-bool arm at it. ⚖️ The BARE-bool arm is deliberately untouched. `param: bool` with no default legitimately means "false unless asked for" — `confirm`, `dry_run`, `strict_policy` — and making absence an error would turn every one of those into a `400`. Tested at the mechanism: absent vs explicit `false` vs explicit `true`, the generated `unwrap_or(default)` shape verbatim, and the control that an explicit `false` still overrides a `true` default. A consumer-side end-to-end test OMITS the parameter, which is the assertion — supplying it explicitly passes against the broken build, which is how this nearly shipped unnoticed. Gate: fmt, clippy `-D warnings`, `cargo test --workspace` — 18 suites, 0 failed. Claude-Session: https://claude.ai/code/session_015Qr4t8PPka4VCoAbRUS9kt
macrini
commented
Sep 4, 2026
Reviewed and landed on Verified the mechanism rather than taking the description on faith: Three adjustments on the way in: 1. The tests did not guard the fix. This is the one worth carrying forward. Your tests call c7b5747 adds a test that goes through Your own commit message already identified this ("supplying it explicitly passes against the broken build") — the end-to-end test you mentioned was consumer-side, so this repo still had nothing that would catch a regression. 2. 3. Added the One housekeeping note: the commit carried a Gate on the final tree: |
A route parameter's declared default is reached through the generated
get_x(name).unwrap_or(default), which works becauseget_xreturnsErrwhen theparameter is missing — every typed getter goes through
require_scalar.boolis the one type whose missing is itself a usable value, soget_boolansweredOk(false)rather than erroring.unwrap_orunwrapped thatfalse, and the declareddefault was unreachable for every
param: bool = true.Why it is worth fixing rather than working around
Found in a consumer: a cancellation route declared
at_period_end: bool = trueanddocumented the reversible, deferred form as its default. A client that omitted the
parameter got the immediate cancellation instead — the destructive direction, and
the opposite of what the route promised.
It stayed invisible because the route behaved correctly whenever the parameter was
supplied, so every test that passed one passed.
The change
Extracted::get_bool_opt, which distinguishes absent fromfalse;boolarm at it.⚖️ The bare-
boolarm is deliberately untouched.param: boolwith no defaultlegitimately means "false unless asked for" —
confirm,dry_run,strict_policy—and making absence an error would turn each of those into a
400.Tests
Unit tests at the mechanism: absent vs explicit
falsevs explicittrue; the generatedunwrap_or(default)shape verbatim; and the control that an explicitfalsestilloverrides a
truedefault.cargo fmt,clippy --workspace --all-targets -D warnings,cargo test --workspace—18 suites, 0 failed.