Status: Superseded by ADR-282 — its D1-D2 are D11 and D25 there
Date: September 24, 2026
Target Version: Nikaia 0.0.184
Answers: the owner’s point after ADR-207: a language that hides
ownership this thoroughly has to explain the one place it does not — otherwise the
programmer asks why the compiler, which knows exactly what to write, does not
write it here
Related: ADR-207 (literals; D3’s &str parameter this reads),
ADR-005 §3 (no copy the program did not write — the reason the
refusal gives), ADR-107 D3 (a copy is .to_owned()),
ADR-094 (keeps; NK1137, the & that is the compiler’s), Part III
C.2 (a help line is paste-ready)
After ADR-207 the one text refusal left is a view of text standing
where a String is wanted. Its message named the two types and said write
.to_owned(). Taken one at a time, each of those refusals raises the same
question, and it is a fair one: this language infers the &, the lifetimes, the
sync, the lock order — why not this?
Looking at what the refusal actually covered answered part of it the hard way:
fn show(s: String) { println(s) }
fn relay(city: ref String) { show(city) }
was refused, asking for city.to_owned() — a copy nothing would keep. show
only reads its parameter, which is a &str below since ADR-207 D3, so the view
was already exactly what it takes. That is not a message to explain better; it is
a correct program refused (Part III C.4).
String the callee only reads is lent as it is.Where the keeps column says the callee reads the parameter and does not keep it,
and the callee is a function this compiler declares — so the &str below is its
own writing — a view of text is accepted and passed through unchanged:
show(city) in the source, show(city) in the Rust. A ref the source wrote at
such a call is still NK1137, for the reason it always was: the reference there
is the compiler’s.
A function of std or of a described crate is not included. Its signature below
is a hand-written description, and String there may mean a Rust String by
value.
What remains refused is a view where something keeps the text — a field, an
annotated let, a return or a body’s last value, an argument the callee keeps.
There the compiler does know what it would write, and the reason it does not is a
decision, so the message states the decision instead of only its consequence.
Three cases, because one sentence for all of them fits none:
ref String. The text belongs to the caller, who
still has it; Person keeps its name after this line, so it needs text of its
own; Nikaia copies text only where the program says so — a copy costs as much as
the text is long, and one made on its own would run every time this line does,
with nothing in the source to show it. The help leads with the answer that
copies nothing — declare n: String, and the caller hands its text over instead
of lending it — and gives n.to_owned() second.String on this line (ADR-207); through a name it is not, because that would
change the type the name was declared with on a line above. The help names the
two spellings that work — the literal in place, or let s: String = "…"..to_owned().The reason is the same in all three and is ADR-005 §3’s: a copy of text is proportional to its length and happens on every run of the line, so it is the one cost this language insists on seeing in the source. The message now says that rather than leaving the reader to reconstruct it.
lends), so D1 does not reach obj.show(city); it will when methods lend.Vec view kept where a
Vec is wanted. Text is where every program meets it first; the others follow
when a program shows the need.D1 in the argument check; D2 as a_view_kept, read by the let, field, return,
tail and argument positions, with the binding remembering the literal it was bound
to. crates/nikaia/tests/text_literals.rs runs D1 end to end and checks each of
D2’s three explanations.