Issue #870: Decision: the receiver follows the parameter rule - mut self for ref mut self, self a view unless kept

Open and answer this issue on GitHub.

ready · opened 2026-10-27 · updated 2026-11-03 · 1 comment

Question

Does a method’s receiver follow the rule every other parameter follows (Part I 6.5)?

For a parameter, ref is no longer written:

The receiver is the one exception:

Today Meaning Uses in tools/*.nika (all .nika) In Part I-III
ref self view 761 (873) 13
ref mut self change in place 471 (519) 11
self by value: the call moves the receiver 76 (78) -
mut self parse error (“Expected :”) 0 0

Probe on today’s develop: a fn show(self) -> i64 { return self.n } called twice on c is refused with “Use of moved value: c. C::show takes ownership of the receiver self”, although the body only reads a copied field. A plain parameter in the same place would be a view.

The deleted converter wrote the parameter rule where a method became a free function. Its R83 said ref mut self -> mut state: CheckState and ref self -> state: ref CheckState. So the same thing has two spellings, depending on whether it is a receiver or not (ADR-140).

Options

A: nothing changes. The receiver keeps its three written forms.

B: mut self replaces ref mut self. mut self changes the receiver in place and is passed as ref mut, as mut out: T is. ref self and self (by value) stay as they are.

C: B, and plain self follows the parameter rule. self is a view unless the body keeps it: hands it back, moves it into a field, gives it to a task, or passes it on to something that keeps it. Then:

impl Counter {
    fn value(self) -> i64 { return self.n }          // view (C); today: moves
    fn hit(mut self, by: i64) { self.n = self.n + by } // today: ref mut self
    fn into_parts(self) -> (i64, String) { return (self.n, self.name) } // keeps self: by value
}
Option D1 the special case pays D2 compiler works D3 no cost in the common case D4 consistent If it is wrong
A no: every method writes ref that no parameter writes no no: 1232 ref words in the tools no: receiver ≠ parameter, R83 shows the two spellings noise; a reading method written self moves its receiver
B partly partly half: ref self stays half small
C yes yes: the walk that decides a parameter’s view decides the receiver’s yes yes: one rule for every parameter, self included a body change turns a view into a move. The ledger shows this already, as it does for every parameter

Recommendation: C, built in two steps so that each one stands alone. B is C’s first step.

What speaks against C, and why it does not outweigh it:

Also found: a garbled sentence in Part I 6.5 (around line 2600)

A mut parameter handed to another mut parameter is passed straight on. ref self is written by the author, and that shape is NK1131, as is a mut parameter given away whole: …

The middle sentence makes no sense. Read against NK1131 in Part III (“a mut parameter whose type is a view, handed back”), it probably meant: A mut parameter whose type is a view and that is handed back is NK1131, as is a mut parameter given away whole. This is fixed in whichever option is chosen (a text fix, no version raise of its own).

To build (once decided; for C)

  1. ADR for the receiver rule. It replaces the receiver lines of Part I 6.5 and 6.8 and the examples (fn hit, fn drop, fn cleanup, fn record, fn note). It also fixes the garbled sentence. ADR-382 D5 says mut self there.
  2. Parser and check: accept mut self as ref mut self, and keep ref mut self working during the transition. Tests in tests/compiler/: mut self changes in place; mut self given away whole is NK1131.
  3. Rewrite ref mut self -> mut self in tools/*.nika, packages/, examples/, guide/. Then ref mut self is refused with a help that writes mut self.
  4. Check: plain self is a view unless the body keeps it. Decide it with the walk that decides a parameter, and write it to the ledger. Tests: show(self) twice is fine; close(self) and into_parts(self) still move.
  5. Rewrite ref self -> self in the same places. ref self stays an accepted assertion (the same as ref on a parameter), or is refused. Which of the two is part of this decision; I recommend accepting it as an assertion, for symmetry with parameters.

Generated by Claude Code

Comments

keywan-ghadami, 2026-10-27

Decided by the owner (2026-10-27): option C, but not now. Other work comes first, so the order of work (docs/priorities.md) decides when this is built. Nobody starts the To build list before the score puts it next.

Still open, to be settled at step 5: whether a written ref self stays accepted as an assertion (the recommendation) or is refused.


Generated by Claude Code

Back to Open Issues