Status: Superseded by ADR-292 — its D1 and D2 are not carried as rules there: they qualified the statement overlapping ADR-050 D1 displaced (D1 there); D1’s test survives as where the touch-set walk stops (D3 there) Amends: ADR-033 D5 — “no speculation” had one case it did not name Builds: ADR-033 §6’s first increment
ADR-033 D5 forbids running an operation early that might not have run at all:
if x { read(a) } else { read(b) }starts one of them. Running both to save latency would burn a request that was never wanted.
It said conditional and meant a branch. Building the first increment found a second shape, and it is the one real Nikaia code is written in:
let a = fs::read_to_string("eins.txt") catch { return }
let b = fs::read_to_string("zwei.txt") catch { "".to_string() }
Both statements are unconditional as written. Neither is inside an if. The touch sets are
disjoint — two different files, both read. Every rule in D2 says they may overlap.
They may not. If the first read fails, its handler leaves the function, and the sequential program never performs the second read at all. Overlapping them performs a read that the program as written would not have performed.
That is the thing D5 exists to prevent, arriving by a route D5 did not look down. catch is not
a branch in the shape of an if, but a handler that can divert makes every statement after it
conditional on the operation before it having succeeded.
“Can leave the function” is any return or throw anywhere in the handler, however deeply
nested. A handler that merely supplies a fallback value — catch { "".to_string() } — does not
divert, and the pair may overlap.
The test is conservative in the direction ADR-033 D4 already set: a handler this compiler cannot see through keeps the order.
D5 should have said, and now says:
An operation may be started early only if the program as written would certainly have performed it.
A branch is one way to be uncertain. A diverting handler is another. A break, a loop condition,
and an early return between two statements are three more, and all of them are covered by the
sentence rather than by a list.
It would have been easy to fix the code and say nothing — the restriction is four lines and a walk. Two reasons not to.
It is a correction to a decision made one day earlier, and ADR-033 is marked provisional partly because decisions of that size are expected to need them. A provisional decision that quietly acquires patches is no longer provisional; it is just vague.
It is the first evidence about ADR-033 that came from building rather than from thinking. ADR-033 §7 accepted a semantic decision without a measurement and owed something in return: that what building it teaches gets written down. This is the first instalment.
lets whose handlers cannot divert overlap; if either handler can return or throw,
they do not.catch { return } is a common shape, and a pair using it
stays sequential. That is correct rather than unfortunate — the second read genuinely might not
have happened.a_diverting_handler_keeps_the_order in tests/touch_sets.rs is the case, and it is named after
the rule rather than after the fix.