ADR-208: A View of Text Is Asked for a Copy Only Where Something Keeps It — and the Refusal Says Why

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)

1. Context

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).

2. Decisions

D1 — A view handed to a 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.

D2 — Where a view is kept, the refusal says why, for the case it is.

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:

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.

3. What this does not decide

4. What is built

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.

This site is open source. Improve this page.