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.
39 lines
1.4 KiB
Plaintext
39 lines
1.4 KiB
Plaintext
// 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;
|
|
}
|