feat: support checked explicit sentinel slices

This commit is contained in:
2026-10-23 11:18:08 +02:00
parent 7cb4ace0fa
commit 8ab5b71a0c
7 changed files with 465 additions and 31 deletions
+23 -1
View File
@@ -34,7 +34,7 @@ roadmap and milestone history.
- compile-time `minval!(T)` and `maxval!(T)` bounds for concrete native, C, and scalar-backed distinct integer types; the result retains `T`
- arrays `[N]T`, inferred-count arrays `[_]T`, sentinel arrays `[N;S]T`, compile-time expression array counts, slices `[]T` / `[;S]T`, single-item pointers `@T`, many-item pointers `*T`, and sentinel many-item pointers `[*;S]T`
- pointer mutability via `mut`, optional pointers as nullable pointers, pointer arithmetic for many-item pointers, postfix dereference `^`, and trapping optional unwrap `?`
- pointer-to-array `.len`, indexing, slicing, `.ptr` on slices and pointers-to-arrays, implicit address-taking for array-variable slices, and pointer/slice sentinel weakening
- pointer-to-array `.len`, indexing, slicing, `.ptr` on slices and pointers-to-arrays, implicit address-taking for array-variable slices, pointer/slice sentinel weakening, and checked explicit sentinel slicing `base[start..end;S]`
- `ptrcast!(ptr)` infers its complete pointer result from context; `ptrcast!(P, ptr)` supplies `P` explicitly; both change the child type, then permit only ordinary implicit pointer conversions to the requested target
- unsafe `constcast!(value)` for restoring mutability to pointers, optional pointers, and slices without changing their child type or shape
- UTF-8 string literals as immutable pointers to static zero-terminated byte arrays, supporting `\\`, `\"`, `\n`, `\r`, `\t`, `\0`, and `\xNN` escapes, plus raw backtick multiline strings
@@ -48,6 +48,28 @@ roadmap and milestone history.
- fallible channel types `T ! E`, where `E` is a native enum, native struct, tagged union, or supported sum composition; `void ! E` functions complete successfully on fallthrough, and void-success `catch` handlers may fall through without `yield`
- bodyful local functions and root `main` may write `T!` to infer a specialization-local error channel from propagated `try` expressions and concretely typed error returns; inference composes only existing named error types, never synthesizes variants, and requires at least one inferred error
#### checked sentinel slicing
`base[start..end;S]` constructs a sentinel slice `[;S]T` without copying elements.
The sentinel `S` must be a compile-time integer representable by the source element type `T`;
the result retains the source's element mutability. Bounds use `usize`, as in ordinary slicing.
`start` defaults to zero; `end` may be omitted for arrays, pointers-to-arrays, and slices, where
it defaults to the logical length. Many-item pointers, including sentinel pointers, always
require an explicit end: `pointer[..count;0]`.
The result contains elements `[start, end)` and excludes the sentinel at `end`.
Before constructing it, runtime checks require ordered in-range bounds, a readable endpoint,
and `base[end] == S`; failure traps. For a bounded source without a sentinel, `end` must be
strictly less than its length. A sentinel source permits `end == len`, reading its stored
sentinel. A many-item pointer has no length to check: the caller must provide valid memory
through the endpoint, and the endpoint value is still checked. Comptime evaluation enforces
the same endpoint and sentinel requirements and diagnoses failures.
Ordinary `base[start..end]` slicing keeps its existing bounds rules and preserves a source
sentinel only when the end bound is omitted. Explicit sentinel slicing can assert a different
sentinel only when the actual endpoint matches it; it never adds a terminator or restores
mutability.
#### distinct types
`Name :: distinct T` creates a nominal identity and reuses `T`'s runtime representation. When