fix: allow void (zero-sized) struct/tuple fields instead of crashing (issue 0150)
A struct/tuple/?T with a void field crashed the compiler: the field lowered to LLVM's unsized 'void' type, which traps getTypeSizeInBits. Lower a void field to a SIZED zero-byte [0 x i8] (fieldLLVMType) so the enclosing aggregate stays sized with identical element indices, and skip inserting a value for a void field in emitStructInit (the i64 placeholder would type-mismatch the [0 x i8] slot and corrupt the aggregate constant -> runtime bus error). Future(void) now works. Regression: examples/0190-types-void-struct-field-zero-sized.sx
This commit is contained in:
@@ -1720,6 +1720,18 @@ pub const Ops = struct {
|
||||
const elem_llvm_ty = if (is_array) c.LLVMGetElementType(struct_ty) else null;
|
||||
var result = c.LLVMGetUndef(struct_ty);
|
||||
for (agg.fields, 0..) |field_ref, i| {
|
||||
// A `void` (zero-sized) struct/tuple field lowers to a zero-width
|
||||
// `[0 x i8]` slot (see `TypeLowering.fieldLLVMType`); it carries no
|
||||
// data. Skip inserting a value — the field's lowered ref is an i64
|
||||
// placeholder (`emitConstInt`'s void path) whose type mismatches the
|
||||
// slot and would corrupt the aggregate. The undef `[0 x i8]` element
|
||||
// is already the correct zero-width value.
|
||||
const field_is_void = switch (self.e.ir_mod.types.get(instruction.ty)) {
|
||||
.@"struct" => |s| i < s.fields.len and s.fields[i].ty == .void,
|
||||
.tuple => |t| i < t.fields.len and t.fields[i] == .void,
|
||||
else => false,
|
||||
};
|
||||
if (field_is_void) continue;
|
||||
var field_val = self.e.resolveRef(field_ref);
|
||||
if (is_vector) {
|
||||
// Coerce element to match vector element type
|
||||
|
||||
Reference in New Issue
Block a user