Programming Language

Nocter

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

/development/releases/v0.6.0.md

Nocter v0.6.0 Release Qualification Record

Purpose

v0.6.0 makes compiler-owned callable contracts and their semantic presentation a stable foundation for subsequent language and standard-library growth. Editor features must present one resolved declaration consistently and must not expose compiler-only ownership, provenance, allocator, or aggregate-representation facts.

The released baseline is v0.5.0. Phase 0 preserves its language behavior while replacing remaining editor-only formatting and source-fragment fallbacks with shared analysis models. Phase 1 intentionally revises result-allocation and result-provenance source contracts without retaining a legacy spelling. The package graph, immutable LSP snapshots, and semantic occurrence identities remain the foundation for both phases.

Phase 0: Semantic Presentation Foundation

Phase 0 owns the common boundary between resolver/typechecker facts and editor-facing output.

Compiler Boundaries

  • resolve continues to own declaration identity, visibility, signatures, and source spans.
  • typecheck continues to own lossless allocation-effect and value-provenance facts used by ownership and lowering.
  • analysis/presentation owns callable source anchors, normalized declarations, specialization, user-facing semantic details, and rendering.
  • hover, completion, signature help, construction queries, and inlay hints consume the same presentation values rather than rebuilding declarations.
  • driver/lsp remains a protocol adapter and performs only range, Markdown, and protocol conversion.

Completion Gate

  • every callable kind has compiler-owned declaration identity and signature anchors
  • inferred effect and provenance hints use AST/resolver spans rather than source-text searches
  • result-storage presentation omits storage-independent branches, private representation fields, and scalar dataflow that is not a storage dependency
  • nested aggregate and outcome summaries are bounded and stable under private layout changes
  • hover, completion detail, and signature help render the same specialized callable declaration
  • semantic editor features do not format callable signatures from raw source fragments
  • exact analysis tests cover functions, primitives, methods, interface methods, construct entries, literals, and tests; framed LSP tests cover hint positions and UTF-16 conversion
  • the complete repository verification suite and a packaged-home LSP smoke pass

Non-goals

Phase 0 does not add source-level lifetime parameters, new provenance syntax, new allocation-effect syntax, runtime interface dispatch, incremental mutable analysis caches, or a new language-server protocol capability. It changes the implementation and quality of already specified editor output.

Phase 0 Completion Record

Phase 0 is complete. analysis/presentation is split into focused callable, type, local, source anchor, normalized-AST fallback, semantic-detail, and resolution-independent symbol modules. Every callable kind is indexed by declaration identity with separate name, return-type, explicit-origin, and signature-end spans. Inlay hints use those anchors, including signatures with explicit from clauses, and a framed LSP test fixes the inferred-origin hint after the return type.

Typecheck retains its lossless aggregate provenance facts. Presentation now derives bounded storage-only summaries: it drops storage-independent branches and copy-only input dataflow, coalesces equivalent origins, preserves meaningful success/error differences, and does not expose private field names. Concrete storage-independent generic calls suppress declaration-level result provenance.

Hover, completion detail, signature help, source edits, literals, and construction entries share the normalized declaration renderers. Method signatures retain owner-generic arity explicitly, so owner specialization cannot appear as invented method arguments. Degraded recovery labels render from canonical AST notation rather than raw declaration substrings. A parity test fixes one specialized method label across completion, hover, and signature help.

The complete repository verification suite passes: 2,239 compiler-library tests, 296 build tests, 449 run tests, 23 framed LSP tests, 18 package tests, 11 native-test tests, 206 distributed-home tests, public examples, source corpus, formatting, and warnings-denied Clippy. Distributed-home coverage includes the installed LSP lifecycle and standard-library editor paths.

Phase 1: Explicit Result Allocation Contracts

Phase 1 introduces one source-level distinction that the current inferred allocation-effect label cannot express: whether newly allocated storage remains in a callable result. It does not expose whether a callable happens to allocate temporary storage while executing.

The adopted source model is:

func len(text: &str): usize
alloc func copy(text: &str): String
func view(text: &String): &str from text
alloc func copy_with(allocator: &+Allocator, text: &str): String from allocator
  • alloc means that some storage-carrying projection of a returned value may retain storage newly allocated while producing that value.
  • from X means that the returned value may retain storage or lifetime provenance carried by the resolved receiver, parameter, or static origin X.
  • alloc and from are independent result contracts. Allocation used only as temporary scratch work does not justify or propagate alloc.
  • absence of alloc is not an allocation-free execution guarantee. Execution-time allocation and hidden current-context propagation remain compiler-inferred implementation facts.
  • source-level from current is removed. An alloc result without a named from origin may retain storage from the caller's ambient allocation domain, which remains an internal provenance fact.
  • a non-alloc result without from may not retain an ambient allocation capability or another unreported storage origin.

alloc is contextual declaration syntax rather than a globally reserved identifier. The existing std/mem.alloc function therefore remains an ordinary name. Canonical modifier order is defined once for functions, methods, primitives, construction functions, literals, interface/default/impl members, and callable types; unsupported declaration kinds do not grow ad hoc parser exceptions.

The planned canonical forms are:

pub alloc func make(): Buffer
pub alloc method &self.copy(): Buffer
pub(nocter) alloc primitive allocate_raw(size: usize): RawBuffer

construct String {
    pub default alloc literal ""(text: &str): Self
}

interface Factory {
    pub alloc method &self.create(): Buffer
}

impl Factory for SystemFactory {
    alloc method &self.create(): Buffer { ... }
}

For structural callable types, alloc precedes the existing invocation capability:

alloc &func(Input): Output
alloc &+func(Input): Output
alloc func(Input): Output

Visibility comes first, default remains adjacent to its construction role, alloc immediately precedes the callable declaration kind, and result provenance remains after the return type. The formatter owns this order; the parser does not accept alternative modifier permutations.

Semantic Boundaries

Phase 1 must keep three facts separate:

result allocation provenance
  newly allocated storage survives in a returned projection

result external provenance
  returned storage depends on self, a parameter, or static storage

execution allocation requirement
  evaluating the callable may allocate and may need a hidden ambient context

The first two form the source-visible result contract. The third remains an inferred lowering fact. In particular, a function that allocates through an explicit Allocator has an execution allocation requirement without necessarily needing the ambient context, while a function that allocates scratch storage and returns usize has no result allocation provenance.

The compiler representation must preserve allocation provenance through aggregate fields, elements, optional presence, fallible success and error branches, calls, closures, and generic specialization. Discarding or dropping an allocated intermediate must not propagate result allocation to its enclosing callable. No phase may recover these facts by searching for names such as String, Vec, alloc, copy, or reserve.

Named from origins are resolved by declaration identity. Phase 1 extends origin eligibility from borrow-only spelling to any receiver or parameter whose semantic value can carry storage provenance, including allocator capabilities and moved owning values. Ownership checking must still reject a returned borrow whose owner is destroyed; widening origin eligibility does not weaken escape or drop validation.

Contract Validation and Compatibility

  • every body-backed callable computes exact result-allocation provenance independently of its written modifier and diagnoses a missing or unjustified alloc
  • a trusted bodyless declaration must agree with compiler-owned allocation-operation metadata
  • a bodyless interface or callable contract uses the written modifier as its result upper bound
  • an implementation or callable value with no allocated result may satisfy an alloc result contract; the reverse substitution is invalid
  • from covariance remains unchanged: an implementation may retain a narrower, longer-lived set of origins but may not introduce an undeclared external origin
  • recursive and mutually recursive result summaries converge without using the written modifier as evidence for a body-backed return path
  • error recovery may propose alloc, but accepted source never silently receives the contract

The exact-body check prevents alloc from becoming a blanket permission marker. Interface and callable-type compatibility still permit a narrower implementation because callers must be checked against the declared upper bound.

Implementation Order

  1. 1. Revise the focused provenance-contract implementation design and add a lossless result-allocation fact. Split it from the existing current-context requirement before changing syntax or presentation.
  2. Add contextual alloc syntax, AST/JSON spans, normalized notation, formatter rules, and parser recovery for every supported callable form and callable type.
  3. Propagate result allocation through expressions, aggregates, outcomes, calls, closures, interface defaults, conformances, and specialization. Validate written contracts only after the independent fixed point converges.
  4. Remove from current, extend identity-resolved from inputs, and migrate region escape checks to the combined result-allocation and external-provenance contract.
  5. Migrate the standard library, examples, fixtures, and documentation. Audit empty and zero-capacity owners so a non-alloc, no-from result does not retain a hidden region capability; use a neutral empty representation until storage is actually selected.
  6. Project the same contract through hover, completion, signature help, construction surfaces, semantic tokens, diagnostics, and code actions. Remove inline allocates execution hints and the non-source phrase from inferred storage.
  7. Run focused semantic and protocol matrices, the complete repository suite, a packaged-home LSP lifecycle, and distributed standard-library execution before recording completion.

Completion Gate

  • every callable declaration and callable type parses, formats, serializes, resolves, and presents alloc from one shared semantic model
  • result allocation is retained through every supported value shape and disappears when the allocated value does not escape through the result
  • ambient, explicit-allocator, static, receiver, borrowed-input, and moved-input origins remain distinct through calls and region escape validation
  • from current, inferred execution-effect signature text, and compatibility-only parsing are absent from accepted source and normalized editor declarations
  • interface matching and callable conversion enforce the result-allocation variance rules across modules and generic specialization
  • standard String, Vec<T>, iterator collection, process, I/O, typed literal, and recoverable allocator APIs carry truthful contracts without blanket alloc modifiers
  • diagnostics identify the returned projection or call that requires alloc and offer a shared compiler-planned edit at the canonical modifier position
  • exact parser, formatter, AST JSON, resolver, typecheck, ownership, IR, analysis, and framed LSP tests cover positive, negative, recovery, Unicode-range, and cross-module cases
  • the full repository, public example, source-corpus, packaged-home, distribution, formatting, diff, and warnings-denied Clippy gates pass

Non-goals

Phase 1 does not add noalloc, realtime, async, source-visible execution-effect annotations, structured per-field/per-outcome from syntax, named lifetime parameters, runtime interface dispatch, or an allocator selected by name-based compiler behavior. noalloc and realtime are reserved as future explicit guarantees; Phase 1 neither recognizes them nor treats absence of alloc as either guarantee.

Phase 2: Allocation Contract Stabilization

Phase 2 qualifies the Phase 1 contract across recursive analysis, substitution boundaries, diagnostics, editor presentation, the distributed standard library, and packaged execution. It adds no source syntax. In particular, it does not turn result alloc into an execution effect and does not introduce noalloc or realtime.

Audit Boundaries

  1. 1. Exercise direct and mutual recursion, outcome branches, aggregates, closures, generic specialization, interface defaults, and retained readwrite-input mutations with positive and negative contract tests. Body-backed inference must converge without treating a written modifier as implementation evidence.
  2. Exercise callable assignment, interface implementation, generic bounds, and cross-package public signatures. A non-allocating implementation may satisfy an alloc upper bound; an allocating implementation must never cross a non-alloc boundary.
  3. Preserve evidence for the returned expression or call that introduces a missing result allocation contract. E0462 must identify both the declaration that needs alloc and a concrete return path when source evidence exists. Source edits remain anchored by the shared callable presentation model.
  4. Audit every public callable in the distributed standard library. Written alloc and from clauses must match compiler inference, allocator-backed results must retain the allocator origin, and empty owners must remain neutral until first growth.
  5. Verify normalized hover, completion, signature help, diagnostics, and code actions from an immutable package snapshot and an installed Nocter home. No editor surface may synthesize compiler-only allocation or aggregate-provenance prose.

Completion Gate

  • the focused recursion, outcome, mutation, callable-variance, interface, generic, and cross-module matrices pass with exact E0462/E0463 expectations
  • missing-contract diagnostics retain a bounded, deterministic source witness and code actions edit only the declaration owning that witness
  • all distributed standard-library public callable contracts pass an automated compiler audit; manual name-based allowlists are not used as semantic evidence
  • source and packaged-home LSP tests present the same canonical declaration for alloc and from
  • public examples and the source corpus cover both ambient and explicit-allocator result paths
  • clean and incremental runs of the complete repository verification suite pass, including formatting, warnings-denied Clippy, documentation generation, distribution, installed-home LSP, and archive smoke checks
  • the release record states the exact tested artifact identity; publication remains a separate authorized action

Non-goals

Phase 2 does not add execution-effect syntax, noalloc, realtime, async, named lifetime parameters, runtime interface dispatch, a package format change, or a compatibility parser for the removed from current spelling. Those features require independent milestones and must not weaken the exact result contract completed here.

v0.6.0 Completion Definition

Phase 1 completed on 2026-08-07. The source language now distinguishes newly allocated result storage (alloc) from external result provenance (from) and the compiler-only execution allocation requirement. from current and inferred effect prose are no longer accepted or presented as source contracts.

The compiler retains allocation provenance through aggregate and outcome shapes, mutable owners, wrapper calls, generic/interface specialization, and neutral empty collection growth. Public contract validation projects those lossless facts through the semantic return type, preventing allocated locals and scalar outcome branches from becoming false alloc requirements. Return checking consumes the same retained-input mutation summaries, so storage first allocated by Vec.empty() growth remains visible to lexical-region escape checks.

The distributed standard library, examples, fixtures, and editor surfaces use canonical written contracts. Hover, completion, and signature help share normalized declarations; inlay hints do not invent result contracts; E0462 uses a compiler-planned source edit at the callable keyword. Focused and complete verification cover parser/formatter/AST JSON, resolution, callable variance, typecheck, ownership, IR, standard String and Vec<T>, allocator failure, packaged-home LSP, public examples, and source corpus behavior.

Phase 2 Completion Record

Phase 2 completed on 2026-08-07. Recursive and mutually recursive body-backed summaries now begin at the semantic bottom, so a written alloc modifier cannot justify itself. Allocation evidence is retained separately from aggregate provenance and gives E0462 one deterministic returned expression or call witness while the shared source-edit planner changes only the owning declaration. Closure bodies are checked against function and method callable substitutions across source and imported package boundaries; a non-allocating closure satisfies an alloc upper bound, but the reverse conversion reports E0464.

Generic type parameters remain storage-capable until a concrete scalar substitution proves otherwise. The iterator protocol consequently declares truthful alloc ... from self upper bounds, propagates allocation-capable map and fold callbacks, and keeps scalar terminal results allocation-independent. Collection for bindings instantiate the resolved conversion and step summaries instead of becoming independent synthetic locals. A validated pointer ownership-transfer role removes only the lexical scope of the transferred container, preserving every region, input, and nested element origin. Interface conformance permits a concrete storage-independent result to narrow an otherwise applicable provenance upper bound.

The distributed audit discovers all 23 standard-library source modules from the installed home; it does not maintain a semantic name allowlist. Clean and subsequent incremental runs of the complete repository verification pass 2,277 compiler-library tests, 296 build tests, 7 formatter CLI tests, 24 framed LSP tests, 18 package tests, 449 run tests, 11 native-test tests, 208 distributed-home tests, 2 public-example tests, 7 source-corpus tests, formatting, and warnings-denied Clippy. The distributed suite covers the installed LSP lifecycle, every standard callable contract, callback allocation in lexical regions, callback borrow origins, and region escape rejection.

The qualified artifact is dist/nocter-v0.6.0-arm64-darwin.tar.gz, exactly 3,301,773 bytes with SHA-256 ccb53525eb931b743a80a8c73af206cad794e1b3d8753c55dd0afb30c1a65c07. A fresh isolated extraction, without NOCTER_HOME, passes doctor, init, locked/offline check and native tests, locked/offline JSON graph generation, run, explicit build, and direct Mach-O execution. The archive contains the compiler, v0.6.0 metadata, license notices, and the complete standard library.

All v0.6.0 phases are complete. Publication was authorized on 2026-08-07. The exact archive named above was the only permitted release asset.

Publication Record

Nocter v0.6.0 was published at on 2026-08-07. Annotated tag v0.6.0 identifies commit c1e7eeb76cca668935207d0267e01e469a5edc7b, which contains the English release notes, current specification, standard library, packaging inputs, and generated website. The GitHub Release is neither a draft nor a prerelease.

GitHub reports the only attached asset as nocter-v0.6.0-arm64-darwin.tar.gz, 3,301,773 bytes, with digest sha256:ccb53525eb931b743a80a8c73af206cad794e1b3d8753c55dd0afb30c1a65c07. This exactly matches the qualified local candidate; the release asset was not rebuilt or replaced during publication.

Post-Publication Audit

The asset was downloaded again from its public release URL into a fresh temporary directory. Its size and SHA-256 digest matched the qualification record. The extracted ARM64 Mach-O compiler reported Nocter 0.6.0, found its installed home without NOCTER_HOME, and passed doctor.

The downloaded compiler initialized a fresh executable package. That package passed locked/offline check, one native test, deterministic JSON graph generation, run, explicit build, and direct execution of the emitted Mach-O image. Publication is complete and no release repair remains.