diff options
| author | Veikka Tuominen <git@vexu.eu> | 2022-12-02 18:46:59 +0200 |
|---|---|---|
| committer | Veikka Tuominen <git@vexu.eu> | 2022-12-02 18:46:59 +0200 |
| commit | 59dad43de26a89ca72a97224a171d724dcc6ee41 (patch) | |
| tree | 63377949939557a1edf03c90be77508051d9354f /src | |
| parent | 86e6acb37b242a60917f5552999d918c24fdf791 (diff) | |
| download | zig-59dad43de26a89ca72a97224a171d724dcc6ee41.tar.gz zig-59dad43de26a89ca72a97224a171d724dcc6ee41.zip | |
Sema: add error for failed assumption about struct having runtime bits
Diffstat (limited to 'src')
| -rw-r--r-- | src/Module.zig | 2 | ||||
| -rw-r--r-- | src/Sema.zig | 20 | ||||
| -rw-r--r-- | src/type.zig | 31 | ||||
| -rw-r--r-- | src/value.zig | 2 |
4 files changed, 48 insertions, 7 deletions
diff --git a/src/Module.zig b/src/Module.zig index a18297c8ff..68d0ac8af5 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -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`. diff --git a/src/Sema.zig b/src/Sema.zig index c384605e1b..73ebf3d0aa 100644 --- a/src/Sema.zig +++ b/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 diff --git a/src/type.zig b/src/type.zig index 21cfdf9d73..5fcd0f6a26 100644 --- a/src/type.zig +++ b/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, } diff --git a/src/value.zig b/src/value.zig index be643f65a3..adff60983f 100644 --- a/src/value.zig +++ b/src/value.zig @@ -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; |
