Core-0normative target; implementation partial

The object model, type system, dispatch, generics, and numerics.

Core-0 Objects, Types, and Messages

Status: normative

Objects and visibility

C0-OBJ-001 — Object forms. Every runtime value participates in the message model. A value is sealed, inline/value-semantic, and statically dispatched. A class is a stable heap object whose bare type is its unique owning handle.

C0-OBJ-002 — Explicit openness. Classes and class messages are sealed by default. open permits one concrete base chain and override dispatch. An override must say override, preserves its inherited dispatch contract, and is sealed again unless it also says open.

C0-OBJ-003 — Explicit visibility. Every declaration and member writes one of public, module, or private. Fields are accessed explicitly through a receiver; there are no implicit properties, protected visibility, hidden friend access, or lookup-based visibility exceptions.

Types and evaluation

C0-TYPE-001 — Nominal equality. User values, classes, enums, and errors are nominal. Generic constructors are invariant. The explicit projection from a derived class handle or borrow to its base is the only Core-0 subtype relation.

C0-TYPE-002 — No implicit conversion. Core-0 has no null, truthiness, numeric widening, structural record conversion, user-defined conversion, or ambient coercion. Permitted contextual operations are literal fitting, bounded reborrowing, class-base projection, and checked generic substitution.

C0-TYPE-003 — Core types. The compiler supplies the scalar, Never, Unit, Text, Bytes, Option, Result, InitError, collection, ownership, allocator, class-descriptor, and root-object types enumerated by the semantic reference. Index is target-sized and forbidden in a portable public .zli signature.

C0-TYPE-004 — Evaluation order. Operands and arguments evaluate left to right. && and || short-circuit. Assignment produces a replacement before dropping and storing over the old initialized place; failed production leaves the old place initialized.

C0-TYPE-005 — Closed variants. Enums and errors are closed nominal variants. match is exhaustive, rejects duplicate or unreachable arms, and preserves ownership of observed borrows while consuming selected payloads from owned non-Copy scrutinees.

C0-TYPE-006 — Explicit variant construction. A closed enum or error value is constructed as Type.Variant(arguments...), where Type resolves to the nominal enum/error descriptor and Variant resolves to exactly one declared variant. Arguments correspond positionally and exactly to the variant payload; a fieldless variant is written with an explicit empty (). This form is a statically checked construction operation rather than an ordinary message lookup, evaluates payload arguments left to right, and performs no allocation or implicit conversion.

C0-TYPE-007 — Structural Copy for closed carriers. A closed enum or error instance is Copy if and only if every payload of every variant is Copy; a fieldless declaration is therefore Copy. The compiler-provided Option, Result, and InitError carriers use the same structural rule over all of their payload type arguments. Matching a named owned non-Copy carrier requires move(name), while a fresh temporary transfers directly. An owned arm binding copies a Copy payload and moves a non-Copy payload. When matching Ref<C> or Mut<C>, a Copy payload is copied and a non-Copy payload binds as an arm-scoped Ref<T>; matching never creates an implicit Mut<T>.

C0-TYPE-008 — Finite inline variant layout. Every closed variant instance has a finite, statically known inline layout. A cycle containing only inline owned-payload edges is invalid; recursive data must break each such cycle with an explicit indirection such as a class handle, Box, or Shared. Layout, payload-count, and size calculations use checked arithmetic and must fail with a diagnostic when they exceed the portable implementation bounds.

The bounded Stage0 sealed-value profile for ZLM1 schema 1.8 admits one nominal, sealed, nongeneric value declaration with exactly one public let field. The field has one exact scalar type of at most 32 bits from the set fixed by C0-ART-003. The value declares exactly one public initializer, which must return exactly Result<Self, E> with an empty or explicitly declared effect set and with E inside the bounded Result payload set.

The expression Self { field: value } is valid only inside the declaring value initializer. It names the sole field exactly once, type-checks its expression against the exact declared scalar, and produces a fresh temporary only after the field is initialized. Self cannot otherwise escape the initializer. A missing, repeated, differently named, or differently typed field is rejected. The user value remains non-Copy; a named owner requires move, while a fresh constructed temporary transfers directly.

This is an implementation restriction, not structural record compatibility. Other Core-0 value shapes remain reserved for a later schema/profile. Stage0 must reject a value outside this boundary before checked-module emission and cannot reinterpret it as a scalar alias, class, enum, backend struct, or fieldless value.

The schema-1.9 selfhost byte-kernel profile is the next specified restriction, but is not yet emitted. It admits multiple declarations and multiple fields, including private mutable implementation fields, only under the exact zerglang.selfhost-intrinsics/1 catalog. Field order is source order and every field retains an exact type-instance identity and independent move path. This is nominal aggregate semantics, never structural record compatibility or a host C layout.

For that profile, Unit.value() produces the sole zero-size Unit value and Never is uninhabited. Unit and Never are Copy; Never never occupies a place or payload. Catalog selectors admit receiver kinds Ref, Mut, owned Self, and Class<Self> with the exact ownership stated by their signatures. A type receiver on a catalog construction selector may name a value descriptor; it does not imply class allocation or runtime dispatch.

Result<T, E>, Array<Byte>, Slice<Byte>, Ref<T>, Mut<T>, and Allocator<BytesError> are compiler-known concrete type instances for this profile. Their canonical instance records are fixed by schema 1.9. This admission does not admit user-defined generics, source specialization, generic inference, or arbitrary Array<T>/Slice<T> instances in the first byte kernel.

Messages and generics

C0-MSG-001 — Explicit domain and receiver. Every executable message says algorithm and declares self: Ref<Self>, self: Mut<Self>, self: Self, or type: Class<Self> as its receiver. There are no free functions or implicit receivers.

C0-MSG-002 — Singular lookup. A send resolves from the statically known receiver and one selector. Core-0 has no overload search, argument-dependent lookup, extension search, or alternate named spelling for an operator.

C0-MSG-003 — Dispatch identity. A named selector includes its name and non-receiver parameter labels. An operator selector includes token and arity. Receiver ownership, domain, parameters, result, closed error carrier, generic requirements, effects, and contracts form the dispatch contract.

C0-MSG-004 — Override compatibility. An override preserves the dispatch contract, may narrow its effect set, cannot strengthen caller preconditions, and cannot weaken inherited postconditions.

C0-GEN-001 — Structural requirements. Compile-time polymorphism uses generic parameters constrained by required message signatures. It does not introduce a nominal interface/protocol hierarchy or arbitrary compile-time evaluation.

C0-GEN-002 — Checked specialization. Each concrete generic instance has a canonical identity including declaration, substitutions, requirements, numeric preset, and edition. Required messages are resolved before typed IR is emitted; failure produces a requirement tree in diagnostics.

Numeric semantics

C0-NUM-001 — Independent preset. Every checked package selects exactly one of exact, modular, or approximate. The preset is independent of verification and materialization modes and is recorded at every artifact and call boundary where compatibility matters.

C0-NUM-002 — Integer safety. exact traps on overflow, underflow, invalid shift, division by zero, and signed-minimum divided by negative one. modular wraps addition, subtraction, multiplication, and negation at the declared width, but retains the exceptional division and shift faults.

C0-NUM-003 — Approximation boundary. approximate never relaxes type, memory, bounds, ownership, or integer safety. Floating reassociation, contraction, vectorization, or approximation is legal only when a reflected error/tolerance contract grants that freedom.

Projected fromspec/editions/core-0/objects-types-and-messages.md