authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-12-02 18:46:59+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-12-02 18:46:59+02:00
log59dad43de26a89ca72a97224a171d724dcc6ee41
tree63377949939557a1edf03c90be77508051d9354f
parent86e6acb37b242a60917f5552999d918c24fdf791

Sema: add error for failed assumption about struct having runtime bits


5 files changed, 67 insertions(+), 7 deletions(-)

src/Module.zig+2
......@@ -940,6 +940,7 @@ pub const Struct = struct {
940940 requires_comptime: PropertyBoolean = .unknown,
941941 have_field_inits: bool = false,
942942 is_tuple: bool,
943 assumed_runtime_bits: bool = false,
943944
944945 pub const Fields = std.StringArrayHashMapUnmanaged(Field);
945946
......@@ -1205,6 +1206,7 @@ pub const Union = struct {
12051206 fully_resolved,
12061207 },
12071208 requires_comptime: PropertyBoolean = .unknown,
1209 assumed_runtime_bits: bool = false,
12081210
12091211 pub const Field = struct {
12101212 /// undefined until `status` is `have_field_types` or `have_layout`.
src/Sema.zig+20
......@@ -29237,6 +29237,16 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
2923729237
2923829238 struct_obj.status = .have_layout;
2923929239 _ = try sema.resolveTypeRequiresComptime(resolved_ty);
29240
29241 if (struct_obj.assumed_runtime_bits and !resolved_ty.hasRuntimeBits()) {
29242 const msg = try Module.ErrorMsg.create(
29243 sema.gpa,
29244 struct_obj.srcLoc(sema.mod),
29245 "struct layout depends on it having runtime bits",
29246 .{},
29247 );
29248 return sema.failWithOwnedErrorMsg(msg);
29249 }
2924029250 }
2924129251 // otherwise it's a tuple; no need to resolve anything
2924229252}
......@@ -29401,6 +29411,16 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
2940129411 }
2940229412 union_obj.status = .have_layout;
2940329413 _ = try sema.resolveTypeRequiresComptime(resolved_ty);
29414
29415 if (union_obj.assumed_runtime_bits and !resolved_ty.hasRuntimeBits()) {
29416 const msg = try Module.ErrorMsg.create(
29417 sema.gpa,
29418 union_obj.srcLoc(sema.mod),
29419 "union layout depends on it having runtime bits",
29420 .{},
29421 );
29422 return sema.failWithOwnedErrorMsg(msg);
29423 }
2940429424}
2940529425
2940629426// In case of querying the ABI alignment of this struct, we will ask
src/type.zig+25-6
......@@ -2459,6 +2459,7 @@ pub const Type = extern union {
24592459 if (struct_obj.status == .field_types_wip) {
24602460 // In this case, we guess that hasRuntimeBits() for this type is true,
24612461 // and then later if our guess was incorrect, we emit a compile error.
2462 struct_obj.assumed_runtime_bits = true;
24622463 return true;
24632464 }
24642465 switch (strat) {
......@@ -2491,6 +2492,12 @@ pub const Type = extern union {
24912492
24922493 .@"union" => {
24932494 const union_obj = ty.castTag(.@"union").?.data;
2495 if (union_obj.status == .field_types_wip) {
2496 // In this case, we guess that hasRuntimeBits() for this type is true,
2497 // and then later if our guess was incorrect, we emit a compile error.
2498 union_obj.assumed_runtime_bits = true;
2499 return true;
2500 }
24942501 switch (strat) {
24952502 .sema => |sema| _ = try sema.resolveTypeFields(ty),
24962503 .eager => assert(union_obj.haveFieldTypes()),
......@@ -3027,8 +3034,9 @@ pub const Type = extern union {
30273034 const struct_obj = ty.castTag(.@"struct").?.data;
30283035 if (opt_sema) |sema| {
30293036 if (struct_obj.status == .field_types_wip) {
3030 // We'll guess "pointer-aligned" and if we guess wrong, emit
3031 // a compile error later.
3037 // We'll guess "pointer-aligned", if the struct has an
3038 // underaligned pointer field then some allocations
3039 // might require explicit alignment.
30323040 return AbiAlignmentAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) };
30333041 }
30343042 _ = try sema.resolveTypeFields(ty);
......@@ -3153,8 +3161,9 @@ pub const Type = extern union {
31533161 };
31543162 if (opt_sema) |sema| {
31553163 if (union_obj.status == .field_types_wip) {
3156 // We'll guess "pointer-aligned" and if we guess wrong, emit
3157 // a compile error later.
3164 // We'll guess "pointer-aligned", if the union has an
3165 // underaligned pointer field then some allocations
3166 // might require explicit alignment.
31583167 return AbiAlignmentAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) };
31593168 }
31603169 _ = try sema.resolveTypeFields(ty);
......@@ -5234,7 +5243,12 @@ pub const Type = extern union {
52345243 .@"struct" => {
52355244 const struct_obj = ty.castTag(.@"struct").?.data;
52365245 switch (struct_obj.requires_comptime) {
5237 .wip, .unknown => unreachable, // This function asserts types already resolved.
5246 .wip, .unknown => {
5247 // Return false to avoid incorrect dependency loops.
5248 // This will be handled correctly once merged with
5249 // `Sema.typeRequiresComptime`.
5250 return false;
5251 },
52385252 .no => return false,
52395253 .yes => return true,
52405254 }
......@@ -5243,7 +5257,12 @@ pub const Type = extern union {
52435257 .@"union", .union_safety_tagged, .union_tagged => {
52445258 const union_obj = ty.cast(Type.Payload.Union).?.data;
52455259 switch (union_obj.requires_comptime) {
5246 .wip, .unknown => unreachable, // This function asserts types already resolved.
5260 .wip, .unknown => {
5261 // Return false to avoid incorrect dependency loops.
5262 // This will be handled correctly once merged with
5263 // `Sema.typeRequiresComptime`.
5264 return false;
5265 },
52475266 .no => return false,
52485267 .yes => return true,
52495268 }
src/value.zig+1-1
......@@ -187,7 +187,7 @@ pub const Value = extern union {
187187 bound_fn,
188188 /// The ABI alignment of the payload type.
189189 lazy_align,
190 /// The ABI alignment of the payload type.
190 /// The ABI size of the payload type.
191191 lazy_size,
192192
193193 pub const last_no_payload_tag = Tag.empty_array;
test/cases/compile_errors/invalid_dependency_on_struct_size.zig created+19
......@@ -0,0 +1,19 @@
1comptime {
2 const S = struct {
3 const Foo = struct {
4 y: Bar,
5 };
6 const Bar = struct {
7 y: if (@sizeOf(Foo) == 0) u64 else void,
8 };
9 };
10
11 _ = @sizeOf(S.Foo) + 1;
12}
13
14// error
15// backend=stage2
16// target=native
17//
18// :6:21: error: struct layout depends on it having runtime bits
19// :4:13: note: while checking this field