ADR-225: A View Cut From Text Is Typed as One, and a Kept Argument Is Measured Against What the Receiver Says

Status: Superseded by ADR-282 — its D1-D3 are D18, D19 and D15 there Date: September 26, 2026 Target Version: Nikaia 0.0.208 Answers: #260’s a view pushed into a list a published function handed back reaches rustc, found probing ADR-224 §3 Refines: ADR-208 D2, whose refusal now reaches a view the checker could not see before; ADR-223 §1, whose the checker typed a method’s view of a String it owns as String this corrects Related: ADR-107 D3 (a copy is written, never inserted), ADR-031 (the receiver binds the signature’s names), ADR-105 (Seq)

1. Context

pub fn names() -> Vec[String] { … }
let mut c = names()
for line in text.lines() { c.push(line.trim()) }   // passed the checker; rustc: mismatched types

A published result is never both kinds (ADR-223 D4), so c is a list of text of its own, and the view should be refused with ADR-208 D2’s explanation. Nothing asked. Two gaps lined up:

ADR-223 §1 described the first gap as the checker typing the view as String. It was ?, which is worse: nothing about the value was asked at all.

2. Decisions

D1 — What cuts text into views says so, and text of its own has a view’s methods.

std.contracts describes trim_start, trim_end (-> ref String), lines, split, split_whitespace (-> Seq[ref String] sync ends), each returns = "borrows(self)", beside trim. A method looked up on a String receiver that String has no entry for is looked up on str: text of its own lends itself as a view, as the language below has it.

D2 — A kept argument is measured against what the receiver binds.

Where a signature writes $T for an argument the callee keeps, and the receiver binds $T to String, a view there is the question ADR-208 D2 answers for a parameter that says String itself: NK1102, the view is kept, .clone() is the copy. Vec::push says value: $T. A literal is built where it is kept (ADR-207 D2), as it is for any other argument.

The tier pass has already decided every position the package can decide: a list only views go into is Vec[ref String] by then and fits. So what this refuses is only what that pass could not make a view — a published position, a push inside a hole — which is exactly where the refusal belongs.

D3 — What is handed over as either kind reads as text of its own, and so does a mixed parameter.

value.into_either() is EitherText, which the checker reads as String (ADR-223 D3); so the conversion now reads as text of its own too, rather than as the view it wraps, and either_items() makes a sequence of views one of text. A view handed to a parameter both kinds flow into is let through, as one into a mixed field or result already was: the emitter hands it over.

3. Consequences

#260’s entry closes. Programs that compiled before still compile and do the same; where a value’s type is now known, the Rust may say Some(…) where it said .into() (ADR-068). The corpus refused nothing new: every view the ledger now types went into a position the tier pass had already made a view or mixed. Tests that used repeat as their example of a method nothing describes use to_ascii_uppercase, because a String receiver now finds str::repeat.

4. What is built

All of it, in 0.0.208: the five ledger entries and Vec::push’s $T; the str fallback in Checker::call_on; the substituted kept-argument check (a_view_kept_where_the_receiver_says_text); the conversions read as text of their own; Checker::either_param. crates/nikaia/tests/text_tiers.rs: the program from §1 refused with .clone() named, and views from lines, split and trim handed to a mixed parameter, run at both settings of user_parallelism.

This site is open source. Improve this page.