diff --git a/.llm/BETA_15_RESERVED_GENERIC_COLLECTION_BOUNDARY_HARDENING.md b/.llm/BETA_15_RESERVED_GENERIC_COLLECTION_BOUNDARY_HARDENING.md new file mode 100644 index 0000000..aa15c74 --- /dev/null +++ b/.llm/BETA_15_RESERVED_GENERIC_COLLECTION_BOUNDARY_HARDENING.md @@ -0,0 +1,92 @@ +# 1.0.0-beta.15 Reserved Generic Collection Boundary Hardening And Collection Ledger + +Status: release scope for `1.0.0-beta.15`. + +`1.0.0-beta.15` is a docs/design and compiler-boundary hardening slice for +the existing concrete collection and value-family surface. It keeps the +`1.0.0-beta` source language, typed core, runtime, standard-library/API +surface, diagnostic output shape, diagnostic codes, diagnostic schema, +benchmark metadata schema, ABI/layout behavior, compiler-known runtime names, +and performance claims unchanged while rewording reserved generic/map/set +diagnostic prose away from beta.9-specific text. + +## Scope + +- Add `docs/language/COLLECTIONS.md` as the collection/value-family ledger. +- Inventory the current concrete vector, option, result, and related + option/result-returning facade surfaces by linking to + `docs/language/STDLIB_API.md` instead of duplicating generated counts. +- Record design pressure from duplicated concrete vector, option, and result + helper families. +- Define prerequisites before executable generics, generic aliases, maps, + sets, iterators, mutable vectors, and slice/view APIs can be promoted. +- Record current unsupported diagnostics as boundary evidence, not behavior + changes. +- Centralize reserved generic/collection diagnostics for lowerer, formatter, + and checker paths in `compiler/src/reserved.rs`. +- Reword affected reserved-boundary snapshots from `beta.9` to current-beta + wording while preserving codes, schema, spans, expected/found values, hints, + and output shape. +- Add focused `reserved_generic_collection_beta15` coverage and run it from + `scripts/release-gate.sh`. +- Update README, post-beta roadmap, language/compiler roadmaps, language spec, + release notes, compiler release notes, and this release contract to introduce + beta15. + +## Acceptance + +- Public docs name current release/stage `1.0.0-beta.15`. +- `docs/language/COLLECTIONS.md` links to `docs/language/STDLIB_API.md` for + exact public helper signatures and does not duplicate generated helper + counts. +- The ledger inventories the current concrete collection/value-family surface: + five concrete vector modules, concrete option families, concrete result + families, and option/result-returning host/parsing facades. +- The ledger records why repeated concrete vector/option/result facades create + design pressure for later generic work. +- The ledger defines promotion prerequisites for executable generics, generic + aliases, maps, sets, iterators, mutable vectors, and slice/view APIs. +- The docs state that current unsupported diagnostics are boundaries, that + beta15 rewords only reserved-boundary diagnostic prose, and that beta15 does + not change diagnostic output shape, codes, schema, spans, expected/found + values, or hints. +- Focused compiler tests prove `check`, `fmt --check`, and project-root + `check` reject reserved generic/map/set surfaces with stage-neutral current + beta wording. +- Explicit exclusions include no source-language change, no runtime change, no + stdlib/API surface change, no diagnostic output shape/code/schema change, no + benchmark metadata schema change, no ABI/layout change, no performance + claim, and no stable API freeze. + +## Explicit Non-Scope + +- no executable generics, traits, inference, monomorphization, or generic + stdlib dispatch +- no generic aliases or parameterized aliases +- no map or set semantics +- no iterator API +- no mutable vector API +- no slice/view API +- no new compiler-known runtime names or helper symbols +- no standard-library/API addition, removal, rename, or stable freeze +- no diagnostic output shape, code, schema, span, expected/found, or hint change +- no diagnostic policy change beyond reserved-boundary prose rewording +- no benchmark metadata schema change +- no source-language syntax, typed-core, lowering, runtime, ABI/layout, or + optimizer change +- no performance threshold or cross-machine performance claim +- no worker-owned release publication work before controller review and gates + +## Expected Controller Verification + +- Run lightweight docs checks: + - `git diff --check -- README.md docs/POST_BETA_ROADMAP.md docs/language/ROADMAP.md docs/language/SPEC-v1.md docs/language/RELEASE_NOTES.md docs/language/COLLECTIONS.md .llm/BETA_15_RESERVED_GENERIC_COLLECTION_BOUNDARY_HARDENING.md` + - run an `rg` check for stale beta14-only current-stage phrasing across the + same touched docs +- Run focused compiler checks: + - `cargo test --test reserved_generic_collection_beta15` + - `cargo test --test diagnostics_contract` + - `cargo test --test formatter` + - `cargo test --test project_mode` + - `rg -n "not supported in beta\\.9" compiler/src tests` +- Do not commit, tag, push, or run release publication from this worker scope. diff --git a/.llm/reviews/BETA_15_RELEASE_REVIEW.md b/.llm/reviews/BETA_15_RELEASE_REVIEW.md new file mode 100644 index 0000000..c9d2062 --- /dev/null +++ b/.llm/reviews/BETA_15_RELEASE_REVIEW.md @@ -0,0 +1,53 @@ +# 1.0.0-beta.15 Release Review + +## Findings + +No blocking findings. + +- Ready for controller release gate. The beta15 candidate consistently scopes + this release as reserved generic collection boundary hardening plus a + collection ledger, without promoting executable generics, maps, sets, + generic stdlib dispatch, runtime names, ABI/layout, or stable API behavior. +- Evidence: the release contract preserves diagnostic shape/codes/schema while + allowing reserved-boundary prose rewording + (`.llm/BETA_15_RESERVED_GENERIC_COLLECTION_BOUNDARY_HARDENING.md:5`, + `.llm/BETA_15_RESERVED_GENERIC_COLLECTION_BOUNDARY_HARDENING.md:27`, + `.llm/BETA_15_RESERVED_GENERIC_COLLECTION_BOUNDARY_HARDENING.md:49`), + public docs describe the same boundary + (`README.md:86`, `docs/language/COLLECTIONS.md:12`, + `docs/language/COLLECTIONS.md:113`), and compiler docs mirror the + centralized-diagnostic scope (`docs/compiler/RELEASE_NOTES.md:28`, + `docs/compiler/ROADMAP.md:64`). +- Evidence: reserved diagnostic construction is centralized in + `compiler/src/reserved.rs:9`, `compiler/src/reserved.rs:62`, + `compiler/src/reserved.rs:77`, `compiler/src/reserved.rs:92`, and + `compiler/src/reserved.rs:107`; lowerer, formatter, and checker paths import + those helpers at `compiler/src/lower.rs:12`, + `compiler/src/formatter.rs:6`, and `compiler/src/check.rs:10`. +- Evidence: release gate wiring includes the focused beta15 test at + `scripts/release-gate.sh:68`, and the version bump is present in + `compiler/Cargo.toml:3` and `compiler/Cargo.lock:7`. + +## Verification + +- `cargo fmt --check`: passed. +- `cargo test --test reserved_generic_collection_beta15`: passed, 1 test. +- `cargo test --test diagnostics_contract`: passed, 1 test. +- `cargo test --test formatter`: passed, 16 tests. +- `cargo test --test project_mode`: passed, 36 tests. +- `rg -n "not supported in beta\\.9" compiler/src tests`: passed, no matches. +- `git diff --check`: passed. + +Additional review scans: + +- Current-stage stale beta14 scan across README/docs/.llm/Cargo metadata: + passed, no current-stage matches. +- Private/local publication text scan across README, docs, scripts, compiler + sources/tests, lib, examples, benchmarks, tests, and `.llm`: passed, no + matches. + +## Residual Risk + +Full release gate was not run by this reviewer because the requested scope was +focused review-only. Controller should still run `./scripts/release-gate.sh` +after accepting the candidate and before tagging/publishing. diff --git a/README.md b/README.md index a974e4b..608bed9 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This repository is the canonical public monorepo for the language design, standard library source, compiler, runtime, examples, benchmarks, and technical documents. -Current release: `1.0.0-beta.14`. +Current release: `1.0.0-beta.15`. ## Repository Layout @@ -24,7 +24,7 @@ scripts/ local release and document tooling ## Beta Scope -`1.0.0-beta.14` keeps the `1.0.0-beta` language baseline, includes the +`1.0.0-beta.15` keeps the `1.0.0-beta` language baseline, includes the `1.0.0-beta.1` tooling/install hardening slice, the `1.0.0-beta.2` runtime/resource foundation bundle, the `1.0.0-beta.3` standard-library stabilization bundle, the `1.0.0-beta.4` language-usability diagnostics @@ -35,8 +35,10 @@ alias foundation, the `1.0.0-beta.9` collection alias unification and generic reservation slice, the `1.0.0-beta.10` developer-experience API discovery slice, and the `1.0.0-beta.11` local package API documentation slice, plus the `1.0.0-beta.12` concrete vector query and prefix parity -slice, the `1.0.0-beta.13` diagnostic catalog and schema policy slice, and -the `1.0.0-beta.14` benchmark suite catalog and metadata gate. +slice, the `1.0.0-beta.13` diagnostic catalog and schema policy slice, the +`1.0.0-beta.14` benchmark suite catalog and metadata gate, and the +`1.0.0-beta.15` reserved generic collection boundary hardening and collection +ledger. The language baseline supports practical local command-line, file, and loopback-network programs with: @@ -81,16 +83,32 @@ inventory and `python3 benchmarks/runner.py --suite-list --json` for beta tooling metadata, with required scaffold-file verification for each current suite. Benchmark timings remain local-machine evidence only; the JSON field set is not a stable public schema. +The `1.0.0-beta.15` collection ledger and reserved diagnostic hardening slice +adds +[`docs/language/COLLECTIONS.md`](docs/language/COLLECTIONS.md) as the +docs/design ledger for current concrete collection and value-family +boundaries. It links to the generated +[`docs/language/STDLIB_API.md`](docs/language/STDLIB_API.md) catalog for exact +public helper signatures, records design pressure from duplicated concrete +vector/option/result families, defines prerequisites before executable +generics, generic aliases, maps, sets, iterators, mutable vectors, or +slice/view APIs can be promoted, and treats current unsupported diagnostics as +boundaries. It rewords affected reserved-boundary diagnostics from +beta.9-specific text to current-beta wording while preserving diagnostic +codes, schema, spans, expected/found values, hints, and output shape. It +changes no source language, runtime, stdlib/API surface, benchmark metadata +schema, ABI/layout behavior, or performance claim. -Still deferred before stable: executable generics, maps/sets, broad package -registry semantics, stable Markdown schema, stable stdlib/API compatibility -freeze, DNS/TLS/async networking, LSP/watch guarantees, SARIF and daemon -protocols, stable `1.0.0` diagnostics freeze, re-exports/globs/hierarchical -modules, mutable vectors, slice/view APIs, iterators, new compiler-known -runtime names, stable ABI and layout, performance claims, stable benchmark -JSON metadata schema, and runtime changes for generic collections. +Still deferred before stable: executable generics, generic aliases, maps/sets, +broad package registry semantics, stable Markdown schema, stable stdlib/API +compatibility freeze, DNS/TLS/async networking, LSP/watch guarantees, SARIF +and daemon protocols, stable `1.0.0` diagnostics freeze, +re-exports/globs/hierarchical modules, mutable vectors, slice/view APIs, +iterators, new compiler-known runtime names, stable ABI and layout, +performance claims, stable benchmark JSON metadata schema, and runtime changes +for generic collections. -The next likely language slice after `1.0.0-beta.14` should continue from the +The next likely language slice after `1.0.0-beta.15` should continue from the developer-experience, package, benchmark metadata, and reserved generic/collection lanes without claiming executable generics, maps, sets, traits, inference, monomorphization, iterators, ABI stability, runtime changes, @@ -341,6 +359,30 @@ This release does not change the source language, runtime, stdlib API, diagnostic output shape, compiler CLI, LSP/watch behavior, SARIF/daemon protocols, stable Markdown schema, or stable `1.0.0` diagnostics freeze. +## 1.0.0-beta.15 Reserved Generic Collection Boundary Hardening And Collection Ledger + +The `1.0.0-beta.15` release documents the current concrete collection and +value-family boundary. It adds +[`docs/language/COLLECTIONS.md`](docs/language/COLLECTIONS.md), which links to +the generated +[`docs/language/STDLIB_API.md`](docs/language/STDLIB_API.md) catalog instead +of duplicating generated helper counts. + +The ledger inventories concrete vector, option, result, and related +option/result-returning facade surfaces; records the design pressure from +duplicated concrete vector/option/result helpers; and defines prerequisites +before executable generics, generic aliases, maps, sets, iterators, mutable +vectors, or slice/view APIs can be promoted. + +Current unsupported diagnostics are documented as release boundaries, not as +new behavior. This release does not change the source language, runtime, +stdlib/API surface, diagnostic output shape/codes/schema, benchmark metadata +schema, compiler ABI/layout behavior, or performance claims, and it does not +create a stable stdlib/API freeze. It does reword affected reserved-boundary +diagnostic messages from beta.9-specific text to current-beta wording while +preserving diagnostic codes, schema, spans, expected/found values, hints, and +output shape. + ## 1.0.0-beta.14 Benchmark Suite Catalog And Metadata Gate The `1.0.0-beta.14` release documents the existing benchmark suite catalog as @@ -370,6 +412,7 @@ performance claims. - [Diagnostics Policy](docs/language/DIAGNOSTICS.md) - [Local Package And Workspace Guide](docs/language/PACKAGES.md) - [Standard Library API Catalog](docs/language/STDLIB_API.md) +- [Collection Ledger](docs/language/COLLECTIONS.md) - [Benchmark Suite Catalog](benchmarks/README.md) - [Compiler Manifest](docs/compiler/GLAGOL_COMPILER_MANIFEST.md) - [Post-Beta Roadmap](docs/POST_BETA_ROADMAP.md) diff --git a/compiler/Cargo.lock b/compiler/Cargo.lock index 15044d4..82172f6 100644 --- a/compiler/Cargo.lock +++ b/compiler/Cargo.lock @@ -4,4 +4,4 @@ version = 3 [[package]] name = "glagol" -version = "1.0.0-beta.14" +version = "1.0.0-beta.15" diff --git a/compiler/Cargo.toml b/compiler/Cargo.toml index 3578a33..f839ffb 100644 --- a/compiler/Cargo.toml +++ b/compiler/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "glagol" -version = "1.0.0-beta.14" +version = "1.0.0-beta.15" edition = "2021" description = "Glagol, the first compiler for the Slovo language" license = "MIT OR Apache-2.0" diff --git a/compiler/src/check.rs b/compiler/src/check.rs index be1e5e1..46d36bc 100644 --- a/compiler/src/check.rs +++ b/compiler/src/check.rs @@ -6,7 +6,9 @@ use crate::{ StructDecl, StructInitField, Test, TypeAliasDecl, }, diag::Diagnostic, - lower, std_runtime, + lower, + reserved::{is_generic_type_parameter_name, unsupported_generic_type_parameter}, + std_runtime, token::Span, types::Type, unsafe_ops, @@ -5537,25 +5539,6 @@ fn check_vector_type(file: &str, ty: &Type, span: Span) -> Result<(), Diagnostic Ok(()) } -fn unsupported_generic_type_parameter(file: &str, span: Span, name: &str) -> Diagnostic { - Diagnostic::new( - file, - "UnsupportedGenericTypeParameter", - format!( - "generic type parameter `{}` is reserved but not supported in beta.9", - name - ), - ) - .with_span(span) - .expected("concrete supported type") - .found(name.to_string()) - .hint("use a concrete promoted type such as `i32`, `string`, or `(vec i32)`") -} - -fn is_generic_type_parameter_name(name: &str) -> bool { - name.len() == 1 && name.bytes().all(|byte| byte.is_ascii_uppercase()) -} - fn array_index_range(len: usize) -> String { if len == 1 { "0".to_string() diff --git a/compiler/src/formatter.rs b/compiler/src/formatter.rs index 81956e4..36c0281 100644 --- a/compiler/src/formatter.rs +++ b/compiler/src/formatter.rs @@ -2,6 +2,11 @@ use std::collections::{HashMap, HashSet}; use crate::{ diag::Diagnostic, + reserved::{ + is_unsupported_generic_standard_library_call, unsupported_generic_function, + unsupported_generic_standard_library_call, unsupported_generic_type_alias, + unsupported_reserved_type_diagnostic, + }, sexpr::{Atom, SExpr, SExprKind}, std_runtime, token::Span, @@ -2496,138 +2501,6 @@ struct RenderedMatchPattern<'a> { text: String, } -fn unsupported_reserved_type_diagnostic(file: &str, form: &SExpr) -> Option { - if let Some(name) = expect_ident(form) { - if is_generic_type_parameter_name(name) { - return Some(unsupported_generic_type_parameter(file, form.span, name)); - } - } - - let items = expect_list(form)?; - let head = items.first().and_then(expect_ident)?; - match head { - "map" => Some( - Diagnostic::new( - file, - "UnsupportedMapType", - "`map` types are reserved but not supported in beta.9", - ) - .with_span(form.span) - .expected("supported concrete type") - .found(render_type_form(form)) - .hint( - "use current concrete arrays, vectors, option/result, structs, enums, or scalars", - ), - ), - "set" => Some( - Diagnostic::new( - file, - "UnsupportedSetType", - "`set` types are reserved but not supported in beta.9", - ) - .with_span(form.span) - .expected("supported concrete type") - .found(render_type_form(form)) - .hint( - "use current concrete arrays, vectors, option/result, structs, enums, or scalars", - ), - ), - "vec" if items.len() != 2 => Some( - Diagnostic::new( - file, - "UnsupportedGenericTypeParameter", - "generic vector syntax is reserved but not supported in beta.9", - ) - .with_span(form.span) - .expected("(vec i32), (vec i64), (vec f64), (vec bool), or (vec string)") - .found(render_type_form(form)) - .hint("choose one current concrete vector family explicitly"), - ), - _ => items - .iter() - .find_map(|item| unsupported_reserved_type_diagnostic(file, item)), - } -} - -fn unsupported_generic_function(file: &str, span: Span) -> Diagnostic { - Diagnostic::new( - file, - "UnsupportedGenericFunction", - "generic function declarations are reserved but not supported in beta.9", - ) - .with_span(span) - .expected("(fn name ((arg ConcreteType) ...) -> ConcreteType body...)") - .found("(type_params ...)") - .hint("write a concrete function for each currently supported type family") -} - -fn unsupported_generic_type_alias(file: &str, span: Span) -> Diagnostic { - Diagnostic::new( - file, - "UnsupportedGenericTypeAlias", - "parameterized type aliases are reserved but not supported in beta.9", - ) - .with_span(span) - .expected("(type Alias ConcreteType)") - .found("(type_params ...)") - .hint("aliases remain transparent names for concrete supported target types") -} - -fn unsupported_generic_type_parameter(file: &str, span: Span, name: &str) -> Diagnostic { - Diagnostic::new( - file, - "UnsupportedGenericTypeParameter", - format!( - "generic type parameter `{}` is reserved but not supported in beta.9", - name - ), - ) - .with_span(span) - .expected("concrete supported type") - .found(name.to_string()) - .hint("use a concrete promoted type such as `i32`, `string`, or `(vec i32)`") -} - -fn unsupported_generic_standard_library_call(file: &str, span: Span, name: &str) -> Diagnostic { - Diagnostic::new( - file, - "UnsupportedGenericStandardLibraryCall", - format!( - "generic standard-library call `{}` is reserved but not supported in beta.9", - name - ), - ) - .with_span(span) - .expected("promoted concrete standard-library function") - .found(name.to_string()) - .hint("use current concrete families such as `std.vec.i32.empty`") -} - -fn is_unsupported_generic_standard_library_call(name: &str) -> bool { - matches!(name, "std.vec.empty" | "std.result.map") -} - -fn is_generic_type_parameter_name(name: &str) -> bool { - name.len() == 1 && name.bytes().all(|byte| byte.is_ascii_uppercase()) -} - -fn render_type_form(form: &SExpr) -> String { - match &form.kind { - SExprKind::Atom(Atom::Ident(name)) => name.clone(), - SExprKind::Atom(Atom::Int(value)) => value.to_string(), - SExprKind::Atom(Atom::I64(value)) => format!("{}i64", value), - SExprKind::Atom(Atom::U32(value)) => format!("{}u32", value), - SExprKind::Atom(Atom::U64(value)) => format!("{}u64", value), - SExprKind::Atom(Atom::Float(value)) => value.to_string(), - SExprKind::Atom(Atom::String(value)) => format!("{:?}", value), - SExprKind::Atom(Atom::Arrow) => "->".to_string(), - SExprKind::List(items) => { - let parts = items.iter().map(render_type_form).collect::>(); - format!("({})", parts.join(" ")) - } - } -} - fn collect_function_names(forms: &[SExpr]) -> HashSet { let mut names = HashSet::new(); for form in forms { diff --git a/compiler/src/lower.rs b/compiler/src/lower.rs index 9daab13..31d38e1 100644 --- a/compiler/src/lower.rs +++ b/compiler/src/lower.rs @@ -8,6 +8,11 @@ use crate::{ Test, TypeAliasDecl, }, diag::Diagnostic, + reserved::{ + is_unsupported_generic_standard_library_call, unsupported_generic_function, + unsupported_generic_standard_library_call, unsupported_generic_type_alias, + unsupported_reserved_type_diagnostic, + }, sexpr::{Atom, SExpr, SExprKind}, token::Span, types::Type, @@ -2536,138 +2541,6 @@ fn invalid_type_diagnostic( diagnostic } -fn unsupported_reserved_type_diagnostic(file: &str, form: &SExpr) -> Option { - if let Some(name) = expect_ident(form) { - if is_generic_type_parameter_name(name) { - return Some(unsupported_generic_type_parameter(file, form.span, name)); - } - } - - let items = expect_list(form)?; - let head = items.first().and_then(expect_ident)?; - match head { - "map" => Some( - Diagnostic::new( - file, - "UnsupportedMapType", - "`map` types are reserved but not supported in beta.9", - ) - .with_span(form.span) - .expected("supported concrete type") - .found(render_type_form(form)) - .hint( - "use current concrete arrays, vectors, option/result, structs, enums, or scalars", - ), - ), - "set" => Some( - Diagnostic::new( - file, - "UnsupportedSetType", - "`set` types are reserved but not supported in beta.9", - ) - .with_span(form.span) - .expected("supported concrete type") - .found(render_type_form(form)) - .hint( - "use current concrete arrays, vectors, option/result, structs, enums, or scalars", - ), - ), - "vec" if items.len() != 2 => Some( - Diagnostic::new( - file, - "UnsupportedGenericTypeParameter", - "generic vector syntax is reserved but not supported in beta.9", - ) - .with_span(form.span) - .expected("(vec i32), (vec i64), (vec f64), (vec bool), or (vec string)") - .found(render_type_form(form)) - .hint("choose one current concrete vector family explicitly"), - ), - _ => items - .iter() - .find_map(|item| unsupported_reserved_type_diagnostic(file, item)), - } -} - -fn unsupported_generic_function(file: &str, span: Span) -> Diagnostic { - Diagnostic::new( - file, - "UnsupportedGenericFunction", - "generic function declarations are reserved but not supported in beta.9", - ) - .with_span(span) - .expected("(fn name ((arg ConcreteType) ...) -> ConcreteType body...)") - .found("(type_params ...)") - .hint("write a concrete function for each currently supported type family") -} - -fn unsupported_generic_type_alias(file: &str, span: Span) -> Diagnostic { - Diagnostic::new( - file, - "UnsupportedGenericTypeAlias", - "parameterized type aliases are reserved but not supported in beta.9", - ) - .with_span(span) - .expected("(type Alias ConcreteType)") - .found("(type_params ...)") - .hint("aliases remain transparent names for concrete supported target types") -} - -fn unsupported_generic_type_parameter(file: &str, span: Span, name: &str) -> Diagnostic { - Diagnostic::new( - file, - "UnsupportedGenericTypeParameter", - format!( - "generic type parameter `{}` is reserved but not supported in beta.9", - name - ), - ) - .with_span(span) - .expected("concrete supported type") - .found(name.to_string()) - .hint("use a concrete promoted type such as `i32`, `string`, or `(vec i32)`") -} - -fn unsupported_generic_standard_library_call(file: &str, span: Span, name: &str) -> Diagnostic { - Diagnostic::new( - file, - "UnsupportedGenericStandardLibraryCall", - format!( - "generic standard-library call `{}` is reserved but not supported in beta.9", - name - ), - ) - .with_span(span) - .expected("promoted concrete standard-library function") - .found(name.to_string()) - .hint("use current concrete families such as `std.vec.i32.empty`") -} - -fn is_unsupported_generic_standard_library_call(name: &str) -> bool { - matches!(name, "std.vec.empty" | "std.result.map") -} - -fn is_generic_type_parameter_name(name: &str) -> bool { - name.len() == 1 && name.bytes().all(|byte| byte.is_ascii_uppercase()) -} - -fn render_type_form(form: &SExpr) -> String { - match &form.kind { - SExprKind::Atom(Atom::Ident(name)) => name.clone(), - SExprKind::Atom(Atom::Int(value)) => value.to_string(), - SExprKind::Atom(Atom::I64(value)) => format!("{}i64", value), - SExprKind::Atom(Atom::U32(value)) => format!("{}u32", value), - SExprKind::Atom(Atom::U64(value)) => format!("{}u64", value), - SExprKind::Atom(Atom::Float(value)) => value.to_string(), - SExprKind::Atom(Atom::String(value)) => format!("{:?}", value), - SExprKind::Atom(Atom::Arrow) => "->".to_string(), - SExprKind::List(items) => { - let parts = items.iter().map(render_type_form).collect::>(); - format!("({})", parts.join(" ")) - } - } -} - fn list_head(form: &SExpr) -> Option<&str> { let items = expect_list(form)?; let first = items.first()?; diff --git a/compiler/src/main.rs b/compiler/src/main.rs index 3cfb8d6..d9e8fe8 100644 --- a/compiler/src/main.rs +++ b/compiler/src/main.rs @@ -8,6 +8,7 @@ mod lexer; mod llvm; mod lower; mod project; +mod reserved; mod scaffold; mod sexpr; mod std_runtime; diff --git a/compiler/src/reserved.rs b/compiler/src/reserved.rs new file mode 100644 index 0000000..d8afc9a --- /dev/null +++ b/compiler/src/reserved.rs @@ -0,0 +1,163 @@ +use crate::{ + diag::Diagnostic, + sexpr::{Atom, SExpr, SExprKind}, + token::Span, +}; + +const CURRENT_BETA_UNSUPPORTED: &str = "reserved but not supported in the current beta"; + +pub(crate) fn unsupported_reserved_type_diagnostic(file: &str, form: &SExpr) -> Option { + if let Some(name) = expect_ident(form) { + if is_generic_type_parameter_name(name) { + return Some(unsupported_generic_type_parameter(file, form.span, name)); + } + } + + let items = expect_list(form)?; + let head = items.first().and_then(expect_ident)?; + match head { + "map" => Some( + Diagnostic::new( + file, + "UnsupportedMapType", + format!("`map` types are {}", CURRENT_BETA_UNSUPPORTED), + ) + .with_span(form.span) + .expected("supported concrete type") + .found(render_type_form(form)) + .hint( + "use current concrete arrays, vectors, option/result, structs, enums, or scalars", + ), + ), + "set" => Some( + Diagnostic::new( + file, + "UnsupportedSetType", + format!("`set` types are {}", CURRENT_BETA_UNSUPPORTED), + ) + .with_span(form.span) + .expected("supported concrete type") + .found(render_type_form(form)) + .hint( + "use current concrete arrays, vectors, option/result, structs, enums, or scalars", + ), + ), + "vec" if items.len() != 2 => Some( + Diagnostic::new( + file, + "UnsupportedGenericTypeParameter", + format!("generic vector syntax is {}", CURRENT_BETA_UNSUPPORTED), + ) + .with_span(form.span) + .expected("(vec i32), (vec i64), (vec f64), (vec bool), or (vec string)") + .found(render_type_form(form)) + .hint("choose one current concrete vector family explicitly"), + ), + _ => items + .iter() + .find_map(|item| unsupported_reserved_type_diagnostic(file, item)), + } +} + +pub(crate) fn unsupported_generic_function(file: &str, span: Span) -> Diagnostic { + Diagnostic::new( + file, + "UnsupportedGenericFunction", + format!( + "generic function declarations are {}", + CURRENT_BETA_UNSUPPORTED + ), + ) + .with_span(span) + .expected("(fn name ((arg ConcreteType) ...) -> ConcreteType body...)") + .found("(type_params ...)") + .hint("write a concrete function for each currently supported type family") +} + +pub(crate) fn unsupported_generic_type_alias(file: &str, span: Span) -> Diagnostic { + Diagnostic::new( + file, + "UnsupportedGenericTypeAlias", + format!( + "parameterized type aliases are {}", + CURRENT_BETA_UNSUPPORTED + ), + ) + .with_span(span) + .expected("(type Alias ConcreteType)") + .found("(type_params ...)") + .hint("aliases remain transparent names for concrete supported target types") +} + +pub(crate) fn unsupported_generic_type_parameter(file: &str, span: Span, name: &str) -> Diagnostic { + Diagnostic::new( + file, + "UnsupportedGenericTypeParameter", + format!( + "generic type parameter `{}` is {}", + name, CURRENT_BETA_UNSUPPORTED + ), + ) + .with_span(span) + .expected("concrete supported type") + .found(name.to_string()) + .hint("use a concrete promoted type such as `i32`, `string`, or `(vec i32)`") +} + +pub(crate) fn unsupported_generic_standard_library_call( + file: &str, + span: Span, + name: &str, +) -> Diagnostic { + Diagnostic::new( + file, + "UnsupportedGenericStandardLibraryCall", + format!( + "generic standard-library call `{}` is {}", + name, CURRENT_BETA_UNSUPPORTED + ), + ) + .with_span(span) + .expected("promoted concrete standard-library function") + .found(name.to_string()) + .hint("use current concrete families such as `std.vec.i32.empty`") +} + +pub(crate) fn is_unsupported_generic_standard_library_call(name: &str) -> bool { + matches!(name, "std.vec.empty" | "std.result.map") +} + +pub(crate) fn is_generic_type_parameter_name(name: &str) -> bool { + name.len() == 1 && name.bytes().all(|byte| byte.is_ascii_uppercase()) +} + +fn expect_list(expr: &SExpr) -> Option<&[SExpr]> { + match &expr.kind { + SExprKind::List(items) => Some(items), + _ => None, + } +} + +fn expect_ident(expr: &SExpr) -> Option<&str> { + match &expr.kind { + SExprKind::Atom(Atom::Ident(name)) => Some(name), + _ => None, + } +} + +fn render_type_form(form: &SExpr) -> String { + match &form.kind { + SExprKind::Atom(Atom::Ident(name)) => name.clone(), + SExprKind::Atom(Atom::Int(value)) => value.to_string(), + SExprKind::Atom(Atom::I64(value)) => format!("{}i64", value), + SExprKind::Atom(Atom::U32(value)) => format!("{}u32", value), + SExprKind::Atom(Atom::U64(value)) => format!("{}u64", value), + SExprKind::Atom(Atom::Float(value)) => value.to_string(), + SExprKind::Atom(Atom::String(value)) => format!("{:?}", value), + SExprKind::Atom(Atom::Arrow) => "->".to_string(), + SExprKind::List(items) => { + let parts = items.iter().map(render_type_form).collect::>(); + format!("({})", parts.join(" ")) + } + } +} diff --git a/compiler/tests/reserved_generic_collection_beta15.rs b/compiler/tests/reserved_generic_collection_beta15.rs new file mode 100644 index 0000000..5f41e65 --- /dev/null +++ b/compiler/tests/reserved_generic_collection_beta15.rs @@ -0,0 +1,239 @@ +use std::{ + ffi::OsStr, + fs, + path::PathBuf, + process::{Command, Output}, + sync::atomic::{AtomicUsize, Ordering}, + time::{SystemTime, UNIX_EPOCH}, +}; + +static NEXT_FIXTURE_ID: AtomicUsize = AtomicUsize::new(0); + +const CASES: &[ReservedCase] = &[ + ReservedCase { + name: "generic-function", + source: r#" +(module main) + +(fn id (type_params T) ((value T)) -> T + value) + +(fn main () -> i32 + 0) +"#, + code: "UnsupportedGenericFunction", + message: "generic function declarations are reserved but not supported in the current beta", + }, + ReservedCase { + name: "generic-type-alias", + source: r#" +(module main) + +(type VecOf (type_params T) (vec T)) + +(fn main () -> i32 + 0) +"#, + code: "UnsupportedGenericTypeAlias", + message: "parameterized type aliases are reserved but not supported in the current beta", + }, + ReservedCase { + name: "generic-type-parameter", + source: r#" +(module main) + +(fn main () -> i32 + (let xs (vec T) (std.vec.i32.empty)) + 0) +"#, + code: "UnsupportedGenericTypeParameter", + message: "generic type parameter `T` is reserved but not supported in the current beta", + }, + ReservedCase { + name: "generic-vector-spelling", + source: r#" +(module main) + +(fn main () -> (vec) + (std.vec.i32.empty)) +"#, + code: "UnsupportedGenericTypeParameter", + message: "generic vector syntax is reserved but not supported in the current beta", + }, + ReservedCase { + name: "map-type", + source: r#" +(module main) + +(fn main () -> (map string i32) + 0) +"#, + code: "UnsupportedMapType", + message: "`map` types are reserved but not supported in the current beta", + }, + ReservedCase { + name: "set-type", + source: r#" +(module main) + +(fn main () -> (set string) + 0) +"#, + code: "UnsupportedSetType", + message: "`set` types are reserved but not supported in the current beta", + }, + ReservedCase { + name: "std-vec-empty", + source: r#" +(module main) + +(fn main () -> i32 + (std.vec.empty i32) + 0) +"#, + code: "UnsupportedGenericStandardLibraryCall", + message: + "generic standard-library call `std.vec.empty` is reserved but not supported in the current beta", + }, + ReservedCase { + name: "std-result-map", + source: r#" +(module main) + +(fn main () -> i32 + (std.result.map (ok string i32 "a") mapper) + 0) +"#, + code: "UnsupportedGenericStandardLibraryCall", + message: + "generic standard-library call `std.result.map` is reserved but not supported in the current beta", + }, +]; + +#[test] +fn check_fmt_and_project_paths_reject_reserved_generic_collection_surface() { + for case in CASES { + let fixture = write_fixture(case); + + let check = run_glagol([OsStr::new("check"), fixture.as_os_str()]); + assert_rejection(&format!("{} check", case.name), &check, case); + + let fmt = run_glagol([ + OsStr::new("fmt"), + OsStr::new("--check"), + fixture.as_os_str(), + ]); + assert_rejection(&format!("{} fmt --check", case.name), &fmt, case); + + let project = write_project(case); + let project_check = run_glagol([OsStr::new("check"), project.as_os_str()]); + assert_rejection( + &format!("{} project check", case.name), + &project_check, + case, + ); + } +} + +struct ReservedCase { + name: &'static str, + source: &'static str, + code: &'static str, + message: &'static str, +} + +fn assert_rejection(context: &str, output: &Output, case: &ReservedCase) { + assert_eq!( + output.status.code(), + Some(1), + "{} exit code mismatch\nstdout:\n{}\nstderr:\n{}", + context, + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr) + ); + assert!( + output.stdout.is_empty(), + "{} wrote stdout:\n{}", + context, + String::from_utf8_lossy(&output.stdout) + ); + + let stderr = String::from_utf8_lossy(&output.stderr); + assert!( + stderr.contains(&format!("error[{}]", case.code)), + "{} human diagnostic did not contain code `{}`:\n{}", + context, + case.code, + stderr + ); + assert!( + stderr.contains(&format!(" (code {})", case.code)), + "{} machine diagnostic did not contain code `{}`:\n{}", + context, + case.code, + stderr + ); + assert!( + stderr.contains(case.message), + "{} stderr did not contain message `{}`:\n{}", + context, + case.message, + stderr + ); + assert!( + !stderr.contains("beta.9"), + "{} stderr still used beta.9 wording:\n{}", + context, + stderr + ); +} + +fn write_fixture(case: &ReservedCase) -> PathBuf { + let id = NEXT_FIXTURE_ID.fetch_add(1, Ordering::Relaxed); + let path = unique_base_path(&format!("file-{}-{}", id, case.name)).with_extension("slo"); + fs::write(&path, case.source) + .unwrap_or_else(|err| panic!("write `{}`: {}", path.display(), err)); + path +} + +fn write_project(case: &ReservedCase) -> PathBuf { + let id = NEXT_FIXTURE_ID.fetch_add(1, Ordering::Relaxed); + let root = unique_base_path(&format!("project-{}-{}", id, case.name)); + let src = root.join("src"); + fs::create_dir_all(&src).unwrap_or_else(|err| panic!("create `{}`: {}", src.display(), err)); + fs::write( + root.join("slovo.toml"), + format!( + "[project]\nname = \"reserved-beta15-{}\"\nsource_root = \"src\"\nentry = \"main\"\n", + case.name + ), + ) + .unwrap_or_else(|err| panic!("write project manifest for `{}`: {}", case.name, err)); + fs::write(src.join("main.slo"), case.source) + .unwrap_or_else(|err| panic!("write project source for `{}`: {}", case.name, err)); + root +} + +fn unique_base_path(name: &str) -> PathBuf { + let nanos = SystemTime::now() + .duration_since(UNIX_EPOCH) + .map(|duration| duration.as_nanos()) + .unwrap_or(0); + std::env::temp_dir().join(format!( + "glagol-reserved-beta15-{}-{}-{}", + std::process::id(), + nanos, + name + )) +} + +fn run_glagol(args: I) -> Output +where + I: IntoIterator, + S: AsRef, +{ + Command::new(env!("CARGO_BIN_EXE_glagol")) + .args(args) + .output() + .expect("run glagol") +} diff --git a/docs/POST_BETA_ROADMAP.md b/docs/POST_BETA_ROADMAP.md index 3b4a448..3f6f156 100644 --- a/docs/POST_BETA_ROADMAP.md +++ b/docs/POST_BETA_ROADMAP.md @@ -411,6 +411,50 @@ Why fourteenth: the benchmark suite is already part of the public monorepo, but its suite-level inventory and metadata boundary need one central reference before future tooling can rely on it. +### 15. Reserved Generic Collection Boundary Hardening And Collection Ledger + +Goal: document the current concrete collection and value-family boundary before +executable generics, maps, sets, iterators, mutable vectors, or slice/view APIs +are designed as executable features. + +Work: + +- add [`docs/language/COLLECTIONS.md`](language/COLLECTIONS.md) as the + collection/value-family ledger +- link to the generated [`docs/language/STDLIB_API.md`](language/STDLIB_API.md) + catalog for exact public helper signatures instead of duplicating generated + counts +- inventory the current concrete vector, option, result, and related + option/result-returning facade surfaces +- record design pressure from duplicated concrete vector, option, and result + helper families +- define prerequisites before executable generics, generic aliases, maps, + sets, iterators, mutable vectors, or slice/view APIs can be promoted +- state that current unsupported diagnostics are boundaries, not behavior + changes +- centralize reserved generic/map/set diagnostics and reword affected + reserved-boundary messages from beta.9-specific text to current-beta wording +- keep source-language/runtime/stdlib/API changes, diagnostic output shape/ + code/schema/span/expected/found/hint changes, benchmark metadata schema + changes, ABI/layout changes, performance claims, and stable API freeze out + of scope + +Released in `1.0.0-beta.15`: +[`docs/language/COLLECTIONS.md`](language/COLLECTIONS.md) now records the +collection/value-family ledger and links to the generated standard-library API +catalog for exact signatures. The release also centralizes reserved +generic/map/set diagnostics and rewords affected reserved-boundary messages +away from beta.9-specific text. It does not change the source language, +runtime, stdlib/API surface, diagnostic output shape, diagnostic codes, +diagnostic schema, spans, expected/found values, hints, benchmark metadata +schema, ABI/layout behavior, or performance claims, and it does not create a +stable stdlib/API freeze. + +Why fifteenth: the concrete vector, option, and result facades have enough +duplication to justify generic collection planning, but the public contract +needs an explicit boundary ledger before executable generic, map, set, +iterator, mutable-vector, or slice/view semantics are promoted. + ## Stable `1.0.0` Gate Slovo should not become stable until all of these are true: diff --git a/docs/compiler/RELEASE_NOTES.md b/docs/compiler/RELEASE_NOTES.md index 3912f1e..b0c034e 100644 --- a/docs/compiler/RELEASE_NOTES.md +++ b/docs/compiler/RELEASE_NOTES.md @@ -10,11 +10,47 @@ integration/readiness release, not the first real beta. ## Unreleased -Next scoped Glagol work is expected to continue after the `1.0.0-beta.14` -benchmark suite catalog and metadata gate. +Next scoped Glagol work is expected to continue after the `1.0.0-beta.15` +reserved generic collection boundary hardening and collection ledger update. No unreleased compiler scope is committed here yet. +## 1.0.0-beta.15 + +Release label: `1.0.0-beta.15` + +Release date: 2026-05-22 + +Release state: reserved generic collection boundary hardening and collection ledger + +### Summary + +The beta.15 compiler-side contract hardens the already-reserved +generic-shaped collection boundary without promoting executable generics, +maps, or sets. It keeps diagnostic codes and machine shapes stable while +removing beta.9-specific wording from current reserved diagnostics. + +- Bump the `glagol` compiler package version to `1.0.0-beta.15`. +- Centralize reserved generic and collection diagnostic construction in + `compiler/src/reserved.rs` for lowerer, formatter, and checker paths. +- Reword live compiler diagnostics and affected snapshots to say the surface + is reserved but not supported in the current beta while preserving existing + codes, schema, spans, expected/found values, and hints. +- Add focused `reserved_generic_collection_beta15` coverage for `check`, + `fmt --check`, and project-root `check` rejection of generic functions, + parameterized aliases, generic type parameters, generic vector spelling, + map/set types, and reserved generic stdlib calls `std.vec.empty` and + `std.result.map`. +- Run the focused beta.15 reserved-boundary test in `scripts/release-gate.sh` + before the full compiler test suite. + +### Explicit Deferrals + +This release does not implement executable generics, parameterized alias +expansion, generic vectors, map/set types, generic standard-library dispatch, +runtime collection names, ABI/layout claims, parser semantic expansion, or +current concrete collection behavior changes. + ## 1.0.0-beta.14 Release label: `1.0.0-beta.14` diff --git a/docs/compiler/ROADMAP.md b/docs/compiler/ROADMAP.md index 125e993..c762836 100644 --- a/docs/compiler/ROADMAP.md +++ b/docs/compiler/ROADMAP.md @@ -22,9 +22,9 @@ general-purpose beta release. A Glagol feature is done only when it has parser/lowerer support, checker behavior, diagnostics for invalid forms, backend behavior or explicit unsupported diagnostics, and tests. -Current stage: `1.0.0-beta.14`, released on 2026-05-22 as a benchmark suite -catalog and metadata gate update. It keeps the `1.0.0-beta` -language/compiler support baseline and includes the +Current stage: `1.0.0-beta.15`, released on 2026-05-22 as a reserved generic +collection boundary hardening and collection ledger update. It keeps the +`1.0.0-beta` language/compiler support baseline and includes the `1.0.0-beta.1` tooling hardening release, the `1.0.0-beta.2` runtime/resource foundation release, the `1.0.0-beta.3` standard-library stabilization release, the `1.0.0-beta.4` language-usability diagnostics release, the @@ -61,8 +61,15 @@ suite-level local benchmark listing and release-gate coverage for benchmark directories, timing modes, cold/hot loop counts, checksum metadata, required scaffold-file status, implementation slots, and a local-only timing disclaimer without publishing timing results or claiming a stable JSON schema. +The beta.15 compiler/tooling slice centralizes reserved generic and collection +diagnostics across lowerer, formatter, and checker paths, rewords current +reserved diagnostics to stage-neutral current-beta text, and gates the +collection ledger for generic functions, parameterized aliases, generic type +parameters, generic vector spelling, map/set types, `std.vec.empty`, and +`std.result.map` across check, fmt, and project paths without promoting those +surfaces. -Next stage target: post-`1.0.0-beta.14` developer-experience, package, and +Next stage target: post-`1.0.0-beta.15` developer-experience, package, and collection/generic planning. Generic vectors, generic collections, maps, sets, generic stdlib dispatch, runtime collection changes, collection unification, stable human diagnostic text, stable Markdown schema, LSP/watch protocols, diff --git a/docs/language/COLLECTIONS.md b/docs/language/COLLECTIONS.md new file mode 100644 index 0000000..d6f5903 --- /dev/null +++ b/docs/language/COLLECTIONS.md @@ -0,0 +1,139 @@ +# Slovo Collection Ledger + +Status: beta design ledger for `1.0.0-beta.15`. + +This document inventories the current concrete collection and value-family +surface without redefining the generated public API catalog. Exact exported +helper signatures live in +[`STDLIB_API.md`](STDLIB_API.md), which is generated from `lib/std/*.slo`. +This ledger records design boundaries, pressure, and promotion prerequisites +for future generic collection work. + +`1.0.0-beta.15` is documentation/design and compiler-boundary hardening. It +does not change the source language, typed core, runtime, +standard-library/API surface, diagnostic output shape, diagnostic codes, +diagnostic schema, benchmark metadata schema, ABI/layout behavior, or +performance claims. It does reword current reserved generic/map/set diagnostic +prose from beta.9-specific text to current-beta wording. + +## Catalog Boundary + +[`STDLIB_API.md`](STDLIB_API.md) remains the source of truth for current +exported standard-library helper signatures. It normalizes module-local +concrete aliases such as `VecI32`, `OptionString`, and `ResultU64` to concrete +public types, and omits non-exported helpers and `(type ...)` aliases. + +This ledger intentionally does not duplicate generated module or helper +counts. If an exact signature or count is needed, use the generated catalog. +If this ledger and the catalog drift, the catalog describes the generated API +surface while this file describes the intended design boundary. + +## Current Concrete Surface + +| Surface | Current concrete families | Public catalog reference | Boundary | +| --- | --- | --- | --- | +| Concrete vectors | `(vec i32)`, `(vec i64)`, `(vec f64)`, `(vec bool)`, `(vec string)` | [`std.vec_i32`](STDLIB_API.md#stdvec_i32), [`std.vec_i64`](STDLIB_API.md#stdvec_i64), [`std.vec_f64`](STDLIB_API.md#stdvec_f64), [`std.vec_bool`](STDLIB_API.md#stdvec_bool), [`std.vec_string`](STDLIB_API.md#stdvec_string) | Concrete immutable value-family helpers over the existing vector runtime names. No generic vector dispatch, element-level mutation, slice/view API, iterator API, nested vector family, new runtime helper name, stable helper-symbol contract, or ABI/layout promise is implied. | +| Option value families | `(option i32)`, `(option u32)`, `(option i64)`, `(option u64)`, `(option f64)`, `(option bool)`, `(option string)` | [`std.option`](STDLIB_API.md#stdoption) | Concrete constructors, observers, unwrap/fallback helpers, and option-to-result bridges. No generic option helper, mapping/chaining API, transpose/flatten family, stable API freeze, or payload-family expansion is implied. | +| Result value families | `(result i32 i32)`, `(result u32 i32)`, `(result i64 i32)`, `(result u64 i32)`, `(result f64 i32)`, `(result bool i32)`, `(result string i32)` | [`std.result`](STDLIB_API.md#stdresult) | Concrete `i32` error-code result helpers. No generic result helper, rich error ADT, mapping/chaining API, transpose/flatten family, stable API freeze, or alternate error payload family is implied. | +| Host and parsing result/option flows | Concrete option/result values returned by current host, CLI, file, network, parse, and numeric helpers | [`std.cli`](STDLIB_API.md#stdcli), [`std.env`](STDLIB_API.md#stdenv), [`std.fs`](STDLIB_API.md#stdfs), [`std.io`](STDLIB_API.md#stdio), [`std.net`](STDLIB_API.md#stdnet), [`std.num`](STDLIB_API.md#stdnum), [`std.string`](STDLIB_API.md#stdstring) | These helpers expose the same concrete value families through ordinary source facades. They do not create generic payload types, generic host errors, stable ABI names, or a stable compatibility freeze. | + +Fixed arrays are part of the current language surface, but they are not a +standard-library helper family in the generated API catalog. Future work that +connects arrays to slices, views, iterators, maps, sets, or generic collection +helpers must define its own language, runtime, diagnostic, and documentation +contract. + +## Design Pressure + +The current surface deliberately repeats concrete helper families. That +duplication has been useful because each family could be promoted with narrow +tests and without a generic type system, but it now creates clear pressure: + +- Vector helpers repeat construction, indexing, fallback, search, query, + concatenation, slicing-by-copy, replacement, and removal names across five + concrete element families. +- `std.option` and `std.result` repeat constructor, observer, unwrap, + fallback, and bridge helpers across concrete payload families, including the + unsigned payloads added before beta. +- Helper parity can drift between concrete modules, as shown by the beta12 + vector query and prefix parity release. +- Module-local concrete aliases reduce source repetition inside facades, and + the generated catalog hides those aliases from public signatures, but aliases + do not define generic API compatibility or migration behavior. +- Host and parsing facades spread concrete option/result values through the + broader API surface, so future generic work must account for both dedicated + `std.option`/`std.result` modules and callers that already depend on + concrete return types. + +This pressure is a reason to design generics carefully, not a license to infer +generic behavior from existing concrete helpers. + +## Promotion Prerequisites + +Before any executable generic collection feature is promoted, a release must +define and gate the full contract for that feature. At minimum: + +- Executable generics need source syntax, type-parameter rules, explicit + inference policy, type-checking behavior, formatter layout, typed-core + representation, lowering/monomorphization or dispatch strategy, diagnostic + coverage, public documentation, examples, and migration rules for existing + concrete helpers. +- Generic aliases need a separate alias contract, including parameter syntax, + allowed targets, cycle checks, export/import visibility, formatter behavior, + diagnostics, and the relationship to runtime layout and public API docs. +- Maps and sets need key/value constraints, equality and hashing or ordering + policy, construction and update semantics, iteration order or non-order + policy, error behavior, runtime/resource ownership, diagnostics, and public + API stability rules. +- Iterators need an ownership and lifetime model, exhaustion semantics, + composition rules, interaction with `match` and future loops, diagnostics, + and guarantees about whether iteration is copying, borrowing, or consuming. +- Mutable vectors need element-mutation syntax, aliasing and ownership rules, + capacity/reallocation behavior, interaction with whole-value `var` / `set`, + runtime helper names, trap/error behavior, diagnostics, and layout/ABI + boundaries. +- Slice/view APIs need borrowing or ownership rules, bounds behavior, + invalidation rules when mutation exists, array/vector/string applicability, + formatter behavior, diagnostics, and runtime representation boundaries. +- Any stable stdlib/API claim needs explicit stable and experimental tiers, + compatibility and deprecation policy, migration tests, generated API-doc + behavior, and release-gate coverage. + +Until those prerequisites are satisfied by a specific release, the current +concrete families remain the entire supported collection/value-family surface. + +## Unsupported Boundaries + +Current diagnostics that reject generic aliases, unsupported alias targets, +unsupported collection forms, unsupported vector element types, maps, sets, +iterators, slice/view APIs, mutable element operations, or broader +option/result payload shapes are boundary diagnostics. They document where the +current beta stops. + +`1.0.0-beta.15` does not add, remove, rename, or reclassify diagnostic codes. +It does not change the `slovo.diagnostic` schema, JSON/S-expression output +shape, spans, expected/found values, hints, or human-readable diagnostic prose +policy. The only diagnostic-fixture change in this release is reserved-boundary +message text that no longer names beta.9 as the unsupported stage. Future +releases that change diagnostics for collection boundaries must do so through +the diagnostic policy in [`DIAGNOSTICS.md`](DIAGNOSTICS.md) and their own +release gates. + +## Explicit Non-Changes + +This ledger does not promote: + +- executable generics +- generic aliases or parameterized aliases +- generic stdlib dispatch +- maps or sets +- iterator APIs +- mutable vector APIs +- slice/view APIs +- new runtime names or helper symbols +- stdlib/API additions, removals, or renames +- diagnostic output shape, code, schema, span, expected/found, or hint changes +- benchmark metadata schema changes +- ABI/layout guarantees +- performance claims or thresholds +- a stable `1.0.0` stdlib/API freeze diff --git a/docs/language/RELEASE_NOTES.md b/docs/language/RELEASE_NOTES.md index f8279be..4b02f76 100644 --- a/docs/language/RELEASE_NOTES.md +++ b/docs/language/RELEASE_NOTES.md @@ -8,7 +8,7 @@ Historical `exp-*` releases listed here are experimental maturity milestones. The pushed tag `v2.0.0-beta.1` is historical. It is now documented as an experimental integration/readiness release, not as a beta maturity claim. -The current release is `1.0.0-beta.14`, published on 2026-05-22. It keeps the +The current release is `1.0.0-beta.15`, published on 2026-05-22. It keeps the `1.0.0-beta` language surface, includes the first post-beta tooling/install hardening bundle from `1.0.0-beta.1`, and adds the first runtime/resource foundation bundle from `1.0.0-beta.2` plus the first standard-library @@ -24,12 +24,51 @@ collection alias unification and generic reservation slice from `1.0.0-beta.11`, plus the concrete vector query and prefix parity slice from `1.0.0-beta.12`, and the diagnostic catalog and schema policy slice from `1.0.0-beta.13`, plus the benchmark suite catalog and metadata gate from -`1.0.0-beta.14`. +`1.0.0-beta.14`, plus the reserved generic collection boundary hardening and +collection ledger from `1.0.0-beta.15`. ## Unreleased No unreleased language scope is committed here yet. +## 1.0.0-beta.15 + +Release label: `1.0.0-beta.15` + +Release name: Reserved Generic Collection Boundary Hardening And Collection Ledger + +Release date: 2026-05-22 + +Status: released beta docs/design ledger and compiler-boundary hardening +update on the `1.0.0-beta` language baseline. + +`1.0.0-beta.15` documents the current concrete collection and value-family +boundary without changing executable behavior: + +- Adds [`COLLECTIONS.md`](COLLECTIONS.md) as the collection/value-family + ledger. +- Links to the generated [`STDLIB_API.md`](STDLIB_API.md) catalog for exact + public helper signatures instead of duplicating generated helper counts. +- Inventories the current concrete vector, option, result, and related + option/result-returning facade surfaces. +- Records design pressure from duplicated concrete vector, option, and result + helper families. +- Defines prerequisites before executable generics, generic aliases, maps, + sets, iterators, mutable vectors, or slice/view APIs can be promoted. +- Documents current unsupported diagnostics as boundaries, not behavior + changes. +- Centralizes reserved generic/map/set diagnostics and rewords affected + reserved-boundary messages from beta.9-specific text to current-beta wording + while preserving diagnostic codes, schema, spans, expected/found values, + hints, and output shape. + +This release does not change the source language, typed core, runtime, +stdlib/API surface, diagnostic output shape, diagnostic codes, diagnostic +schema, benchmark metadata schema, compiler-known runtime names, ABI/layout +behavior, optimizer behavior, or performance claims. It does not add +executable generics, generic aliases, maps, sets, iterators, mutable vectors, +slice/view APIs, new runtime names, or a stable stdlib/API freeze. + ## 1.0.0-beta.14 Release label: `1.0.0-beta.14` diff --git a/docs/language/ROADMAP.md b/docs/language/ROADMAP.md index e9bf9db..d1821c3 100644 --- a/docs/language/ROADMAP.md +++ b/docs/language/ROADMAP.md @@ -10,10 +10,11 @@ Long-horizon planning lives in release train from the historical `v2.0.0-beta.1` tag toward and beyond the first real general-purpose beta Slovo contract. -Current stage: `1.0.0-beta.14`, released on 2026-05-22 as a post-beta -benchmark suite catalog and metadata gate. It keeps the `1.0.0-beta` language -contract and includes the `1.0.0-beta.1` tooling hardening release, the -`1.0.0-beta.2` runtime/resource foundation release, the `1.0.0-beta.3` +Current stage: `1.0.0-beta.15`, released on 2026-05-22 as a post-beta +reserved generic collection boundary hardening and collection ledger. It keeps +the `1.0.0-beta` language contract and includes the `1.0.0-beta.1` tooling +hardening release, the `1.0.0-beta.2` runtime/resource foundation release, +the `1.0.0-beta.3` standard-library stabilization release, the `1.0.0-beta.4` language-usability diagnostics release, the `1.0.0-beta.5` package/workspace discipline release, and a narrow `std.net` source facade for blocking loopback @@ -38,18 +39,30 @@ the beta-scoped benchmark suite catalog documenting the current suite inventory, `python3 benchmarks/runner.py --suite-list`, and `python3 benchmarks/runner.py --suite-list --json`. Benchmark timings remain local-machine evidence only, and suite-list JSON is beta tooling metadata -rather than a stable public schema. JSON parsing, recursive JSON values, -executable generics, generic aliases, parameterized aliases, cross-module alias -visibility, maps/sets, traits, inference, monomorphization, iterators, runtime -changes for generic collections, DNS, TLS, UDP, async IO, non-loopback binding, -HTTP frameworks, rich host-error ADTs, stable ABI/layout, stable Markdown -schema, stable stdlib/API compatibility freeze, LSP/watch, SARIF/daemon -protocols, stable `1.0.0` diagnostics freeze, re-exports/globs/hierarchical -modules, mutable vectors, slice/view APIs, new runtime names, timing -publication, performance claims, stable benchmark JSON schema, and package -registry semantics remain deferred. +rather than a stable public schema. The current stage also adds +[`COLLECTIONS.md`](COLLECTIONS.md) as the collection/value-family ledger. It +links to the generated [`STDLIB_API.md`](STDLIB_API.md) catalog for exact +signatures, records design pressure from duplicated concrete +vector/option/result families, defines prerequisites for future executable +generics, generic aliases, maps, sets, iterators, mutable vectors, and +slice/view APIs, and treats current unsupported diagnostics as boundaries +rather than behavior changes. It also rewords affected reserved-boundary +diagnostic messages away from beta.9-specific text while preserving diagnostic +codes, schema, spans, expected/found values, hints, and output shape. +`1.0.0-beta.15` changes no source language, runtime, stdlib/API surface, +diagnostic output shape/codes/schema, benchmark metadata schema, ABI/layout +behavior, or performance claim. JSON parsing, +recursive JSON values, executable generics, generic aliases, parameterized +aliases, cross-module alias visibility, maps/sets, traits, inference, +monomorphization, iterators, runtime changes for generic collections, DNS, +TLS, UDP, async IO, non-loopback binding, HTTP frameworks, rich host-error +ADTs, stable ABI/layout, stable Markdown schema, stable stdlib/API +compatibility freeze, LSP/watch, SARIF/daemon protocols, stable `1.0.0` +diagnostics freeze, re-exports/globs/hierarchical modules, mutable vectors, +slice/view APIs, new runtime names, timing publication, performance claims, +stable benchmark JSON schema, and package registry semantics remain deferred. -Next stage target: continue after `1.0.0-beta.14` from developer-experience, +Next stage target: continue after `1.0.0-beta.15` from developer-experience, package, benchmark metadata, and reserved generic/map/set planning without claiming executable generics, an LSP/watch protocol, SARIF/daemon protocol, stable Markdown schema, registry semantics, stable benchmark JSON schema, diff --git a/docs/language/SPEC-v1.md b/docs/language/SPEC-v1.md index e39ed5e..f8ff028 100644 --- a/docs/language/SPEC-v1.md +++ b/docs/language/SPEC-v1.md @@ -6,7 +6,9 @@ foundation update, `1.0.0-beta.10` developer-experience API discovery update, `1.0.0-beta.11` local package API documentation update, and `1.0.0-beta.12` concrete vector query and prefix parity update, and `1.0.0-beta.13` diagnostic catalog and schema policy update, and `1.0.0-beta.14` benchmark -suite catalog and metadata gate. The language contract integrates +suite catalog and metadata gate, and `1.0.0-beta.15` reserved generic +collection boundary hardening and collection ledger. The language contract +integrates promoted language slices through `exp-125` and the historical publication baseline through `exp-123`. `1.0.0-beta` is the first real general-purpose beta release. `exp-125` completed the unsigned numeric and stdlib breadth @@ -168,6 +170,20 @@ Current v1 release surface and explicit experimental targets: benchmark kernels, timing publication, performance thresholds, source-language/runtime/stdlib/API changes, diagnostic-output changes, or ABI/layout changes +- `1.0.0-beta.15` reserved generic collection boundary hardening target: + [`COLLECTIONS.md`](COLLECTIONS.md) documents the current concrete collection + and value-family boundary by linking to the generated + [`STDLIB_API.md`](STDLIB_API.md) catalog for exact helper signatures, + recording design pressure from duplicated concrete vector/option/result + families, defining promotion prerequisites for executable generics, generic + aliases, maps, sets, iterators, mutable vectors, and slice/view APIs, and + treating current unsupported diagnostics as boundaries; this is docs/design + and compiler-boundary hardening only, not a source-language, runtime, + stdlib/API, diagnostic output shape, diagnostic code, diagnostic schema, + diagnostic span, expected/found value, hint, benchmark metadata schema, + ABI/layout, performance-claim, or stable stdlib/API change; affected + reserved-boundary messages are reworded from beta.9-specific text to + current-beta wording - `exp-1` owned runtime strings: compiler-known `std.string.concat` accepts two `string` values and returns an immutable runtime-owned `string`; existing string equality, length, printing, locals, parameters, returns, and calls work @@ -1423,6 +1439,39 @@ slots, timing publication, performance thresholds, cross-machine performance claims, a stable benchmark JSON schema, source-language/runtime/stdlib/API changes, diagnostic-output changes, or ABI/layout guarantees. +### 4.4.12 Post-Beta Reserved Generic Collection Boundary Hardening And Collection Ledger + +Status: released in `1.0.0-beta.15` as a docs/design ledger and +compiler-boundary hardening update for the existing concrete collection and +value-family surface. + +`1.0.0-beta.15` adds +[`docs/language/COLLECTIONS.md`](COLLECTIONS.md) as the public collection +ledger. The ledger links to the generated +[`docs/language/STDLIB_API.md`](STDLIB_API.md) catalog for exact exported +standard-library helper signatures instead of duplicating generated counts. + +The ledger inventories the current concrete vector, option, result, and +related option/result-returning facade surfaces. It records design pressure +from duplicated concrete vector/option/result helper families and defines +prerequisites before executable generics, generic aliases, maps, sets, +iterators, mutable vectors, or slice/view APIs can be promoted. + +Current unsupported diagnostics are documented as boundaries of the existing +beta surface. This target does not add, remove, rename, or reclassify +diagnostic codes and does not change the `slovo.diagnostic` schema, +diagnostic output shape, golden fixture shape, or human-readable diagnostic +prose policy. It does intentionally reword affected reserved-boundary messages +from beta.9-specific text to current-beta wording while preserving diagnostic +codes, schema, spans, expected/found values, hints, and output shape. + +The source language, typed core, runtime, standard library, public API surface, +benchmark metadata schema, compiler-known runtime names, ABI/layout behavior, +optimizer contract, and performance claims are unchanged by this target. This +target explicitly does not add executable generics, generic aliases, +parameterized aliases, maps, sets, generic stdlib dispatch, iterators, mutable +vectors, slice/view APIs, new runtime names, or a stable stdlib/API freeze. + ## 4.5 v2.0.0-beta.1 Experimental Integration Readiness Status: current experimental Slovo-side release contract, released 2026-05-17. diff --git a/docs/language/STDLIB_API.md b/docs/language/STDLIB_API.md index a829356..4c1824b 100644 --- a/docs/language/STDLIB_API.md +++ b/docs/language/STDLIB_API.md @@ -6,7 +6,7 @@ Do not edit this file by hand. ## Stability Tiers - `beta-supported`: exported from `lib/std` and covered by source-search, promotion, or facade gates in the current beta line. -- `experimental`: not used for exported `lib/std` helpers in `1.0.0-beta.14`; future releases may mark new helpers this way before they graduate. +- `experimental`: not used for exported `lib/std` helpers in `1.0.0-beta.15`; future releases may mark new helpers this way before they graduate. - `internal`: helper names that are not exported from their module; they are intentionally omitted from this catalog. The catalog is a beta API discovery aid, not a stable `1.0.0` standard-library freeze. diff --git a/scripts/release-gate.sh b/scripts/release-gate.sh index cde4909..d38ad71 100755 --- a/scripts/release-gate.sh +++ b/scripts/release-gate.sh @@ -65,6 +65,7 @@ cd "${compiler_dir}" cargo fmt --check cargo test --test diagnostics_schema_beta13 cargo test --test benchmark_suite_catalog_beta14 +cargo test --test reserved_generic_collection_beta15 # Full cargo test includes unignored integration gates such as dx_v1_7, # beta_v2_0_0_beta_1, and beta_1_0_0. cargo test diff --git a/tests/std-result-map-unsupported.diag b/tests/std-result-map-unsupported.diag index 179efe5..b2463bc 100644 --- a/tests/std-result-map-unsupported.diag +++ b/tests/std-result-map-unsupported.diag @@ -3,7 +3,7 @@ (version 1) (severity error) (code UnsupportedGenericStandardLibraryCall) - (message "generic standard-library call `std.result.map` is reserved but not supported in beta.9") + (message "generic standard-library call `std.result.map` is reserved but not supported in the current beta") (file "") (span (bytes 38 52) diff --git a/tests/std-vec-empty-generic-unsupported.diag b/tests/std-vec-empty-generic-unsupported.diag index 7b9812a..76de9b0 100644 --- a/tests/std-vec-empty-generic-unsupported.diag +++ b/tests/std-vec-empty-generic-unsupported.diag @@ -3,7 +3,7 @@ (version 1) (severity error) (code UnsupportedGenericStandardLibraryCall) - (message "generic standard-library call `std.vec.empty` is reserved but not supported in beta.9") + (message "generic standard-library call `std.vec.empty` is reserved but not supported in the current beta") (file "") (span (bytes 38 51) diff --git a/tests/unsupported-generic-function.diag b/tests/unsupported-generic-function.diag index 7401330..5bd2af4 100644 --- a/tests/unsupported-generic-function.diag +++ b/tests/unsupported-generic-function.diag @@ -3,7 +3,7 @@ (version 1) (severity error) (code UnsupportedGenericFunction) - (message "generic function declarations are reserved but not supported in beta.9") + (message "generic function declarations are reserved but not supported in the current beta") (file "") (span (bytes 23 38) diff --git a/tests/unsupported-generic-type-alias.diag b/tests/unsupported-generic-type-alias.diag index 03c4b2e..ee56470 100644 --- a/tests/unsupported-generic-type-alias.diag +++ b/tests/unsupported-generic-type-alias.diag @@ -3,7 +3,7 @@ (version 1) (severity error) (code UnsupportedGenericTypeAlias) - (message "parameterized type aliases are reserved but not supported in beta.9") + (message "parameterized type aliases are reserved but not supported in the current beta") (file "") (span (bytes 28 43) diff --git a/tests/unsupported-generic-type-parameter.diag b/tests/unsupported-generic-type-parameter.diag index c607a33..c95bace 100644 --- a/tests/unsupported-generic-type-parameter.diag +++ b/tests/unsupported-generic-type-parameter.diag @@ -3,7 +3,7 @@ (version 1) (severity error) (code UnsupportedGenericTypeParameter) - (message "generic type parameter `T` is reserved but not supported in beta.9") + (message "generic type parameter `T` is reserved but not supported in the current beta") (file "") (span (bytes 42 44) diff --git a/tests/unsupported-generic-vec-type.diag b/tests/unsupported-generic-vec-type.diag index d0b810a..05207ff 100644 --- a/tests/unsupported-generic-vec-type.diag +++ b/tests/unsupported-generic-vec-type.diag @@ -3,7 +3,7 @@ (version 1) (severity error) (code UnsupportedGenericTypeParameter) - (message "generic vector syntax is reserved but not supported in beta.9") + (message "generic vector syntax is reserved but not supported in the current beta") (file "") (span (bytes 31 36) diff --git a/tests/unsupported-map-type.diag b/tests/unsupported-map-type.diag index ee8661d..4537d71 100644 --- a/tests/unsupported-map-type.diag +++ b/tests/unsupported-map-type.diag @@ -3,7 +3,7 @@ (version 1) (severity error) (code UnsupportedMapType) - (message "`map` types are reserved but not supported in beta.9") + (message "`map` types are reserved but not supported in the current beta") (file "") (span (bytes 31 47) diff --git a/tests/unsupported-set-type.diag b/tests/unsupported-set-type.diag index ec68a3f..625367f 100644 --- a/tests/unsupported-set-type.diag +++ b/tests/unsupported-set-type.diag @@ -3,7 +3,7 @@ (version 1) (severity error) (code UnsupportedSetType) - (message "`set` types are reserved but not supported in beta.9") + (message "`set` types are reserved but not supported in the current beta") (file "") (span (bytes 31 43)