check.hpp¶
Precondition checking for shulib core.
This header declares 1 type (1 member), 4 free functions, and 1 type alias.
Extracted from include/shulib/core/check.hpp — this page is that header's documentation, reformatted, so it cannot disagree with the code. Prose about how to think about the API lives in the user guide; worked recipes live in the cookbook; this page is the complete, mechanical list of what exists.
Contents¶
struct PreconditionErrorlogic_errorPreconditionHandler— type aliasthrowingPreconditionHandler— free functionsetPreconditionHandler— free functionpreconditionHandler (overload 2)— free functionprecondition_failed— free function
struct PreconditionError¶
What a violated precondition throws under BOTH shipped policies. A logic_error because a breach is a CALLER bug, not a runtime condition to retry: nothing catches it at the call site, because the call sites guard invariants (bounds, non-null, finite) past which continuing is undefined behavior. The motion scheduler catches it at the task boundary and turns it into a FAULT_ABORT exit plus a safe drivetrain, so one bad reading costs one motion — never the auton.
struct, declared at include/shulib/core/check.hpp:49.
PreconditionError::logic_error¶
Inherits logic_error's constructors: the message is the literal handed to SHULIB_PRECONDITION, readable through what().
alias, declared at include/shulib/core/check.hpp:52.
PreconditionHandler¶
The policy hook type. MUST NOT RETURN (see header contract).
type alias, declared at include/shulib/core/check.hpp:56.
throwingPreconditionHandler¶
The host/test default policy: throw, so breaches turn tests red.
free function, declared at include/shulib/core/check.hpp:59.
setPreconditionHandler¶
Install a policy handler; returns the PREVIOUS handler so a caller (e.g. a test) can restore it. Passing nullptr restores the default throwing policy — the seam is never left empty.
free function, declared at include/shulib/core/check.hpp:73.
preconditionHandler (overload 2)¶
The currently installed policy (introspection; used by tests to restore).
free function, declared at include/shulib/core/check.hpp:81.
precondition_failed¶
Report a violated precondition through whichever policy is installed. Reach it through SHULIB_PRECONDITION rather than calling it directly — the macro is what keeps the call sites identical on every target. [[noreturn]] is load-bearing: a handler must not return, and if a broken one does, this calls std::terminate() rather than let execution continue past a violated invariant. That terminate is unreachable through either shipped policy; only a handler that breaks the seam's contract can get there.
free function, declared at include/shulib/core/check.hpp:91.
Design commentary, from the header¶
The header opens with the reasoning behind these shapes. It is reproduced here in full because a reference that only lists signatures teaches nobody why.
The header’s own reasoning — 35 lines
Precondition checking for shulib core.
SHULIB_PRECONDITION(cond, msg) guards a CALLER contract. On a violation it calls
precondition_failed(), which routes through an installable POLICY HANDLER — the
§18.4 policy seam (resolved at chunk A1; this replaced the former TODO here).
The two policies, and why the seam exists:
* HOST/TEST (the DEFAULT handler, installed at startup automatically): THROW a
catchable PreconditionError, so a contract breach turns a test RED instead of
silently corrupting state (e.g. a NaN flowing into the pose estimate).
* ON-ROBOT (installed once at init by R1's hal/pros bootstrap): raise
diag::FaultCode::Precondition on the fault latch, then THROW the same
PreconditionError — which the motion scheduler catches at the task boundary and
converts to a FAULT_ABORT exit + a safe drivetrain state. Recovery happens at
the MOTION boundary, not the call site: the call sites guard invariants
(bounds, non-null, finite) past which continuing would be undefined behavior,
so "log and continue right here" is not a safe fallback — unwinding to the
nearest boundary that CAN recover is. One bad reading degrades one motion to a
fault code; it never aborts the auton.
The call sites never change — SHULIB_PRECONDITION(cond, msg) everywhere, on every
target — only the installed policy differs. That is the whole design.
HANDLER CONTRACT (load-bearing): a handler must NOT return — it throws (both shipped
policies do) or otherwise diverts control. precondition_failed() is [[noreturn]];
if a broken handler does return, std::terminate() fires rather than letting
execution continue past a violated invariant into undefined behavior. (This
terminate is reachable ONLY via a handler that violates the seam's contract — the
shipped policies can never hit it.)
Concurrency contract: the handler is installed ONCE, at startup, before any other
task exists (host: never re-installed outside tests; robot: in R1's init). The slot
is a plain pointer read on the hot path — no atomics, because installation is not
concurrent with use by contract.
Last updated 2026-08-15 — published from the main release branch, commit fa545ff. This site tracks releases, so between them it can lag the repository — that lag is deliberate, and it is what keeps the development log off the public site. For the current state of the code, see the repository.