ADR-232: A Published Parameter Takes Either Kind of Text From Its Own Package

Status: Superseded by ADR-282 — its D1-D2 are D23 and D24 there Date: September 26, 2026 Target Version: Nikaia 0.0.216 Answers: the README’s hand a view of text to a published (pub) function that also gets text of its own for the same String parameter — refused Refines: ADR-223 D4, which kept a published parameter both kinds flow into text of its own Related: ADR-222 D2 (a published field or result is never both kinds), ADR-224 D2 (IntoEither), ADR-037 D8 (a published representation is chosen before its users exist)

1. Context

pub fn tag(s: String) -> Tag { return Tag { label: s } }
pub fn both(text: ref String) -> String {
    let a = tag(text.trim())       // NK1102: write `.clone()`
    let b = tag(f"own")
    …
}

ADR-223 D4 refused the view because the parameter’s representation is published: another package calls tag with what the ledger says, and a representation that followed this package’s own calls would change under it. That reason is about the callers elsewhere, and they only ever hand over text of its own. The package’s own calls were paying for a promise to somebody else.

2. Decisions

D1 — Below, a published parameter both kinds flow into takes whatever hands over as either.

The ledger still says String, so a caller in another package hands over text of its own, as before. Below, the parameter is impl IntoEither<Either = EitherText<'e>> (IntoEitherMaybe for a String?), and the body’s first line takes it as it goes in. Text of its own is moved in; this package’s view is borrowed. So the one published signature serves both, nothing is copied, and no caller elsewhere can tell. Only the parameter itself: a list of text it takes stays what it is published as.

D2 — Unless its value leaves through something published as text of its own.

pub fn greet(who: String) -> String { return who } hands the parameter back through a published result, and a published result or field is never both kinds (ADR-222 D2). Such a parameter stays text of its own, and a view handed to it is refused as before, naming .clone(). The tier pass follows a parameter’s value into the positions it goes into to decide this.

3. What is still refused

A published field or result both kinds flow into (ADR-222 D2): there the representation is what every user reads and builds, and a representation another package could not know is the reason the rule exists. And D2’s parameter, which is the same case one step removed.

4. What is built

All of it, in 0.0.216: the tier pass no longer fixes a published parameter (decide), and follows a parameter’s value into what it goes into (Flows::param_into); the emitter writes the parameter generic, names 'e on the result where it is the only lifetime, and takes the value on the body’s first line. crates/nikaia/tests/project.rs runs a package calling its own pub fn with both kinds and a program in another package calling it with text of its own; crates/nikaia/tests/typecheck.rs keeps D2’s refusal.

This site is open source. Improve this page.