Programming Language

Nocter

A self-contained systems language built around simplicity, encapsulation, and foolproof design.

/development/reviews/v0.21.0-phase-3.md

v0.21.0 Phase 3 Private-Table and Map Review

Result

Phase 3 is complete. std/internal/table owns one seeded open-addressed implementation and std/map exposes the adopted representation-neutral Map<K, V> contract by delegation. The compiler does not recognize Map, hashing, buckets, or probing. Set and all associative iterators remain Phase 4 work.

Native qualification found and removed one unsafe initial representation. The first table stored Entry<K, V> wrappers in one dense Vec. It passed scalar tests but an owning String key became invalid when lookup projected the generic key field from stored entries. The completed design does not mask that failure with a key-type exception: independent dense key and value owners remove the generic wrapper projection, simplify entry transfer, and make public capacity the minimum of three independent stores. Owning strings, zero-sized values, deliberate collisions, growth, and removal now execute through the native backend without failure.

No unresolved Phase 3 correctness or responsibility-boundary finding remains.

Representation and Authority

  • std/internal/table is the sole owner of hashing, probing, tombstones, dense indices, growth, replacement, removal repair, clear, and semantic table equality.
  • Parallel Vec<K> and Vec<V> stores are the sole owners of initialized user values. Their lengths are changed only together by the table. Buckets own no user value; they contain only empty/deleted state or one dense index.
  • Rebuilding appends a complete bucket range, hashes each dense key into that range, then publishes the prepared metadata. It never moves, copies, or destroys a key or value.
  • Removal applies the same swap removal to keys and values, destroys the removed key, transfers the removed value, and repairs the one bucket that referenced a moved final dense entry.
  • std/map/storage.nct owns only the private Map { table } representation. Public operations do not read bucket fields or repeat a probe decision.

Ownership, Capacity, and Failure

  • New insertion completes all recoverable capacity work before publishing either input. Equal-key insertion retains the original key, replaces only the value, and lets the incoming key clean up once.
  • Public capacity is min(key capacity, value capacity, usable bucket capacity). Preparing one internal store before another allocation fails cannot increase the published capacity or change logical entries.
  • Capacity addition and bucket doubling use the standard checked-arithmetic authority. A failed recoverable reserve cannot wrap or publish a partial logical mutation.
  • Sparse cleanup is an optional metadata optimization. Its allocation failure leaves the previous table usable and does not turn a capacity-sufficient insertion into a recoverable failure.
  • Clear destroys both initialized dense prefixes and resets bucket metadata while retaining the seed and allocations.
  • std/internal/ptr.replace_value encapsulates take-then-store replacement of one initialized place. Its caller never observes an uninitialized bucket or value slot.

Public Boundary and Visibility

  • Map<K, V> exposes only key/value meaning, length, minimum no-allocation capacity, lookup, mutation, reserve, indexing, and semantic equality.
  • Missing indexing terminates through a target-neutral package safety boundary. Map source does not import a target trap or OS module.
  • Table, bucket, probe, dense storage, replacement helper, safety termination, and Vec swap removal are package-only. No HashMap, HashSet, raw-table accessor, seed, hash result, or bucket count is exported.
  • The reviewed standard dependency graph records the new module edges explicitly and remains acyclic. Map depends on the table contract rather than its implementation files.
  • Compiler production source contains no Map/HashMap/HashSet name branch. Mapping literals select the source-declared literal through the ordinary construction and keyed-pack contracts.

Native Qualification

Four external-package tests execute through discovery, semantic computation, target closure, MIR, MachineProgram, ARM64, Mach-O, and the native test harness. They cover:

  • mapping-literal order, duplicate replacement, mutable indexing, equality, clear, and retained capacity;
  • owned String keys and values, including replacement and removal transfer;
  • zero-sized custom keys and values;
  • a constant-hash custom key across collision chains, repeated growth, swap removal, and lookup;
  • explicit recoverable allocation, keyed-pack construction, checked capacity overflow, and observable failure atomicity.

Evidence

  • cargo test -p nocter-discovery authored_standard_library_is_one_discoverable_declaration_unit
  • cargo test -p nocter-native-session standard_map_contract_crosses_native_tests
  • cargo test --workspace --quiet
  • cargo fmt --all --check
  • node docs/build-docs.js
  • git diff --check

All commands passed on 2026-08-30. The full workspace test retained the repository's existing ignored tests and reported no failure.