ref, And The Ledger Names The ReceiverStatus: Accepted
Date: September 23, 2026
Narrows: ADR-083 D2’s both ways out are in the message. The two
ways out stay the whole answer where a field is bound or passed; where it
is handed back and the result is declared a view, there is no refusal to have
a way out of
Related: ADR-094 D1 (the compiler writes the reference) and D4
(the positions it writes it in), ADR-291 (returns = "borrows(…)"),
ADR-283 (a field that already is a view),
ADR-184 D4 (ref X is the spelling, &X is not),
ADR-288 (the emitter has no types, so the checker answers),
ADR-251 D4 (the ledger writes what a result points into as
ref(…) in the result)
The accessor a program most often writes needs a spelling of its own:
pub struct Holder { text: String }
impl Holder {
pub fn text(ref self) -> ref String {
return self.text
}
}
would be two refusals at once — NK1131 self is borrowed here, so text
cannot be handed back by value, and NK1104 this returns String, and the
function declares ref String. Both are about the same missing character, and
neither names it: the result is declared a view, the value is a place inside a
borrowed subject, and there is nothing else the line could have meant.
One spelling works without this, and it is the one ADR-094
D1 says the author should not have to write: return ref self.text. That would
leave a reference the author writes is required in one position and refused in
two others — the state ADR-094 D1 exists to end.
& at a return is the compiler’s, and it is ADR-094 D1’s third positionWhere a function declares a view and hands back a place inside a borrowed
subject, the reference is written by the compiler. return self.text out of a
ref self method declaring -> ref String lowers to &self.text, and so does
the tail form { self.text } — a tail is a return written without the word,
and one of the two answering differently would be a spelling that decides a
refusal.
Both halves are required and neither is inferred from the other. A result
declared by value is a move out of a loan and stays NK1131; a receiver taken by
value has nothing to lend, so the subject dies at the end of the call and the
refusal is NK1104’s — the value is a String where a ref String was
declared, said in this language’s words rather than by rustc about a file
nobody wrote (Part III C.1).
A place inside the subject and not the subject itself. return self out of a
ref self method is already a view and owes nothing.
Decided in the checker and written in the emitter, which is
ADR-288’s division: which place is a view of what is a question
about types, and the emitter keeps none. The answer travels as a set of statement
positions, exactly as the let position’s already does.
ref is not refused here, and that is a staging rather than a second ruleChanged by ADR-views-3 D4, D7: ref is not written on a result at all; a view of the subject is handed back without a mark.
Changed by #96: the inference reaches a parameter declared ref T - fn of(row: ref Row) -> ref String { return row.name } lends as return self.name does - and with every root a lending return can have covered, the written ref there is NK1137. A let bound to a view keeps its own words.
return ref self.text goes on working. ADR-094 D4 already stages
its own refusals — NK1137 covers the for position and not the let one — for
the reason that applies here too: a refusal that arrives before the inference
which replaces it takes away the only way to say what a line means. The
inference covers a borrowed subject but not every root (§4), and the refusal
answers to different evidence than the inference: the corpus is what says
whether the second spelling is still written anywhere.
borrows columnChanged by ADR-251 D4: the ledger writes the column in the result, -> ref(self) String, rather than as returns = "borrows(self)"; what it names is unchanged.
A method whose result is a view and whose receiver is ref self records the
receiver as a position its result may point into: -> ref(self) String. The
column names the positions a result may point into (ADR-291), a
ref self is a view the caller gave, and a result that is a view may point into
any view it was handed.
Without it, the view analysis reads no position at all for the accessor a program most often writes, which is the empty column that means nobody said and refuses. So this is the half of D1 a caller in another package sees.
NK1131’s help names a third way out where the field is handed back — declare
the result ref T and the view is what this line means — and only there. A
field bound to a local or passed to a call has nowhere declared to point, so the
two ways out are still the whole answer, and offering a third there would be
Part III C.2 from the other side.
examples/http’s Request::body() is such an accessor
(ADR-289 D20), so the request’s whole surface is methods rather
than a mixture of methods and fields the reader has to tell apart.
A widened borrows column is the fail-closed direction for the one reader of
it: the view analysis asks that every named position be clear of the carrier,
so naming one more position can only make it refuse more often, never less.
The refusal of the written ref (D2), which waits on the corpus rather than
on a mechanism.
A place inside a lent parameter. fn a(row: ref Row) -> ref String { return
row.name } is the same derivation with a different root, and it wants the
written ref — which is the other half of why D2 does not refuse one yet. The
root has to be a view whose buffer is the caller’s, and that is a question
about the binding rather than about the place; a local bound to a view of
something this body owns is not it. #96 carries both halves
together, because the refusal may only land once the inference covers every root.
A view of a field’s field, return self.head.method(), is not this: that is a
call, and what its result points into is the callee’s column to say.