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:
38
examples/0640-comptime-list-grown-variant-define.sx
Normal file
38
examples/0640-comptime-list-grown-variant-define.sx
Normal file
@@ -0,0 +1,38 @@
|
||||
// Comptime type construction from a List grown at compile time: assemble the
|
||||
// variant set in a `List(EnumVariant)` via `.append` (which allocates + grows
|
||||
// its backing through the comptime `context.allocator`), then mint an enum from
|
||||
// the grown backing sliced to its length — `vs.items[0..vs.len]`. The comptime
|
||||
// VM evaluates the List growth, the slice, and `define`/`declare` end-to-end.
|
||||
//
|
||||
// A `[*]T` many-pointer (the List's bare `items` field) carries no length, so it
|
||||
// must be sliced with `[0..len]` to form a `[]T`; passing `vs.items` bare is a
|
||||
// rejected coercion (see the diagnostic example for that path).
|
||||
//
|
||||
// Regression (issue 0141): the List-grown form used to segfault in the comptime
|
||||
// VM's slice decoder.
|
||||
#import "modules/std.sx";
|
||||
#import "modules/std/meta.sx";
|
||||
|
||||
make_enum :: (name: string, variants: []EnumVariant) -> Type {
|
||||
return define(declare(name), .enum(.{ variants = variants }));
|
||||
}
|
||||
|
||||
build_color :: () -> Type {
|
||||
vs : List(EnumVariant) = .{};
|
||||
vs.append(EnumVariant.{ name = "red", payload = void });
|
||||
vs.append(EnumVariant.{ name = "green", payload = i64 });
|
||||
vs.append(EnumVariant.{ name = "blue", payload = void });
|
||||
return make_enum("Color", vs.items[0..vs.len]);
|
||||
}
|
||||
|
||||
Color :: build_color();
|
||||
|
||||
main :: () -> i32 {
|
||||
c : Color = .green(7);
|
||||
if c == {
|
||||
case .red: { print("red\n"); }
|
||||
case .green: (v) { print("green={}\n", v); }
|
||||
case .blue: { print("blue\n"); }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
24
examples/1183-diagnostics-many-pointer-to-slice-rejected.sx
Normal file
24
examples/1183-diagnostics-many-pointer-to-slice-rejected.sx
Normal file
@@ -0,0 +1,24 @@
|
||||
// A many-pointer `[*]T` carries NO length, so it cannot coerce to a slice `[]T`
|
||||
// implicitly — doing so would pass a bare 8-byte pointer where a 16-byte
|
||||
// `{ptr,len}` fat pointer is expected, silently corrupting the callee's view of
|
||||
// the data (garbage length, mis-aligned element reads). The compiler rejects it
|
||||
// loudly and tells the user to supply the length via `ptr[0..len]`.
|
||||
//
|
||||
// Regression (issue 0141): this silent mis-coercion segfaulted the comptime VM
|
||||
// and failed LLVM verification at runtime; it now produces a clean diagnostic.
|
||||
#import "modules/std.sx";
|
||||
|
||||
sum :: (s: []i64) -> i64 {
|
||||
total := 0;
|
||||
for s (x) { total += x; }
|
||||
return total;
|
||||
}
|
||||
|
||||
main :: () -> i32 {
|
||||
xs : List(i64) = .{};
|
||||
xs.append(10);
|
||||
xs.append(20);
|
||||
r := sum(xs.items); // [*]i64 → []i64 — needs xs.items[0..xs.len]
|
||||
print("{}\n", r);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
green=7
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,5 @@
|
||||
error: a many-pointer '[*]T' does not coerce to a slice '[]T' implicitly (it carries no length) — slice it with a length: ptr[0..len]
|
||||
--> examples/1183-diagnostics-many-pointer-to-slice-rejected.sx:21:10
|
||||
|
|
||||
21 | r := sum(xs.items); // [*]i64 → []i64 — needs xs.items[0..xs.len]
|
||||
| ^^^^^^^^^^^^^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
Reference in New Issue
Block a user