P5.7 Step E: fix issue 0141 (reject silent [*]T -> []T coercion); land regression

The 0141 repro relied on a silent-wrong coercion: passing List.items (a
[*]T many-pointer, no length) to a []T parameter passed the bare 8-byte
pointer into a 16-byte {ptr,len} slot — garbage .len, at comptime a segfault
in the VM slice decoder (decodeMemberSlice), at runtime an LLVM verify failure.

Fix (root cause): classify [*]T -> []T as many_to_slice_reject in
conversions.zig and emit a build-gating diagnostic in coerce.zig telling the
user to slice with a length (ptr[0..len]). Guard runComptimeTypeFunc to skip
VM eval once diagnostics.hasErrors() — a type-fn body that failed coercion
holds malformed comptime data (a real host Addr) that would fault the VM's
Ref-level guards.

Land the corrected feature as examples/0640 (List-grown comptime enum via
vs.items[0..vs.len] -> green=7) and the rejection as
examples/1183-diagnostics-many-pointer-to-slice-rejected. Mark issue 0141
RESOLVED.

708/0 corpus + 476/476 unit.
This commit is contained in:
agra
2026-06-19 20:40:21 +03:00
parent 7b8be86834
commit 61f5700a36
13 changed files with 147 additions and 34 deletions

View File

@@ -43,6 +43,7 @@ pub const CoercionResolver = struct {
widen, // same kind, dst wider
narrow, // same kind, dst narrower
array_to_slice, // [N]T → []T (materialize backing storage + header)
many_to_slice_reject, // [*]T → []T (no length — needs ptr[0..len]; diagnostic)
string_to_cstring, // literal-only implicit; other strings need to_cstring
cstring_to_string_reject, // explicit from_cstring required (diagnostic)
none, // nothing applies — pass the value through
@@ -82,6 +83,15 @@ pub const CoercionResolver = struct {
if (si == .array and di == .slice and si.array.element == di.slice.element) {
return .array_to_slice;
}
// `[*]T → []T`: a many-pointer carries NO length, so it cannot form a
// `{ptr,len}` slice header implicitly. Silently passing the bare 8-byte
// pointer where a 16-byte fat pointer is expected corrupts the callee's
// view (garbage `.len`, mis-aligned reads) — at comptime it segfaults
// (issue 0141), at runtime it fails LLVM verification. Reject loudly so
// the user supplies the length via `ptr[0..len]`.
if (si == .many_pointer and di == .slice) {
return .many_to_slice_reject;
}
}
// Optional → Concrete unwrap (narrowing).