mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 21:08:36 +00:00
Sema: add error for failed assumption about struct having runtime bits
This commit is contained in:
parent
86e6acb37b
commit
59dad43de2
@ -940,6 +940,7 @@ pub const Struct = struct {
|
||||
requires_comptime: PropertyBoolean = .unknown,
|
||||
have_field_inits: bool = false,
|
||||
is_tuple: bool,
|
||||
assumed_runtime_bits: bool = false,
|
||||
|
||||
pub const Fields = std.StringArrayHashMapUnmanaged(Field);
|
||||
|
||||
@ -1205,6 +1206,7 @@ pub const Union = struct {
|
||||
fully_resolved,
|
||||
},
|
||||
requires_comptime: PropertyBoolean = .unknown,
|
||||
assumed_runtime_bits: bool = false,
|
||||
|
||||
pub const Field = struct {
|
||||
/// undefined until `status` is `have_field_types` or `have_layout`.
|
||||
|
||||
20
src/Sema.zig
20
src/Sema.zig
@ -29237,6 +29237,16 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
|
||||
|
||||
struct_obj.status = .have_layout;
|
||||
_ = try sema.resolveTypeRequiresComptime(resolved_ty);
|
||||
|
||||
if (struct_obj.assumed_runtime_bits and !resolved_ty.hasRuntimeBits()) {
|
||||
const msg = try Module.ErrorMsg.create(
|
||||
sema.gpa,
|
||||
struct_obj.srcLoc(sema.mod),
|
||||
"struct layout depends on it having runtime bits",
|
||||
.{},
|
||||
);
|
||||
return sema.failWithOwnedErrorMsg(msg);
|
||||
}
|
||||
}
|
||||
// otherwise it's a tuple; no need to resolve anything
|
||||
}
|
||||
@ -29401,6 +29411,16 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
|
||||
}
|
||||
union_obj.status = .have_layout;
|
||||
_ = try sema.resolveTypeRequiresComptime(resolved_ty);
|
||||
|
||||
if (union_obj.assumed_runtime_bits and !resolved_ty.hasRuntimeBits()) {
|
||||
const msg = try Module.ErrorMsg.create(
|
||||
sema.gpa,
|
||||
union_obj.srcLoc(sema.mod),
|
||||
"union layout depends on it having runtime bits",
|
||||
.{},
|
||||
);
|
||||
return sema.failWithOwnedErrorMsg(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// In case of querying the ABI alignment of this struct, we will ask
|
||||
|
||||
31
src/type.zig
31
src/type.zig
@ -2459,6 +2459,7 @@ pub const Type = extern union {
|
||||
if (struct_obj.status == .field_types_wip) {
|
||||
// In this case, we guess that hasRuntimeBits() for this type is true,
|
||||
// and then later if our guess was incorrect, we emit a compile error.
|
||||
struct_obj.assumed_runtime_bits = true;
|
||||
return true;
|
||||
}
|
||||
switch (strat) {
|
||||
@ -2491,6 +2492,12 @@ pub const Type = extern union {
|
||||
|
||||
.@"union" => {
|
||||
const union_obj = ty.castTag(.@"union").?.data;
|
||||
if (union_obj.status == .field_types_wip) {
|
||||
// In this case, we guess that hasRuntimeBits() for this type is true,
|
||||
// and then later if our guess was incorrect, we emit a compile error.
|
||||
union_obj.assumed_runtime_bits = true;
|
||||
return true;
|
||||
}
|
||||
switch (strat) {
|
||||
.sema => |sema| _ = try sema.resolveTypeFields(ty),
|
||||
.eager => assert(union_obj.haveFieldTypes()),
|
||||
@ -3027,8 +3034,9 @@ pub const Type = extern union {
|
||||
const struct_obj = ty.castTag(.@"struct").?.data;
|
||||
if (opt_sema) |sema| {
|
||||
if (struct_obj.status == .field_types_wip) {
|
||||
// We'll guess "pointer-aligned" and if we guess wrong, emit
|
||||
// a compile error later.
|
||||
// We'll guess "pointer-aligned", if the struct has an
|
||||
// underaligned pointer field then some allocations
|
||||
// might require explicit alignment.
|
||||
return AbiAlignmentAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) };
|
||||
}
|
||||
_ = try sema.resolveTypeFields(ty);
|
||||
@ -3153,8 +3161,9 @@ pub const Type = extern union {
|
||||
};
|
||||
if (opt_sema) |sema| {
|
||||
if (union_obj.status == .field_types_wip) {
|
||||
// We'll guess "pointer-aligned" and if we guess wrong, emit
|
||||
// a compile error later.
|
||||
// We'll guess "pointer-aligned", if the union has an
|
||||
// underaligned pointer field then some allocations
|
||||
// might require explicit alignment.
|
||||
return AbiAlignmentAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) };
|
||||
}
|
||||
_ = try sema.resolveTypeFields(ty);
|
||||
@ -5234,7 +5243,12 @@ pub const Type = extern union {
|
||||
.@"struct" => {
|
||||
const struct_obj = ty.castTag(.@"struct").?.data;
|
||||
switch (struct_obj.requires_comptime) {
|
||||
.wip, .unknown => unreachable, // This function asserts types already resolved.
|
||||
.wip, .unknown => {
|
||||
// Return false to avoid incorrect dependency loops.
|
||||
// This will be handled correctly once merged with
|
||||
// `Sema.typeRequiresComptime`.
|
||||
return false;
|
||||
},
|
||||
.no => return false,
|
||||
.yes => return true,
|
||||
}
|
||||
@ -5243,7 +5257,12 @@ pub const Type = extern union {
|
||||
.@"union", .union_safety_tagged, .union_tagged => {
|
||||
const union_obj = ty.cast(Type.Payload.Union).?.data;
|
||||
switch (union_obj.requires_comptime) {
|
||||
.wip, .unknown => unreachable, // This function asserts types already resolved.
|
||||
.wip, .unknown => {
|
||||
// Return false to avoid incorrect dependency loops.
|
||||
// This will be handled correctly once merged with
|
||||
// `Sema.typeRequiresComptime`.
|
||||
return false;
|
||||
},
|
||||
.no => return false,
|
||||
.yes => return true,
|
||||
}
|
||||
|
||||
@ -187,7 +187,7 @@ pub const Value = extern union {
|
||||
bound_fn,
|
||||
/// The ABI alignment of the payload type.
|
||||
lazy_align,
|
||||
/// The ABI alignment of the payload type.
|
||||
/// The ABI size of the payload type.
|
||||
lazy_size,
|
||||
|
||||
pub const last_no_payload_tag = Tag.empty_array;
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
comptime {
|
||||
const S = struct {
|
||||
const Foo = struct {
|
||||
y: Bar,
|
||||
};
|
||||
const Bar = struct {
|
||||
y: if (@sizeOf(Foo) == 0) u64 else void,
|
||||
};
|
||||
};
|
||||
|
||||
_ = @sizeOf(S.Foo) + 1;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :6:21: error: struct layout depends on it having runtime bits
|
||||
// :4:13: note: while checking this field
|
||||
Loading…
x
Reference in New Issue
Block a user