Skip to content

docs: anchor pool and move-guest liveness rules - #149

Merged
TheLazyCat00 merged 2 commits into
agent/fix-host-overwrite-reusefrom
claude/pr-review-fixes-t94tbq
Jul 28, 2026
Merged

docs: anchor pool and move-guest liveness rules#149
TheLazyCat00 merged 2 commits into
agent/fix-host-overwrite-reusefrom
claude/pr-review-fixes-t94tbq

Conversation

@TheLazyCat00

@TheLazyCat00 TheLazyCat00 commented Jul 28, 2026

Copy link
Copy Markdown
Member

Clarify the anchor cell allocation model and add move-guest liveness constraints to the spec and stories.

Summary

This change documents two related refinements to the memory and lifetime models:

  1. Anchor pool architecture: Anchor cells are allocated from a single global pool (not per-scope), with immediate reuse safety guaranteed by scope rules. The glossary definition is updated to reflect this.

  2. Move-guest liveness rule: A move into an initialized host is rejected when both source and destination have live guests, since one hosting lineage can only carry one anchor identity. This is formalized in lifetimes.md §1.10 with examples.

Key changes

  • spec/memory.md:

    • Expanded §3.1 to explain segmented offset materialization and clarify that anchor pool never issues 0 as an identity (first slot of first page reserved)
    • Enhanced §3.2 to detail fixed-size region as pure bump allocator with no reclamation, and clarify that scope drain unmaps chunks in bulk with no per-object teardown pass
    • Updated §4.1 to remove "scope-local anchor regions" language; anchors are global-pool only
    • Added story pointers to new "Two payload streams, and the anchor that leaves the scope" chapter
    • Updated story title in §3.6 from "costs one reserved identity" to "costs nothing"
    • Added move-guest liveness row to summary table
  • spec/lifetimes.md:

    • New §1.10 formalizes move-guest liveness rule with legal and illegal examples
    • Added move-guest liveness row to summary table in §2
  • spec/glossary.md:

    • Updated anchor cell definition (3.23) to specify global pool allocation, 8-byte slots, and lifecycle tied to hosting lineage
    • Clarified arena placement definition (3.25) to distinguish fixed-size vs. dynamic regions
  • README.md: Updated stories table entry for memory.md to reflect chunked bump arenas focus

  • stories/memory.md: Partial diff shown; full story chapter on two-payload-streams scenario added (not fully visible in truncated diff)

Implementation notes

The anchor pool model ensures O(1) anchor operations under concurrency while maintaining immediate reuse safety through lexical scope guarantees. The move-guest liveness rule prevents the impossible case where a single anchor cell would need to carry two distinct guest identities.

https://claude.ai/code/session_016YnNCXtguHg4tSbLCtTT2c

Summary by CodeRabbit

  • Documentation
    • Clarified the memory model, including segmented offsets, arena regions, allocation reuse, teardown, and global anchor management.
    • Documented anchor cell behavior and arena promotion rules.
    • Added move-liveness rules, examples, and guidance for preserving anchor identity.
    • Updated memory and placement story references and explanations.

Repair the integration half of the memory-model revision and the
cross-references it left stale.

- Restore the story pointer at memory.md §3.6; it named a chapter
  heading that no longer exists, so the link resolved to nothing.
- Point the sections whose rules the revision changed (§3.1, §3.2,
  §3.6, §4.1, §4.5, §4.6) at the new story chapter; §4.6 had no
  pointer at all.
- Restore the story's placement chapter to its previous wording: the
  chapter predates this change, and its in-prose spec reference is a
  commit-pinned permalink rather than a living relative link.
- Update the glossary entries for anchor cell and arena placement,
  which still described a scope-local anchor region.
- Record the both-sides-guests move restriction in lifetimes.md, the
  home of move legality, as §1.10 with a summary row.
- Restore the arena-granularity latitude and the destruction-timing
  distinction dropped from §3.1 and §3.2, and note that the
  fixed-size region reclaims nothing individually.
- State how the anchor pool avoids issuing identity 0, restore the
  address formula, drop a contrast with storage the language has no
  form for, and square the segmented-offset diagram.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016YnNCXtguHg4tSbLCtTT2c
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository: zane-lang/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2e435831-3772-4166-8009-950e47d7cfc0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The memory specification now defines regioned scope arenas, segmented offsets, dynamic reuse, and a runtime-global anchor pool. Lifetime rules add guest-liveness checks for moves, while glossary entries, stories, README text, and cross-references are updated to match.

Changes

Memory model rules

Layer / File(s) Summary
Segmented arenas and allocation
spec/glossary.md, spec/memory.md, stories/memory.md, README.md
Scope arenas are divided into fixed-size and dynamic regions; segmented offsets, alignment, reuse, teardown, and related story descriptions are updated.
Anchor pools and move liveness
spec/glossary.md, spec/memory.md, spec/lifetimes.md
Anchor cells use a runtime-global recyclable pool, and moves into initialized hosts are rejected when both sides have live guests; permitted moves preserve the surviving lineage’s anchor.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • zane-lang/spec#147: Updates the same memory-model areas around segmented offsets, regioned arenas, anchor pools, and move semantics.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the two main documentation changes: anchor pool behavior and move-guest liveness rules.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/pr-review-fixes-t94tbq

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@spec/memory.md`:
- Line 521: Update the “Move guest liveness” summary in memory.md to distinguish
all cases: reject moves when both sides have live guests, use the surviving
side’s anchor only when exactly one side has live guests, and document that when
neither side has live guests no anchor survives; if the moved-from slot remains
readable, §4.5 lazily allocates an anchor for the new guest.
- Line 253: Clarify the scope-drain guarantee in spec/memory.md at lines 253-253
to describe the lifetime of promoted payloads, not source-arena allocations or
all reachable guests. In spec/glossary.md at lines 188-189, state that promotion
copies the fixed-size representation or handle while transferring the dynamic
backing store without copying. In stories/memory.md at line 43, replace
stack/heap terminology with fixed-size representation and dynamic scope-arena
terminology.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: zane-lang/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 0243aa4a-691b-49cf-9695-aad167964a92

📥 Commits

Reviewing files that changed from the base of the PR and between 2feefae and 742ed1d.

📒 Files selected for processing (5)
  • README.md
  • spec/glossary.md
  • spec/lifetimes.md
  • spec/memory.md
  • stories/memory.md

Comment thread spec/memory.md Outdated

Each region is a separate chain of fixed-size **1 MiB chunks** mapped from the OS on demand. A chunk belongs to exactly one region: fixed-size slots and dynamic backing stores never coexist in the same chunk. A region maps no chunk until its first allocation. When its current chunk cannot satisfy an allocation, the runtime maps another chunk for that region, assigns it the next **chunk id**, and makes it current.

Scopes nest last-in-first-out, and their arenas nest with them: both regions of a scope are unmapped in full the moment the scope drains (§3.2, [`lifetimes.md`](lifetimes.md) §2.1). Arena granularity is an implementation choice, like boolean packing (§3.4) and placement (§3.5) — the compiler may fold several lexical scopes into one arena. What the language fixes is the observable behavior: memory a scope allocates outlives every guest that can reach it and is released together when the scope drains.

@coderabbitai coderabbitai Bot Jul 28, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Keep physical allocation lifetime separate from logical hosting lifetime.

The affected text mixes arena placement, promotion, and object reachability. Fixed-size representations may be promoted to a parent arena, dynamic backing stores transfer without copying into storage whose lifetime covers the destination, and the source arena may unmap while guests continue through the global anchor.

  • spec/memory.md#L253-L253: rewrite the scope-drain guarantee so it describes promoted payloads rather than claiming source allocations outlive all reachable guests.
  • spec/glossary.md#L188-L189: state that promotion copies the fixed-size representation/handle, not the dynamic backing store.
  • stories/memory.md#L43-L43: replace stack/heap wording with fixed-size and dynamic scope-arena terminology.
📍 Affects 3 files
  • spec/memory.md#L253-L253 (this comment)
  • spec/glossary.md#L188-L189
  • stories/memory.md#L43-L43
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@spec/memory.md` at line 253, Clarify the scope-drain guarantee in
spec/memory.md at lines 253-253 to describe the lifetime of promoted payloads,
not source-arena allocations or all reachable guests. In spec/glossary.md at
lines 188-189, state that promotion copies the fixed-size representation or
handle while transferring the dynamic backing store without copying. In
stories/memory.md at line 43, replace stack/heap terminology with fixed-size
representation and dynamic scope-arena terminology.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in the two spec sites; declining the story site.

spec/memory.md §3.1 — agreed, the sentence was inherited from the pre-promotion wording and is false once a payload can be promoted out of a draining scope. The guarantee is now stated as reachability rather than as memory outliving guests: a scope's memory is released together when that scope drains, no guest ever resolves into released memory, and an escaping value is promoted out first with its guests following the canonical anchor (§3.5, §3.7, §4.5).

spec/glossary.md §3.25 — agreed, "copied (promoted) into a parent arena" glossed over the split. It now says promotion copies the fixed-size bytes (the inline payload, or the handle of a dynamically-sized type) while a dynamic backing store transfers to the new host without being copied, matching §3.5.

stories/memory.md line 43 — declining. That line is a paragraph of an earlier chapter written when the model really was stack-versus-heap, and stories in this repo accumulate rather than being rewritten to match the present spec (contributing/writing-stories-docs.md §5). Its in-prose spec reference is a commit-pinned permalink to the commit where that wording was normative, so the link and the prose agree at the pinned revision. This PR in fact restores that line: it had been rewritten into current terminology, which also downgraded the permalink to a living relative link. The fixed-size/dynamic terminology belongs in the new chapter "Two payload streams, and the anchor that leaves the scope", where it already appears.


Generated by Claude Code

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- glossary: promotion definition ---'
nl -ba spec/glossary.md | sed -n '180,200p'

printf '%s\n' '--- story: historical wording and reference ---'
nl -ba stories/memory.md | sed -n '35,50p'

printf '%s\n' '--- story-writing convention ---'
fd -a '^writing-stories-docs\.md$' contributing -x sh -c 'nl -ba "$1" | sed -n "1,180p"' sh {}

printf '%s\n' '--- current scope-drain wording ---'
nl -ba spec/memory.md | sed -n '245,270p'

printf '%s\n' '--- pinned GitHub links near the historical story passage ---'
rg -n -C2 'github\.com/.+/(blob|commit)/[0-9a-f]{7,}|stack|heap|fixed-size|dynamic' stories/memory.md

Length of output: 1043


🏁 Script executed:

#!/bin/bash
set -euo pipefail

show_range() {
  file="$1"
  start="$2"
  end="$3"
  printf '%s\n' "--- ${file}:${start}-${end} ---"
  awk -v start="$start" -v end="$end" 'NR >= start && NR <= end { printf "%6d  %s\n", NR, $0 }' "$file"
}

show_range spec/glossary.md 180 200
show_range stories/memory.md 35 50
show_range contributing/writing-stories-docs.md 1 180
show_range spec/memory.md 245 270

printf '%s\n' '--- relevant story references and terminology ---'
grep -nE -C 2 'github\.com/.+/(blob|commit)/[0-9a-f]{7,}|stack|heap|fixed-size|dynamic' stories/memory.md || true

Length of output: 83309


@TheLazyCat00, verified. The revisions at spec/memory.md Line 253 and spec/glossary.md Line 188 correctly separate source-arena reclamation from promoted payload reachability and dynamic-store transfer.

I also agree with declining the stories/memory.md change. Its historical stack/heap account is backed by a commit-pinned permalink, and preserving it follows contributing/writing-stories-docs.md §4.2 and §5’s append-don’t-overwrite convention. No further changes are needed.

🐇📜

Comment thread spec/memory.md Outdated
Address review on the promotion and move-liveness wording.

- State the drain guarantee as reachability: a scope's memory is
  released at drain and no guest resolves into released memory, with
  an escaping value promoted out first and its guests following the
  canonical anchor. The previous phrasing claimed source-arena memory
  outlives every guest that can reach it, which promotion breaks.
- Say in the glossary that promotion copies the fixed-size bytes —
  the inline payload or the handle — while a dynamic backing store
  transfers without being copied.
- Complete the move-liveness summary row with the case where neither
  side has live guests: a moved-from slot that stays readable anchors
  lazily.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016YnNCXtguHg4tSbLCtTT2c
@TheLazyCat00
TheLazyCat00 merged commit b5cab00 into agent/fix-host-overwrite-reuse Jul 28, 2026
1 check passed
@TheLazyCat00
TheLazyCat00 deleted the claude/pr-review-fixes-t94tbq branch July 28, 2026 13:52
TheLazyCat00 added a commit that referenced this pull request Jul 31, 2026
…ename receiver to subject (#151)

* add one-shot memory spec fix workflow

* clarify host overwrite slot reuse

* Add one-shot memory layout updater

* Specify arena regions and dynamic backing-store reuse

* Add one-shot review fix updater

* Remove inactive review updater

* Use global recyclable anchor pool

* Align memory story with global anchors

* Clarify anchor layout and rehosting conflicts

* Align memory story with anchor rules

* Preserve memory story and append allocator revision

* docs: anchor pool and move-guest liveness rules (#149)

* docs: fix review defects in the arena and global-anchor change

Repair the integration half of the memory-model revision and the
cross-references it left stale.

- Restore the story pointer at memory.md §3.6; it named a chapter
  heading that no longer exists, so the link resolved to nothing.
- Point the sections whose rules the revision changed (§3.1, §3.2,
  §3.6, §4.1, §4.5, §4.6) at the new story chapter; §4.6 had no
  pointer at all.
- Restore the story's placement chapter to its previous wording: the
  chapter predates this change, and its in-prose spec reference is a
  commit-pinned permalink rather than a living relative link.
- Update the glossary entries for anchor cell and arena placement,
  which still described a scope-local anchor region.
- Record the both-sides-guests move restriction in lifetimes.md, the
  home of move legality, as §1.10 with a summary row.
- Restore the arena-granularity latitude and the destruction-timing
  distinction dropped from §3.1 and §3.2, and note that the
  fixed-size region reclaims nothing individually.
- State how the anchor pool avoids issuing identity 0, restore the
  address formula, drop a contrast with storage the language has no
  form for, and square the segmented-offset diagram.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016YnNCXtguHg4tSbLCtTT2c

* docs: sharpen the scope-drain guarantee and the move-liveness summary

Address review on the promotion and move-liveness wording.

- State the drain guarantee as reachability: a scope's memory is
  released at drain and no guest resolves into released memory, with
  an escaping value promoted out first and its guests following the
  canonical anchor. The previous phrasing claimed source-arena memory
  outlives every guest that can reach it, which promotion breaks.
- Say in the glossary that promotion copies the fixed-size bytes —
  the inline payload or the handle — while a dynamic backing store
  transfers without being copied.
- Complete the move-liveness summary row with the case where neither
  side has live guests: a moved-from slot that stays readable anchors
  lazily.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016YnNCXtguHg4tSbLCtTT2c

---------

Co-authored-by: Claude <noreply@anthropic.com>

* Clarify rehosting storage relocation

Define rehosting as copying the complete hosted representation into destination-owned storage. Inline bytes move into the destination slot, dynamic backing stores relocate into equal-size destination-region allocations, old source storage ceases to be live, and the source host-capable slot becomes a guest through the canonical tether.

Keep anchor bookkeeping O(1) in the number of guests while stating the physical relocation cost explicitly. Align the normative memory model, glossary, and design story, and complete the glossary's verb list with operators and lambdas.

* Add temporary forwarding-anchor update workflow

* Specify forwarding anchors for merged host identities

* docs: bare symbols are no longer guest sources; add the 'T borrow mode

A new `&` may now be minted only from a field access or an `&T` parameter.
A bare symbol stays a place expression but is no longer a guest source, so
nothing can point at a local's own hosting slot and the slot stays free to
be overwritten or moved from. This is what makes the aliasing case that
started this — a guest to `main`, then `second = main` — a compile error at
the line that mints the guest rather than a question about what the guest
then denotes.

Removing that source leaves a hole where a bare symbol needs to reach a
callee, so reference types gain a third passing mode: `'T`, a borrow. The
three modes are now `T` (swallow), `&T` (guest), and `'T` (borrow, any
place including a bare symbol, read and mut for the call only, never
stored, returned, or moved). A reference receiver written bare is an
implicit `'T` borrow; `this &T` is the guest receiver a method writes when
it stores or returns the receiver.

Consequences carried through: a returned `&T` must be rooted in an `&T`
parameter; a field reached through a borrow is not a guest source either;
overloads may not differ only by passing mode; an `&` field and a recursive
`#variant` case are fed from a field or an `&` parameter, so a recursive
structure is rooted in a field rather than a bare local.

The anchor system is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7

* docs: story chapters for the guest-source restriction and the three modes

stories/memory.md gains "The slot that could not be pointed at" — the
five-line aliasing program, the roads tried in order (smarter guests, the
name/location/object middle layer, immovable objects, no guests at all) and
why each failed, and the narrowing that finally settled it. Then "Three ways
to hand over an object": why an `&T`-parameter exemption would have needed
interprocedural inference, how the borrow fell out of that, why the receiver
became a borrow too, and the defence of `'` over redefining `&`.

stories/lifetimes.md gains "Where a guest may be rooted" — what the source
rule did to the scope check and the return rule, and why a field reached
through a borrow is not a guest source either.

Spec sections point into the new chapters; in-prose references are pinned to
b10eaed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7

* docs: address CodeRabbit review on #151

- CLAUDE.md: the guest-source guard was end-anchored, so it matched no line
  carrying a `// ILLEGAL: ...` comment — which is every deliberate bad example
  in the spec. It now tolerates an inline comment and trailing whitespace, and
  catches all three (memory.md 150/159, lifetimes.md 27) instead of none.
- glossary.md §3.1, §3.33, §3.36: mirror memory.md §2.8's exclusion of field
  accesses whose base chain passes through a `'T` borrow. Without it the
  glossary made `borrowed.field` a legal guest source while the canonical rule
  rejected it.
- syntax.md §3.1, §3.2: scope the three passing modes to reference types. A
  value parameter is always a read-only borrow and a value receiver is borrowed,
  so neither selects a mode; the unqualified wording contradicted effects.md §2.
- memory.md §3.1: tag the segmented-offset diagram fence `text`. It was the only
  untagged opening fence in spec/.
- memory.md §4.8: stop promising unchanged reuse order under thread-local anchor
  caches. Which free slot an allocation receives is unobservable from the source
  language, so §3.2's LIFO describes the central pool rather than binding an
  implementation; what a cache may not change is identity uniqueness, the §4.6
  retirement events, and the lifetime guarantees resting on them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7

* docs: second CodeRabbit round on #151

- memory.md §2.9: the borrow paragraph said a borrow "cannot be stored in a
  field, and cannot be returned" and then that a value is copied when bound
  into "a field or return store" — a flat contradiction. Split the two: the
  borrow is never storage, but binding *through* one copies the value, and the
  copy escapes fine. A reference type has no copy, so a `'T` leaves nothing.
- glossary.md §3.33: restore the place requirement the shortened wording lost.
  "A field access not rooted in a borrow" would have admitted
  `makeCar().engine`; mirror memory.md §2.8 in full.
- CLAUDE.md: the guard now accepts a leading-underscore private name
  (`_engine`) and tab-formatted assignments. Prose rewritten to say what the
  guard does — it matches a bare-symbol right-hand side only, so every hit is a
  candidate bug and the legal forms never appear.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7

* docs: third CodeRabbit round on #151

- CLAUDE.md: the guard's prose claimed the legal sources "never match". That is
  true only of a field access, which `.` excludes syntactically. An `&T`
  parameter is written bare, so `r &Node = source` inside a callee matches and
  is correct — the reviewing rule now lists it as a keep, checked against the
  enclosing signature rather than the line.
- glossary.md §3.27: the borrow entry still carried the contradiction fixed in
  memory.md §2.9 — "cannot be stored, returned, or moved" against a value being
  copied into a fresh slot. Scope it to the borrow itself.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7

* docs(meta): make the glossary a required stop when a rule changes

Two findings on #151 were the same defect: a rule was corrected in its
canonical home and its glossary entry left paraphrasing the superseded
version, so the spec contradicted itself until review caught it. Both times
the author missed it, which makes it a habit worth writing down rather than a
one-off slip.

Adds it to the "Before you edit" list: after editing any normative rule, grep
spec/glossary.md for the concept and update the entry in the same commit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7

* docs: the borrow is the non-swallowing way to pass a bare symbol

"Passing a bare symbol into a call is the borrow mode's job" overstated it: a
bare symbol is a move-source (lifetimes.md §1.2), so a plain `T` parameter
swallows one perfectly well. `'T` is the only *non-swallowing* mode that
accepts a bare symbol, which is the claim the surrounding rules actually
support.

Corrected in all three places that carried it — memory.md §2.8.1 (canonical),
glossary.md §3.36, and the foundations.md bullet — rather than only where the
review pointed, since the imprecision started in the canonical home and
propagated from there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7

* docs: tighten two guest-source summaries

- foundations.md §7: the bullet said a guest is minted "from a field access or
  an `&T` parameter", which over-approximates memory.md §2.8.1 — the base must
  be a place and must not be reached through a `'T` borrow. Named both
  qualifiers compactly rather than reproducing the rule; foundations.md is a
  map that defers to canonical homes.
- memory.md §2.8.1: "a field, a container element, a callee" listed where a
  guest may live, not what may mint one, and was read as the latter. Says it in
  the precise terms instead — an `&` field, a container element, an `&T`
  parameter inside a callee.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7

* docs: never write ' on this; add a forward pointer in the anchor story

Maintainer review on #151.

The receiver was specified two ways at once: memory.md §2.9 said a bare
`this T` on a reference type is an implicit `'T` borrow, and then every
example in that same section wrote `this 'Car`. Decided in favour of the
implicit form — `'` is never written on `this`.

The rule is forced rather than chosen. If the marker were required on the
receiver, a bare `this T` would have to mean the method swallows its own
receiver, which no method wants; so the borrow has to be the bare meaning,
and `this 'T` is then a second spelling for the default. It also makes the
two type worlds agree: value and reference receivers are both borrows and
both written bare, with `&` the single marker `this` may carry.

Applied to memory.md, functions.md, lifetimes.md, syntax.md, glossary.md,
and effects.md — including dropping the `this 'ReceiverType` production from
syntax.md §3.2 and the function-type form in §2.9.

stories/memory.md: the segmented-offset chapter still ends on the one-cell
promotion model, which the later global-pool chapter superseded. Stories are
append-only, so rather than rewrite it, that chapter now carries a forward
pointer naming what did not survive and why — the cell leaving the payload
stream, and one-cell promotion failing once both sides of a move are
anchored.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7

* docs(stories): keep stories/memory.md strictly append-only against main

Maintainer ruling on #151: the story is append-only, and that is verified by
diffing against main — an existing chapter is not edited, and a new chapter
goes at the end rather than being slotted into the middle.

Two violations, both now gone:

- One sentence in "The last table problem, and the segmented offset" had been
  rewritten (it came in with the PR 147 commits, and I then appended a
  forward-pointer paragraph to the same chapter, which is the same violation
  again). Both reverted; that chapter is byte-identical to main.
- "Two payload streams, and the anchor that leaves the scope" had been
  inserted between two chapters that already existed on main. Moved to the
  append position, after "Two vocabularies" and before the chapters this PR
  adds — which is also the right chronology, since the arena and anchor work
  came after the host/guest rename.

The correction the forward pointer was carrying now lives where it belongs,
in the appended chapter: it names the one-cell promotion claim from the
segmented-offset chapter and says what retires it — that the claim holds only
while a payload has one cell to rewrite, and fails once both sides of a move
are anchored.

`git diff origin/main -- stories/memory.md` is now additions only.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7

* docs(meta): state the append-only story rule literally, with a check

The story guide licensed exactly what review just rejected: §5 said to "open a
new chapter (or extend the relevant one)", which reads as permission to edit an
existing chapter, and it said nothing about where a new chapter goes. Both
gaps were used in this PR — a chapter was edited and another was inserted
between two that already existed.

§5 now spells out the two teeth: an existing chapter is not touched at all,
not even to bolt a forward pointer onto its end, and a new chapter goes at the
end of the file rather than into the middle. The correction a forward pointer
would carry belongs in the new chapter, naming the older chapter's claim.

Both are mechanically checkable, so the guide and CLAUDE.md now carry the
check — `git diff origin/main -- stories/<topic>.md | grep -E "^-[^-]"` must
print nothing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7

* docs: the receiver is never a swallow position, and say why properly

Maintainer asked why bare `T` borrows on `this` when the default for `T` is
swallowing. Fair — the justification I had written was wrong. It said the
borrow "has to be" the bare meaning because otherwise a method would swallow
its own receiver, which implies the swallow reading was ever on the table.

It never was. main already says a reference receiver is an implicit `&`
reference "(never swallowed)", and memory.md §2.9 on main says the same. So
the receiver has never been a swallow position, and bare `T` meaning swallow
is a rule about ordinary parameters. What this PR changes is only *which*
non-swallowing mode a bare receiver is — guest before, borrow now — because
the call-site receiver is usually a bare symbol, which §2.8.1 no longer
admits as a guest source.

§2.9 now states that, says plainly that bare `T` does not mean the same thing
in both positions, and names the pre-existing rule that makes it consistent
rather than arguing from convenience. The §2.9 mode table is scoped to
parameters, and functions.md §2.4 and both summary rows match.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7

* docs: say which sense of "receiver" each rule means

"Receiver" was doing three jobs at once — the object a method is
called on, the `this` parameter that fixes the passing mode, and the
call-site expression that supplies the object — and the rule that it is
never a swallow position is about the second of those, not the first.

Define the three in functions.md §2.1, add a glossary entry, and use
the precise term wherever the distinction carries weight.

* docs: rename receiver to subject

"Receiver" is Smalltalk residue — a call was a message and the object
received it. Zane has no messages, so the word named nothing: it neither
fought its old meaning nor fed the new one, it was simply dead metaphor.

"Subject" puts the concept in the register the spec already chose when
it named callables verbs. A call reads subject-verb-object, and the
subject is what the verb acts from.

Merged story chapters keep the old word — they record the language as it
was — so the term is split across the two trees by construction. Also
records that append-only is per pull request, not per commit: chapters a
branch has not merged yet are still drafts.

* docs: tell the receiver-to-subject story

Appends "What does a receiver receive?" to stories/functions.md: the
word arrived free with the object model and went unexamined until a rule
about `this` forced us to say which of its three senses we meant, and
then until someone asked what a receiver receives. Records the dead
metaphor, the grammar register that supplied the replacement, the
candidates weighed, and the cost — merged chapters keep the old word, so
the two doc trees disagree by design.

Pointer added from functions.md §2.1; README row updated.

* docs(meta): make the stories guide the source of truth for append-only

The rule lived in two places at once, and CLAUDE.md — which is agent
notes, not contributor documentation — had grown a full normative
restatement of it. Now the story guide §5 owns the rule and says how it
is enforced (by hand, by author and reviewer; there is no CI), and
CLAUDE.md keeps only the command to run and the two ways sessions have
actually got it wrong: editing a merged chapter, and refusing to edit an
unmerged one.

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants