diff options
| author | Cody Tapscott <topolarity@tapscott.me> | 2022-02-27 09:50:53 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-02-27 14:24:47 -0700 |
| commit | 71aa5084edd1d3fba5bf8db87c4cf0d03667a566 (patch) | |
| tree | 6437ecf24efbe2d047568960f0f939d55059d96e /src | |
| parent | 139b731d82d0b851c8fb2e6dbb48b735e63eecd1 (diff) | |
| download | zig-71aa5084edd1d3fba5bf8db87c4cf0d03667a566.tar.gz zig-71aa5084edd1d3fba5bf8db87c4cf0d03667a566.zip | |
stage2: Resolve alignment for union field in `@TypeInfo`
This also includes two other small fixes:
- Instantiate void TypeInfo fields as void
- Return error in `type.comptimeOnly` on unresolved comptime requirements
Diffstat (limited to 'src')
| -rw-r--r-- | src/Sema.zig | 31 | ||||
| -rw-r--r-- | src/type.zig | 18 |
2 files changed, 32 insertions, 17 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 5b97305010..4a8cd38dd4 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -9903,63 +9903,63 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai type_info_ty, try Value.Tag.@"union".create(sema.arena, .{ .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Type)), - .val = Value.initTag(.unreachable_value), + .val = Value.@"void", }), ), .Void => return sema.addConstant( type_info_ty, try Value.Tag.@"union".create(sema.arena, .{ .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Void)), - .val = Value.initTag(.unreachable_value), + .val = Value.@"void", }), ), .Bool => return sema.addConstant( type_info_ty, try Value.Tag.@"union".create(sema.arena, .{ .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Bool)), - .val = Value.initTag(.unreachable_value), + .val = Value.@"void", }), ), .NoReturn => return sema.addConstant( type_info_ty, try Value.Tag.@"union".create(sema.arena, .{ .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.NoReturn)), - .val = Value.initTag(.unreachable_value), + .val = Value.@"void", }), ), .ComptimeFloat => return sema.addConstant( type_info_ty, try Value.Tag.@"union".create(sema.arena, .{ .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.ComptimeFloat)), - .val = Value.initTag(.unreachable_value), + .val = Value.@"void", }), ), .ComptimeInt => return sema.addConstant( type_info_ty, try Value.Tag.@"union".create(sema.arena, .{ .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.ComptimeInt)), - .val = Value.initTag(.unreachable_value), + .val = Value.@"void", }), ), .Undefined => return sema.addConstant( type_info_ty, try Value.Tag.@"union".create(sema.arena, .{ .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Undefined)), - .val = Value.initTag(.unreachable_value), + .val = Value.@"void", }), ), .Null => return sema.addConstant( type_info_ty, try Value.Tag.@"union".create(sema.arena, .{ .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Null)), - .val = Value.initTag(.unreachable_value), + .val = Value.@"void", }), ), .EnumLiteral => return sema.addConstant( type_info_ty, try Value.Tag.@"union".create(sema.arena, .{ .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.EnumLiteral)), - .val = Value.initTag(.unreachable_value), + .val = Value.@"void", }), ), .Fn => { @@ -10380,6 +10380,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai }; const union_ty = try sema.resolveTypeFields(block, src, ty); + try sema.resolveTypeLayout(block, src, ty); // Getting alignment requires type layout + const layout = union_ty.containerLayout(); + const union_fields = union_ty.unionFields(); const union_field_vals = try fields_anon_decl.arena().alloc(Value, union_fields.count()); @@ -10398,13 +10401,18 @@ 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), + .Packed => 0, + }; + union_field_fields.* = .{ // name: []const u8, name_val, // field_type: type, try Value.Tag.ty.create(fields_anon_decl.arena(), field.ty), // alignment: comptime_int, - try field.abi_align.copy(fields_anon_decl.arena()), + try Value.Tag.int_u64.create(fields_anon_decl.arena(), alignment), }; field_val.* = try Value.Tag.@"struct".create(fields_anon_decl.arena(), union_field_fields); } @@ -10435,7 +10443,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai // layout: ContainerLayout, try Value.Tag.enum_field_index.create( sema.arena, - @enumToInt(union_ty.containerLayout()), + @enumToInt(layout), ), // tag_type: ?type, @@ -10473,6 +10481,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai break :t try struct_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena()); }; const struct_ty = try sema.resolveTypeFields(block, src, ty); + try sema.resolveTypeLayout(block, src, ty); // Getting alignment requires type layout const layout = struct_ty.containerLayout(); const struct_field_vals = fv: { diff --git a/src/type.zig b/src/type.zig index a84a0f4520..30f06a6296 100644 --- a/src/type.zig +++ b/src/type.zig @@ -1619,6 +1619,10 @@ 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, @@ -1632,7 +1636,7 @@ pub const Type = extern union { .const_slice, .mut_slice, .pointer, - => !ty.comptimeOnly(), + => !(ty.comptimeOnly() catch return true), .@"struct" => { const struct_obj = ty.castTag(.@"struct").?.data; @@ -1728,7 +1732,7 @@ pub const Type = extern union { .Inline => return false, else => {}, } - if (fn_info.return_type.comptimeOnly()) return false; + if (fn_info.return_type.comptimeOnly() catch unreachable) return false; return true; }, else => return ty.hasRuntimeBits(), @@ -3610,7 +3614,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) bool { + pub fn comptimeOnly(ty: Type) error{StatusNotResolved}!bool { return switch (ty.tag()) { .u1, .u8, @@ -3731,7 +3735,7 @@ pub const Type = extern union { .tuple => { const tuple = ty.castTag(.tuple).?.data; for (tuple.types) |field_ty| { - if (field_ty.comptimeOnly()) return true; + if (try field_ty.comptimeOnly()) return true; } return false; }, @@ -3739,18 +3743,20 @@ 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 => unreachable, .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, .unknown => unreachable, // This function asserts types already resolved. + .wip => unreachable, .no => return false, .yes => return true, + .unknown => return error.StatusNotResolved, } }, |
