?. Has No Escape In ItStatus: Superseded by ADR-278 — its D1 and D4 are part of D17, its D2 is answered by D20, its D3 is part of D19 there
Date: September 22, 2026
Target Version: Nikaia 0.0.141
Corrects the reason of: ADR-189 D3 and §4, whose conclusion
stands and whose stated cause does not — the record is not rewritten
Related: ADR-008 D2 (the lattice, and what escapes means),
ADR-113 D2 (a reached member that does not copy is a view),
ADR-156 D4 (NK2303, the refusal that stands where Tethered
would)
ADR-189 put the third of ?. — a member that does not copy —
behind #196, the tether. The owner asked
the right question about that: the tether is only needed at very specific
boundaries, isn’t it?
It is, and ADR-008 D2 says so in its own table: Tethered is
chosen when the value escapes the buffer’s owning scope, which means returned
past it, captured by a @detached lambda, or written into a longer-lived
container or a global. A struct field is not an escape by itself — that sentence
is what makes the 1BRC inner loop free.
None of that is a ?..
The lowering ADR-113 D2 asks for is
x.as_ref().map(|it| &it.a). Against this repository’s toolchain:
| shape | what happens | state |
|---|---|---|
| receiver is a local, the view stays in its scope | compiles, runs | Borrowed |
| receiver is a temporary, the view is consumed in the same statement | compiles, runs | Borrowed |
view ?? view — user?.name ?? "nobody", and a literal is a view |
compiles, runs, zero cost | Borrowed |
view bound past a temporary — let n = find(1)?.name |
rustc: temporary value dropped while borrowed |
an escape |
Only the last is an escape, and it is not Tethered either: it is the case
NK2303 already covers one construct over — a view of a buffer that does not
outlive it, refused in this language’s words and naming .to_owned()
(ADR-156 D4). This compiler already builds that answer twice.
So no part of ?. needs the representation. ADR-189’s §4 said
it waits on #196 with everything else that wants a state between Borrowed and
Owned, and that sentence is what this record takes back.
??.A view on the left of a ?? and an owned value on the right:
user?.name ?? "nobody".to_owned(). Measured, the two cannot be joined:
"nobody" already is and
"nobody".to_owned() is not;.to_owned(), which the program already wrote.That is a decision about what ?? means over a view, not a representation, and
it is the owner’s: it decides whether ~6 sites in
crates/nikaia/tests/nullable.rs drop a .to_owned() they only ever needed
because the left side was owned. It goes to
open-decisions.md in that page’s shape.
The third case still lowers as it did and is still not refused — that half
was right, and for the reason it gave: refusing find(1)?.name ?? "nobody".to_owned()
would refuse a program that compiles and runs today
(C.4). What changes is the cause written beside it:
it waits on D2’s answer, not on a representation.
The record is not rewritten (ADR-187 D4’s rule, met a second time inside one day): a record says what was decided when, and the correction goes to the living sentences and to the index’s superseded and narrowed table.
ADR-008’s own worked check names the one shape in that program:
a Summary returned past main’s scope — a container of views outliving
the buffer they point into. That, a parser handing its rows past the buffer’s
scope, and a @detached lambda capturing one are what Tethered is for.
And nothing in the tree is one, which the analysis has already measured:
every view in examples/, benches/ and tests/ solves to Borrowed, and
crates/nikaia/tests/tethers.rs holds that as a ceiling over the whole corpus.
?? decision away from finished, not four change packages.keeps at 0.0.137, and this. What is left on it is text is one type
and Bytes.?? means over a view. D2’s question, on
open-decisions.md.?. over a non-copy member should yield a view at all. It should
— ADR-113 D2 decided that, and this record only says what the
answer costs.The correction, at 0.0.141.
check, diagnostics and crates/nikaia/tests/nullable.rs
that named #196 for this case.?? question on open-decisions.md.