?? Lends Its Left Side Where the Answer Is Read, and Takes It Where It Is KeptStatus: Superseded by ADR-279 — its D1-D3 are D5-D7 there
Date: September 30, 2026
Target Version: Nikaia 0.0.288
Answers: open-decisions.md, Whether ??
takes its left side. The owner chose option (1), prepared against
ADR-258’s four weights.
Related: ADR-094 D1 (whether an argument is lent or handed
over is decided by the function, not the call), ADR-191 D2
(?? joins two views), ADR-114 D4 (a map read on the left of a
?? is a view of the map), ADR-213 (a map’s read is lent),
ADR-008 D5 (the compiler inserts no copy)
viewed ?? "none" over a viewed: String? lowered to a move of viewed,
and nothing recorded it, so a use of viewed after the line reached rustc
as borrow of moved value (found moving Ty::parse into Nikaia, ADR-257).
0.0.286 made that use NK2105, which is right for what the compiler did.
Whether the compiler should do that was not written anywhere: Part I 3.5
said what ?? answers and not what it does to its left side.
The owner remembered the question, and it was close. ADR-190 D2 and
ADR-191 D2 decided what ?? produces when its left side is already a view
(a ?. reach): two views join into a view, and an owned fallback beside a
view is NK1185. ADR-114 D4 and ADR-213 decided that a map read on the left
stays a view of the map. None of them decided what happens to an owned
name on the left. All of them point where this record goes: a ?? that only
needs to be read yields a view.
A name on the left of a ?? is lent where the answer is only read, and
taken where the answer is kept: the rule an argument follows (ADR-094
D1), applied to the one operator that hands a value on.
print(user ?? "guest"), shown(v ?? other): the option is
opened below (.as_deref() for text, .as_ref() for anything else) and
the answer is a view of the name or of the fallback. Nothing is copied, and
the name is usable on the next line.let name = user ?? "guest", return user ?? "x", a field: the
name is taken, as let b = a takes a, and a use of it afterwards is
NK2105, whose way out is .clone().All four point the same way. D1: only a program that keeps the answer
and uses the name again pays, which is what let b = a already makes it
pay. D2: the developer writes nothing in either common shape.
D3: neither common shape copies. D4: it is the argument rule and the
let rule, and it agrees with ADR-191’s ?? joins two views.
A text literal is a view already; a name is viewed where it stands; a variant of an enum the file declares is a constant. Any other fallback (a call, an expression that builds a value) takes the left side as before, which is the direction that cannot be wrong below. That is D1’s special case carrying its cost, as ADR-258 D1 says it should.
?? does to its left side.NK2105 after a ?? means the answer was kept, which is the one shape
where the program has to say .clone(), or that it stood in a read position
§4 has not reached yet.D1 at a call’s argument that the callee only reads, which is where the
checker already decides lending (the_compiler_writes_the_reference), and at
the four print calls, whose argument is formatted by reference: a ?? there
is recorded as lent, and the emitter opens the option. Every
other ?? over a name is taken when its statement ends, as before.
The other reading positions (0.0.294, #98):
f"…" hole is formatted by reference, so a ?? that is the hole
lends, whatever it holds.?? of text on either side. Text alone, and
that is D3’s rule again: the language below compares a view of text with
text, with a literal and with a view, and a view of anything else with a
view only, so (t ?? other) == value over a struct would need a reference
the source did not write on the other side. It is taken, as before.(name ?? "guest").len(),
(t ?? fallback).shown(). A name nothing describes is claimed nothing
about, and takes.tests/nullable.rs runs each read shape (a literal, a name of text, a
declared variant, a name of a struct, a hole, a comparison, a receiver) and
the kept ones.