Issue #588: Decision: fn longest(a: String, b: String) -> ref String is NK2302 since D25. Keep the refusal?

Open and answer this issue on GitHub.

language, decision · opened 2026-10-12 · updated 2026-10-12 · 0 comments

What this is, from zero

A function can hand back a view of one of its arguments instead of a copy:

fn first_word(text: String) -> ref String { text.split(' ')[0] }

The result points into text’s buffer, so it is valid as long as text is. Nikaia writes no lifetimes; the compiler works out which argument the result points into. That is easy with one source. With two it is a question:

fn longest(a: String, b: String) -> ref String {
    if a.len() > b.len() { return a }
    return b
}

Which buffer does the result point into? It depends on a run-time comparison. The caller cannot know, so it must keep both a and b alive as long as it uses the result. That is what the language did until 0.0.836 (parameters lowered as views shared one lifetime: “union”), silently: every caller met the constraint at its own line.

Where the question comes from

#580 (ADR-283 D25, written by the Opus review of the owner’s note on NK2302, 2026-10-11): a result views exactly one source over all ways out; two sources chosen at run time are refused with NK2302. Part I 6.5 says ref on a parameter is only an assertion, so longest(a: String, b: String) and longest(a: ref String, ...) follow the same rule. This took back something that compiled before. It is isolated in crates/nikaia/tests/result_source.rs::plain_string_longest_is_refused_since_d25 (the doc comment says how to revert). One existing test program had the shape (tests/language/src/views_handed_back.nika, views_handed_back_first) and was rewritten to return ref a or a literal, same output.

Facts

Options

Risk if wrong

Keeping the refusal: a user with a real run-time choice must clone or split. Reverting: callers fail far from the definition.

Recommendation

Keep the refusal (Part I 6.5 and 6.6 are then consistent, and the owner’s note chose a hard stop for run-time ambiguity). Revisit only with an explicit marker if a measured cost of the clone shows.

Related: #580, #579 (the importer meets this shape often), docs/mitigation-hurdles.md section 1.

Back to Open Issues