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