Commit 9d4cfd9048
Changed files (3)
src/Module.zig
@@ -1125,6 +1125,8 @@ pub const Union = struct {
abi_align: Value,
/// Returns the field alignment, assuming the union is not packed.
+ /// Keep implementation in sync with `Sema.unionFieldAlignment`.
+ /// Prefer to call that function instead of this one during Sema.
pub fn normalAlignment(field: Field, target: Target) u32 {
if (field.abi_align.tag() == .abi_align_default) {
return field.ty.abiAlignment(target);
src/Sema.zig
@@ -10402,7 +10402,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const union_field_fields = try fields_anon_decl.arena().create([3]Value);
const alignment = switch (layout) {
- .Auto, .Extern => field.normalAlignment(target),
+ .Auto, .Extern => try sema.unionFieldAlignment(block, src, field),
.Packed => 0,
};
@@ -17713,6 +17713,10 @@ fn resolveTypeLayout(
.Optional => {
var buf: Type.Payload.ElemType = undefined;
const payload_ty = ty.optionalChild(&buf);
+ // In case of querying the ABI alignment of this optional, we will ask
+ // for hasRuntimeBits() of the payload type, so we need "requires comptime"
+ // to be known already before this function returns.
+ _ = try sema.typeRequiresComptime(block, src, payload_ty);
return sema.resolveTypeLayout(block, src, payload_ty);
},
.ErrorUnion => {
@@ -17744,6 +17748,13 @@ fn resolveStructLayout(
try sema.resolveTypeLayout(block, src, field.ty);
}
struct_obj.status = .have_layout;
+
+ // In case of querying the ABI alignment of this struct, we will ask
+ // for hasRuntimeBits() of each field, so we need "requires comptime"
+ // to be known already before this function returns.
+ for (struct_obj.fields.values()) |field| {
+ _ = try sema.typeRequiresComptime(block, src, field.ty);
+ }
}
// otherwise it's a tuple; no need to resolve anything
}
@@ -19297,6 +19308,21 @@ fn typeAbiAlignment(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !u32
return ty.abiAlignment(target);
}
+/// Not valid to call for packed unions.
+/// Keep implementation in sync with `Module.Union.Field.normalAlignment`.
+fn unionFieldAlignment(
+ sema: *Sema,
+ block: *Block,
+ src: LazySrcLoc,
+ field: Module.Union.Field,
+) !u32 {
+ if (field.abi_align.tag() == .abi_align_default) {
+ return sema.typeAbiAlignment(block, src, field.ty);
+ } else {
+ return @intCast(u32, field.abi_align.toUnsignedInt());
+ }
+}
+
/// Synchronize logic with `Type.isFnOrHasRuntimeBits`.
pub fn fnHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool {
const fn_info = ty.fnInfo();
src/type.zig
@@ -1619,10 +1619,6 @@ pub const Type = extern union {
// These types have more than one possible value, so the result is the same as
// asking whether they are comptime-only types.
- //
- // If we get an error that the comptimeOnly status hasn't been
- // resolved yet, then we assume that there are runtime bits,
- // just like we do for structs below
.anyframe_T,
.optional,
.optional_single_mut_pointer,
@@ -1636,7 +1632,7 @@ pub const Type = extern union {
.const_slice,
.mut_slice,
.pointer,
- => !(ty.comptimeOnly() catch return true),
+ => !ty.comptimeOnly(),
.@"struct" => {
const struct_obj = ty.castTag(.@"struct").?.data;
@@ -1732,7 +1728,7 @@ pub const Type = extern union {
.Inline => return false,
else => {},
}
- if (fn_info.return_type.comptimeOnly() catch unreachable) return false;
+ if (fn_info.return_type.comptimeOnly()) return false;
return true;
},
else => return ty.hasRuntimeBits(),
@@ -3614,7 +3610,7 @@ pub const Type = extern union {
/// During semantic analysis, instead call `Sema.typeRequiresComptime` which
/// resolves field types rather than asserting they are already resolved.
- pub fn comptimeOnly(ty: Type) error{StatusNotResolved}!bool {
+ pub fn comptimeOnly(ty: Type) bool {
return switch (ty.tag()) {
.u1,
.u8,
@@ -3735,7 +3731,7 @@ pub const Type = extern union {
.tuple => {
const tuple = ty.castTag(.tuple).?.data;
for (tuple.types) |field_ty| {
- if (try field_ty.comptimeOnly()) return true;
+ if (field_ty.comptimeOnly()) return true;
}
return false;
},
@@ -3743,20 +3739,18 @@ pub const Type = extern union {
.@"struct" => {
const struct_obj = ty.castTag(.@"struct").?.data;
switch (struct_obj.requires_comptime) {
- .wip => unreachable,
+ .wip, .unknown => unreachable, // This function asserts types already resolved.
.no => return false,
.yes => return true,
- .unknown => return error.StatusNotResolved,
}
},
.@"union", .union_tagged => {
const union_obj = ty.cast(Type.Payload.Union).?.data;
switch (union_obj.requires_comptime) {
- .wip => unreachable,
+ .wip, .unknown => unreachable, // This function asserts types already resolved.
.no => return false,
.yes => return true,
- .unknown => return error.StatusNotResolved,
}
},