keep, ref leaves the language, a result’s source is inferred or written from (ADR-views-3)Open and answer this issue on GitHub.
ready · opened 2026-11-03 · updated 2026-11-03 · 0 comments
Decided by the owner (2026-11-03): option B of the former #1211 with the word keep, and option D below for a result’s source. This issue now carries the whole topic; #1211 (the keep question), #1115, #1093, #1152, #1165 and #1171 are folded into it. The record is ADR-views-3 (pushed); the changed rules of ADR-094, 184, 202, 251, 353, 354 and 358 carry its notes.
keep. Keeping means storing it in a field, returning it, or handing it to a task. A plain parameter is lent: the caller’s value is usable again after the call. The body is checked against the signature: a body that keeps an unmarked parameter is refused, with a help that adds keep; a keep that is never kept gets a warning. Methods and trait methods say it too. self follows the same rule: self looks, mut self changes in place, keep self consumes the object.ref leaves the language, except in extern "C", where it keeps its C meaning. ref self becomes self, ref mut self becomes mut self, and return ref s becomes return s.tethered = [...]). A field or element that is changed must be an own value; the error says where to write .clone(). A let from a place only looks; taking the value out is written (remove, drain, .clone()). A struct literal takes a local or a parameter the way a call argument does (the case of #1152).views), and a caller that changes the source while it still uses the result is refused, with an error naming the function and the parameter. It may also be written on the result: -> String from s, or from a | b for several sources. Where it is written, the body is checked against it. It must be written where there is no body to infer it from: trait methods, function types, and foreign or Rust functions. Elsewhere, for example on public library functions, writing it is optional.ref and ref mut from every rule outside extern "C", including the fold step in Part II 10.x, which becomes fn(mut A, T) / fn(mut A, A) (the contradiction of #1093) and the same wording in ADR-372 D9 and 10.7. Then, as one change with every citation moved: move ADR-202, 353 and 354 to docs/history/adr/ (ADR-decision-records-1 D3), since views-3 restates all of them that still holds; rewrite ADR-094 D2 and D6, ADR-184 D1, ADR-251 D4 and ADR-358 D3 in place under their Changed by notes (ADR-094 and 184 keep other live rules).keep: a body that keeps an unmarked parameter is refused, and a keep that is never kept gets a warning; this covers self / mut self / keep self and trait methods..clone() help). A struct literal lends a local or a parameter as a call argument does: the struct may not outlive it, and it is no keep while it stays in the function (#1152’s probe).from s / from a | b is parsed and checked against the body. It is required on trait methods, function types and foreign functions. A caller that changes a source while using the result is refused, naming the function and the parameter.keeps and views stay. A change of either on a pub function is reported as a contract change, and a written from is recorded as written.tools/*.nika, a nikaia subcommand): writes keep from the ledger, removes ref everywhere outside extern "C", and rewrites the self forms. Run it over crates/nikaia-std, the packages, the examples, guide/ and the tests, then update the expected outputs. This settles #1115 (ref before a tuple), #1165 and #1171 (NK1261, the “ref is redundant” warning, which then retires).tests/compiler/, one per rule above, plus a refusal for each error.