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 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
|
/// Rename a nominal type to a new name, re-keying `intern_map` so
|
||||||
|
|||||||
Reference in New Issue
Block a user