Programming Language

Nocter

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

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

v0.21.0 Phase 2 Hash-Foundation Review

Result

Phase 2 is complete. std/hash now owns one opaque public state, one Hash capability, one private streaming algorithm, and coherent implementations for every adopted scalar, text, slice, and Vec surface. Target entropy remains a separate standard-internal responsibility. No table, Map, Set, public final hash, custom hasher, or compiler-known hashing behavior entered this phase.

The review found and resolved two design issues during implementation. First, package-only HashState lifecycle methods were initially placed beside their bodies. The source contract model correctly rejected non-private visibility outside index.nct; construction, restart, and finalization contracts now live with the opaque type owner while state.nct contains private bodies only. Second, an early generic raw-scalar helper relied on callers to pass only padding-free built-ins. It was replaced by type-specific scalar helpers in scalars.nct, so that precondition is not an extensible internal contract.

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

State and Algorithm Authority

  • std/hash/index.nct is the sole declaration authority for Hash, HashState, public byte contribution, and package-only lifecycle access.
  • state.nct alone owns seed retention, buffered bytes, algorithm lanes, compression, and finalization. Consumers cannot initialize fields or reproduce the algorithm.
  • A HashState template receives entropy once. restart creates independent state with the same hidden seed, allowing one Map to compare all keys coherently across lookup and rehash without requesting fresh entropy.
  • The private implementation buffers eight bytes and uses add/XOR/rotate compression and a separate finalization. No algorithm constant or output is public or normative.
  • std/internal/hash owns only target seed acquisition. It cannot inspect, construct, restart, or finalize HashState; std/hash cannot observe syscall details.

Value Encoding and Coherence

  • bool and every current built-in integer contribute their exact initialized fixed-width bytes. Each helper has an exact scalar type, avoiding narrowing conversions and an unsafe generic promise about padding.
  • str contributes its length and UTF-8 bytes. String delegates to the same borrowed text path, so equal owned and borrowed text use the same encoding.
  • [T] contributes its length and each element through T impl Hash. Vec<T> delegates to that borrowed view, so equal owning and borrowed sequences use the same component boundaries.
  • The Hash prerequisite requires (&Self == &Self): bool. Existing prerequisite expansion supplies equality evidence for generic slices and Vec values from T impl Hash; hashing does not duplicate an equality-selection rule.
  • Map and Set remain deliberately non-hashable in v0.21.0.

Ownership, Failure, and Allocation

  • HashState contains only fixed-width scalar fields. Restart and finalization use stack values and do not allocate or expose borrows into mutable state.
  • Scalar hashing forms readonly byte views over initialized compiler built-ins. Text and sequence hashing use existing readonly views; none transfers or mutates the hashed value.
  • Every reachable hashing body calls only fixed-width arithmetic, readonly projection, iteration, or another Hash implementation. It contains no allocator, error, I/O, or target call.
  • Entropy acquisition occurs only when a package-internal template is created and terminates on failure, preserving the public construction failure policy.

Visibility and Dependency Review

  • Public users can construct neither a state nor a final hash. They can only implement Hash and contribute bytes to a state supplied by the standard library.
  • Package-only lifecycle declarations remain associated with HashState; moving them to an internal module would require exposing representation or introducing a dependency cycle.
  • No new exception was added to the standard root-visibility audit. Implementation sources still cannot declare non-private visibility.
  • The reviewed dependency graph records hash dependencies on only internal/hash, internal/ptr, num, ptr, string, and vec. The entropy module continues to depend only on the Darwin OS adapter and pointer API.

Native Qualification

Four authored standard tests execute through checking, target closure, MIR, MachineProgram, ARM64, Mach-O, and the native test harness. They cover equal primitive/text contributions, streaming write boundaries, seed separation, nested component boundaries, target entropy, and deterministic restart from one hidden seed.

Evidence

  • cargo test -p nocter-discovery authored_standard_library_is_one_discoverable_declaration_unit
  • cargo test -p nocter-native-session standard_hash_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 one existing ignored test and reported no failure.