refine distinct construction semantics

This commit is contained in:
2026-08-02 19:13:13 +02:00
parent b9526b5f06
commit f25f76adff
5 changed files with 88 additions and 36 deletions
+11 -8
View File
@@ -38,7 +38,7 @@ roadmap and milestone history.
- UTF-8 string literals as immutable pointers to static zero-terminated byte arrays, plus raw backtick multiline strings
- narrow immutable zero-terminated byte pointer/slice conversion to `*c_char` / `?*c_char` without general `u8`/`c_char` interchange
- optionals with `null`, `orelse`, postfix `?`, conditional unwraps, guarded unwraps, and left-to-right short-circuiting multi-unwraps
- nominal distinct types with exact backing construction and explicit scalar backing extraction, native enums with optional explicit integer backing and explicit backing-to-scalar casts, contextual enum literals, and imported C enums as target-backed integer aliases
- nominal distinct types with explicit scalar backing conversion during construction and explicit scalar backing extraction, native enums with optional explicit integer backing and explicit backing-to-scalar casts, contextual enum literals, and imported C enums as target-backed integer aliases
- source-order native structs, opaque nominal records with `Name :: opaque`, complete `c_struct { ... }`, keyed record literals, native untagged unions, and native tagged unions `union(Enum)` / `union(enum)`
- named native struct fields may declare defaults with `field T = expression`; keyed literals use defaults for omitted fields and explicit initializers override them
- void-payload tagged-union variants, anonymous struct payloads, contextual `.variant`, `.variant{payload}`, and `.variant{field = value}` construction
@@ -47,17 +47,20 @@ roadmap and milestone history.
#### distinct types
`Name :: distinct T` creates a nominal identity and reuses `T`'s runtime representation.
Construction accepts exactly one value of the immediate backing type. There is no implicit
conversion in either direction, and separate distinct declarations never mix. An explicit scalar
cast extracts exactly one layer: `u32(id)` works for `UserID :: distinct u32`, while nested
distinct values must be peeled one declared layer at a time.
`Name :: distinct T` creates a nominal identity and reuses `T`'s runtime representation. When
`T` is a concrete numeric scalar, construction first applies the corresponding explicit scalar
cast, so `UserID(index)` is sufficient for `UserID :: distinct u32` even when `index` is `usize`.
There is still no implicit conversion in either direction. Construction with a non-scalar or
distinct immediate backing requires that exact backing type. An explicit scalar cast extracts one
layer: `u32(id)` works for `UserID`, while nested distinct values must be peeled one declared layer
at a time.
Scalar-backed distinct values support the operations of their representation while preserving the
nominal result type: checked integer `+`, `-`, `*`, unary `-`, bitwise operators, shifts,
comparisons, and compound assignments; float arithmetic, unary `-`, comparisons, and compound
assignments; and boolean equality/inequality. Integer literals and float literals are contextual,
but typed backing values remain barred. Distinct integers also work as indices and slice bounds;
assignments; and boolean equality/inequality. Integer literals and float literals are contextual.
Typed backing values and separate distinct identities remain incompatible in ordinary operations;
an explicit constructor is required to cross that boundary. Distinct integers also work as indices and slice bounds;
`minval!` / `maxval!` return the distinct type. Runtime and comptime behavior match.
`typeinfo!(Distinct).backing` reports the immediate declared backing. Standard formatting peels