V1 Scope Review¶
Review of the V1 design (current-scope.md and the topic pages it links) for the goal of handing the design to a compiler implementer. Focus: conflicts to resolve before implementation, missing or ambiguous compiler-facing specs, and deliberate scope choices that should be reaffirmed before V1 compiler work starts.
Overall, the design is broad, coherent, and unusually well cross-linked. The remaining handoff risk is not that the language lacks direction; it is that a few accepted areas still require implementers to invent parser, type-checker, comptime, lowering, runtime-support, or public-reflection details. The list below is the definitive issue list to address before treating V1 as implementation-ready.
Blocking Issues¶
Resolve these before handing the design to a compiler implementer.
1. Integer arithmetic result typing contradicts examples and leaves literal operands underspecified¶
Status: resolved.
Resolution: V1 primitive integer arithmetic resolves to one of the existing operand types. Same-type operands preserve their type. Mixed concrete integer operands are accepted only when one operand type can represent every value of the other; the result is that existing wider operand type. If neither operand type represents the other, operator syntax is rejected. comptime_int operands are contextualized to the concrete primitive operand type before primitive conformance matching when representable; pure comptime_int arithmetic remains comptime-only within the V1 bounded exact range. Division is truncating integer division and % is remainder; Euclidean division and modulo helpers are deferred to std.math under CEP-0054.
2. Bare range endpoint inference contradicts the no-default-integer rule¶
Status: resolved.
Resolution: V1 keeps no global default integer literal type. Range endpoint inference first uses ordinary endpoint, item, range, or slicing context. If both endpoint expressions remain unresolved comptime_int values, the range falls back to the smallest primitive integer type that can represent both stored endpoint values. Non-negative fallback endpoints choose uN; any negative endpoint chooses iN. Concrete typed endpoints keep type-range semantics, and expected range/item context may request a wider type through ordinary coercion. Fallback inference is valid but lintable as ranges/inferred-narrow-endpoints, with diagnostics suggesting an explicit range or loop item type.
3. Newline-significant grammar has no continuation model¶
Status: resolved.
Resolution: Newline significance is parser-contextual. The lexer preserves newlines but does not classify braces or synthesize semicolons. In statement-list contexts, newline and ; separate statements only where the parser can accept statement end; otherwise newline is ordinary whitespace inside the current grammar construct. Comma-separated lists still require commas. V1 uses a Go-like same-line rule for trailing continuation keywords such as else and catch when the preceding expression could otherwise end at the newline. Kotlin-style newline-permissive trailing continuations are deferred to CEP-0060.
4. Expression-bodied arrow function grammar is not formally specified¶
Status: resolved.
Resolution: => expression is a general function body form for ordinary functions, methods, and comptime fn declarations. The signature before => is the same signature shape used by block-bodied functions, including ordinary success inference and T! error-set inference. An arrow body is checked as a one-expression function body that produces its result through normal final-expression completion, not by inserting a hidden return. The arrow body accepts any expression, including block expressions and diverging expressions such as return expr; redundant arrow-block and arrow-return forms are lintable style findings.
5. Allocation-backed V1 features have no concrete V1 allocator source¶
Status: resolved.
Resolution: V1 accepts std.mem.FixedBufferAllocator as the only public concrete allocator implementation. It borrows caller-provided mutable byte storage, allocates monotonically from that buffer, returns AllocError.OutOfMemory when exhausted, and may treat valid deallocate calls as no-op with no storage-reuse guarantee. This gives runnable examples and dynamic-dispatch tests an allocator source for Box, box, box_dyn, Box(dyn C).create_from_dyn, iter_dyn, and iter_dyn_mut without accepting OS heap allocation, erased allocator adapters, reusable free lists, reset APIs, testing allocators, or a broader allocator catalog. Other allocator families remain deferred to CEP-0047, and leak-reporting test allocators remain deferred to CEP-0059.
6. Comptime bootstrapping and compiler-object evaluation are underspecified¶
Status: resolved.
Resolution: V1 defines the compiler-facing seam in Comptime Bootstrapping and Compiler Objects. Comptime still uses one evaluator: demanded units lower through SIR and IR and run on the shared IR interpreter. Compiler-owned values such as Type, Namespace, Scope, Type.Predicate, reflection metadata, attribute targets, and dynamic metadata are opaque comptime handles backed by compiler-owned identities. Operations that need compiler tables, visibility, semantic identity, target facts, diagnostics, source loading, or phase-owned mutation are public context-gated compiler intrinsics; ordinary helper code on top remains interpreted IR. Prelude bootstrap uses lazy top-level analysis from a seeded initial scope, primitive factories take comptime_int, and cross-run incremental comptime-cache invalidation is deferred to CEP-0061.
7. SIR, IR, and lowering schemas are accepted only at a high level¶
Status: resolved.
Resolution: SIR, IR, and Lowering defines the V1 schema obligations and representative lowering recipes without freezing final opcode names or dump syntax. SIR owns resolved semantic evidence, cleanup obligations, function items, fallible expression semantics, attribute-produced target metadata, ABI facts, and rich source spans. IR owns backend-neutral executable categories, explicit checks/traps, result operations, slice descriptors, dynamic descriptors/calls, concrete ABI facts, and ordinary cleanup control flow. Box remains prelude source; SIR/IR carry the general allocation, opaque-pointer, dynamic metadata, descriptor, and cleanup primitives needed to implement it. Backends consume verified IR only and never redo method lookup, conformance lookup, dyn-safety checks, attribute evaluation, ABI validation, or source-level cleanup inference.
8. @repr, @align, and layout reflection need exact V1 layout semantics¶
Status: resolved.
Resolution: V1 accepts only .catalyst representation. @repr(.catalyst) is valid but redundant, and T.repr() can only return .catalyst in V1. @repr(.c) and @repr(.packed) are rejected rather than accepted as provenance-only metadata; future representation modes, packed layout, std.c aliases, C layout profiles, and compound C ABI expansion are deferred to CEP-0063. Layout Reflection now defines deterministic source-order .catalyst struct layout, exact @align behavior, zero-sized field and array handling, target maximum object alignment rejection, and reflection output rules.
9. Public reflection metadata names are frozen¶
Status: resolved.
Resolution: V1 freezes the documented public reflection metadata names. Conformance Reflection now treats T.implements, T.conformance, Type.Conformance, Type.ConformanceOperation, lookup errors, candidates, and related enum/field names as public V1 reflection surface. Semantic Contracts now freezes ContractSurface.current(), is_static, is_dyn, contract, implementer, scope, and contract helper names such as is_contract, contract_required_functions, contract_default_functions, and contract_dependencies. The remaining reflection pages already expose their listed Type.* metadata names as public V1 APIs unless a page explicitly states an implementation-private boundary.
10. catch binding versus parenthesized fallback needs parser disambiguation¶
Status: resolved.
Resolution: V1 uses catch as name { ... } for binding the caught error and keeps catch fallback / catch { ... } as unbound fallback forms. Without as, the parser treats the following source as a normal fallback expression, so catch (err) is a parenthesized fallback expression and never a catch binding. The old catch (err) { ... } binding form is rejected with diagnostics that suggest catch as err { ... }. Bound catch without braces, including catch as err => expr, is rejected in V1. Pattern catch arms remain deferred; future pattern matching may add a catch switch form under CEP-0002.
Scope Pressure To Reaffirm¶
These are not contradictions by themselves. They are deliberate V1 scope decisions that materially affect compiler complexity and should be reaffirmed before implementation starts.
11. Arbitrary-width integers amplify arithmetic and backend complexity¶
Status: reaffirmed.
Resolution: V1 keeps every i1..i128 and u1..u128 as valid primitive type identities, including non-power-of-two widths. Signed integers are two's-complement, and i1 is valid with values -1 and 0. Standard runtime widths are always supported, while non-standard runtime widths such as u1, i1, u7, i13, or u65 are target/backend-gated. The C backend should lower them through C23 _BitInt(N) / unsigned _BitInt(N) when available and otherwise emit a target-support error; V1 does not require portable helper-struct lowering for arbitrary widths.
12. Contract and dynamic dispatch are the V1 implementation cost center¶
Status: reaffirmed.
The contract model is coherent, but V1 includes a large amount of advanced machinery: static constraint parameters, anonymous *impl parameters, operation guards, ContractSurface.current().is_static()/is_dyn(), default-method dynamic wrappers, dyn-safety after guard evaluation, intersection vtables, opaque static returns, Box(dyn C), into_dyn, upcast, boxed iterator forwarding, and dynamic iterator construction.
Resolution: V1 scope is complete and keeps the full accepted contract and dynamic-dispatch surface. The design should not reconsider or split this surface during compiler handoff. Implementation should still be staged through many vertical slices that begin with a tiny non-contract language subset and only reach contracts after primitives, functions, structs, arrays/slices, control flow, errors, modules/comptime, and concrete allocation are independently testable. Contract work should then stage from contract/impl parsing through static dispatch before borrowed dyn, owned Box(dyn C), upcasts, boxed iterator forwarding, and dynamic iteration.
Valid But Not Handoff Blockers¶
These review notes are valid but should not block compiler handoff once the blocking items above are resolved.
not a == bparses as(not a) == bunder current precedence. This is specified in Operators. Add examples or lints if desired, but it is not ambiguous.- Destructuring rename uses
local = field, and_ = fieldignores a named field. This is unusual but specified in Destructuring. Good diagnostics can handle the unfamiliar direction. - Enum cases and error cases use different naming conventions. This is a style asymmetry, not a source-semantics blocker.
- Pattern Matching is open/deferred but still appears in the language reference index. That could be labeled more clearly as deferred, but V1 rejection behavior is explicit.
Bottom Line¶
The listed pre-handoff blockers are resolved in the active design docs.
All listed blockers and scope-pressure points are resolved or reaffirmed. The remaining work is implementation staging, not V1 scope reconsideration.