Programming Language

Nocter

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

/development/milestones/v0.8.0.md

Nocter v0.8.0 Milestone

Status: Phase 0, Phase 1, and Phase 2 completed on 2026-08-08. The qualified v0.8.0 archive was published and audited on 2026-08-08.

Purpose

v0.8.0 introduces type-owned borrow coercions for APIs that expose a safe borrowed view of a nominal value. The feature removes repetitive calls such as text.view() without hiding whether a caller borrows, readwrite-borrows, or moves a value.

The accepted declaration shape is:

coerce String {
    pub &self as &str from self {
        return self.view()
    }
}

The as token points from the explicit receiver capability to the contextual target type. The ordinary from clause remains the sole source contract for returned caller-managed storage.

Phase 0: Borrow Coercion Foundation

Phase 0 completes declaration, contextual selection, ownership, lowering, and editor behavior for one-step borrowed-view coercions. It does not introduce a general conversion graph.

Source Contract

  • coerce Type { ... } is a top-level type-owned declaration and does not use a block-level visibility modifier.
  • each entry has the form pub? &self as BorrowType from self { ... } or pub? &+self as BorrowType from self { ... }
  • source receivers are borrowed; owned self is rejected
  • result types are borrowed types or views and cannot be owned, optional, or fallible
  • from self is required exactly; coercions cannot claim fresh, static, allocator, parameter, or aggregate origins
  • readonly input cannot produce a readwrite result
  • &+self may produce a readonly or readwrite view, but the body must satisfy the declared capability and provenance contract
  • entries are private unless marked pub; external selection observes ordinary module visibility
  • a coercion declaration is legal only in the module that defines its nominal source type
  • a source receiver capability and canonical target type identify one entry; duplicates are errors

Contextual Selection

  • coercion is considered only when an expression already has a borrowed nominal source type and a concrete expected borrowed target type
  • callers write &value or &+value; coercion never inserts a borrow or move
  • Phase 0 applies one user-defined coercion step at binding initialization, assignment, argument, field/element initialization, and callable return boundaries that already own an expected type
  • built-in readwrite-to-readonly reborrowing may precede readonly selection; user-defined coercions do not chain
  • coercion does not participate in unconstrained generic inference, binary operators, casts, member lookup, construction selection, or overload ranking
  • expression as Type remains the explicit lossless numeric conversion syntax and does not invoke a user-defined coercion in Phase 0
  • exact type equality wins without consulting coercions; zero or one accessible exact coercion is valid, and ambiguity is diagnosed before lowering

Semantic Boundary

  • resolver assigns stable declaration identity to each coercion and validates ownership, coherence, visibility, and duplicate keys without recognizing standard-library names
  • typecheck validates the entry body as an unnamed callable with an implicit receiver, ordinary result provenance, ownership, and region rules
  • expected-type checking creates an immutable CoercionPlan containing declaration identity, concrete source and target types, receiver capability, generic substitution, result provenance, source span, and call target
  • ownership, region checking, buildability, analysis, and IR consume that plan instead of repeating lookup or comparing type spellings
  • lowering evaluates the source once and emits the selected entry as an ordinary statically resolved borrow-returning call
  • compiler and standard-library code do not special-case String, Vec, str, or slice names

Standard Library and Tooling

  • String publicly coerces &String to &str; it never exposes a mutable byte view
  • Vec<T> publicly coerces &Vec<T> to &[T] and &+Vec<T> to &+[T]
  • existing explicit view methods remain available in Phase 0
  • formatter and AST JSON preserve the accepted declaration exactly
  • hover presents normalized coercion entries on their exact source ranges
  • definition, references, semantic tokens, and rename use declaration and type identities rather than source-text recovery
  • diagnostics identify the source expression, expected target, rejected capability, inaccessible declaration, duplicate definition, or unsupported declaration contract as applicable

Completion Gate

  • parser, formatter, AST JSON, and malformed-source recovery cover the complete declaration grammar
  • resolver tests cover ownership, visibility, duplicate keys, generic source types, and imported use sites
  • typecheck tests cover exact matches, one-step contextual selection, every expected-type boundary, generic substitution, provenance, readonly/readwrite capability, ambiguity, and no-auto-borrow
  • ownership and region tests prove loans remain attached to the original source through last use
  • build/run tests prove source evaluation occurs once and readonly/readwrite coercions call the selected body
  • String and Vec<T> coercions work from repository source and a packaged Nocter home
  • hover, definition, references, rename, semantic tokens, and diagnostics use shared semantic facts
  • public specification and compiler documentation describe implemented behavior and explicit non-goals without changing the published v0.7.0 release record
  • documentation generation, diff checking, formatting, warnings-denied Clippy, focused tests, and clean and incremental complete repository verification pass

Non-goals

Phase 0 does not add owned-value coercions, implicit borrowing, implicit moves, transitive coercion, fallible or optional coercion, allocation-backed coercion, user-defined expression as Type, coercion-based method lookup, coercion-driven generic inference, extension declarations, runtime dispatch, noalloc, realtime, async, or named lifetime parameters.

Completion Record

Phase 0 completed the declaration-to-execution path without adding nominal standard-library cases:

  • lexer, AST, parser recovery, formatter, AST JSON, and normalized presentation own the complete coerce declaration model
  • resolver coherence and one nominal-type surface assembler preserve methods, literals, construction, and coercion entries through direct imports and public re-exports
  • expected-type checking records one concrete coercion plan for typed bindings, simple assignment, callable arguments, struct fields, fixed-array elements, and callable returns
  • ownership, provenance, regions, generic specialization, analysis, and IR consume the same plan; native lowering supports borrowed local replacement and aggregate borrow fields through that path
  • packaged String and Vec<T> readonly/readwrite coercions pass both compiler checking and native execution
  • hover uses the exact as anchor, receiver semantic tokens use parameter capability, and type hover lists the accessible normalized coercion surface
  • the versioned public specification records syntax, contextual selection, execution, lifetime, standard-library behavior, editor behavior, and Phase 0 limits without changing the published v0.7.0 contract

On 2026-08-08, development/compiler/scripts/verify.sh passed cargo check, all 3,310 tests, cargo fmt --check, and cargo clippy --all-targets -- -D warnings. The test total includes all compiler units, CLI build/run/LSP/package/native-test suites, 210 distributed-home cases, public examples, and the source corpus. node docs/build-docs.js generated 121 pages, and git diff --check passed.

Phase 1: Explicit Selection and Unified Conversion Plans

Phase 1 extends the existing expression as Type expression so an explicit borrowed nominal source may select the same type-owned coercion used by a contextual expected-type boundary:

let text_view = &text as &str
let values_view = &values as &[i32]
let values_mut = &+values as &+[i32]

The source borrow remains visible and mandatory. Phase 1 does not turn as into an owned-value or representation conversion mechanism.

Unified Conversion Contract

  • exact compatibility, lossless integer conversion, capability weakening, contextual borrow coercion, and explicit borrow coercion have one semantic selection result
  • a successful non-trivial selection produces an immutable ConversionPlan with a stable kind, source and target types, source and operator spans, and any selected coercion call plan
  • typecheck facts own the plan; ownership, provenance, regions, specialization, analysis, and IR consume it instead of re-running selection
  • contextual selection remains available only after exact expression assignability fails
  • explicit as first applies the existing lossless integer rule, then tries one accessible exact borrow coercion; it never chains and never inserts a source borrow
  • the result type of an explicit conversion is its written target, so ordinary generic inference may consume that result without making coercions participate in generic inference

Expected-Type Propagation

  • grouped, branch, match, optional/fallible projection, callable argument, struct field, fixed-array element, typed-sequence capture, assignment, binding, and return contexts propagate one concrete expectation to the selected leaf expression
  • checker acceptance and fact collection use the same conversion selector at every boundary
  • a leaf expression owns at most one plan; nested contexts do not select or lower the same conversion twice
  • an explicit conversion is a boundary of its own and does not inherit an outer coercion target

Diagnostics and Editor Behavior

  • invalid as distinguishes an unsupported source/target pair from a missing source borrow, insufficient readwrite capability, and an inaccessible matching declaration
  • contextual mismatch diagnostics may offer an explicit borrow/coercion spelling but do not rewrite ownership implicitly
  • hover on the exact expression as token presents normalized source, target, selected declaration, and from self lifetime behavior
  • definition on that as token targets the selected coercion entry; semantic type occurrences and rename remain identity-based
  • numeric as hover remains a conversion description and has no declaration target

Standard Library and Compatibility

  • explicit and contextual String and Vec<T> conversions pass check, build, and native run from a packaged Nocter home
  • existing view and view_mut methods remain source-compatible and documented
  • existing lossless integer as behavior, diagnostics, formatting, AST JSON, and lowering remain unchanged

Completion Gate

  • unit tests cover selection precedence, explicit generic sources, readonly weakening, readwrite targets, visibility, missing borrows, no chaining, and numeric compatibility
  • conversion facts cover every expected-type boundary and explicit as without duplicate plans
  • ownership and provenance tests prove explicit results retain the source loan and cannot escape it
  • IR and native tests prove explicit conversion evaluates its source once and invokes the selected concrete body
  • LSP tests cover exact hover and definition ranges for explicit coercion and numeric conversion
  • public specification and compiler design documentation describe the implemented contract and retain the published v0.7.0 record
  • documentation generation, diff checking, formatting, warnings-denied Clippy, focused tests, and the complete repository verification pass

Phase 1 Non-goals

Phase 1 does not add implicit borrowing or moves, owned/fallible/optional/allocation-backed coercions, user-defined numeric conversion, transitive conversion, coercion-driven method lookup, coercion-driven generic inference, overload ranking, runtime dispatch, removal of explicit view methods, or a public lifetime-parameter syntax.

Phase 1 Completion Record

Phase 1 completed explicit selection without creating a second coercion system:

  • one semantic selector classifies contextual compatibility and explicit as as exact, lossless-integer, capability-weakening, or borrow-coercion selection
  • one immutable ConversionPlan owns concrete types and spans and nests the selected coercion call plan; ownership, provenance, analysis, specialization, and lowering do not repeat lookup
  • prefix borrowing binds before as, so &value as &View is canonical while &(value as WiderInteger) remains available when the converted value is borrowed
  • concrete expectations reach grouped and branch results, optional/fallible projection, typed-sequence captures, and generic enum payload arguments without duplicate plans
  • native borrow destinations cover value-producing if, if is, and match, borrow-returning calls, and outcome projection while preserving the separate readonly temporary-borrow path
  • diagnostics distinguish missing source borrow, insufficient readwrite capability, inaccessible declarations, and unsupported conversions
  • expression hover focuses the exact as token and uses the shared plan; definition follows a selected local or imported coercion identity, while numeric conversion invents no target
  • explicit and contextual String and Vec<T> views pass packaged check and native execution; explicit coercion evaluates its source once and region checking rejects a local loan escape

On 2026-08-08, development/compiler/scripts/verify.sh passed cargo check, all 3,334 tests, cargo fmt --check, and cargo clippy --all-targets -- -D warnings. The total includes 2,310 compiler unit tests, CLI build/run/LSP/package/native-test suites, 210 distributed-home cases, public examples, and the source corpus. node docs/build-docs.js generated 121 pages, and git diff --check passed.

Phase 2: Contract Freeze and Release Qualification

Phase 2 stabilizes the completed borrow-coercion feature and prepares the exact v0.8.0 release candidate. It adds no new conversion category and does not broaden selection beyond the Phase 1 contract.

Stability Audit

  • audit every ConversionPlan producer and consumer so typecheck is the only conversion selector
  • require ownership, provenance, region checking, specialization, analysis, and lowering to use recorded declaration identity and concrete types rather than repeat lookup or compare display text
  • verify contextual and explicit conversions have one precedence model, one capability model, and one source-evaluation rule across compound expressions
  • review diagnostics and normalized notation against the public specification; internal names, inferred implementation storage, and repository paths must not leak into user-facing output
  • reject malformed and incomplete coercion syntax without panics or unstable editor ranges

Regression Matrix

  • direct CLI LSP protocol tests cover local, imported, publicly re-exported, private, numeric, and incomplete-source as hover and definition behavior
  • ownership and region tests cover readonly and readwrite loans, branch joins, outcome projection, local escape rejection, and use after an explicit conversion
  • native tests cover exact body selection, generic substitution, source evaluation once, compound values, packaged String, and packaged Vec<T>
  • clean and incremental verification must both pass so cached artifacts cannot conceal missing generated or packaged inputs

Release Candidate

  • compiler, Cargo lockfile, installed VERSION, distribution manifest, CLI version, and LSP server version identify v0.8.0 as one candidate
  • public release notes describe borrow coercions, explicit as, migration impact, limits, and the supported target in English
  • the root README and public release index continue to identify v0.7.0 as the latest published release until publication is separately authorized
  • the generated archive contains one .nocter/ root and is tested from a fresh extraction without repository source, target artifacts, or an inherited NOCTER_HOME
  • archive qualification covers version, doctor, installed-home checks, locked/offline dependency resolution, native run and build, direct executable launch, native tests, deterministic package graph output, and a framed LSP initialize/shutdown/exit lifecycle
  • the release record captures the exact archive name, byte size, SHA-256 digest, test count, and candidate commit; tagging, pushing, and GitHub publication remain outside Phase 2

Completion Gate

  • the stability audit finds no duplicate semantic selection or display-text-dependent behavior
  • focused regression tests cover every listed LSP, ownership, region, and native execution boundary
  • the public specification and development architecture agree with the implemented frozen contract
  • candidate version metadata, release notes, generated website, and qualification record are internally consistent while published-download pages remain on v0.7.0
  • documentation generation, diff checking, formatting, warnings-denied Clippy, clean and incremental complete repository verification pass
  • the exact candidate archive passes the complete fresh-extraction smoke matrix
  • the worktree is clean and remote publication is the only remaining release action

Phase 2 Non-goals

Phase 2 does not add owned, fallible, optional, allocation-backed, or transitive coercion; implicit borrowing or moving; coercion-driven member lookup, generic inference, or overload ranking; public lifetime parameters; runtime dispatch; or removal of explicit view methods. Those changes require a later milestone with their own source and semantic contracts.

Phase 2 Completion Record

Phase 2 froze the implemented contract and closed one ownership hole found by the release audit:

  • conversion selection remains unique to typecheck/conversions.rs; downstream compatibility accessors only project the borrow-call part of the recorded ConversionPlan
  • borrow-source collection now follows explicit conversion, projection, if, if is, and match results in branch-specific environments, so every possible source loan remains active until the result binding's last use
  • framed process-level LSP tests prove exact as hover and definition ranges for local, imported, publicly re-exported, private, numeric, and incomplete sources
  • native tests prove generic body selection, single source evaluation, contextual branch lowering, optional projection, and packaged String and Vec<T> behavior
  • compiler, Cargo lockfile, installed-home metadata, CLI, LSP, specification status, and English release notes share the v0.8.0 candidate identity while published-download pages remain v0.7.0

Incremental and clean development/compiler/scripts/verify.sh runs both passed on 2026-08-08. Each run passed 3,345 tests: 2,315 library, 296 build CLI, 7 formatter CLI, 27 framed LSP CLI, 18 package CLI, 452 run CLI, 11 native-test CLI, 210 distributed-home, 2 public-example, and 7 source-corpus tests. Both runs also passed cargo check, cargo fmt --check, and cargo clippy --all-targets -- -D warnings.

Candidate commit 0c3c3ee059b9e160578d1bc893fc7b473986c1a0 produced nocter-v0.8.0-arm64-darwin.tar.gz, exactly 3,319,650 bytes with SHA-256 cb6f0ce6b81e1aa71a65797e21f9f1d05a4164a17cf76427f34955966a63298a. A fresh extraction without NOCTER_HOME passed the complete Phase 2 smoke matrix. node docs/build-docs.js generated 123 pages, and git diff --check passed. Publication was separately authorized after qualification completed, and the public asset passed the recorded post-publication audit.