fix(metatype): reject declare() never completed by define()
A bare declare("X") with no define left a zero-field nominal slot that
panicked at codegen (verifySizes: llvm_size != ir_size). evalComptimeType
now detects a zero-variant tagged_union result and emits a clean
build-gating diagnostic naming the type — a zero-variant enum is never a
legitimate construction result (defineEnum rejects empty variant lists
too). Self-reference (a declared slot completed by define) is unaffected.
This commit is contained in:
@@ -473,7 +473,21 @@ pub fn evalComptimeType(self: *Lowering, expr: *const Node) ?TypeId {
|
||||
}
|
||||
return null;
|
||||
};
|
||||
return result.asTypeId();
|
||||
const tid = result.asTypeId() orelse return null;
|
||||
// A bare `declare("X")` that is never completed by a `define(handle, …)`
|
||||
// leaves a zero-FIELD nominal slot (an undefined enum). Sizing / constructing
|
||||
// / emitting it panics at codegen (`verifySizes`: llvm_size != ir_size).
|
||||
// Reject it loudly here — a zero-variant enum is never a legitimate result
|
||||
// (`defineEnum` rejects an empty variant list too).
|
||||
if (!tid.isBuiltin()) {
|
||||
const info = self.module.types.get(tid);
|
||||
if (info == .tagged_union and info.tagged_union.fields.len == 0) {
|
||||
if (self.diagnostics) |d|
|
||||
d.addFmt(.err, expr.span, "type '{s}' is declared but never defined — complete it with define(handle, info)", .{self.module.types.getString(info.tagged_union.name)});
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return tid;
|
||||
}
|
||||
|
||||
/// Rename a nominal type to a new name, re-keying `intern_map` so
|
||||
|
||||
Reference in New Issue
Block a user