diff --git a/doc/langref.html.in b/doc/langref.html.in index dcf13e812d7a..4ea68503322e 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -638,7 +638,7 @@ {#syntax#}i7{#endsyntax#} refers to a signed 7-bit integer. The maximum allowed bit-width of an integer type is {#syntax#}65535{#endsyntax#}.
- {#see_also|Integers|Floats|void|Errors|@Type#} + {#see_also|Integers|Floats|void|Errors|@Int#} {#header_close#} {#header_open|Primitive Values#}{#syntax#}@Type(comptime info: std.builtin.Type) type{#endsyntax#}+ {#header_open|@Enum#} +
{#syntax#}@Enum(comptime info: std.builtin.Type.Enum) type{#endsyntax#}
- This function is the inverse of {#link|@typeInfo#}. It reifies type information - into a {#syntax#}type{#endsyntax#}. + This function reifies an enum type with the given information.
+ {#header_close#} + {#header_open|@EnumLiteral#} +{#syntax#}@EnumLiteral() type{#endsyntax#}
- It is available for the following types: + This function reifies the special enum literal type. + A unique type that represents anonymous enum values that can coerce to any enum type. +
+ {#header_close#} + {#header_open|@Int#} +{#syntax#}@Int(comptime signedness: std.builtin.Signedness, comptime bits: u16) type{#endsyntax#}+
+ This function reifies an integer type with the given signness and bit count. +
+ {#header_close#} + {#header_open|@Pointer#} +{#syntax#}@Pointer(comptime info: std.builtin.Type.Pointer) type{#endsyntax#}+
+ This function reifies a pointer type with the given information. +
+ {#header_close#} + {#header_open|@Struct#} +{#syntax#}@Struct(comptime info: std.builtin.Type.Struct) type{#endsyntax#}+
+ This function reifies an struct type with the given information.
-{#syntax#}@Union(comptime info: std.builtin.Type.Union) type{#endsyntax#}+
+ This function reifies a union type with the given information. +
+ {#header_close#} + {#header_open|@Vector#} +{#syntax#}@Vector(len: comptime_int, Element: type) type{#endsyntax#}+
Creates {#link|Vectors#}.
+ {#header_close#} + {#header_open|@typeInfo#}{#syntax#}@typeInfo(comptime T: type) std.builtin.Type{#endsyntax#}
@@ -5834,12 +5841,6 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
{#header_close#} - - {#header_open|@Vector#} -{#syntax#}@Vector(len: comptime_int, Element: type) type{#endsyntax#}-
Creates {#link|Vectors#}.
- {#header_close#} - {#header_open|@volatileCast#}{#syntax#}@volatileCast(value: anytype) DestType{#endsyntax#}
diff --git a/doc/langref/std_options.zig b/doc/langref/std_options.zig index b37d407fc86a..c424d2adb77c 100644 --- a/doc/langref/std_options.zig +++ b/doc/langref/std_options.zig @@ -11,7 +11,7 @@ pub const std_options: std.Options = .{ fn myLogFn( comptime level: std.log.Level, - comptime scope: @Type(.enum_literal), + comptime scope: @TypeOf(.enum_literal), comptime format: []const u8, args: anytype, ) void { diff --git a/lib/compiler/aro/aro/Attribute.zig b/lib/compiler/aro/aro/Attribute.zig index a5b78b8463a4..b1d777fe28f5 100644 --- a/lib/compiler/aro/aro/Attribute.zig +++ b/lib/compiler/aro/aro/Attribute.zig @@ -712,13 +712,11 @@ pub const Arguments = blk: { }; } - break :blk @Type(.{ - .@"union" = .{ - .layout = .auto, - .tag_type = null, - .fields = &union_fields, - .decls = &.{}, - }, + break :blk @Union(.{ + .layout = .auto, + .tag_type = null, + .fields = &union_fields, + .decls = &.{}, }); }; diff --git a/lib/compiler/resinator/code_pages.zig b/lib/compiler/resinator/code_pages.zig index 53cbdb768cd8..73874de3b521 100644 --- a/lib/compiler/resinator/code_pages.zig +++ b/lib/compiler/resinator/code_pages.zig @@ -179,12 +179,12 @@ pub const UnsupportedCodePage = enum(u16) { pub const CodePage = blk: { const fields = @typeInfo(SupportedCodePage).@"enum".fields ++ @typeInfo(UnsupportedCodePage).@"enum".fields; - break :blk @Type(.{ .@"enum" = .{ + break :blk @Enum(.{ .tag_type = u16, .decls = &.{}, .fields = fields, .is_exhaustive = true, - } }); + }); }; pub fn isSupported(code_page: CodePage) bool { diff --git a/lib/compiler/resinator/errors.zig b/lib/compiler/resinator/errors.zig index 14a001894e4c..b7231c8134b3 100644 --- a/lib/compiler/resinator/errors.zig +++ b/lib/compiler/resinator/errors.zig @@ -868,12 +868,12 @@ pub const ErrorDetailsWithoutCodePage = blk: { i += 1; } std.debug.assert(i == fields_without_codepage.len); - break :blk @Type(.{ .@"struct" = .{ + break :blk @Struct(.{ .layout = .auto, .fields = &fields_without_codepage, .decls = &.{}, .is_tuple = false, - } }); + }); }; fn cellCount(code_page: SupportedCodePage, source: []const u8, start_index: usize, end_index: usize) usize { diff --git a/lib/compiler/test_runner.zig b/lib/compiler/test_runner.zig index 929bd1c417f9..87bae23b99c1 100644 --- a/lib/compiler/test_runner.zig +++ b/lib/compiler/test_runner.zig @@ -266,7 +266,7 @@ fn mainTerminal() void { pub fn log( comptime message_level: std.log.Level, - comptime scope: @Type(.enum_literal), + comptime scope: @TypeOf(.enum_literal), comptime format: []const u8, args: anytype, ) void { diff --git a/lib/compiler_rt/common.zig b/lib/compiler_rt/common.zig index f5423019f14d..4639fc656322 100644 --- a/lib/compiler_rt/common.zig +++ b/lib/compiler_rt/common.zig @@ -261,10 +261,7 @@ pub fn normalize(comptime T: type, significand: *std.meta.Int(.unsigned, @typeIn pub inline fn fneg(a: anytype) @TypeOf(a) { const F = @TypeOf(a); const bits = @typeInfo(F).float.bits; - const U = @Type(.{ .int = .{ - .signedness = .unsigned, - .bits = bits, - } }); + const U = @Int(.unsigned, bits); const sign_bit_mask = @as(U, 1) << (bits - 1); const negated = @as(U, @bitCast(a)) ^ sign_bit_mask; return @bitCast(negated); diff --git a/lib/compiler_rt/float_from_int.zig b/lib/compiler_rt/float_from_int.zig index 98659d275bc8..9ce43b4d701e 100644 --- a/lib/compiler_rt/float_from_int.zig +++ b/lib/compiler_rt/float_from_int.zig @@ -66,17 +66,17 @@ pub inline fn floatFromBigInt(comptime T: type, comptime signedness: std.builtin switch (x.len) { 0 => return 0, inline 1...4 => |limbs_len| return @floatFromInt(@as( - @Type(.{ .int = .{ .signedness = signedness, .bits = 32 * limbs_len } }), + @Int(signedness, 32 * limbs_len), @bitCast(x[0..limbs_len].*), )), else => {}, } // sign implicit fraction round sticky - const I = comptime @Type(.{ .int = .{ - .signedness = signedness, - .bits = @as(u16, @intFromBool(signedness == .signed)) + 1 + math.floatFractionalBits(T) + 1 + 1, - } }); + const I = comptime @Int( + signedness, + @as(u16, @intFromBool(signedness == .signed)) + 1 + math.floatFractionalBits(T) + 1 + 1, + ); const clrsb = clrsb: { var clsb: usize = 0; diff --git a/lib/compiler_rt/int_from_float.zig b/lib/compiler_rt/int_from_float.zig index 0c2c73bb427f..111143f211b9 100644 --- a/lib/compiler_rt/int_from_float.zig +++ b/lib/compiler_rt/int_from_float.zig @@ -56,7 +56,7 @@ pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, resul 0 => return, inline 1...4 => |limbs_len| { result[0..limbs_len].* = @bitCast(@as( - @Type(.{ .int = .{ .signedness = signedness, .bits = 32 * limbs_len } }), + @Int(signedness, 32 * limbs_len), @intFromFloat(a), )); return; @@ -66,10 +66,7 @@ pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, resul // sign implicit fraction const significand_bits = 1 + math.floatFractionalBits(@TypeOf(a)); - const I = @Type(comptime .{ .int = .{ - .signedness = signedness, - .bits = @as(u16, @intFromBool(signedness == .signed)) + significand_bits, - } }); + const I = @Int(signedness, @as(u16, @intFromBool(signedness == .signed)) + significand_bits); const parts = math.frexp(a); const significand_bits_adjusted_to_handle_smin = @as(i32, significand_bits) + diff --git a/lib/compiler_rt/memcpy.zig b/lib/compiler_rt/memcpy.zig index 30971677ab0f..c8fd8813a597 100644 --- a/lib/compiler_rt/memcpy.zig +++ b/lib/compiler_rt/memcpy.zig @@ -159,7 +159,7 @@ inline fn copyFixedLength( else if (len > @sizeOf(usize)) @Vector(len, u8) else - @Type(.{ .int = .{ .signedness = .unsigned, .bits = len * 8 } }); + @Int(.unsigned, len * 8); const loop_count = @divExact(len, @sizeOf(T)); diff --git a/lib/fuzzer.zig b/lib/fuzzer.zig index ce23f63421ac..58ba2d19e7f2 100644 --- a/lib/fuzzer.zig +++ b/lib/fuzzer.zig @@ -14,7 +14,7 @@ var log_file_writer: ?std.fs.File.Writer = null; fn logOverride( comptime level: std.log.Level, - comptime scope: @Type(.enum_literal), + comptime scope: @TypeOf(.enum_literal), comptime format: []const u8, args: anytype, ) void { diff --git a/lib/std/Io.zig b/lib/std/Io.zig index 00ff0cea9836..cba90c0abb78 100644 --- a/lib/std/Io.zig +++ b/lib/std/Io.zig @@ -858,12 +858,12 @@ pub fn PollFiles(comptime StreamEnum: type) type { .alignment = @alignOf(fs.File), }; } - return @Type(.{ .@"struct" = .{ + return @Struct(.{ .layout = .auto, .fields = &struct_fields, .decls = &.{}, .is_tuple = false, - } }); + }); } test { diff --git a/lib/std/Io/Reader.zig b/lib/std/Io/Reader.zig index 518fdf256824..9e8952b6ee03 100644 --- a/lib/std/Io/Reader.zig +++ b/lib/std/Io/Reader.zig @@ -1172,10 +1172,10 @@ pub const TakeLeb128Error = Error || error{Overflow}; /// Read a single LEB128 value as type T, or `error.Overflow` if the value cannot fit. pub fn takeLeb128(r: *Reader, comptime Result: type) TakeLeb128Error!Result { const result_info = @typeInfo(Result).int; - return std.math.cast(Result, try r.takeMultipleOf7Leb128(@Type(.{ .int = .{ - .signedness = result_info.signedness, - .bits = std.mem.alignForwardAnyAlign(u16, result_info.bits, 7), - } }))) orelse error.Overflow; + return std.math.cast(Result, try r.takeMultipleOf7Leb128(@Int( + result_info.signedness, + std.mem.alignForwardAnyAlign(u16, result_info.bits, 7), + ))) orelse error.Overflow; } pub fn expandTotalCapacity(r: *Reader, allocator: Allocator, n: usize) Allocator.Error!void { @@ -1231,10 +1231,7 @@ fn takeMultipleOf7Leb128(r: *Reader, comptime Result: type) TakeLeb128Error!Resu const result_info = @typeInfo(Result).int; comptime assert(result_info.bits % 7 == 0); var remaining_bits: std.math.Log2IntCeil(Result) = result_info.bits; - const UnsignedResult = @Type(.{ .int = .{ - .signedness = .unsigned, - .bits = result_info.bits, - } }); + const UnsignedResult = @Int(.unsigned, result_info.bits); var result: UnsignedResult = 0; var fits = true; while (true) { diff --git a/lib/std/Io/Writer.zig b/lib/std/Io/Writer.zig index 1d6bcb613966..7b1f9894509d 100644 --- a/lib/std/Io/Writer.zig +++ b/lib/std/Io/Writer.zig @@ -1781,7 +1781,7 @@ pub fn writeUleb128(w: *Writer, value: anytype) Error!void { try w.writeLeb128(switch (@typeInfo(@TypeOf(value))) { .comptime_int => @as(std.math.IntFittingRange(0, @abs(value)), value), .int => |value_info| switch (value_info.signedness) { - .signed => @as(@Type(.{ .int = .{ .signedness = .unsigned, .bits = value_info.bits -| 1 } }), @intCast(value)), + .signed => @as(@Int(.unsigned, value_info.bits -| 1), @intCast(value)), .unsigned => value, }, else => comptime unreachable, @@ -1794,7 +1794,7 @@ pub fn writeSleb128(w: *Writer, value: anytype) Error!void { .comptime_int => @as(std.math.IntFittingRange(@min(value, -1), @max(0, value)), value), .int => |value_info| switch (value_info.signedness) { .signed => value, - .unsigned => @as(@Type(.{ .int = .{ .signedness = .signed, .bits = value_info.bits + 1 } }), value), + .unsigned => @as(@Int(.signed, value_info.bits + 1), value), }, else => comptime unreachable, }); @@ -1803,10 +1803,10 @@ pub fn writeSleb128(w: *Writer, value: anytype) Error!void { /// Write a single integer as LEB128 to the given writer. pub fn writeLeb128(w: *Writer, value: anytype) Error!void { const value_info = @typeInfo(@TypeOf(value)).int; - try w.writeMultipleOf7Leb128(@as(@Type(.{ .int = .{ - .signedness = value_info.signedness, - .bits = std.mem.alignForwardAnyAlign(u16, value_info.bits, 7), - } }), value)); + try w.writeMultipleOf7Leb128(@as(@Int( + value_info.signedness, + std.mem.alignForwardAnyAlign(u16, value_info.bits, 7), + ), value)); } fn writeMultipleOf7Leb128(w: *Writer, value: anytype) Error!void { @@ -1821,16 +1821,10 @@ fn writeMultipleOf7Leb128(w: *Writer, value: anytype) Error!void { .unsigned => remaining > std.math.maxInt(u7), }; byte.* = if (@inComptime()) @typeInfo(@TypeOf(buffer)).pointer.child{ - .bits = @bitCast(@as(@Type(.{ .int = .{ - .signedness = value_info.signedness, - .bits = 7, - } }), @truncate(remaining))), + .bits = @bitCast(@as(@Int(value_info.signedness, 7), @truncate(remaining))), .more = more, } else .{ - .bits = @bitCast(@as(@Type(.{ .int = .{ - .signedness = value_info.signedness, - .bits = 7, - } }), @truncate(remaining))), + .bits = @bitCast(@as(@Int(value_info.signedness, 7), @truncate(remaining))), .more = more, }; if (value_info.bits > 7) remaining >>= 7; diff --git a/lib/std/Io/fixed_buffer_stream.zig b/lib/std/Io/fixed_buffer_stream.zig index 67d6f3d28638..aff921f73dc2 100644 --- a/lib/std/Io/fixed_buffer_stream.zig +++ b/lib/std/Io/fixed_buffer_stream.zig @@ -126,7 +126,7 @@ fn Slice(comptime T: type) type { else => @compileError("invalid type given to fixedBufferStream"), } new_ptr_info.size = .slice; - return @Type(.{ .pointer = new_ptr_info }); + return @Pointer(new_ptr_info); }, else => @compileError("invalid type given to fixedBufferStream"), } diff --git a/lib/std/crypto/phc_encoding.zig b/lib/std/crypto/phc_encoding.zig index 507a02b983e5..b24c55a08848 100644 --- a/lib/std/crypto/phc_encoding.zig +++ b/lib/std/crypto/phc_encoding.zig @@ -94,12 +94,12 @@ pub fn deserialize(comptime HashResult: type, str: []const u8) Error!HashResult if (kvSplit(field)) |opt_version| { if (mem.eql(u8, opt_version.key, version_param_name)) { if (@hasField(HashResult, "alg_version")) { - const value_type_info = switch (@typeInfo(@TypeOf(out.alg_version))) { - .optional => |opt| @typeInfo(opt.child), - else => |t| t, + const ValueType = switch (@typeInfo(@TypeOf(out.alg_version))) { + .optional => |opt| opt.child, + else => @TypeOf(out.alg_version), }; out.alg_version = fmt.parseUnsigned( - @Type(value_type_info), + ValueType, opt_version.value, 10, ) catch return Error.InvalidEncoding; diff --git a/lib/std/crypto/tls.zig b/lib/std/crypto/tls.zig index 74113225cbb7..ec03eba35179 100644 --- a/lib/std/crypto/tls.zig +++ b/lib/std/crypto/tls.zig @@ -601,7 +601,7 @@ pub inline fn array( const elem_size = @divExact(@bitSizeOf(Elem), 8); var arr: [len_size + elem_size * elems.len]u8 = undefined; std.mem.writeInt(Len, arr[0..len_size], @intCast(elem_size * elems.len), .big); - const ElemInt = @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(Elem) } }); + const ElemInt = @Int(.unsigned, @bitSizeOf(Elem)); for (0.., @as([elems.len]Elem, elems)) |index, elem| { std.mem.writeInt( ElemInt, diff --git a/lib/std/enums.zig b/lib/std/enums.zig index e34cf17e0720..f2ff91810f34 100644 --- a/lib/std/enums.zig +++ b/lib/std/enums.zig @@ -43,12 +43,12 @@ pub fn EnumFieldStruct(comptime E: type, comptime Data: type, comptime field_def .alignment = if (@sizeOf(Data) > 0) @alignOf(Data) else 0, }; } - return @Type(.{ .@"struct" = .{ + return @Struct(.{ .layout = .auto, .fields = &struct_fields, .decls = &.{}, .is_tuple = false, - } }); + }); } /// Looks up the supplied fields in the given enum type. diff --git a/lib/std/fmt/float.zig b/lib/std/fmt/float.zig index 16df95ad28e7..44a71f90f42c 100644 --- a/lib/std/fmt/float.zig +++ b/lib/std/fmt/float.zig @@ -61,7 +61,7 @@ pub fn render(buf: []u8, value: anytype, options: Options) Error![]const u8 { const T = @TypeOf(v); comptime std.debug.assert(@typeInfo(T) == .float); - const I = @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(T) } }); + const I = @Int(.unsigned, @bitSizeOf(T)); const DT = if (@bitSizeOf(T) <= 64) u64 else u128; const tables = switch (DT) { @@ -1516,7 +1516,7 @@ const FLOAT128_POW5_INV_ERRORS: [154]u64 = .{ const builtin = @import("builtin"); fn check(comptime T: type, value: T, comptime expected: []const u8) !void { - const I = @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(T) } }); + const I = @Int(.unsigned, @bitSizeOf(T)); var buf: [6000]u8 = undefined; const value_bits: I = @bitCast(value); diff --git a/lib/std/hash.zig b/lib/std/hash.zig index e0eca9e39173..d7b8b62e2cb8 100644 --- a/lib/std/hash.zig +++ b/lib/std/hash.zig @@ -45,7 +45,7 @@ pub fn int(input: anytype) @TypeOf(input) { const info = @typeInfo(@TypeOf(input)).int; const bits = info.bits; // Convert input to unsigned integer (easier to deal with) - const Uint = @Type(.{ .int = .{ .bits = bits, .signedness = .unsigned } }); + const Uint = @Int(.unsigned, bits); const u_input: Uint = @bitCast(input); if (bits > 256) @compileError("bit widths > 256 are unsupported, use std.hash.autoHash functionality."); // For bit widths that don't have a dedicated function, use a heuristic diff --git a/lib/std/hash/auto_hash.zig b/lib/std/hash/auto_hash.zig index 7ecd1860e460..0182dce9d9c7 100644 --- a/lib/std/hash/auto_hash.zig +++ b/lib/std/hash/auto_hash.zig @@ -91,10 +91,7 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void { // Help the optimizer see that hashing an int is easy by inlining! // TODO Check if the situation is better after #561 is resolved. .int => |int| switch (int.signedness) { - .signed => hash(hasher, @as(@Type(.{ .int = .{ - .bits = int.bits, - .signedness = .unsigned, - } }), @bitCast(key)), strat), + .signed => hash(hasher, @as(@Int(.unsigned, int.bits), @bitCast(key)), strat), .unsigned => { if (std.meta.hasUniqueRepresentation(Key)) { @call(.always_inline, Hasher.update, .{ hasher, std.mem.asBytes(&key) }); diff --git a/lib/std/log.zig b/lib/std/log.zig index ca3896e2da27..dcb7224bc01a 100644 --- a/lib/std/log.zig +++ b/lib/std/log.zig @@ -28,7 +28,7 @@ //! //! pub fn myLogFn( //! comptime level: std.log.Level, -//! comptime scope: @Type(.enum_literal), +//! comptime scope: @TypeOf(.enum_literal), //! comptime format: []const u8, //! args: anytype, //! ) void { @@ -107,7 +107,7 @@ pub const default_level: Level = switch (builtin.mode) { const level = std.options.log_level; pub const ScopeLevel = struct { - scope: @Type(.enum_literal), + scope: @TypeOf(.enum_literal), level: Level, }; @@ -115,7 +115,7 @@ const scope_levels = std.options.log_scope_levels; fn log( comptime message_level: Level, - comptime scope: @Type(.enum_literal), + comptime scope: @TypeOf(.enum_literal), comptime format: []const u8, args: anytype, ) void { @@ -125,7 +125,7 @@ fn log( } /// Determine if a specific log message level and scope combination are enabled for logging. -pub fn logEnabled(comptime message_level: Level, comptime scope: @Type(.enum_literal)) bool { +pub fn logEnabled(comptime message_level: Level, comptime scope: @TypeOf(.enum_literal)) bool { inline for (scope_levels) |scope_level| { if (scope_level.scope == scope) return @intFromEnum(message_level) <= @intFromEnum(scope_level.level); } @@ -144,7 +144,7 @@ pub fn defaultLogEnabled(comptime message_level: Level) bool { /// function returns. pub fn defaultLog( comptime message_level: Level, - comptime scope: @Type(.enum_literal), + comptime scope: @TypeOf(.enum_literal), comptime format: []const u8, args: anytype, ) void { @@ -158,7 +158,7 @@ pub fn defaultLog( /// Returns a scoped logging namespace that logs all messages using the scope /// provided here. -pub fn scoped(comptime scope: @Type(.enum_literal)) type { +pub fn scoped(comptime scope: @TypeOf(.enum_literal)) type { return struct { /// Log an error message. This log level is intended to be used /// when something has gone wrong. This might be recoverable or might diff --git a/lib/std/math.zig b/lib/std/math.zig index 1cd9a83a1403..49d095e56198 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -449,12 +449,7 @@ pub fn wrap(x: anytype, r: anytype) @TypeOf(x) { // in the rare usecase of r not being comptime_int or float, // take the penalty of having an intermediary type conversion, // otherwise the alternative is to unwind iteratively to avoid overflow - const R = comptime do: { - var info = info_r; - info.int.bits += 1; - info.int.signedness = .signed; - break :do @Type(info); - }; + const R = @Int(.signed, info_r.int.bits + 1); const radius: if (info_r.int.signedness == .signed) @TypeOf(r) else R = r; return @intCast(@mod(x - radius, 2 * @as(R, r)) - r); // provably impossible to overflow }, @@ -776,14 +771,14 @@ pub fn Log2IntCeil(comptime T: type) type { pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) type { assert(from <= to); const signedness: std.builtin.Signedness = if (from < 0) .signed else .unsigned; - return @Type(.{ .int = .{ - .signedness = signedness, - .bits = @as(u16, @intFromBool(signedness == .signed)) + + return @Int( + signedness, + @as(u16, @intFromBool(signedness == .signed)) + switch (if (from < 0) @max(@abs(from) - 1, to) else to) { 0 => 0, else => |pos_max| 1 + log2(pos_max), }, - } }); + ); } test IntFittingRange { @@ -1085,8 +1080,8 @@ pub const AlignCastError = error{UnalignedMemory}; fn AlignCastResult(comptime alignment: Alignment, comptime Ptr: type) type { var ptr_info = @typeInfo(Ptr); - ptr_info.pointer.alignment = alignment.toByteUnits(); - return @Type(ptr_info); + ptr_info.alignment = alignment.toByteUnits(); + return @Pointer(ptr_info); } /// Align cast a pointer but return an error if it's the wrong alignment diff --git a/lib/std/math/big/int_test.zig b/lib/std/math/big/int_test.zig index f44b254cf196..1134cb6623ba 100644 --- a/lib/std/math/big/int_test.zig +++ b/lib/std/math/big/int_test.zig @@ -2788,11 +2788,11 @@ test "bitNotWrap more than two limbs" { const bits = @bitSizeOf(Limb) * 4 + 2; try res.bitNotWrap(&a, .unsigned, bits); - const Unsigned = @Type(.{ .int = .{ .signedness = .unsigned, .bits = bits } }); + const Unsigned = @Int(.unsigned, bits); try testing.expectEqual((try res.toInt(Unsigned)), ~@as(Unsigned, maxInt(Limb))); try res.bitNotWrap(&a, .signed, bits); - const Signed = @Type(.{ .int = .{ .signedness = .signed, .bits = bits } }); + const Signed = @Int(.signed, bits); try testing.expectEqual((try res.toInt(Signed)), ~@as(Signed, maxInt(Limb))); } diff --git a/lib/std/math/float.zig b/lib/std/math/float.zig index df7d7fe1abcf..7df18c4cb2cb 100644 --- a/lib/std/math/float.zig +++ b/lib/std/math/float.zig @@ -16,22 +16,10 @@ pub fn FloatRepr(comptime Float: type) type { exponent: BiasedExponent, sign: Sign, - pub const StoredMantissa = @Type(.{ .int = .{ - .signedness = .unsigned, - .bits = floatMantissaBits(Float), - } }); - pub const Mantissa = @Type(.{ .int = .{ - .signedness = .unsigned, - .bits = 1 + fractional_bits, - } }); - pub const Exponent = @Type(.{ .int = .{ - .signedness = .signed, - .bits = exponent_bits, - } }); - pub const BiasedExponent = enum(@Type(.{ .int = .{ - .signedness = .unsigned, - .bits = exponent_bits, - } })) { + pub const StoredMantissa = @Int(.unsigned, floatMantissaBits(Float)); + pub const Mantissa = @Int(.unsigned, 1 + fractional_bits); + pub const Exponent = @Int(.signed, exponent_bits); + pub const BiasedExponent = enum(@Int(.unsigned, exponent_bits)) { denormal = 0, min_normal = 1, zero = (1 << (exponent_bits - 1)) - 1, @@ -58,14 +46,8 @@ pub fn FloatRepr(comptime Float: type) type { fraction: Fraction, exponent: Normalized.Exponent, - pub const Fraction = @Type(.{ .int = .{ - .signedness = .unsigned, - .bits = fractional_bits, - } }); - pub const Exponent = @Type(.{ .int = .{ - .signedness = .signed, - .bits = 1 + exponent_bits, - } }); + pub const Fraction = @Int(.unsigned, fractional_bits); + pub const Exponent = @Int(.signed, 1 + exponent_bits); /// This currently truncates denormal values, which needs to be fixed before this can be used to /// produce a rounded value. @@ -124,7 +106,7 @@ inline fn mantissaOne(comptime T: type) comptime_int { /// Creates floating point type T from an unbiased exponent and raw mantissa. inline fn reconstructFloat(comptime T: type, comptime exponent: comptime_int, comptime mantissa: comptime_int) T { - const TBits = @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(T) } }); + const TBits = @Int(.unsigned, @bitSizeOf(T)); const biased_exponent = @as(TBits, exponent + floatExponentMax(T)); return @as(T, @bitCast((biased_exponent << floatMantissaBits(T)) | @as(TBits, mantissa))); } @@ -211,7 +193,7 @@ pub inline fn floatEps(comptime T: type) T { pub inline fn floatEpsAt(comptime T: type, x: T) T { switch (@typeInfo(T)) { .float => |F| { - const U: type = @Type(.{ .int = .{ .signedness = .unsigned, .bits = F.bits } }); + const U: type = @Int(.unsigned, F.bits); const u: U = @bitCast(x); const y: T = @bitCast(u ^ 1); return @abs(x - y); diff --git a/lib/std/math/log2.zig b/lib/std/math/log2.zig index f5f0cf771e2e..31b5e8283df7 100644 --- a/lib/std/math/log2.zig +++ b/lib/std/math/log2.zig @@ -33,10 +33,7 @@ pub fn log2(x: anytype) @TypeOf(x) { return result; }, .int => |int_info| math.log2_int(switch (int_info.signedness) { - .signed => @Type(.{ .int = .{ - .signedness = .unsigned, - .bits = int_info.bits -| 1, - } }), + .signed => @Int(.unsigned, int_info.bits -| 1), .unsigned => T, }, @intCast(x)), else => @compileError("log2 not implemented for " ++ @typeName(T)), diff --git a/lib/std/math/log_int.zig b/lib/std/math/log_int.zig index 96227639d0b7..6a4318e1da03 100644 --- a/lib/std/math/log_int.zig +++ b/lib/std/math/log_int.zig @@ -65,7 +65,7 @@ test "log_int" { // Test all unsigned integers with 2, 3, ..., 64 bits. // We cannot test 0 or 1 bits since base must be > 1. inline for (2..64 + 1) |bits| { - const T = @Type(.{ .int = .{ .signedness = .unsigned, .bits = @intCast(bits) } }); + const T = @Int(.unsigned, @intCast(bits)); // for base = 2, 3, ..., min(maxInt(T),1024) var base: T = 1; diff --git a/lib/std/math/signbit.zig b/lib/std/math/signbit.zig index 2b50d0cbd9ff..7c0ea05d7421 100644 --- a/lib/std/math/signbit.zig +++ b/lib/std/math/signbit.zig @@ -6,10 +6,7 @@ const expect = std.testing.expect; pub fn signbit(x: anytype) bool { return switch (@typeInfo(@TypeOf(x))) { .int, .comptime_int => x, - .float => |float| @as(@Type(.{ .int = .{ - .signedness = .signed, - .bits = float.bits, - } }), @bitCast(x)), + .float => |float| @as(@Int(.signed, float.bits), @bitCast(x)), .comptime_float => @as(i128, @bitCast(@as(f128, x))), // any float type will do else => @compileError("std.math.signbit does not support " ++ @typeName(@TypeOf(x))), } < 0; diff --git a/lib/std/math/sqrt.zig b/lib/std/math/sqrt.zig index 0753277bb75d..b91e94987e22 100644 --- a/lib/std/math/sqrt.zig +++ b/lib/std/math/sqrt.zig @@ -80,7 +80,7 @@ test sqrt_int { /// Returns the return type `sqrt` will return given an operand of type `T`. pub fn Sqrt(comptime T: type) type { return switch (@typeInfo(T)) { - .int => |int| @Type(.{ .int = .{ .signedness = .unsigned, .bits = (int.bits + 1) / 2 } }), + .int => |int| @Int(.unsigned, (int.bits + 1) / 2), else => T, }; } diff --git a/lib/std/mem.zig b/lib/std/mem.zig index c9d0bddc74a8..fa7e4b8a0778 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -821,7 +821,7 @@ fn Span(comptime T: type) type { .one, .slice => @compileError("invalid type given to std.mem.span: " ++ @typeName(T)), } new_ptr_info.size = .slice; - return @Type(.{ .pointer = new_ptr_info }); + return @Pointer(new_ptr_info); }, else => {}, } @@ -913,7 +913,7 @@ fn SliceTo(comptime T: type, comptime end: std.meta.Elem(T)) type { new_ptr_info.is_allowzero = false; }, } - return @Type(.{ .pointer = new_ptr_info }); + return @Pointer(new_ptr_info); }, else => {}, } @@ -3673,14 +3673,14 @@ fn ReverseIterator(comptime T: type) type { new_ptr_info.size = .many; new_ptr_info.child = array_info.child; new_ptr_info.sentinel_ptr = array_info.sentinel_ptr; - break :blk @Type(.{ .pointer = new_ptr_info }); + break :blk @Pointer(new_ptr_info); }, else => {}, }, .slice => { var new_ptr_info = ptr_info; new_ptr_info.size = .many; - break :blk @Type(.{ .pointer = new_ptr_info }); + break :blk @Pointer(new_ptr_info); }, else => {}, }, @@ -3689,13 +3689,13 @@ fn ReverseIterator(comptime T: type) type { @compileError("expected slice or pointer to array, found '" ++ @typeName(T) ++ "'"); }; const Element = std.meta.Elem(Pointer); - const ElementPointer = @Type(.{ .pointer = ptr: { + const ElementPointer = @Pointer(ptr: { var ptr = @typeInfo(Pointer).pointer; ptr.size = .one; ptr.child = Element; ptr.sentinel_ptr = null; break :ptr ptr; - } }); + }); return struct { ptr: Pointer, index: usize, @@ -4055,17 +4055,15 @@ fn CopyPtrAttrs( comptime child: type, ) type { const info = @typeInfo(source).pointer; - return @Type(.{ - .pointer = .{ - .size = size, - .is_const = info.is_const, - .is_volatile = info.is_volatile, - .is_allowzero = info.is_allowzero, - .alignment = info.alignment, - .address_space = info.address_space, - .child = child, - .sentinel_ptr = null, - }, + return @Pointer(.{ + .size = size, + .is_const = info.is_const, + .is_volatile = info.is_volatile, + .is_allowzero = info.is_allowzero, + .alignment = info.alignment, + .address_space = info.address_space, + .child = child, + .sentinel_ptr = null, }); } @@ -4637,17 +4635,15 @@ test "freeing empty string with null-terminated sentinel" { /// all other pointer attributes copied from `AttributeSource`. fn AlignedSlice(comptime AttributeSource: type, comptime new_alignment: usize) type { const info = @typeInfo(AttributeSource).pointer; - return @Type(.{ - .pointer = .{ - .size = .slice, - .is_const = info.is_const, - .is_volatile = info.is_volatile, - .is_allowzero = info.is_allowzero, - .alignment = new_alignment, - .address_space = info.address_space, - .child = info.child, - .sentinel_ptr = null, - }, + return @Pointer(.{ + .size = .slice, + .is_const = info.is_const, + .is_volatile = info.is_volatile, + .is_allowzero = info.is_allowzero, + .alignment = new_alignment, + .address_space = info.address_space, + .child = info.child, + .sentinel_ptr = null, }); } diff --git a/lib/std/meta.zig b/lib/std/meta.zig index 0cee23cfa883..e1549e96ea2e 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -170,57 +170,41 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type { switch (@typeInfo(T)) { .pointer => |info| switch (info.size) { .one => switch (@typeInfo(info.child)) { - .array => |array_info| return @Type(.{ - .pointer = .{ - .size = info.size, - .is_const = info.is_const, - .is_volatile = info.is_volatile, - .alignment = info.alignment, - .address_space = info.address_space, - .child = @Type(.{ - .array = .{ - .len = array_info.len, - .child = array_info.child, - .sentinel_ptr = @as(?*const anyopaque, @ptrCast(&sentinel_val)), - }, - }), - .is_allowzero = info.is_allowzero, - .sentinel_ptr = info.sentinel_ptr, - }, - }), - else => {}, - }, - .many, .slice => return @Type(.{ - .pointer = .{ + .array => |array_info| return @Pointer(.{ .size = info.size, .is_const = info.is_const, .is_volatile = info.is_volatile, .alignment = info.alignment, .address_space = info.address_space, - .child = info.child, + .child = [array_info.len:@as(?*const anyopaque, @ptrCast(&sentinel_val))]array_info.child, .is_allowzero = info.is_allowzero, - .sentinel_ptr = @as(?*const anyopaque, @ptrCast(&sentinel_val)), - }, + .sentinel_ptr = info.sentinel_ptr, + }), + else => {}, + }, + .many, .slice => return @Pointer(.{ + .size = info.size, + .is_const = info.is_const, + .is_volatile = info.is_volatile, + .alignment = info.alignment, + .address_space = info.address_space, + .child = info.child, + .is_allowzero = info.is_allowzero, + .sentinel_ptr = @as(?*const anyopaque, @ptrCast(&sentinel_val)), }), else => {}, }, .optional => |info| switch (@typeInfo(info.child)) { .pointer => |ptr_info| switch (ptr_info.size) { - .many => return @Type(.{ - .optional = .{ - .child = @Type(.{ - .pointer = .{ - .size = ptr_info.size, - .is_const = ptr_info.is_const, - .is_volatile = ptr_info.is_volatile, - .alignment = ptr_info.alignment, - .address_space = ptr_info.address_space, - .child = ptr_info.child, - .is_allowzero = ptr_info.is_allowzero, - .sentinel_ptr = @as(?*const anyopaque, @ptrCast(&sentinel_val)), - }, - }), - }, + .many => return ?@Pointer(.{ + .size = ptr_info.size, + .is_const = ptr_info.is_const, + .is_volatile = ptr_info.is_volatile, + .alignment = ptr_info.alignment, + .address_space = ptr_info.address_space, + .child = ptr_info.child, + .is_allowzero = ptr_info.is_allowzero, + .sentinel_ptr = @as(?*const anyopaque, @ptrCast(&sentinel_val)), }), else => {}, }, @@ -489,13 +473,11 @@ pub fn FieldEnum(comptime T: type) type { const field_infos = fields(T); if (field_infos.len == 0) { - return @Type(.{ - .@"enum" = .{ - .tag_type = u0, - .fields = &.{}, - .decls = &.{}, - .is_exhaustive = true, - }, + return @Enum(.{ + .tag_type = u0, + .fields = &.{}, + .decls = &.{}, + .is_exhaustive = true, }); } @@ -518,13 +500,11 @@ pub fn FieldEnum(comptime T: type) type { .value = i, }; } - return @Type(.{ - .@"enum" = .{ - .tag_type = std.math.IntFittingRange(0, field_infos.len - 1), - .fields = &enumFields, - .decls = &decls, - .is_exhaustive = true, - }, + return @Enum(.{ + .tag_type = std.math.IntFittingRange(0, field_infos.len - 1), + .fields = &enumFields, + .decls = &decls, + .is_exhaustive = true, }); } @@ -588,13 +568,11 @@ pub fn DeclEnum(comptime T: type) type { inline for (fieldInfos, 0..) |field, i| { enumDecls[i] = .{ .name = field.name, .value = i }; } - return @Type(.{ - .@"enum" = .{ - .tag_type = std.math.IntFittingRange(0, if (fieldInfos.len == 0) 0 else fieldInfos.len - 1), - .fields = &enumDecls, - .decls = &decls, - .is_exhaustive = true, - }, + return @Enum(.{ + .tag_type = std.math.IntFittingRange(0, if (fieldInfos.len == 0) 0 else fieldInfos.len - 1), + .fields = &enumDecls, + .decls = &decls, + .is_exhaustive = true, }); } @@ -871,26 +849,20 @@ pub fn declList(comptime Namespace: type, comptime Decl: type) []const *const De } } +/// Deprecated: use @Int pub fn Int(comptime signedness: std.builtin.Signedness, comptime bit_count: u16) type { - return @Type(.{ - .int = .{ - .signedness = signedness, - .bits = bit_count, - }, - }); + return @Int(signedness, bit_count); } pub fn Float(comptime bit_count: u8) type { - return @Type(.{ - .float = .{ .bits = bit_count }, - }); -} - -test Float { - try testing.expectEqual(f16, Float(16)); - try testing.expectEqual(f32, Float(32)); - try testing.expectEqual(f64, Float(64)); - try testing.expectEqual(f128, Float(128)); + return switch (bit_count) { + 16 => f16, + 32 => f32, + 64 => f64, + 80 => f80, + 128 => f128, + else => @compileError("invalid float bit count"), + }; } /// For a given function type, returns a tuple type which fields will @@ -943,13 +915,11 @@ fn CreateUniqueTuple(comptime N: comptime_int, comptime types: [N]type) type { }; } - return @Type(.{ - .@"struct" = .{ - .is_tuple = true, - .layout = .auto, - .decls = &.{}, - .fields = &tuple_fields, - }, + return @Struct(.{ + .is_tuple = true, + .layout = .auto, + .decls = &.{}, + .fields = &tuple_fields, }); } diff --git a/lib/std/meta/trailer_flags.zig b/lib/std/meta/trailer_flags.zig index ddf3790c194c..9df59abfa5ac 100644 --- a/lib/std/meta/trailer_flags.zig +++ b/lib/std/meta/trailer_flags.zig @@ -30,13 +30,11 @@ pub fn TrailerFlags(comptime Fields: type) type { .alignment = @alignOf(?struct_field.type), }; } - break :blk @Type(.{ - .@"struct" = .{ - .layout = .auto, - .fields = &fields, - .decls = &.{}, - .is_tuple = false, - }, + break :blk @Struct(.{ + .layout = .auto, + .fields = &fields, + .decls = &.{}, + .is_tuple = false, }); }; diff --git a/lib/std/multi_array_list.zig b/lib/std/multi_array_list.zig index 160a9f2fba6f..0f2d06a5b89a 100644 --- a/lib/std/multi_array_list.zig +++ b/lib/std/multi_array_list.zig @@ -32,12 +32,12 @@ pub fn MultiArrayList(comptime T: type) type { const Elem = switch (@typeInfo(T)) { .@"struct" => T, .@"union" => |u| struct { - pub const Bare = @Type(.{ .@"union" = .{ + pub const Bare = @Union(.{ .layout = u.layout, .tag_type = null, .fields = u.fields, .decls = &.{}, - } }); + }); pub const Tag = u.tag_type orelse @compileError("MultiArrayList does not support untagged unions"); tags: Tag, @@ -586,12 +586,12 @@ pub fn MultiArrayList(comptime T: type) type { .is_comptime = fields[i].is_comptime, .alignment = fields[i].alignment, }; - break :entry @Type(.{ .@"struct" = .{ + break :entry @Struct(.{ .layout = .@"extern", .fields = &entry_fields, .decls = &.{}, .is_tuple = false, - } }); + }); }; /// This function is used in the debugger pretty formatters in tools/ to fetch the /// child field order and entry type to facilitate fancy debug printing for this type. @@ -1002,13 +1002,12 @@ test "struct with many fields" { .alignment = @alignOf(u32), }; } - const info: std.builtin.Type = .{ .@"struct" = .{ + return @Struct(.{ .layout = .auto, .fields = &fields, .decls = &.{}, .is_tuple = false, - } }; - return @Type(info); + }); } fn doTest(ally: std.mem.Allocator, count: comptime_int) !void { diff --git a/lib/std/zig.zig b/lib/std/zig.zig index fd22da91db1a..8b2ad83c8267 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -709,7 +709,10 @@ pub const EnvVar = enum { pub const SimpleComptimeReason = enum(u32) { // Evaluating at comptime because a builtin operand must be comptime-known. // These messages all mention a specific builtin. - operand_Type, + operand_Enum, + operand_Pointer, + operand_Struct, + operand_Union, operand_setEvalBranchQuota, operand_setFloatMode, operand_branchHint, @@ -791,7 +794,10 @@ pub const SimpleComptimeReason = enum(u32) { pub fn message(r: SimpleComptimeReason) []const u8 { return switch (r) { // zig fmt: off - .operand_Type => "operand to '@Type' must be comptime-known", + .operand_Enum => "operand to '@Enum' must be comptime-known", + .operand_Pointer => "operand to '@Pointer' must be comptime-known", + .operand_Struct => "operand to '@Struct' must be comptime-known", + .operand_Union => "operand to '@Union' must be comptime-known", .operand_setEvalBranchQuota => "operand to '@setEvalBranchQuota' must be comptime-known", .operand_setFloatMode => "operand to '@setFloatMode' must be comptime-known", .operand_branchHint => "operand to '@branchHint' must be comptime-known", diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index e2ec0e9eb6b3..e1b0e610cff6 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -1181,11 +1181,17 @@ fn nameStratExpr( => { const builtin_token = tree.nodeMainToken(node); const builtin_name = tree.tokenSlice(builtin_token); - if (!std.mem.eql(u8, builtin_name, "@Type")) return null; + const info = BuiltinFn.list.get(builtin_name) orelse return null; + const zir_tag, const builtin_val = switch (info.tag) { + .Enum => .{ Zir.Inst.Extended.enum_reify, Zir.Inst.BuiltinValue.enum_info }, + .Struct => .{ Zir.Inst.Extended.struct_reify, Zir.Inst.BuiltinValue.struct_info }, + .Union => .{ Zir.Inst.Extended.union_reify, Zir.Inst.BuiltinValue.union_info }, + else => return null, + }; var buf: [2]Ast.Node.Index = undefined; const params = tree.builtinCallParams(&buf, node).?; if (params.len != 1) return null; // let `builtinCall` error - return try builtinReify(gz, scope, ri, node, params[0], name_strat); + return try builtinReify(gz, scope, ri, node, params[0], name_strat, zir_tag, builtin_val); }, else => return null, } @@ -2691,6 +2697,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As .elem_type, .indexable_ptr_elem_type, .vec_arr_elem_type, + .int_reify, .vector_type, .indexable_ptr_len, .anyframe_type, @@ -9396,9 +9403,20 @@ fn builtinCall( return rvalue(gz, ri, try gz.addNodeExtended(.in_comptime, node), node); }, - .Type => { - return builtinReify(gz, scope, ri, node, params[0], .anon); + .Int => { + const signedness_ty = try gz.addBuiltinValue(node, .signedness); + const result = try gz.addPlNode(.int_reify, node, Zir.Inst.Bin{ + .lhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = signedness_ty } }, params[0], .type), + .rhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, params[1], .type), + }); + return rvalue(gz, ri, result, node); }, + .EnumLiteral => return rvalue(gz, ri, .enum_literal_type, node), + .Enum => return builtinReify(gz, scope, ri, node, params[0], .anon, .enum_reify, .enum_info), + .Pointer => return builtinReify(gz, scope, ri, node, params[0], .anon, .pointer_reify, .pointer_info), + .Struct => return builtinReify(gz, scope, ri, node, params[0], .anon, .struct_reify, .struct_info), + .Union => return builtinReify(gz, scope, ri, node, params[0], .anon, .union_reify, .union_info), + .panic => { try emitDbgNode(gz, node); return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0], .panic); @@ -9725,11 +9743,13 @@ fn builtinReify( node: Ast.Node.Index, arg_node: Ast.Node.Index, name_strat: Zir.Inst.NameStrategy, + tag: Zir.Inst.Extended, + builtin_val: Zir.Inst.BuiltinValue, ) InnerError!Zir.Inst.Ref { const astgen = gz.astgen; const gpa = astgen.gpa; - const type_info_ty = try gz.addBuiltinValue(node, .type_info); + const type_info_ty = try gz.addBuiltinValue(node, builtin_val); const operand = try expr(gz, scope, .{ .rl = .{ .coerced_ty = type_info_ty } }, arg_node); try gz.instructions.ensureUnusedCapacity(gpa, 1); @@ -9744,7 +9764,7 @@ fn builtinReify( astgen.instructions.appendAssumeCapacity(.{ .tag = .extended, .data = .{ .extended = .{ - .opcode = .reify, + .opcode = tag, .small = @intFromEnum(name_strat), .operand = payload_index, } }, diff --git a/lib/std/zig/AstRlAnnotate.zig b/lib/std/zig/AstRlAnnotate.zig index 52900224ccb0..48e0a061d7fe 100644 --- a/lib/std/zig/AstRlAnnotate.zig +++ b/lib/std/zig/AstRlAnnotate.zig @@ -886,6 +886,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. // TODO: this is a workaround for llvm/llvm-project#68409 // Zig tracking issue: #16876 .frame_address => return true, + .EnumLiteral => return false, // These builtins take a single argument with a known result type, but do not consume their // result pointer. .size_of, @@ -899,7 +900,10 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. .embed_file, .error_name, .set_runtime_safety, - .Type, + .Enum, + .Pointer, + .Struct, + .Union, .c_undef, .c_include, .wasm_memory_size, @@ -1064,6 +1068,11 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. _ = try astrl.expr(args[3], block, ResultInfo.none); return false; }, + .Int => { + _ = try astrl.expr(args[0], block, ResultInfo.type_only); + _ = try astrl.expr(args[1], block, ResultInfo.type_only); + return false; + }, .Vector => { _ = try astrl.expr(args[0], block, ResultInfo.type_only); _ = try astrl.expr(args[1], block, ResultInfo.type_only); diff --git a/lib/std/zig/BuiltinFn.zig b/lib/std/zig/BuiltinFn.zig index 5ef28fdfaf7b..ba778a679ef0 100644 --- a/lib/std/zig/BuiltinFn.zig +++ b/lib/std/zig/BuiltinFn.zig @@ -110,12 +110,17 @@ pub const Tag = enum { This, trap, truncate, - Type, + Enum, + EnumLiteral, + Int, + Pointer, + Struct, + Union, + Vector, type_info, type_name, TypeOf, union_init, - Vector, volatile_cast, work_item_id, work_group_size, @@ -937,9 +942,44 @@ pub const list = list: { }, }, .{ - "@Type", + "@Enum", + .{ + .tag = .Enum, + .param_count = 1, + }, + }, + .{ + "@EnumLiteral", + .{ + .tag = .EnumLiteral, + .param_count = 0, + }, + }, + .{ + "@Int", + .{ + .tag = .Int, + .param_count = 2, + }, + }, + .{ + "@Pointer", + .{ + .tag = .Pointer, + .param_count = 1, + }, + }, + .{ + "@Struct", + .{ + .tag = .Struct, + .param_count = 1, + }, + }, + .{ + "@Union", .{ - .tag = .Type, + .tag = .Union, .param_count = 1, }, }, diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig index c53ec630bacc..e1d75b96eafe 100644 --- a/lib/std/zig/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -260,6 +260,10 @@ pub const Inst = struct { /// `[N:S]T` syntax. Source location is the array type expression node. /// Uses the `pl_node` union field. Payload is `ArrayTypeSentinel`. array_type_sentinel, + /// `@Int` builtin. + /// Uses the `pl_node` union field with `Bin` payload. + /// lhs is signedness, rhs is bit count. + int_reify, /// `@Vector` builtin. /// Uses the `pl_node` union field with `Bin` payload. /// lhs is length, rhs is element type. @@ -1095,6 +1099,7 @@ pub const Inst = struct { .array_mul, .array_type, .array_type_sentinel, + .int_reify, .vector_type, .elem_type, .indexable_ptr_elem_type, @@ -1392,6 +1397,7 @@ pub const Inst = struct { .array_mul, .array_type, .array_type_sentinel, + .int_reify, .vector_type, .elem_type, .indexable_ptr_elem_type, @@ -1627,6 +1633,7 @@ pub const Inst = struct { .array_mul = .pl_node, .array_type = .pl_node, .array_type_sentinel = .pl_node, + .int_reify = .pl_node, .vector_type = .pl_node, .elem_type = .un_node, .indexable_ptr_elem_type = .un_node, @@ -2023,10 +2030,22 @@ pub const Inst = struct { /// Implement builtin `@errorFromInt`. /// `operand` is payload index to `UnNode`. error_from_int, - /// Implement builtin `@Type`. + /// Implement builtin `@Enum`. + /// `operand` is payload index to `Reify`. + /// `small` contains `NameStrategy`. + enum_reify, + /// Implement builtin `@Pointer`. + /// `operand` is payload index to `Reify`. + /// `small` contains `NameStrategy`. + pointer_reify, + /// Implement builtin `@Struct`. + /// `operand` is payload index to `Reify`. + /// `small` contains `NameStrategy`. + struct_reify, + /// Implement builtin `@Union`. /// `operand` is payload index to `Reify`. /// `small` contains `NameStrategy`. - reify, + union_reify, /// Implements the `@cmpxchgStrong` and `@cmpxchgWeak` builtins. /// `small` 0=>weak 1=>strong /// `operand` is payload index to `Cmpxchg`. @@ -3475,11 +3494,16 @@ pub const Inst = struct { calling_convention, address_space, float_mode, + signedness, reduce_op, call_modifier, prefetch_options, export_options, extern_options, + enum_info, + pointer_info, + struct_info, + union_info, type_info, branch_hint, // Values @@ -4107,6 +4131,7 @@ fn findTrackableInner( .array_mul, .array_type, .array_type_sentinel, + .int_reify, .vector_type, .elem_type, .indexable_ptr_elem_type, @@ -4379,7 +4404,12 @@ fn findTrackableInner( }, // Reifications and opaque declarations need tracking, but have no body. - .reify, .opaque_decl => return contents.other.append(gpa, inst), + .enum_reify, + .pointer_reify, + .struct_reify, + .union_reify, + .opaque_decl, + => return contents.other.append(gpa, inst), // Struct declarations need tracking and have bodies. .struct_decl => { @@ -5134,7 +5164,10 @@ pub fn assertTrackable(zir: Zir, inst_idx: Zir.Inst.Index) void { .union_decl, .enum_decl, .opaque_decl, - .reify, + .enum_reify, + .pointer_reify, + .struct_reify, + .union_reify, => {}, // tracked in order, as the owner instructions of explicit container types else => unreachable, // assertion failure; not trackable }, diff --git a/lib/std/zig/c_translation.zig b/lib/std/zig/c_translation.zig index c8cd980f5799..ff222ed0fa0b 100644 --- a/lib/std/zig/c_translation.zig +++ b/lib/std/zig/c_translation.zig @@ -337,7 +337,7 @@ test "shuffleVectorIndex" { pub fn FlexibleArrayType(comptime SelfType: type, comptime ElementType: type) type { switch (@typeInfo(SelfType)) { .pointer => |ptr| { - return @Type(.{ .pointer = .{ + return @Pointer(.{ .size = .c, .is_const = ptr.is_const, .is_volatile = ptr.is_volatile, @@ -346,7 +346,7 @@ pub fn FlexibleArrayType(comptime SelfType: type, comptime ElementType: type) ty .child = ElementType, .is_allowzero = true, .sentinel_ptr = null, - } }); + }); }, else => |info| @compileError("Invalid self type \"" ++ @tagName(info) ++ "\" for flexible array getter: " ++ @typeName(SelfType)), } diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig index a16ad688d1bf..e40eb6e54a51 100644 --- a/lib/std/zig/llvm/Builder.zig +++ b/lib/std/zig/llvm/Builder.zig @@ -8549,12 +8549,12 @@ pub const Metadata = enum(u32) { } fmt_str = fmt_str ++ ")\n"; - var fmt_args: @Type(.{ .@"struct" = .{ + var fmt_args: @Struct(.{ .layout = .auto, .fields = &fields, .decls = &.{}, .is_tuple = false, - } }) = undefined; + }) = undefined; fmt_args.distinct = @tagName(distinct); fmt_args.node = @tagName(node); inline for (names) |name| @field(fmt_args, name) = try formatter.fmt( diff --git a/src/InternPool.zig b/src/InternPool.zig index ba5725ec3072..3bc462461673 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -1138,12 +1138,12 @@ const Local = struct { .is_comptime = false, .alignment = 0, }; - return @Type(.{ .@"struct" = .{ + return @Struct(.{ .layout = .auto, .fields = &new_fields, .decls = &.{}, .is_tuple = elem_info.is_tuple, - } }); + }); } fn PtrElem(comptime opts: struct { size: std.builtin.Type.Pointer.Size, @@ -1154,7 +1154,7 @@ const Local = struct { var new_fields: [elem_fields.len]std.builtin.Type.StructField = undefined; for (&new_fields, elem_fields) |*new_field, elem_field| new_field.* = .{ .name = elem_field.name, - .type = @Type(.{ .pointer = .{ + .type = @Pointer(.{ .size = opts.size, .is_const = opts.is_const, .is_volatile = false, @@ -1163,17 +1163,17 @@ const Local = struct { .child = elem_field.type, .is_allowzero = false, .sentinel_ptr = null, - } }), + }), .default_value_ptr = null, .is_comptime = false, .alignment = 0, }; - return @Type(.{ .@"struct" = .{ + return @Struct(.{ .layout = .auto, .fields = &new_fields, .decls = &.{}, .is_tuple = elem_info.is_tuple, - } }); + }); } pub fn addOne(mutable: Mutable) Allocator.Error!PtrElem(.{ .size = .one }) { @@ -1983,7 +1983,7 @@ pub const Key = union(enum) { error_union_type: ErrorUnionType, simple_type: SimpleType, /// This represents a struct that has been explicitly declared in source code, - /// or was created with `@Type`. It is unique and based on a declaration. + /// or was created with `@Struct`. It is unique and based on a declaration. /// It may be a tuple, if declared like this: `struct {A, B, C}`. struct_type: NamespaceType, /// This is a tuple type. Tuples are logically similar to structs, but have some @@ -2140,7 +2140,7 @@ pub const Key = union(enum) { /// The union for which this is a tag type. union_type: Index, }, - /// This type originates from a reification via `@Type`, or from an anonymous initialization. + /// This type originates from a reification via `@Enum`, `@Struct`, `@Union`, or from an anonymous initialization. /// It is hashed based on its ZIR instruction index and fields, attributes, etc. /// To avoid making this key overly complex, the type-specific data is hashed by Sema. reified: struct { @@ -10158,16 +10158,8 @@ pub fn getGeneratedTagEnumType( } pub const OpaqueTypeInit = struct { - key: union(enum) { - declared: struct { - zir_index: TrackedInst.Index, - captures: []const CaptureValue, - }, - reified: struct { - zir_index: TrackedInst.Index, - // No type hash since reifid opaques have no data other than the `@Type` location - }, - }, + zir_index: TrackedInst.Index, + captures: []const CaptureValue, }; pub fn getOpaqueType( @@ -10176,15 +10168,11 @@ pub fn getOpaqueType( tid: Zcu.PerThread.Id, ini: OpaqueTypeInit, ) Allocator.Error!WipNamespaceType.Result { - var gop = try ip.getOrPutKey(gpa, tid, .{ .opaque_type = switch (ini.key) { - .declared => |d| .{ .declared = .{ - .zir_index = d.zir_index, - .captures = .{ .external = d.captures }, - } }, - .reified => |r| .{ .reified = .{ - .zir_index = r.zir_index, - .type_hash = 0, - } }, + var gop = try ip.getOrPutKey(gpa, tid, .{ .opaque_type = .{ + .declared = .{ + .zir_index = ini.zir_index, + .captures = .{ .external = ini.captures }, + }, } }); defer gop.deinit(); if (gop == .existing) return .{ .existing = gop.existing }; @@ -10194,30 +10182,19 @@ pub fn getOpaqueType( const extra = local.getMutableExtra(gpa); try items.ensureUnusedCapacity(1); - try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeOpaque).@"struct".fields.len + switch (ini.key) { - .declared => |d| d.captures.len, - .reified => 0, - }); + try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeOpaque).@"struct".fields.len + ini.captures.len); const extra_index = addExtraAssumeCapacity(extra, Tag.TypeOpaque{ .name = undefined, // set by `finish` .name_nav = undefined, // set by `finish` .namespace = undefined, // set by `finish` - .zir_index = switch (ini.key) { - inline else => |x| x.zir_index, - }, - .captures_len = switch (ini.key) { - .declared => |d| @intCast(d.captures.len), - .reified => std.math.maxInt(u32), - }, + .zir_index = ini.zir_index, + .captures_len = @intCast(ini.captures.len), }); items.appendAssumeCapacity(.{ .tag = .type_opaque, .data = extra_index, }); - switch (ini.key) { - .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}), - .reified => {}, - } + extra.appendSliceAssumeCapacity(.{@ptrCast(ini.captures)}); return .{ .wip = .{ .tid = tid, diff --git a/src/Sema.zig b/src/Sema.zig index 92f6705e4ea3..67e5fa8c9b1d 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1167,6 +1167,7 @@ fn analyzeBodyInner( .array_mul => try sema.zirArrayMul(block, inst), .array_type => try sema.zirArrayType(block, inst), .array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst), + .int_reify => try sema.zirReifyInt(block, inst), .vector_type => try sema.zirVectorType(block, inst), .as_node => try sema.zirAsNode(block, inst), .as_shift_operand => try sema.zirAsShiftOperand(block, inst), @@ -1411,7 +1412,10 @@ fn analyzeBodyInner( .select => try sema.zirSelect( block, extended), .int_from_error => try sema.zirIntFromError( block, extended), .error_from_int => try sema.zirErrorFromInt( block, extended), - .reify => try sema.zirReify( block, extended, inst), + .enum_reify => try sema.zirReifyEnum( block, extended, inst), + .pointer_reify => try sema.zirReifyPointer( block, extended, inst), + .struct_reify => try sema.zirReifyStruct( block, extended, inst), + .union_reify => try sema.zirReifyUnion( block, extended, inst), .cmpxchg => try sema.zirCmpxchg( block, extended), .c_va_arg => try sema.zirCVaArg( block, extended), .c_va_copy => try sema.zirCVaCopy( block, extended), @@ -3428,10 +3432,8 @@ fn zirOpaqueDecl( extra_index += captures_len * 2; const opaque_init: InternPool.OpaqueTypeInit = .{ - .key = .{ .declared = .{ - .zir_index = tracked_inst, - .captures = captures, - } }, + .zir_index = tracked_inst, + .captures = captures, }; const wip_ty = switch (try ip.getOpaqueType(gpa, pt.tid, opaque_init)) { .existing => |ty| { @@ -20663,7 +20665,18 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air return block.addUnOp(.tag_name, casted_operand); } -fn zirReify( +fn zirReifyInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { + const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; + const signedness_src = block.builtinCallArgSrc(inst_data.src_node, 0); + const bits_src = block.builtinCallArgSrc(inst_data.src_node, 1); + const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; + const signedness = try sema.resolveBuiltinEnum(block, signedness_src, extra.lhs, .Signedness, .{ .simple = .type }); + const bits: u16 = @intCast(try sema.resolveInt(block, bits_src, extra.rhs, .u16, .{ .simple = .type })); + const int_type = try sema.pt.intType(signedness, bits); + return Air.internedToRef(int_type.toIntern()); +} + +fn zirReifyEnum( sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, @@ -20673,6 +20686,9 @@ fn zirReify( const zcu = pt.zcu; const gpa = sema.gpa; const ip = &zcu.intern_pool; + + // This logic must stay in sync with the structure of `std.builtin.Type.Enum` - search for `fieldValue`. + const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small); const extra = sema.code.extraData(Zir.Inst.Reify, extended.operand).data; const tracked_inst = try block.trackZir(inst); @@ -20689,519 +20705,40 @@ fn zirReify( }, }, }; - const type_info_ty = try sema.getBuiltinType(src, .Type); + const enum_info_ty = try sema.getBuiltinType(src, .@"Type.Enum"); const uncasted_operand = try sema.resolveInst(extra.operand); - const type_info = try sema.coerce(block, type_info_ty, uncasted_operand, operand_src); - const val = try sema.resolveConstDefinedValue(block, operand_src, type_info, .{ .simple = .operand_Type }); - const union_val = ip.indexToKey(val.toIntern()).un; - if (try sema.anyUndef(block, operand_src, Value.fromInterned(union_val.val))) { + const type_info = try sema.coerce(block, enum_info_ty, uncasted_operand, operand_src); + const val = try sema.resolveConstDefinedValue(block, operand_src, type_info, .{ .simple = .operand_Enum }); + if (try sema.anyUndef(block, operand_src, val)) { return sema.failWithUseOfUndef(block, operand_src); } - const tag_index = type_info_ty.unionTagFieldIndex(Value.fromInterned(union_val.tag), zcu).?; - switch (@as(std.builtin.TypeId, @enumFromInt(tag_index))) { - .type => return .type_type, - .void => return .void_type, - .bool => return .bool_type, - .noreturn => return .noreturn_type, - .comptime_float => return .comptime_float_type, - .comptime_int => return .comptime_int_type, - .undefined => return .undefined_type, - .null => return .null_type, - .@"anyframe" => return sema.failWithUseOfAsync(block, src), - .enum_literal => return .enum_literal_type, - .int => { - const int = try sema.interpretBuiltinType(block, operand_src, .fromInterned(union_val.val), std.builtin.Type.Int); - const ty = try pt.intType(int.signedness, int.bits); - return Air.internedToRef(ty.toIntern()); - }, - .vector => { - const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); - const len_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "len", .no_embedded_nulls), - ).?); - const child_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "child", .no_embedded_nulls), - ).?); - - const len: u32 = @intCast(try len_val.toUnsignedIntSema(pt)); - const child_ty = child_val.toType(); - - try sema.checkVectorElemType(block, src, child_ty); - - const ty = try pt.vectorType(.{ - .len = len, - .child = child_ty.toIntern(), - }); - return Air.internedToRef(ty.toIntern()); - }, - .float => { - const float = try sema.interpretBuiltinType(block, operand_src, .fromInterned(union_val.val), std.builtin.Type.Float); - - const ty: Type = switch (float.bits) { - 16 => .f16, - 32 => .f32, - 64 => .f64, - 80 => .f80, - 128 => .f128, - else => return sema.fail(block, src, "{d}-bit float unsupported", .{float.bits}), - }; - return Air.internedToRef(ty.toIntern()); - }, - .pointer => { - const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); - const size_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "size", .no_embedded_nulls), - ).?); - const is_const_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "is_const", .no_embedded_nulls), - ).?); - const is_volatile_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "is_volatile", .no_embedded_nulls), - ).?); - const alignment_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "alignment", .no_embedded_nulls), - ).?); - const address_space_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "address_space", .no_embedded_nulls), - ).?); - const child_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "child", .no_embedded_nulls), - ).?); - const is_allowzero_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "is_allowzero", .no_embedded_nulls), - ).?); - const sentinel_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "sentinel_ptr", .no_embedded_nulls), - ).?); - - if (!try sema.intFitsInType(alignment_val, .u32, null)) { - return sema.fail(block, src, "alignment must fit in 'u32'", .{}); - } - - const alignment_val_int = try alignment_val.toUnsignedIntSema(pt); - if (alignment_val_int > 0 and !math.isPowerOfTwo(alignment_val_int)) { - return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{alignment_val_int}); - } - const abi_align = Alignment.fromByteUnits(alignment_val_int); - - const elem_ty = child_val.toType(); - if (abi_align != .none) { - try elem_ty.resolveLayout(pt); - } - - const ptr_size = try sema.interpretBuiltinType(block, operand_src, size_val, std.builtin.Type.Pointer.Size); - - const actual_sentinel: InternPool.Index = s: { - if (!sentinel_val.isNull(zcu)) { - if (ptr_size == .one or ptr_size == .c) { - return sema.fail(block, src, "sentinels are only allowed on slices and unknown-length pointers", .{}); - } - const sentinel_ptr_val = sentinel_val.optionalValue(zcu).?; - const ptr_ty = try pt.singleMutPtrType(elem_ty); - const sent_val = (try sema.pointerDeref(block, src, sentinel_ptr_val, ptr_ty)).?; - try sema.checkSentinelType(block, src, elem_ty); - break :s sent_val.toIntern(); - } - break :s .none; - }; - - if (elem_ty.zigTypeTag(zcu) == .noreturn) { - return sema.fail(block, src, "pointer to noreturn not allowed", .{}); - } else if (elem_ty.zigTypeTag(zcu) == .@"fn") { - if (ptr_size != .one) { - return sema.fail(block, src, "function pointers must be single pointers", .{}); - } - } else if (ptr_size == .many and elem_ty.zigTypeTag(zcu) == .@"opaque") { - return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{}); - } else if (ptr_size == .c) { - if (!try sema.validateExternType(elem_ty, .other)) { - const msg = msg: { - const msg = try sema.errMsg(src, "C pointers cannot point to non-C-ABI-compatible type '{f}'", .{elem_ty.fmt(pt)}); - errdefer msg.destroy(gpa); - - try sema.explainWhyTypeIsNotExtern(msg, src, elem_ty, .other); - - try sema.addDeclaredHereNote(msg, elem_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); - } - if (elem_ty.zigTypeTag(zcu) == .@"opaque") { - return sema.fail(block, src, "C pointers cannot point to opaque types", .{}); - } - } - - const ty = try pt.ptrTypeSema(.{ - .child = elem_ty.toIntern(), - .sentinel = actual_sentinel, - .flags = .{ - .size = ptr_size, - .is_const = is_const_val.toBool(), - .is_volatile = is_volatile_val.toBool(), - .alignment = abi_align, - .address_space = try sema.interpretBuiltinType(block, operand_src, address_space_val, std.builtin.AddressSpace), - .is_allowzero = is_allowzero_val.toBool(), - }, - }); - return Air.internedToRef(ty.toIntern()); - }, - .array => { - const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); - const len_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "len", .no_embedded_nulls), - ).?); - const child_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "child", .no_embedded_nulls), - ).?); - const sentinel_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "sentinel_ptr", .no_embedded_nulls), - ).?); - - const len = try len_val.toUnsignedIntSema(pt); - const child_ty = child_val.toType(); - const sentinel = if (sentinel_val.optionalValue(zcu)) |p| blk: { - const ptr_ty = try pt.singleMutPtrType(child_ty); - try sema.checkSentinelType(block, src, child_ty); - break :blk (try sema.pointerDeref(block, src, p, ptr_ty)).?; - } else null; - - const ty = try pt.arrayType(.{ - .len = len, - .sentinel = if (sentinel) |s| s.toIntern() else .none, - .child = child_ty.toIntern(), - }); - return Air.internedToRef(ty.toIntern()); - }, - .optional => { - const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); - const child_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "child", .no_embedded_nulls), - ).?); - - const child_ty = child_val.toType(); - - const ty = try pt.optionalType(child_ty.toIntern()); - return Air.internedToRef(ty.toIntern()); - }, - .error_union => { - const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); - const error_set_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "error_set", .no_embedded_nulls), - ).?); - const payload_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "payload", .no_embedded_nulls), - ).?); - - const error_set_ty = error_set_val.toType(); - const payload_ty = payload_val.toType(); - - if (error_set_ty.zigTypeTag(zcu) != .error_set) { - return sema.fail(block, src, "Type.ErrorUnion.error_set must be an error set type", .{}); - } - - const ty = try pt.errorUnionType(error_set_ty, payload_ty); - return Air.internedToRef(ty.toIntern()); - }, - .error_set => { - const payload_val = Value.fromInterned(union_val.val).optionalValue(zcu) orelse - return .anyerror_type; - - const names_val = try sema.derefSliceAsArray(block, src, payload_val, .{ .simple = .error_set_contents }); - - const len = try sema.usizeCast(block, src, names_val.typeOf(zcu).arrayLen(zcu)); - var names: InferredErrorSet.NameMap = .{}; - try names.ensureUnusedCapacity(sema.arena, len); - for (0..len) |i| { - const elem_val = try names_val.elemValue(pt, i); - const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern())); - const name_val = try elem_val.fieldValue(pt, elem_struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "name", .no_embedded_nulls), - ).?); - - const name = try sema.sliceToIpString(block, src, name_val, .{ .simple = .error_set_contents }); - _ = try pt.getErrorValue(name); - const gop = names.getOrPutAssumeCapacity(name); - if (gop.found_existing) { - return sema.fail(block, src, "duplicate error '{f}'", .{ - name.fmt(ip), - }); - } - } - - const ty = try pt.errorSetFromUnsortedNames(names.keys()); - return Air.internedToRef(ty.toIntern()); - }, - .@"struct" => { - const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); - const layout_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "layout", .no_embedded_nulls), - ).?); - const backing_integer_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "backing_integer", .no_embedded_nulls), - ).?); - const fields_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "fields", .no_embedded_nulls), - ).?); - const decls_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "decls", .no_embedded_nulls), - ).?); - const is_tuple_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "is_tuple", .no_embedded_nulls), - ).?); - - const layout = try sema.interpretBuiltinType(block, operand_src, layout_val, std.builtin.Type.ContainerLayout); - - // Decls - if (try decls_val.sliceLen(pt) > 0) { - return sema.fail(block, src, "reified structs must have no decls", .{}); - } - - if (layout != .@"packed" and !backing_integer_val.isNull(zcu)) { - return sema.fail(block, src, "non-packed struct does not support backing integer type", .{}); - } - - const fields_arr = try sema.derefSliceAsArray(block, operand_src, fields_val, .{ .simple = .struct_fields }); - - if (is_tuple_val.toBool()) { - switch (layout) { - .@"extern" => return sema.fail(block, src, "extern tuples are not supported", .{}), - .@"packed" => return sema.fail(block, src, "packed tuples are not supported", .{}), - .auto => {}, - } - return sema.reifyTuple(block, src, fields_arr); - } else { - return sema.reifyStruct(block, inst, src, layout, backing_integer_val, fields_arr, name_strategy); - } - }, - .@"enum" => { - const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); - const tag_type_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "tag_type", .no_embedded_nulls), - ).?); - const fields_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "fields", .no_embedded_nulls), - ).?); - const decls_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "decls", .no_embedded_nulls), - ).?); - const is_exhaustive_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "is_exhaustive", .no_embedded_nulls), - ).?); - - if (try decls_val.sliceLen(pt) > 0) { - return sema.fail(block, src, "reified enums must have no decls", .{}); - } - - const fields_arr = try sema.derefSliceAsArray(block, operand_src, fields_val, .{ .simple = .enum_fields }); - - return sema.reifyEnum(block, inst, src, tag_type_val.toType(), is_exhaustive_val.toBool(), fields_arr, name_strategy); - }, - .@"opaque" => { - const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); - const decls_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "decls", .no_embedded_nulls), - ).?); - - // Decls - if (try decls_val.sliceLen(pt) > 0) { - return sema.fail(block, src, "reified opaque must have no decls", .{}); - } - - const wip_ty = switch (try ip.getOpaqueType(gpa, pt.tid, .{ - .key = .{ .reified = .{ - .zir_index = try block.trackZir(inst), - } }, - })) { - .existing => |ty| { - try sema.addTypeReferenceEntry(src, ty); - return Air.internedToRef(ty); - }, - .wip => |wip| wip, - }; - errdefer wip_ty.cancel(ip, pt.tid); - - const type_name = try sema.createTypeName( - block, - name_strategy, - "opaque", - inst, - wip_ty.index, - ); - wip_ty.setName(ip, type_name.name, type_name.nav); - - const new_namespace_index = try pt.createNamespace(.{ - .parent = block.namespace.toOptional(), - .owner_type = wip_ty.index, - .file_scope = block.getFileScopeIndex(zcu), - .generation = zcu.generation, - }); - - try sema.addTypeReferenceEntry(src, wip_ty.index); - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); - return Air.internedToRef(wip_ty.finish(ip, new_namespace_index)); - }, - .@"union" => { - const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); - const layout_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "layout", .no_embedded_nulls), - ).?); - const tag_type_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "tag_type", .no_embedded_nulls), - ).?); - const fields_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "fields", .no_embedded_nulls), - ).?); - const decls_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "decls", .no_embedded_nulls), - ).?); - - if (try decls_val.sliceLen(pt) > 0) { - return sema.fail(block, src, "reified unions must have no decls", .{}); - } - const layout = try sema.interpretBuiltinType(block, operand_src, layout_val, std.builtin.Type.ContainerLayout); - - const fields_arr = try sema.derefSliceAsArray(block, operand_src, fields_val, .{ .simple = .union_fields }); - - return sema.reifyUnion(block, inst, src, layout, tag_type_val, fields_arr, name_strategy); - }, - .@"fn" => { - const struct_type = ip.loadStructType(ip.typeOf(union_val.val)); - const calling_convention_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "calling_convention", .no_embedded_nulls), - ).?); - const is_generic_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "is_generic", .no_embedded_nulls), - ).?); - const is_var_args_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "is_var_args", .no_embedded_nulls), - ).?); - const return_type_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "return_type", .no_embedded_nulls), - ).?); - const params_slice_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "params", .no_embedded_nulls), - ).?); - - const is_generic = is_generic_val.toBool(); - if (is_generic) { - return sema.fail(block, src, "Type.Fn.is_generic must be false for @Type", .{}); - } - - const is_var_args = is_var_args_val.toBool(); - const cc = try sema.analyzeValueAsCallconv(block, src, calling_convention_val); - if (is_var_args) { - try sema.checkCallConvSupportsVarArgs(block, src, cc); - } - - const return_type = return_type_val.optionalValue(zcu) orelse - return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{}); - - const params_val = try sema.derefSliceAsArray(block, operand_src, params_slice_val, .{ .simple = .function_parameters }); - - const args_len = try sema.usizeCast(block, src, params_val.typeOf(zcu).arrayLen(zcu)); - const param_types = try sema.arena.alloc(InternPool.Index, args_len); - - var noalias_bits: u32 = 0; - for (param_types, 0..) |*param_type, i| { - const elem_val = try params_val.elemValue(pt, i); - const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern())); - const param_is_generic_val = try elem_val.fieldValue(pt, elem_struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "is_generic", .no_embedded_nulls), - ).?); - const param_is_noalias_val = try elem_val.fieldValue(pt, elem_struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "is_noalias", .no_embedded_nulls), - ).?); - const opt_param_type_val = try elem_val.fieldValue(pt, elem_struct_type.nameIndex( - ip, - try ip.getOrPutString(gpa, pt.tid, "type", .no_embedded_nulls), - ).?); - - if (param_is_generic_val.toBool()) { - return sema.fail(block, src, "Type.Fn.Param.is_generic must be false for @Type", .{}); - } - - const param_type_val = opt_param_type_val.optionalValue(zcu) orelse - return sema.fail(block, src, "Type.Fn.Param.type must be non-null for @Type", .{}); - param_type.* = param_type_val.toIntern(); - - if (param_is_noalias_val.toBool()) { - if (!Type.fromInterned(param_type.*).isPtrAtRuntime(zcu)) { - return sema.fail(block, src, "non-pointer parameter declared noalias", .{}); - } - noalias_bits |= @as(u32, 1) << (std.math.cast(u5, i) orelse - return sema.fail(block, src, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{})); - } - } - - const ty = try pt.funcType(.{ - .param_types = param_types, - .noalias_bits = noalias_bits, - .return_type = return_type.toIntern(), - .cc = cc, - .is_var_args = is_var_args, - }); - return Air.internedToRef(ty.toIntern()); - }, - .frame => return sema.failWithUseOfAsync(block, src), - } -} - -fn reifyEnum( - sema: *Sema, - block: *Block, - inst: Zir.Inst.Index, - src: LazySrcLoc, - tag_ty: Type, - is_exhaustive: bool, - fields_val: Value, - name_strategy: Zir.Inst.NameStrategy, -) CompileError!Air.Inst.Ref { - const pt = sema.pt; - const zcu = pt.zcu; - const gpa = sema.gpa; - const ip = &zcu.intern_pool; - - // This logic must stay in sync with the structure of `std.builtin.Type.Enum` - search for `fieldValue`. - const fields_len: u32 = @intCast(fields_val.typeOf(zcu).arrayLen(zcu)); + const struct_type = ip.loadStructType(ip.typeOf(val.toIntern())); + const tag_type_val = try val.fieldValue(pt, struct_type.nameIndex( + ip, + try ip.getOrPutString(gpa, pt.tid, "tag_type", .no_embedded_nulls), + ).?); + const fields_val = try val.fieldValue(pt, struct_type.nameIndex( + ip, + try ip.getOrPutString(gpa, pt.tid, "fields", .no_embedded_nulls), + ).?); + const decls_val = try val.fieldValue(pt, struct_type.nameIndex( + ip, + try ip.getOrPutString(gpa, pt.tid, "decls", .no_embedded_nulls), + ).?); + const is_exhaustive_val = try val.fieldValue(pt, struct_type.nameIndex( + ip, + try ip.getOrPutString(gpa, pt.tid, "is_exhaustive", .no_embedded_nulls), + ).?); + + if (try decls_val.sliceLen(pt) > 0) { + return sema.fail(block, src, "reified enums must have no decls", .{}); + } + + const tag_ty = tag_type_val.toType(); + const is_exhaustive = is_exhaustive_val.toBool(); + const fields_arr = try sema.derefSliceAsArray(block, operand_src, fields_val, .{ .simple = .enum_fields }); + const fields_len: u32 = @intCast(fields_arr.typeOf(zcu).arrayLen(zcu)); // The validation work here is non-trivial, and it's possible the type already exists. // So in this first pass, let's just construct a hash to optimize for this case. If the @@ -21215,7 +20752,7 @@ fn reifyEnum( std.hash.autoHash(&hasher, fields_len); for (0..fields_len) |field_idx| { - const field_info = try fields_val.elemValue(pt, field_idx); + const field_info = try fields_arr.elemValue(pt, field_idx); const field_name_val = try field_info.fieldValue(pt, 0); const field_value_val = try sema.resolveLazyValue(try field_info.fieldValue(pt, 1)); @@ -21228,8 +20765,6 @@ fn reifyEnum( }); } - const tracked_inst = try block.trackZir(inst); - const wip_ty = switch (try ip.getEnumType(gpa, pt.tid, .{ .has_values = true, .tag_mode = if (is_exhaustive) .explicit else .nonexhaustive, @@ -21277,7 +20812,7 @@ fn reifyEnum( done = true; for (0..fields_len) |field_idx| { - const field_info = try fields_val.elemValue(pt, field_idx); + const field_info = try fields_arr.elemValue(pt, field_idx); const field_name_val = try field_info.fieldValue(pt, 0); const field_value_val = try sema.resolveLazyValue(try field_info.fieldValue(pt, 1)); @@ -21329,15 +20864,153 @@ fn reifyEnum( return Air.internedToRef(wip_ty.index); } -fn reifyUnion( +fn zirReifyPointer( sema: *Sema, block: *Block, + extended: Zir.Inst.Extended.InstData, + inst: Zir.Inst.Index, +) CompileError!Air.Inst.Ref { + const pt = sema.pt; + const zcu = pt.zcu; + const gpa = sema.gpa; + const ip = &zcu.intern_pool; + + // This logic must stay in sync with the structure of `std.builtin.Type.Pointer` - search for `fieldValue`. + + const extra = sema.code.extraData(Zir.Inst.Reify, extended.operand).data; + const tracked_inst = try block.trackZir(inst); + const src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = LazySrcLoc.Offset.nodeOffset(.zero), + }; + const operand_src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = .{ + .node_offset_builtin_call_arg = .{ + .builtin_call_node = .zero, // `tracked_inst` is precisely the `reify` instruction, so offset is 0 + .arg_index = 0, + }, + }, + }; + const pointer_info_ty = try sema.getBuiltinType(src, .@"Type.Pointer"); + const uncasted_operand = try sema.resolveInst(extra.operand); + const type_info = try sema.coerce(block, pointer_info_ty, uncasted_operand, operand_src); + const val = try sema.resolveConstDefinedValue(block, operand_src, type_info, .{ .simple = .operand_Pointer }); + if (try sema.anyUndef(block, operand_src, val)) { + return sema.failWithUseOfUndef(block, operand_src); + } + + const struct_type = ip.loadStructType(ip.typeOf(val.toIntern())); + const size_val = try val.fieldValue(pt, struct_type.nameIndex( + ip, + try ip.getOrPutString(gpa, pt.tid, "size", .no_embedded_nulls), + ).?); + const is_const_val = try val.fieldValue(pt, struct_type.nameIndex( + ip, + try ip.getOrPutString(gpa, pt.tid, "is_const", .no_embedded_nulls), + ).?); + const is_volatile_val = try val.fieldValue(pt, struct_type.nameIndex( + ip, + try ip.getOrPutString(gpa, pt.tid, "is_volatile", .no_embedded_nulls), + ).?); + const alignment_val = try val.fieldValue(pt, struct_type.nameIndex( + ip, + try ip.getOrPutString(gpa, pt.tid, "alignment", .no_embedded_nulls), + ).?); + const address_space_val = try val.fieldValue(pt, struct_type.nameIndex( + ip, + try ip.getOrPutString(gpa, pt.tid, "address_space", .no_embedded_nulls), + ).?); + const child_val = try val.fieldValue(pt, struct_type.nameIndex( + ip, + try ip.getOrPutString(gpa, pt.tid, "child", .no_embedded_nulls), + ).?); + const is_allowzero_val = try val.fieldValue(pt, struct_type.nameIndex( + ip, + try ip.getOrPutString(gpa, pt.tid, "is_allowzero", .no_embedded_nulls), + ).?); + const sentinel_val = try val.fieldValue(pt, struct_type.nameIndex( + ip, + try ip.getOrPutString(gpa, pt.tid, "sentinel_ptr", .no_embedded_nulls), + ).?); + + if (!try sema.intFitsInType(alignment_val, Type.u32, null)) { + return sema.fail(block, src, "alignment must fit in 'u32'", .{}); + } + + const alignment_val_int = try alignment_val.toUnsignedIntSema(pt); + if (alignment_val_int > 0 and !math.isPowerOfTwo(alignment_val_int)) { + return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{alignment_val_int}); + } + const abi_align = Alignment.fromByteUnits(alignment_val_int); + + const elem_ty = child_val.toType(); + if (abi_align != .none) { + try elem_ty.resolveLayout(pt); + } + + const ptr_size = try sema.interpretBuiltinType(block, operand_src, size_val, std.builtin.Type.Pointer.Size); + + const actual_sentinel: InternPool.Index = s: { + if (!sentinel_val.isNull(zcu)) { + if (ptr_size == .one or ptr_size == .c) { + return sema.fail(block, src, "sentinels are only allowed on slices and unknown-length pointers", .{}); + } + const sentinel_ptr_val = sentinel_val.optionalValue(zcu).?; + const ptr_ty = try pt.singleMutPtrType(elem_ty); + const sent_val = (try sema.pointerDeref(block, src, sentinel_ptr_val, ptr_ty)).?; + try sema.checkSentinelType(block, src, elem_ty); + break :s sent_val.toIntern(); + } + break :s .none; + }; + + if (elem_ty.zigTypeTag(zcu) == .noreturn) { + return sema.fail(block, src, "pointer to noreturn not allowed", .{}); + } else if (elem_ty.zigTypeTag(zcu) == .@"fn") { + if (ptr_size != .one) { + return sema.fail(block, src, "function pointers must be single pointers", .{}); + } + } else if (ptr_size == .many and elem_ty.zigTypeTag(zcu) == .@"opaque") { + return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{}); + } else if (ptr_size == .c) { + if (!try sema.validateExternType(elem_ty, .other)) { + const msg = msg: { + const msg = try sema.errMsg(src, "C pointers cannot point to non-C-ABI-compatible type '{f}'", .{elem_ty.fmt(pt)}); + errdefer msg.destroy(gpa); + + try sema.explainWhyTypeIsNotExtern(msg, src, elem_ty, .other); + + try sema.addDeclaredHereNote(msg, elem_ty); + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(block, msg); + } + if (elem_ty.zigTypeTag(zcu) == .@"opaque") { + return sema.fail(block, src, "C pointers cannot point to opaque types", .{}); + } + } + + const ty = try pt.ptrTypeSema(.{ + .child = elem_ty.toIntern(), + .sentinel = actual_sentinel, + .flags = .{ + .size = ptr_size, + .is_const = is_const_val.toBool(), + .is_volatile = is_volatile_val.toBool(), + .alignment = abi_align, + .address_space = try sema.interpretBuiltinType(block, operand_src, address_space_val, std.builtin.AddressSpace), + .is_allowzero = is_allowzero_val.toBool(), + }, + }); + return Air.internedToRef(ty.toIntern()); +} + +fn zirReifyUnion( + sema: *Sema, + block: *Block, + extended: Zir.Inst.Extended.InstData, inst: Zir.Inst.Index, - src: LazySrcLoc, - layout: std.builtin.Type.ContainerLayout, - opt_tag_type_val: Value, - fields_val: Value, - name_strategy: Zir.Inst.NameStrategy, ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; @@ -21346,7 +21019,55 @@ fn reifyUnion( // This logic must stay in sync with the structure of `std.builtin.Type.Union` - search for `fieldValue`. - const fields_len: u32 = @intCast(fields_val.typeOf(zcu).arrayLen(zcu)); + const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small); + const extra = sema.code.extraData(Zir.Inst.Reify, extended.operand).data; + const tracked_inst = try block.trackZir(inst); + const src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = LazySrcLoc.Offset.nodeOffset(.zero), + }; + const operand_src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = .{ + .node_offset_builtin_call_arg = .{ + .builtin_call_node = .zero, // `tracked_inst` is precisely the `reify` instruction, so offset is 0 + .arg_index = 0, + }, + }, + }; + const enum_info_ty = try sema.getBuiltinType(src, .@"Type.Union"); + const uncasted_operand = try sema.resolveInst(extra.operand); + const type_info = try sema.coerce(block, enum_info_ty, uncasted_operand, operand_src); + const val = try sema.resolveConstDefinedValue(block, operand_src, type_info, .{ .simple = .operand_Union }); + if (try sema.anyUndef(block, operand_src, val)) { + return sema.failWithUseOfUndef(block, operand_src); + } + + const struct_type = ip.loadStructType(ip.typeOf(val.toIntern())); + const layout_val = try val.fieldValue(pt, struct_type.nameIndex( + ip, + try ip.getOrPutString(gpa, pt.tid, "layout", .no_embedded_nulls), + ).?); + const opt_tag_type_val = try val.fieldValue(pt, struct_type.nameIndex( + ip, + try ip.getOrPutString(gpa, pt.tid, "tag_type", .no_embedded_nulls), + ).?); + const fields_val = try val.fieldValue(pt, struct_type.nameIndex( + ip, + try ip.getOrPutString(gpa, pt.tid, "fields", .no_embedded_nulls), + ).?); + const decls_val = try val.fieldValue(pt, struct_type.nameIndex( + ip, + try ip.getOrPutString(gpa, pt.tid, "decls", .no_embedded_nulls), + ).?); + + if (try decls_val.sliceLen(pt) > 0) { + return sema.fail(block, src, "reified unions must have no decls", .{}); + } + const layout = try sema.interpretBuiltinType(block, operand_src, layout_val, std.builtin.Type.ContainerLayout); + + const fields_arr = try sema.derefSliceAsArray(block, operand_src, fields_val, .{ .simple = .union_fields }); + const fields_len: u32 = @intCast(fields_arr.typeOf(zcu).arrayLen(zcu)); // The validation work here is non-trivial, and it's possible the type already exists. // So in this first pass, let's just construct a hash to optimize for this case. If the @@ -21362,7 +21083,7 @@ fn reifyUnion( var any_aligns = false; for (0..fields_len) |field_idx| { - const field_info = try fields_val.elemValue(pt, field_idx); + const field_info = try fields_arr.elemValue(pt, field_idx); const field_name_val = try field_info.fieldValue(pt, 0); const field_type_val = try field_info.fieldValue(pt, 1); @@ -21381,8 +21102,6 @@ fn reifyUnion( } } - const tracked_inst = try block.trackZir(inst); - const wip_ty = switch (try ip.getUnionType(gpa, pt.tid, .{ .flags = .{ .layout = layout, @@ -21443,7 +21162,7 @@ fn reifyUnion( var seen_tags = try std.DynamicBitSetUnmanaged.initEmpty(sema.arena, tag_ty_fields_len); for (field_types, 0..) |*field_ty, field_idx| { - const field_info = try fields_val.elemValue(pt, field_idx); + const field_info = try fields_arr.elemValue(pt, field_idx); const field_name_val = try field_info.fieldValue(pt, 0); const field_type_val = try field_info.fieldValue(pt, 1); @@ -21495,7 +21214,7 @@ fn reifyUnion( try field_names.ensureTotalCapacity(sema.arena, fields_len); for (field_types, 0..) |*field_ty, field_idx| { - const field_info = try fields_val.elemValue(pt, field_idx); + const field_info = try fields_arr.elemValue(pt, field_idx); const field_name_val = try field_info.fieldValue(pt, 0); const field_type_val = try field_info.fieldValue(pt, 1); @@ -21587,360 +21306,404 @@ fn reifyUnion( return Air.internedToRef(wip_ty.finish(ip, new_namespace_index)); } -fn reifyTuple( +fn zirReifyStruct( sema: *Sema, block: *Block, - src: LazySrcLoc, - fields_val: Value, + extended: Zir.Inst.Extended.InstData, + inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; const gpa = sema.gpa; const ip = &zcu.intern_pool; + const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small); + const extra = sema.code.extraData(Zir.Inst.Reify, extended.operand).data; + const tracked_inst = try block.trackZir(inst); + const src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = LazySrcLoc.Offset.nodeOffset(.zero), + }; + const operand_src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = .{ + .node_offset_builtin_call_arg = .{ + .builtin_call_node = .zero, // `tracked_inst` is precisely the `reify` instruction, so offset is 0 + .arg_index = 0, + }, + }, + }; + const enum_info_ty = try sema.getBuiltinType(src, .@"Type.Struct"); + const uncasted_operand = try sema.resolveInst(extra.operand); + const type_info = try sema.coerce(block, enum_info_ty, uncasted_operand, operand_src); + const val = try sema.resolveConstDefinedValue(block, operand_src, type_info, .{ .simple = .operand_Struct }); + if (try sema.anyUndef(block, operand_src, val)) { + return sema.failWithUseOfUndef(block, operand_src); + } - const fields_len: u32 = @intCast(fields_val.typeOf(zcu).arrayLen(zcu)); - - const types = try sema.arena.alloc(InternPool.Index, fields_len); - const inits = try sema.arena.alloc(InternPool.Index, fields_len); + const struct_type = ip.loadStructType(ip.typeOf(val.toIntern())); + const layout_val = try val.fieldValue(pt, struct_type.nameIndex( + ip, + try ip.getOrPutString(gpa, pt.tid, "layout", .no_embedded_nulls), + ).?); + const opt_backing_int_val = try val.fieldValue(pt, struct_type.nameIndex( + ip, + try ip.getOrPutString(gpa, pt.tid, "backing_integer", .no_embedded_nulls), + ).?); + const fields_val = try val.fieldValue(pt, struct_type.nameIndex( + ip, + try ip.getOrPutString(gpa, pt.tid, "fields", .no_embedded_nulls), + ).?); + const decls_val = try val.fieldValue(pt, struct_type.nameIndex( + ip, + try ip.getOrPutString(gpa, pt.tid, "decls", .no_embedded_nulls), + ).?); + const is_tuple_val = try val.fieldValue(pt, struct_type.nameIndex( + ip, + try ip.getOrPutString(gpa, pt.tid, "is_tuple", .no_embedded_nulls), + ).?); - for (types, inits, 0..) |*field_ty, *field_init, field_idx| { - const field_info = try fields_val.elemValue(pt, field_idx); + const layout = try sema.interpretBuiltinType(block, operand_src, layout_val, std.builtin.Type.ContainerLayout); - const field_name_val = try field_info.fieldValue(pt, 0); - const field_type_val = try field_info.fieldValue(pt, 1); - const field_default_value_val = try field_info.fieldValue(pt, 2); - const field_is_comptime_val = try field_info.fieldValue(pt, 3); - const field_alignment_val = try sema.resolveLazyValue(try field_info.fieldValue(pt, 4)); - - const field_name = try sema.sliceToIpString(block, src, field_name_val, .{ .simple = .tuple_field_name }); - const field_type = field_type_val.toType(); - const field_default_value: InternPool.Index = if (field_default_value_val.optionalValue(zcu)) |ptr_val| d: { - const ptr_ty = try pt.singleConstPtrType(field_type_val.toType()); - // We need to do this deref here, so we won't check for this error case later on. - const val = try sema.pointerDeref(block, src, ptr_val, ptr_ty) orelse return sema.failWithNeededComptime( - block, - src, - .{ .simple = .tuple_field_default_value }, - ); - // Resolve the value so that lazy values do not create distinct types. - break :d (try sema.resolveLazyValue(val)).toIntern(); - } else .none; + // Decls + if (try decls_val.sliceLen(pt) > 0) { + return sema.fail(block, src, "reified structs must have no decls", .{}); + } - const field_name_index = field_name.toUnsigned(ip) orelse return sema.fail( - block, - src, - "tuple cannot have non-numeric field '{f}'", - .{field_name.fmt(ip)}, - ); - if (field_name_index != field_idx) { - return sema.fail( - block, - src, - "tuple field name '{d}' does not match field index {d}", - .{ field_name_index, field_idx }, - ); - } + if (layout != .@"packed" and !opt_backing_int_val.isNull(zcu)) { + return sema.fail(block, src, "non-packed struct does not support backing integer type", .{}); + } - try sema.validateTupleFieldType(block, field_type, src); + const fields_arr = try sema.derefSliceAsArray(block, operand_src, fields_val, .{ .simple = .struct_fields }); + const fields_len: u32 = @intCast(fields_arr.typeOf(zcu).arrayLen(zcu)); - { - const alignment_ok = ok: { - if (field_alignment_val.toIntern() == .zero) break :ok true; - const given_align = try field_alignment_val.getUnsignedIntSema(pt) orelse break :ok false; - const abi_align = (try field_type.abiAlignmentSema(pt)).toByteUnits() orelse 0; - break :ok abi_align == given_align; - }; - if (!alignment_ok) { - return sema.fail(block, src, "tuple fields cannot specify alignment", .{}); - } + if (is_tuple_val.toBool()) { + switch (layout) { + .@"extern" => return sema.fail(block, src, "extern tuples are not supported", .{}), + .@"packed" => return sema.fail(block, src, "packed tuples are not supported", .{}), + .auto => {}, } + const types = try sema.arena.alloc(InternPool.Index, fields_len); + const inits = try sema.arena.alloc(InternPool.Index, fields_len); - if (field_is_comptime_val.toBool() and field_default_value == .none) { - return sema.fail(block, src, "comptime field without default initialization value", .{}); - } + for (types, inits, 0..) |*field_ty, *field_init, field_idx| { + const field_info = try fields_arr.elemValue(pt, field_idx); - if (!field_is_comptime_val.toBool() and field_default_value != .none) { - return sema.fail(block, src, "non-comptime tuple fields cannot specify default initialization value", .{}); - } + const field_name_val = try field_info.fieldValue(pt, 0); + const field_type_val = try field_info.fieldValue(pt, 1); + const field_default_value_val = try field_info.fieldValue(pt, 2); + const field_is_comptime_val = try field_info.fieldValue(pt, 3); + const field_alignment_val = try sema.resolveLazyValue(try field_info.fieldValue(pt, 4)); + + const field_name = try sema.sliceToIpString(block, src, field_name_val, .{ .simple = .tuple_field_name }); + const field_type = field_type_val.toType(); + const field_default_value: InternPool.Index = if (field_default_value_val.optionalValue(zcu)) |ptr_val| d: { + const ptr_ty = try pt.singleConstPtrType(field_type_val.toType()); + // We need to do this deref here, so we won't check for this error case later on. + const deref_val = try sema.pointerDeref(block, src, ptr_val, ptr_ty) orelse return sema.failWithNeededComptime( + block, + src, + .{ .simple = .tuple_field_default_value }, + ); + // Resolve the value so that lazy values do not create distinct types. + break :d (try sema.resolveLazyValue(deref_val)).toIntern(); + } else .none; - const default_or_opv: InternPool.Index = default: { - if (field_default_value != .none) { - break :default field_default_value; - } - if (try sema.typeHasOnePossibleValue(field_type)) |opv| { - break :default opv.toIntern(); + const field_name_index = field_name.toUnsigned(ip) orelse return sema.fail( + block, + src, + "tuple cannot have non-numeric field '{f}'", + .{field_name.fmt(ip)}, + ); + if (field_name_index != field_idx) { + return sema.fail( + block, + src, + "tuple field name '{}' does not match field index {}", + .{ field_name_index, field_idx }, + ); } - break :default .none; - }; - field_ty.* = field_type.toIntern(); - field_init.* = default_or_opv; - } + try sema.validateTupleFieldType(block, field_type, src); - return Air.internedToRef(try zcu.intern_pool.getTupleType(gpa, pt.tid, .{ - .types = types, - .values = inits, - })); -} + { + const alignment_ok = ok: { + if (field_alignment_val.toIntern() == .zero) break :ok true; + const given_align = try field_alignment_val.getUnsignedIntSema(pt) orelse break :ok false; + const abi_align = (try field_type.abiAlignmentSema(pt)).toByteUnits() orelse 0; + break :ok abi_align == given_align; + }; + if (!alignment_ok) { + return sema.fail(block, src, "tuple fields cannot specify alignment", .{}); + } + } -fn reifyStruct( - sema: *Sema, - block: *Block, - inst: Zir.Inst.Index, - src: LazySrcLoc, - layout: std.builtin.Type.ContainerLayout, - opt_backing_int_val: Value, - fields_val: Value, - name_strategy: Zir.Inst.NameStrategy, -) CompileError!Air.Inst.Ref { - const pt = sema.pt; - const zcu = pt.zcu; - const gpa = sema.gpa; - const ip = &zcu.intern_pool; + if (field_is_comptime_val.toBool() and field_default_value == .none) { + return sema.fail(block, src, "comptime field without default initialization value", .{}); + } - // This logic must stay in sync with the structure of `std.builtin.Type.Struct` - search for `fieldValue`. + if (!field_is_comptime_val.toBool() and field_default_value != .none) { + return sema.fail(block, src, "non-comptime tuple fields cannot specify default initialization value", .{}); + } - const fields_len: u32 = @intCast(fields_val.typeOf(zcu).arrayLen(zcu)); + const default_or_opv: InternPool.Index = default: { + if (field_default_value != .none) { + break :default field_default_value; + } + if (try sema.typeHasOnePossibleValue(field_type)) |opv| { + break :default opv.toIntern(); + } + break :default .none; + }; - // The validation work here is non-trivial, and it's possible the type already exists. - // So in this first pass, let's just construct a hash to optimize for this case. If the - // inputs turn out to be invalid, we can cancel the WIP type later. + field_ty.* = field_type.toIntern(); + field_init.* = default_or_opv; + } - // For deduplication purposes, we must create a hash including all details of this type. - // TODO: use a longer hash! - var hasher = std.hash.Wyhash.init(0); - std.hash.autoHash(&hasher, layout); - std.hash.autoHash(&hasher, opt_backing_int_val.toIntern()); - std.hash.autoHash(&hasher, fields_len); + return Air.internedToRef(try zcu.intern_pool.getTupleType(gpa, pt.tid, .{ + .types = types, + .values = inits, + })); + } else { + // This logic must stay in sync with the structure of `std.builtin.Type.Struct` - search for `fieldValue`. - var any_comptime_fields = false; - var any_default_inits = false; - var any_aligned_fields = false; + // The validation work here is non-trivial, and it's possible the type already exists. + // So in this first pass, let's just construct a hash to optimize for this case. If the + // inputs turn out to be invalid, we can cancel the WIP type later. - for (0..fields_len) |field_idx| { - const field_info = try fields_val.elemValue(pt, field_idx); + // For deduplication purposes, we must create a hash including all details of this type. + // TODO: use a longer hash! + var hasher = std.hash.Wyhash.init(0); + std.hash.autoHash(&hasher, layout); + std.hash.autoHash(&hasher, opt_backing_int_val.toIntern()); + std.hash.autoHash(&hasher, fields_len); - const field_name_val = try field_info.fieldValue(pt, 0); - const field_type_val = try field_info.fieldValue(pt, 1); - const field_default_value_val = try field_info.fieldValue(pt, 2); - const field_is_comptime_val = try field_info.fieldValue(pt, 3); - const field_alignment_val = try sema.resolveLazyValue(try field_info.fieldValue(pt, 4)); - - const field_name = try sema.sliceToIpString(block, src, field_name_val, .{ .simple = .struct_field_name }); - const field_is_comptime = field_is_comptime_val.toBool(); - const field_default_value: InternPool.Index = if (field_default_value_val.optionalValue(zcu)) |ptr_val| d: { - const ptr_ty = try pt.singleConstPtrType(field_type_val.toType()); - // We need to do this deref here, so we won't check for this error case later on. - const val = try sema.pointerDeref(block, src, ptr_val, ptr_ty) orelse return sema.failWithNeededComptime( - block, - src, - .{ .simple = .struct_field_default_value }, - ); - // Resolve the value so that lazy values do not create distinct types. - break :d (try sema.resolveLazyValue(val)).toIntern(); - } else .none; + var any_comptime_fields = false; + var any_default_inits = false; + var any_aligned_fields = false; - std.hash.autoHash(&hasher, .{ - field_name, - field_type_val.toIntern(), - field_default_value, - field_is_comptime, - field_alignment_val.toIntern(), - }); + for (0..fields_len) |field_idx| { + const field_info = try fields_arr.elemValue(pt, field_idx); - if (field_is_comptime) any_comptime_fields = true; - if (field_default_value != .none) any_default_inits = true; - switch (try field_alignment_val.orderAgainstZeroSema(pt)) { - .eq => {}, - .gt => any_aligned_fields = true, - .lt => unreachable, - } - } + const field_name_val = try field_info.fieldValue(pt, 0); + const field_type_val = try field_info.fieldValue(pt, 1); + const field_default_value_val = try field_info.fieldValue(pt, 2); + const field_is_comptime_val = try field_info.fieldValue(pt, 3); + const field_alignment_val = try sema.resolveLazyValue(try field_info.fieldValue(pt, 4)); + + const field_name = try sema.sliceToIpString(block, src, field_name_val, .{ .simple = .struct_field_name }); + const field_is_comptime = field_is_comptime_val.toBool(); + const field_default_value: InternPool.Index = if (field_default_value_val.optionalValue(zcu)) |ptr_val| d: { + const ptr_ty = try pt.singleConstPtrType(field_type_val.toType()); + // We need to do this deref here, so we won't check for this error case later on. + const deref_val = try sema.pointerDeref(block, src, ptr_val, ptr_ty) orelse return sema.failWithNeededComptime( + block, + src, + .{ .simple = .struct_field_default_value }, + ); + // Resolve the value so that lazy values do not create distinct types. + break :d (try sema.resolveLazyValue(deref_val)).toIntern(); + } else .none; - const tracked_inst = try block.trackZir(inst); + std.hash.autoHash(&hasher, .{ + field_name, + field_type_val.toIntern(), + field_default_value, + field_is_comptime, + field_alignment_val.toIntern(), + }); - const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{ - .layout = layout, - .fields_len = fields_len, - .known_non_opv = false, - .requires_comptime = .unknown, - .any_comptime_fields = any_comptime_fields, - .any_default_inits = any_default_inits, - .any_aligned_fields = any_aligned_fields, - .inits_resolved = true, - .key = .{ .reified = .{ - .zir_index = tracked_inst, - .type_hash = hasher.final(), - } }, - }, false)) { - .wip => |wip| wip, - .existing => |ty| { - try sema.declareDependency(.{ .interned = ty }); - try sema.addTypeReferenceEntry(src, ty); - return Air.internedToRef(ty); - }, - }; - errdefer wip_ty.cancel(ip, pt.tid); + if (field_is_comptime) any_comptime_fields = true; + if (field_default_value != .none) any_default_inits = true; + switch (try field_alignment_val.orderAgainstZeroSema(pt)) { + .eq => {}, + .gt => any_aligned_fields = true, + .lt => unreachable, + } + } - const type_name = try sema.createTypeName( - block, - name_strategy, - "struct", - inst, - wip_ty.index, - ); - wip_ty.setName(ip, type_name.name, type_name.nav); + const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{ + .layout = layout, + .fields_len = fields_len, + .known_non_opv = false, + .requires_comptime = .unknown, + .any_comptime_fields = any_comptime_fields, + .any_default_inits = any_default_inits, + .any_aligned_fields = any_aligned_fields, + .inits_resolved = true, + .key = .{ .reified = .{ + .zir_index = tracked_inst, + .type_hash = hasher.final(), + } }, + }, false)) { + .wip => |wip| wip, + .existing => |ty| { + try sema.declareDependency(.{ .interned = ty }); + try sema.addTypeReferenceEntry(src, ty); + return Air.internedToRef(ty); + }, + }; + errdefer wip_ty.cancel(ip, pt.tid); - const struct_type = ip.loadStructType(wip_ty.index); + const type_name = try sema.createTypeName( + block, + name_strategy, + "struct", + inst, + wip_ty.index, + ); + wip_ty.setName(ip, type_name.name, type_name.nav); - for (0..fields_len) |field_idx| { - const field_info = try fields_val.elemValue(pt, field_idx); + const wip_struct_type = ip.loadStructType(wip_ty.index); - const field_name_val = try field_info.fieldValue(pt, 0); - const field_type_val = try field_info.fieldValue(pt, 1); - const field_default_value_val = try field_info.fieldValue(pt, 2); - const field_is_comptime_val = try field_info.fieldValue(pt, 3); - const field_alignment_val = try field_info.fieldValue(pt, 4); + for (0..fields_len) |field_idx| { + const field_info = try fields_arr.elemValue(pt, field_idx); - const field_ty = field_type_val.toType(); - // Don't pass a reason; first loop acts as an assertion that this is valid. - const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined); - if (struct_type.addFieldName(ip, field_name)) |prev_index| { - _ = prev_index; // TODO: better source location - return sema.fail(block, src, "duplicate struct field name {f}", .{field_name.fmt(ip)}); - } + const field_name_val = try field_info.fieldValue(pt, 0); + const field_type_val = try field_info.fieldValue(pt, 1); + const field_default_value_val = try field_info.fieldValue(pt, 2); + const field_is_comptime_val = try field_info.fieldValue(pt, 3); + const field_alignment_val = try field_info.fieldValue(pt, 4); - if (any_aligned_fields) { - if (!try sema.intFitsInType(field_alignment_val, .u32, null)) { - return sema.fail(block, src, "alignment must fit in 'u32'", .{}); + const field_ty = field_type_val.toType(); + // Don't pass a reason; first loop acts as an assertion that this is valid. + const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined); + if (wip_struct_type.addFieldName(ip, field_name)) |prev_index| { + _ = prev_index; // TODO: better source location + return sema.fail(block, src, "duplicate struct field name {f}", .{field_name.fmt(ip)}); } - const byte_align = try field_alignment_val.toUnsignedIntSema(pt); - if (byte_align == 0) { - if (layout != .@"packed") { - struct_type.field_aligns.get(ip)[field_idx] = .none; + if (any_aligned_fields) { + if (!try sema.intFitsInType(field_alignment_val, Type.u32, null)) { + return sema.fail(block, src, "alignment must fit in 'u32'", .{}); + } + + const byte_align = try field_alignment_val.toUnsignedIntSema(pt); + if (byte_align == 0) { + if (layout != .@"packed") { + wip_struct_type.field_aligns.get(ip)[field_idx] = .none; + } + } else { + if (layout == .@"packed") return sema.fail(block, src, "alignment in a packed struct field must be set to 0", .{}); + if (!math.isPowerOfTwo(byte_align)) return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{byte_align}); + wip_struct_type.field_aligns.get(ip)[field_idx] = Alignment.fromNonzeroByteUnits(byte_align); } - } else { - if (layout == .@"packed") return sema.fail(block, src, "alignment in a packed struct field must be set to 0", .{}); - if (!math.isPowerOfTwo(byte_align)) return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{byte_align}); - struct_type.field_aligns.get(ip)[field_idx] = Alignment.fromNonzeroByteUnits(byte_align); } - } - const field_is_comptime = field_is_comptime_val.toBool(); - if (field_is_comptime) { - assert(any_comptime_fields); - switch (layout) { - .@"extern" => return sema.fail(block, src, "extern struct fields cannot be marked comptime", .{}), - .@"packed" => return sema.fail(block, src, "packed struct fields cannot be marked comptime", .{}), - .auto => struct_type.setFieldComptime(ip, field_idx), + const field_is_comptime = field_is_comptime_val.toBool(); + if (field_is_comptime) { + assert(any_comptime_fields); + switch (layout) { + .@"extern" => return sema.fail(block, src, "extern struct fields cannot be marked comptime", .{}), + .@"packed" => return sema.fail(block, src, "packed struct fields cannot be marked comptime", .{}), + .auto => wip_struct_type.setFieldComptime(ip, field_idx), + } } - } - const field_default: InternPool.Index = d: { - if (!any_default_inits) break :d .none; - const ptr_val = field_default_value_val.optionalValue(zcu) orelse break :d .none; - const ptr_ty = try pt.singleConstPtrType(field_ty); - // Asserted comptime-dereferencable above. - const val = (try sema.pointerDeref(block, src, ptr_val, ptr_ty)).?; - // We already resolved this for deduplication, so we may as well do it now. - break :d (try sema.resolveLazyValue(val)).toIntern(); - }; + const field_default: InternPool.Index = d: { + if (!any_default_inits) break :d .none; + const ptr_val = field_default_value_val.optionalValue(zcu) orelse break :d .none; + const ptr_ty = try pt.singleConstPtrType(field_ty); + // Asserted comptime-dereferencable above. + const deref_val = (try sema.pointerDeref(block, src, ptr_val, ptr_ty)).?; + // We already resolved this for deduplication, so we may as well do it now. + break :d (try sema.resolveLazyValue(deref_val)).toIntern(); + }; - if (field_is_comptime and field_default == .none) { - return sema.fail(block, src, "comptime field without default initialization value", .{}); - } + if (field_is_comptime and field_default == .none) { + return sema.fail(block, src, "comptime field without default initialization value", .{}); + } - struct_type.field_types.get(ip)[field_idx] = field_type_val.toIntern(); - if (field_default != .none) { - struct_type.field_inits.get(ip)[field_idx] = field_default; - } + wip_struct_type.field_types.get(ip)[field_idx] = field_type_val.toIntern(); + if (field_default != .none) { + wip_struct_type.field_inits.get(ip)[field_idx] = field_default; + } - if (field_ty.zigTypeTag(zcu) == .@"opaque") { - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); - errdefer msg.destroy(gpa); + if (field_ty.zigTypeTag(zcu) == .@"opaque") { + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); + errdefer msg.destroy(gpa); - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }); - } - if (field_ty.zigTypeTag(zcu) == .noreturn) { - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(src, "struct fields cannot be 'noreturn'", .{}); - errdefer msg.destroy(gpa); + try sema.addDeclaredHereNote(msg, field_ty); + break :msg msg; + }); + } + if (field_ty.zigTypeTag(zcu) == .noreturn) { + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(src, "struct fields cannot be 'noreturn'", .{}); + errdefer msg.destroy(gpa); - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }); - } - if (layout == .@"extern" and !try sema.validateExternType(field_ty, .struct_field)) { - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); - errdefer msg.destroy(gpa); + try sema.addDeclaredHereNote(msg, field_ty); + break :msg msg; + }); + } + if (layout == .@"extern" and !try sema.validateExternType(field_ty, .struct_field)) { + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); + errdefer msg.destroy(gpa); - try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .struct_field); + try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .struct_field); - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }); - } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) { - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); - errdefer msg.destroy(gpa); + try sema.addDeclaredHereNote(msg, field_ty); + break :msg msg; + }); + } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) { + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); + errdefer msg.destroy(gpa); - try sema.explainWhyTypeIsNotPacked(msg, src, field_ty); + try sema.explainWhyTypeIsNotPacked(msg, src, field_ty); - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }); + try sema.addDeclaredHereNote(msg, field_ty); + break :msg msg; + }); + } } - } - if (layout == .@"packed") { - var fields_bit_sum: u64 = 0; - for (0..struct_type.field_types.len) |field_idx| { - const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_idx]); - field_ty.resolveLayout(pt) catch |err| switch (err) { - error.AnalysisFail => { - const msg = sema.err orelse return err; - try sema.errNote(src, msg, "while checking a field of this struct", .{}); - return err; - }, - else => return err, - }; - fields_bit_sum += field_ty.bitSize(zcu); - } + if (layout == .@"packed") { + var fields_bit_sum: u64 = 0; + for (0..wip_struct_type.field_types.len) |field_idx| { + const field_ty = Type.fromInterned(wip_struct_type.field_types.get(ip)[field_idx]); + field_ty.resolveLayout(pt) catch |err| switch (err) { + error.AnalysisFail => { + const msg = sema.err orelse return err; + try sema.errNote(src, msg, "while checking a field of this struct", .{}); + return err; + }, + else => return err, + }; + fields_bit_sum += field_ty.bitSize(zcu); + } - if (opt_backing_int_val.optionalValue(zcu)) |backing_int_val| { - const backing_int_ty = backing_int_val.toType(); - try sema.checkBackingIntType(block, src, backing_int_ty, fields_bit_sum); - struct_type.setBackingIntType(ip, backing_int_ty.toIntern()); - } else { - const backing_int_ty = try pt.intType(.unsigned, @intCast(fields_bit_sum)); - struct_type.setBackingIntType(ip, backing_int_ty.toIntern()); + if (opt_backing_int_val.optionalValue(zcu)) |backing_int_val| { + const backing_int_ty = backing_int_val.toType(); + try sema.checkBackingIntType(block, src, backing_int_ty, fields_bit_sum); + wip_struct_type.setBackingIntType(ip, backing_int_ty.toIntern()); + } else { + const backing_int_ty = try pt.intType(.unsigned, @intCast(fields_bit_sum)); + wip_struct_type.setBackingIntType(ip, backing_int_ty.toIntern()); + } } - } - const new_namespace_index = try pt.createNamespace(.{ - .parent = block.namespace.toOptional(), - .owner_type = wip_ty.index, - .file_scope = block.getFileScopeIndex(zcu), - .generation = zcu.generation, - }); + const new_namespace_index = try pt.createNamespace(.{ + .parent = block.namespace.toOptional(), + .owner_type = wip_ty.index, + .file_scope = block.getFileScopeIndex(zcu), + .generation = zcu.generation, + }); - try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index }); - codegen_type: { - if (zcu.comp.config.use_llvm) break :codegen_type; - if (block.ownerModule().strip) break :codegen_type; - // This job depends on any resolve_type_fully jobs queued up before it. - zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); - try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); + try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index }); + codegen_type: { + if (zcu.comp.config.use_llvm) break :codegen_type; + if (block.ownerModule().strip) break :codegen_type; + // This job depends on any resolve_type_fully jobs queued up before it. + zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); + try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); + } + try sema.declareDependency(.{ .interned = wip_ty.index }); + try sema.addTypeReferenceEntry(src, wip_ty.index); + if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); + return Air.internedToRef(wip_ty.finish(ip, new_namespace_index)); } - try sema.declareDependency(.{ .interned = wip_ty.index }); - try sema.addTypeReferenceEntry(src, wip_ty.index); - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); - return Air.internedToRef(wip_ty.finish(ip, new_namespace_index)); } fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref { @@ -24181,7 +23944,7 @@ fn analyzeShuffle( const b_src = block.builtinCallArgSrc(src_node, 2); const mask_src = block.builtinCallArgSrc(src_node, 3); - // If the type of `a` is `@Type(.undefined)`, i.e. the argument is untyped, + // If the type of `a` is `@TypeOf(undefined)`, i.e. the argument is untyped, // this is 0, because it is an error to index into this vector. const a_len: u32 = switch (sema.typeOf(a_uncoerced).zigTypeTag(zcu)) { .array, .vector => @intCast(sema.typeOf(a_uncoerced).arrayLen(zcu)), @@ -24193,7 +23956,7 @@ fn analyzeShuffle( const a_ty = try pt.vectorType(.{ .len = a_len, .child = elem_ty.toIntern() }); const a_coerced = try sema.coerce(block, a_ty, a_uncoerced, a_src); - // If the type of `b` is `@Type(.undefined)`, i.e. the argument is untyped, this is 0, because it is an error to index into this vector. + // If the type of `b` is `@TypeOf(undefined)`, i.e. the argument is untyped, this is 0, because it is an error to index into this vector. const b_len: u32 = switch (sema.typeOf(b_uncoerced).zigTypeTag(zcu)) { .array, .vector => @intCast(sema.typeOf(b_uncoerced).arrayLen(zcu)), .undefined => 0, @@ -26199,11 +25962,16 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD .calling_convention => try sema.getBuiltinType(src, .CallingConvention), .address_space => try sema.getBuiltinType(src, .AddressSpace), .float_mode => try sema.getBuiltinType(src, .FloatMode), + .signedness => try sema.getBuiltinType(src, .Signedness), .reduce_op => try sema.getBuiltinType(src, .ReduceOp), .call_modifier => try sema.getBuiltinType(src, .CallModifier), .prefetch_options => try sema.getBuiltinType(src, .PrefetchOptions), .export_options => try sema.getBuiltinType(src, .ExportOptions), .extern_options => try sema.getBuiltinType(src, .ExternOptions), + .enum_info => try sema.getBuiltinType(src, .@"Type.Enum"), + .pointer_info => try sema.getBuiltinType(src, .@"Type.Pointer"), + .struct_info => try sema.getBuiltinType(src, .@"Type.Struct"), + .union_info => try sema.getBuiltinType(src, .@"Type.Union"), .type_info => try sema.getBuiltinType(src, .Type), .branch_hint => try sema.getBuiltinType(src, .BranchHint), // zig fmt: on diff --git a/src/Type.zig b/src/Type.zig index a199811c8e52..1dfad34cc3d7 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -295,7 +295,7 @@ pub fn print(ty: Type, writer: *std.io.Writer, pt: Zcu.PerThread) std.io.Writer. .undefined, => try writer.print("@TypeOf({s})", .{@tagName(s)}), - .enum_literal => try writer.writeAll("@Type(.enum_literal)"), + .enum_literal => try writer.writeAll("@TypeOf(.enum_literal)"), .generic_poison => unreachable, }, @@ -3487,7 +3487,10 @@ pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 { .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_line, .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_line, .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_line, - .reify => zir.extraData(Zir.Inst.Reify, inst.data.extended.operand).data.src_line, + .enum_reify => zir.extraData(Zir.Inst.Reify, inst.data.extended.operand).data.src_line, + .pointer_reify => zir.extraData(Zir.Inst.Reify, inst.data.extended.operand).data.src_line, + .struct_reify => zir.extraData(Zir.Inst.Reify, inst.data.extended.operand).data.src_line, + .union_reify => zir.extraData(Zir.Inst.Reify, inst.data.extended.operand).data.src_line, else => unreachable, }, else => unreachable, diff --git a/src/Zcu.zig b/src/Zcu.zig index 6d07477edcc7..c2e34d2b7e8c 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -2623,7 +2623,10 @@ pub const LazySrcLoc = struct { .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_node, .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_node, .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_node, - .reify => zir.extraData(Zir.Inst.Reify, inst.data.extended.operand).data.node, + .enum_reify => zir.extraData(Zir.Inst.Reify, inst.data.extended.operand).data.node, + .pointer_reify => zir.extraData(Zir.Inst.Reify, inst.data.extended.operand).data.node, + .struct_reify => zir.extraData(Zir.Inst.Reify, inst.data.extended.operand).data.node, + .union_reify => zir.extraData(Zir.Inst.Reify, inst.data.extended.operand).data.node, else => unreachable, }, else => unreachable, diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 80542b551f39..86fbc950bcb9 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -194147,9 +194147,7 @@ const Select = struct { } fn adjustedImm(op: Select.Operand, comptime SignedImm: type, s: *const Select) SignedImm { - const UnsignedImm = @Type(.{ - .int = .{ .signedness = .unsigned, .bits = @typeInfo(SignedImm).int.bits }, - }); + const UnsignedImm = @Int(.unsigned, @typeInfo(SignedImm).int.bits); const lhs: SignedImm = lhs: switch (op.flags.adjust.lhs) { .none => 0, .ptr_size => @divExact(s.cg.target.ptrBitWidth(), 8), @@ -194210,10 +194208,10 @@ const Select = struct { const RefImm = switch (size) { else => comptime unreachable, .none => Imm, - .byte, .word, .dword, .qword => @Type(comptime .{ .int = .{ - .signedness = @typeInfo(Imm).int.signedness, - .bits = size.bitSize(undefined), - } }), + .byte, .word, .dword, .qword => @Int( + @typeInfo(Imm).int.signedness, + size.bitSize(undefined), + ), }; break :lhs @bitCast(@as(Imm, @intCast(@as(RefImm, switch (adjust) { else => comptime unreachable, diff --git a/src/arch/x86_64/Emit.zig b/src/arch/x86_64/Emit.zig index da15dc6bfbe2..c0ee44c0411c 100644 --- a/src/arch/x86_64/Emit.zig +++ b/src/arch/x86_64/Emit.zig @@ -648,7 +648,7 @@ pub fn emitMir(emit: *Emit) Error!void { switch (reloc.source_length) { else => unreachable, inline 1, 4 => |source_length| std.mem.writeInt( - @Type(.{ .int = .{ .signedness = .signed, .bits = @as(u16, 8) * source_length } }), + @Int(.signed, @as(u16, 8) * source_length), inst_bytes[reloc.source_offset..][0..source_length], @intCast(disp), .little, diff --git a/src/codegen.zig b/src/codegen.zig index 9bddc51963c8..24f39c504a69 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -209,7 +209,7 @@ pub fn generateLazyFunction( fn writeFloat(comptime F: type, f: F, target: *const std.Target, endian: std.builtin.Endian, code: []u8) void { _ = target; const bits = @typeInfo(F).float.bits; - const Int = @Type(.{ .int = .{ .signedness = .unsigned, .bits = bits } }); + const Int = @Int(.unsigned, bits); const int: Int = @bitCast(f); mem.writeInt(Int, code[0..@divExact(bits, 8)], int, endian); } diff --git a/src/link.zig b/src/link.zig index 0fbd4b28cfdb..4305b87bccc7 100644 --- a/src/link.zig +++ b/src/link.zig @@ -47,10 +47,7 @@ pub const Diags = struct { const Int = blk: { const bits = @typeInfo(@This()).@"struct".fields.len; - break :blk @Type(.{ .int = .{ - .signedness = .unsigned, - .bits = bits, - } }); + break :blk @Int(.unsigned, bits); }; pub fn anySet(ef: Flags) bool { diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index a1a9dedd4bce..4f49084bcb64 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -4210,7 +4210,10 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP .enum_decl => @as(Zir.Inst.EnumDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy, .union_decl => @as(Zir.Inst.UnionDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy, .opaque_decl => @as(Zir.Inst.OpaqueDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy, - .reify => @as(Zir.Inst.NameStrategy, @enumFromInt(decl_inst.data.extended.small)), + .enum_reify => @as(Zir.Inst.NameStrategy, @enumFromInt(decl_inst.data.extended.small)), + .pointer_reify => @as(Zir.Inst.NameStrategy, @enumFromInt(decl_inst.data.extended.small)), + .struct_reify => @as(Zir.Inst.NameStrategy, @enumFromInt(decl_inst.data.extended.small)), + .union_reify => @as(Zir.Inst.NameStrategy, @enumFromInt(decl_inst.data.extended.small)), else => unreachable, }, else => unreachable, @@ -4840,12 +4843,12 @@ fn DeclValEnum(comptime T: type) type { if (min_value == null or min_value.? > value) min_value = value; if (max_value == null or max_value.? < value) max_value = value; } - return @Type(.{ .@"enum" = .{ + return @Enum(.{ .tag_type = std.math.IntFittingRange(min_value orelse 0, max_value orelse 0), .fields = fields[0..fields_len], .decls = &.{}, .is_exhaustive = true, - } }); + }); } const AbbrevCode = enum { @@ -5986,10 +5989,12 @@ fn freeCommonEntry(dwarf: *Dwarf, unit: Unit.Index, entry: Entry.Index) UpdateEr fn writeInt(dwarf: *Dwarf, buf: []u8, int: u64) void { switch (buf.len) { - inline 0...8 => |len| std.mem.writeInt(@Type(.{ .int = .{ - .signedness = .unsigned, - .bits = len * 8, - } }), buf[0..len], @intCast(int), dwarf.endian), + inline 0...8 => |len| std.mem.writeInt( + @Int(.unsigned, len * 8), + buf[0..len], + @intCast(int), + dwarf.endian, + ), else => unreachable, } } diff --git a/src/main.zig b/src/main.zig index 1d178730b054..73a03e2bf3fe 100644 --- a/src/main.zig +++ b/src/main.zig @@ -132,7 +132,7 @@ var log_scopes: std.ArrayListUnmanaged([]const u8) = .empty; pub fn log( comptime level: std.log.Level, - comptime scope: @Type(.enum_literal), + comptime scope: @TypeOf(.enum_literal), comptime format: []const u8, args: anytype, ) void { diff --git a/src/print_zir.zig b/src/print_zir.zig index ae674e43e5a6..08783f414757 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -399,6 +399,7 @@ const Writer = struct { .splat, .reduce, .bitcast, + .int_reify, .vector_type, .max, .min, @@ -574,7 +575,11 @@ const Writer = struct { try self.writeSrcNode(stream, inst_data.node); }, - .reify => { + .enum_reify, + .pointer_reify, + .struct_reify, + .union_reify, + => { const inst_data = self.code.extraData(Zir.Inst.Reify, extended.operand).data; try stream.print("line({d}), ", .{inst_data.src_line}); try self.writeInstRef(stream, inst_data.operand); diff --git a/stage1/zig1.wasm b/stage1/zig1.wasm index f1c50d438d1e..dd3455648381 100644 Binary files a/stage1/zig1.wasm and b/stage1/zig1.wasm differ diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig index bcd72d5176e9..54399377666a 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.zig @@ -1283,12 +1283,9 @@ test "reference to inferred local variable works as expected" { try expect(crasher_local.lets_crash != a.lets_crash); } -test "@Type returned from block" { +test "@Int returned from block" { const T = comptime b: { - break :b @Type(.{ .int = .{ - .signedness = .unsigned, - .bits = 8, - } }); + break :b @Int(.unsigned, 8); }; try std.testing.expect(T == u8); } diff --git a/test/behavior/bit_shifting.zig b/test/behavior/bit_shifting.zig index 33742f21c40e..eabe31b8b23f 100644 --- a/test/behavior/bit_shifting.zig +++ b/test/behavior/bit_shifting.zig @@ -119,21 +119,12 @@ test "Saturating Shift Left where lhs is of a computed type" { if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { - fn getIntShiftType(comptime T: type) type { - var unsigned_shift_type = @typeInfo(std.math.Log2Int(T)).int; - unsigned_shift_type.signedness = .signed; - - return @Type(.{ - .int = unsigned_shift_type, - }); - } - pub fn FixedPoint(comptime ValueType: type) type { return struct { value: ValueType, exponent: ShiftType, - const ShiftType: type = getIntShiftType(ValueType); + const ShiftType = @Int(.signed, @typeInfo(std.math.Log2Int(ValueType)).int.bits); pub fn shiftExponent(self: @This(), shift: ShiftType) @This() { const shiftAbs = @abs(shift); diff --git a/test/behavior/call.zig b/test/behavior/call.zig index e509fcda3597..93573fc68fd6 100644 --- a/test/behavior/call.zig +++ b/test/behavior/call.zig @@ -357,7 +357,7 @@ test "inline call doesn't re-evaluate non generic struct" { try comptime @call(.always_inline, S.foo, ArgTuple{.{ .a = 123, .b = 45 }}); } -test "Enum constructed by @Type passed as generic argument" { +test "Enum constructed by @Enum passed as generic argument" { const S = struct { const E = std.meta.FieldEnum(struct { prev_pos: bool, diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index a0b265490da8..42fa51d2b81a 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -2327,9 +2327,9 @@ test "peer type resolution: pointer attributes are combined correctly" { }; const NonAllowZero = comptime blk: { - var ti = @typeInfo(@TypeOf(r1, r2, r3, r4)); - ti.pointer.is_allowzero = false; - break :blk @Type(ti); + var ti = @typeInfo(@TypeOf(r1, r2, r3, r4)).pointer; + ti.is_allowzero = false; + break :blk @Pointer(ti); }; try expectEqualSlices(u8, std.mem.span(@volatileCast(@as(NonAllowZero, @ptrCast(r1)))), "foo"); try expectEqualSlices(u8, std.mem.span(@volatileCast(@as(NonAllowZero, @ptrCast(r2)))), "bar"); diff --git a/test/behavior/enum.zig b/test/behavior/enum.zig index d5c18fc9f621..fd83109b3cd7 100644 --- a/test/behavior/enum.zig +++ b/test/behavior/enum.zig @@ -1275,10 +1275,7 @@ test "Non-exhaustive enum backed by comptime_int" { test "matching captures causes enum equivalence" { const S = struct { fn Nonexhaustive(comptime I: type) type { - const UTag = @Type(.{ .int = .{ - .signedness = .unsigned, - .bits = @typeInfo(I).int.bits, - } }); + const UTag = @Int(.unsigned, @typeInfo(I).int.bits); return enum(UTag) { _ }; } }; diff --git a/test/behavior/fn.zig b/test/behavior/fn.zig index 6fe569a1f64d..9dd91e5ff58d 100644 --- a/test/behavior/fn.zig +++ b/test/behavior/fn.zig @@ -568,10 +568,10 @@ test "lazy values passed to anytype parameter" { test "pass and return comptime-only types" { const S = struct { - fn returnNull(comptime x: @Type(.null)) @Type(.null) { + fn returnNull(comptime x: @TypeOf(null)) @TypeOf(null) { return x; } - fn returnUndefined(comptime x: @Type(.undefined)) @Type(.undefined) { + fn returnUndefined(comptime x: @TypeOf(undefined)) @TypeOf(undefined) { return x; } }; diff --git a/test/behavior/generics.zig b/test/behavior/generics.zig index a76f5325441e..831e49d6969c 100644 --- a/test/behavior/generics.zig +++ b/test/behavior/generics.zig @@ -271,13 +271,11 @@ test "generic function instantiation turns into comptime call" { pub fn FieldEnum(comptime T: type) type { _ = T; var enumFields: [1]std.builtin.Type.EnumField = .{.{ .name = "A", .value = 0 }}; - return @Type(.{ - .@"enum" = .{ - .tag_type = u0, - .fields = &enumFields, - .decls = &.{}, - .is_exhaustive = true, - }, + return @Enum(.{ + .tag_type = u0, + .fields = &enumFields, + .decls = &.{}, + .is_exhaustive = true, }); } }; diff --git a/test/behavior/sizeof_and_typeof.zig b/test/behavior/sizeof_and_typeof.zig index b5f7e966f014..ffb32fbd6a57 100644 --- a/test/behavior/sizeof_and_typeof.zig +++ b/test/behavior/sizeof_and_typeof.zig @@ -340,14 +340,14 @@ test "peer type resolution with @TypeOf doesn't trigger dependency loop check" { test "@sizeOf reified union zero-size payload fields" { comptime { - try std.testing.expect(0 == @sizeOf(@Type(@typeInfo(union {})))); - try std.testing.expect(0 == @sizeOf(@Type(@typeInfo(union { a: void })))); + try std.testing.expect(0 == @sizeOf(@Union(@typeInfo(union {}).@"union"))); + try std.testing.expect(0 == @sizeOf(@Union(@typeInfo(union { a: void }).@"union"))); if (builtin.mode == .Debug or builtin.mode == .ReleaseSafe) { - try std.testing.expect(1 == @sizeOf(@Type(@typeInfo(union { a: void, b: void })))); - try std.testing.expect(1 == @sizeOf(@Type(@typeInfo(union { a: void, b: void, c: void })))); + try std.testing.expect(1 == @sizeOf(@Union(@typeInfo(union { a: void, b: void }).@"union"))); + try std.testing.expect(1 == @sizeOf(@Union(@typeInfo(union { a: void, b: void, c: void }).@"union"))); } else { - try std.testing.expect(0 == @sizeOf(@Type(@typeInfo(union { a: void, b: void })))); - try std.testing.expect(0 == @sizeOf(@Type(@typeInfo(union { a: void, b: void, c: void })))); + try std.testing.expect(0 == @sizeOf(@Union(@typeInfo(union { a: void, b: void }).@"union"))); + try std.testing.expect(0 == @sizeOf(@Union(@typeInfo(union { a: void, b: void, c: void }).@"union"))); } } } diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 4a66c56cea2b..293130e939ea 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -2066,10 +2066,7 @@ test "matching captures causes struct equivalence" { fn UnsignedWrapper(comptime I: type) type { const bits = @typeInfo(I).int.bits; return struct { - x: @Type(.{ .int = .{ - .signedness = .unsigned, - .bits = bits, - } }), + x: @Int(.unsigned, bits), }; } }; diff --git a/test/behavior/switch.zig b/test/behavior/switch.zig index 873ea1f1daaa..47bdfe96b341 100644 --- a/test/behavior/switch.zig +++ b/test/behavior/switch.zig @@ -849,7 +849,8 @@ test "switch capture peer type resolution" { test "switch capture peer type resolution for in-memory coercible payloads" { const T1 = c_int; - const T2 = @Type(@typeInfo(T1)); + const t1_info = @typeInfo(T1).int; + const T2 = @Int(t1_info.signedness, t1_info.bits); comptime assert(T1 != T2); @@ -869,7 +870,8 @@ test "switch capture peer type resolution for in-memory coercible payloads" { test "switch pointer capture peer type resolution" { const T1 = c_int; - const T2 = @Type(@typeInfo(T1)); + const t1_info = @typeInfo(T1).int; + const T2 = @Int(t1_info.signedness, t1_info.bits); comptime assert(T1 != T2); diff --git a/test/behavior/tuple.zig b/test/behavior/tuple.zig index 891dd2726e9a..3d5d9488256d 100644 --- a/test/behavior/tuple.zig +++ b/test/behavior/tuple.zig @@ -133,26 +133,24 @@ test "array-like initializer for tuple types" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - const T = @Type(.{ - .@"struct" = .{ - .is_tuple = true, - .layout = .auto, - .decls = &.{}, - .fields = &.{ - .{ - .name = "0", - .type = i32, - .default_value_ptr = null, - .is_comptime = false, - .alignment = @alignOf(i32), - }, - .{ - .name = "1", - .type = u8, - .default_value_ptr = null, - .is_comptime = false, - .alignment = @alignOf(u8), - }, + const T = @Struct(.{ + .is_tuple = true, + .layout = .auto, + .decls = &.{}, + .fields = &.{ + .{ + .name = "0", + .type = i32, + .default_value_ptr = null, + .is_comptime = false, + .alignment = @alignOf(i32), + }, + .{ + .name = "1", + .type = u8, + .default_value_ptr = null, + .is_comptime = false, + .alignment = @alignOf(u8), }, }, }); @@ -328,19 +326,17 @@ test "tuple type with void field" { test "zero sized struct in tuple handled correctly" { const State = struct { const Self = @This(); - data: @Type(.{ - .@"struct" = .{ - .is_tuple = true, - .layout = .auto, - .decls = &.{}, - .fields = &.{.{ - .name = "0", - .type = struct {}, - .default_value_ptr = null, - .is_comptime = false, - .alignment = 0, - }}, - }, + data: @Struct(.{ + .is_tuple = true, + .layout = .auto, + .decls = &.{}, + .fields = &.{.{ + .name = "0", + .type = struct {}, + .default_value_ptr = null, + .is_comptime = false, + .alignment = 0, + }}, }), pub fn do(this: Self) usize { @@ -484,12 +480,12 @@ test "coerce anon tuple to tuple" { } test "empty tuple type" { - const S = @Type(.{ .@"struct" = .{ + const S = @Struct(.{ .layout = .auto, .fields = &.{}, .decls = &.{}, .is_tuple = true, - } }); + }); const s: S = .{}; try expect(s.len == 0); diff --git a/test/behavior/type.zig b/test/behavior/type.zig index a2f2afa3487d..55e40c3508cf 100644 --- a/test/behavior/type.zig +++ b/test/behavior/type.zig @@ -4,63 +4,17 @@ const Type = std.builtin.Type; const testing = std.testing; const assert = std.debug.assert; -fn testTypes(comptime types: []const type) !void { - inline for (types) |testType| { - try testing.expect(testType == @Type(@typeInfo(testType))); - } -} - -test "Type.MetaType" { - try testing.expect(type == @Type(.{ .type = {} })); - try testTypes(&[_]type{type}); -} - -test "Type.Void" { - try testing.expect(void == @Type(.{ .void = {} })); - try testTypes(&[_]type{void}); -} - -test "Type.Bool" { - try testing.expect(bool == @Type(.{ .bool = {} })); - try testTypes(&[_]type{bool}); -} - -test "Type.NoReturn" { - try testing.expect(noreturn == @Type(.{ .noreturn = {} })); - try testTypes(&[_]type{noreturn}); -} - test "Type.Int" { - try testing.expect(u1 == @Type(.{ .int = .{ .signedness = .unsigned, .bits = 1 } })); - try testing.expect(i1 == @Type(.{ .int = .{ .signedness = .signed, .bits = 1 } })); - try testing.expect(u8 == @Type(.{ .int = .{ .signedness = .unsigned, .bits = 8 } })); - try testing.expect(i8 == @Type(.{ .int = .{ .signedness = .signed, .bits = 8 } })); - try testing.expect(u64 == @Type(.{ .int = .{ .signedness = .unsigned, .bits = 64 } })); - try testing.expect(i64 == @Type(.{ .int = .{ .signedness = .signed, .bits = 64 } })); - try testTypes(&[_]type{ u8, u32, i64 }); -} - -test "Type.ComptimeFloat" { - try testTypes(&[_]type{comptime_float}); -} -test "Type.ComptimeInt" { - try testTypes(&[_]type{comptime_int}); -} -test "Type.Undefined" { - try testTypes(&[_]type{@TypeOf(undefined)}); -} -test "Type.Null" { - try testTypes(&[_]type{@TypeOf(null)}); -} - -test "Type.EnumLiteral" { - try testTypes(&[_]type{ - @TypeOf(.Dummy), - }); + try testing.expect(u1 == @Int(.unsigned, 1)); + try testing.expect(i1 == @Int(.signed, 1)); + try testing.expect(u8 == @Int(.unsigned, 8)); + try testing.expect(i8 == @Int(.signed, 8)); + try testing.expect(u64 == @Int(.unsigned, 64)); + try testing.expect(i64 == @Int(.signed, 64)); } test "Type.Pointer" { - try testTypes(&[_]type{ + inline for (&[_]type{ // One Value Pointer Types *u8, *const u8, *volatile u8, *const volatile u8, @@ -101,62 +55,27 @@ test "Type.Pointer" { [*c]align(4) volatile u8, [*c]align(4) const volatile u8, [*c]align(8) u8, [*c]align(8) const u8, [*c]align(8) volatile u8, [*c]align(8) const volatile u8, - }); -} - -test "Type.Float" { - try testing.expect(f16 == @Type(.{ .float = .{ .bits = 16 } })); - try testing.expect(f32 == @Type(.{ .float = .{ .bits = 32 } })); - try testing.expect(f64 == @Type(.{ .float = .{ .bits = 64 } })); - try testing.expect(f80 == @Type(.{ .float = .{ .bits = 80 } })); - try testing.expect(f128 == @Type(.{ .float = .{ .bits = 128 } })); - try testTypes(&[_]type{ f16, f32, f64, f80, f128 }); -} - -test "Type.Array" { - try testing.expect([123]u8 == @Type(.{ - .array = .{ - .len = 123, - .child = u8, - .sentinel_ptr = null, - }, - })); - try testing.expect([2]u32 == @Type(.{ - .array = .{ - .len = 2, - .child = u32, - .sentinel_ptr = null, - }, - })); - try testing.expect([2:0]u32 == @Type(.{ - .array = .{ - .len = 2, - .child = u32, - .sentinel_ptr = &@as(u32, 0), - }, - })); - try testTypes(&[_]type{ [1]u8, [30]usize, [7]bool }); + }) |testType| { + try testing.expect(testType == @Pointer(@typeInfo(testType).pointer)); + } } -test "@Type create slice with null sentinel" { - const Slice = @Type(.{ - .pointer = .{ - .size = .slice, - .is_const = true, - .is_volatile = false, - .is_allowzero = false, - .alignment = 8, - .address_space = .generic, - .child = *i32, - .sentinel_ptr = null, - }, +test "@Pointer create slice with null sentinel" { + const Slice = @Pointer(.{ + .size = .slice, + .is_const = true, + .is_volatile = false, + .is_allowzero = false, + .alignment = 8, + .address_space = .generic, + .child = *i32, + .sentinel_ptr = null, }); try testing.expect(Slice == []align(8) const *i32); } -test "@Type picks up the sentinel value from Type" { - try testTypes(&[_]type{ - [11:0]u8, [4:10]u8, +test "@Pointer picks up the sentinel value from Type" { + inline for (&[_]type{ [*:0]u8, [*:0]const u8, [*:0]volatile u8, [*:0]const volatile u8, [*:0]align(4) u8, [*:0]align(4) const u8, @@ -179,91 +98,22 @@ test "@Type picks up the sentinel value from Type" { [:0]allowzero align(4) u8, [:0]allowzero align(4) const u8, [:0]allowzero align(4) volatile u8, [:0]allowzero align(4) const volatile u8, [:4]allowzero align(4) volatile u8, [:4]allowzero align(4) const volatile u8, - }); -} - -test "Type.Optional" { - try testTypes(&[_]type{ - ?u8, - ?*u8, - ?[]u8, - ?[*]u8, - ?[*c]u8, - }); -} - -test "Type.ErrorUnion" { - try testTypes(&[_]type{ - error{}!void, - error{Error}!void, - }); -} - -test "Type.Opaque" { - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - - const Opaque = @Type(.{ - .@"opaque" = .{ - .decls = &.{}, - }, - }); - try testing.expect(Opaque != opaque {}); - try testing.expectEqualSlices( - Type.Declaration, - &.{}, - @typeInfo(Opaque).@"opaque".decls, - ); -} - -test "Type.Vector" { - try testTypes(&[_]type{ - @Vector(0, u8), - @Vector(4, u8), - @Vector(8, *u8), - @Vector(0, u8), - @Vector(4, u8), - @Vector(8, *u8), - }); -} - -test "Type.AnyFrame" { - if (true) { - // https://github.com/ziglang/zig/issues/6025 - return error.SkipZigTest; + }) |TestType| { + try testing.expect(TestType == @Pointer(@typeInfo(TestType).pointer)); } - - try testTypes(&[_]type{ - anyframe, - anyframe->u8, - anyframe->anyframe->u8, - }); } fn add(a: i32, b: i32) i32 { return a + b; } -test "Type.ErrorSet" { - try testing.expect(@Type(.{ .error_set = null }) == anyerror); - - // error sets don't compare equal so just check if they compile - inline for (.{ error{}, error{A}, error{ A, B, C } }) |T| { - const info = @typeInfo(T); - const T2 = @Type(info); - try testing.expect(T == T2); - } -} - test "Type.Struct" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - const A = @Type(@typeInfo(struct { x: u8, y: u32 })); + const A = @Struct(@typeInfo(struct { x: u8, y: u32 }).@"struct"); const infoA = @typeInfo(A).@"struct"; try testing.expectEqual(Type.ContainerLayout.auto, infoA.layout); try testing.expectEqualSlices(u8, "x", infoA.fields[0].name); @@ -281,7 +131,7 @@ test "Type.Struct" { a.y += 1; try testing.expectEqual(@as(u32, 2), a.y); - const B = @Type(@typeInfo(extern struct { x: u8, y: u32 = 5 })); + const B = @Struct(@typeInfo(extern struct { x: u8, y: u32 = 5 }).@"struct"); const infoB = @typeInfo(B).@"struct"; try testing.expectEqual(Type.ContainerLayout.@"extern", infoB.layout); try testing.expectEqualSlices(u8, "x", infoB.fields[0].name); @@ -293,7 +143,7 @@ test "Type.Struct" { try testing.expectEqual(@as(usize, 0), infoB.decls.len); try testing.expectEqual(@as(bool, false), infoB.is_tuple); - const C = @Type(@typeInfo(packed struct { x: u8 = 3, y: u32 = 5 })); + const C = @Struct(@typeInfo(packed struct { x: u8 = 3, y: u32 = 5 }).@"struct"); const infoC = @typeInfo(C).@"struct"; try testing.expectEqual(Type.ContainerLayout.@"packed", infoC.layout); try testing.expectEqualSlices(u8, "x", infoC.fields[0].name); @@ -306,7 +156,7 @@ test "Type.Struct" { try testing.expectEqual(@as(bool, false), infoC.is_tuple); // anon structs - const D = @Type(@typeInfo(@TypeOf(.{ .x = 3, .y = 5 }))); + const D = @Struct(@typeInfo(@TypeOf(.{ .x = 3, .y = 5 })).@"struct"); const infoD = @typeInfo(D).@"struct"; try testing.expectEqual(Type.ContainerLayout.auto, infoD.layout); try testing.expectEqualSlices(u8, "x", infoD.fields[0].name); @@ -319,7 +169,7 @@ test "Type.Struct" { try testing.expectEqual(@as(bool, false), infoD.is_tuple); // tuples - const E = @Type(@typeInfo(@TypeOf(.{ 1, 2 }))); + const E = @Struct(@typeInfo(@TypeOf(.{ 1, 2 })).@"struct"); const infoE = @typeInfo(E).@"struct"; try testing.expectEqual(Type.ContainerLayout.auto, infoE.layout); try testing.expectEqualSlices(u8, "0", infoE.fields[0].name); @@ -332,14 +182,14 @@ test "Type.Struct" { try testing.expectEqual(@as(bool, true), infoE.is_tuple); // empty struct - const F = @Type(@typeInfo(struct {})); + const F = @Struct(@typeInfo(struct {}).@"struct"); const infoF = @typeInfo(F).@"struct"; try testing.expectEqual(Type.ContainerLayout.auto, infoF.layout); try testing.expect(infoF.fields.len == 0); try testing.expectEqual(@as(bool, false), infoF.is_tuple); // empty tuple - const G = @Type(@typeInfo(@TypeOf(.{}))); + const G = @Struct(@typeInfo(@TypeOf(.{})).@"struct"); const infoG = @typeInfo(G).@"struct"; try testing.expectEqual(Type.ContainerLayout.auto, infoG.layout); try testing.expect(infoG.fields.len == 0); @@ -351,30 +201,26 @@ test "Type.Enum" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - const Foo = @Type(.{ - .@"enum" = .{ - .tag_type = u8, - .fields = &.{ - .{ .name = "a", .value = 1 }, - .{ .name = "b", .value = 5 }, - }, - .decls = &.{}, - .is_exhaustive = true, + const Foo = @Enum(.{ + .tag_type = u8, + .fields = &.{ + .{ .name = "a", .value = 1 }, + .{ .name = "b", .value = 5 }, }, + .decls = &.{}, + .is_exhaustive = true, }); try testing.expectEqual(true, @typeInfo(Foo).@"enum".is_exhaustive); try testing.expectEqual(@as(u8, 1), @intFromEnum(Foo.a)); try testing.expectEqual(@as(u8, 5), @intFromEnum(Foo.b)); - const Bar = @Type(.{ - .@"enum" = .{ - .tag_type = u32, - .fields = &.{ - .{ .name = "a", .value = 1 }, - .{ .name = "b", .value = 5 }, - }, - .decls = &.{}, - .is_exhaustive = false, + const Bar = @Enum(.{ + .tag_type = u32, + .fields = &.{ + .{ .name = "a", .value = 1 }, + .{ .name = "b", .value = 5 }, }, + .decls = &.{}, + .is_exhaustive = false, }); try testing.expectEqual(false, @typeInfo(Bar).@"enum".is_exhaustive); try testing.expectEqual(@as(u32, 1), @intFromEnum(Bar.a)); @@ -383,12 +229,12 @@ test "Type.Enum" { { // from https://github.com/ziglang/zig/issues/19985 { // enum with single field can be initialized. - const E = @Type(.{ .@"enum" = .{ + const E = @Enum(.{ .tag_type = u0, .is_exhaustive = true, .fields = &.{.{ .name = "foo", .value = 0 }}, .decls = &.{}, - } }); + }); const s: struct { E } = .{.foo}; try testing.expectEqual(.foo, s[0]); } @@ -413,59 +259,51 @@ test "Type.Union" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - const Untagged = @Type(.{ - .@"union" = .{ - .layout = .@"extern", - .tag_type = null, - .fields = &.{ - .{ .name = "int", .type = i32, .alignment = @alignOf(f32) }, - .{ .name = "float", .type = f32, .alignment = @alignOf(f32) }, - }, - .decls = &.{}, + const Untagged = @Union(.{ + .layout = .@"extern", + .tag_type = null, + .fields = &.{ + .{ .name = "int", .type = i32, .alignment = @alignOf(f32) }, + .{ .name = "float", .type = f32, .alignment = @alignOf(f32) }, }, + .decls = &.{}, }); var untagged = Untagged{ .int = 1 }; untagged.float = 2.0; untagged.int = 3; try testing.expectEqual(@as(i32, 3), untagged.int); - const PackedUntagged = @Type(.{ - .@"union" = .{ - .layout = .@"packed", - .tag_type = null, - .fields = &.{ - .{ .name = "signed", .type = i32, .alignment = @alignOf(i32) }, - .{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) }, - }, - .decls = &.{}, + const PackedUntagged = @Union(.{ + .layout = .@"packed", + .tag_type = null, + .fields = &.{ + .{ .name = "signed", .type = i32, .alignment = @alignOf(i32) }, + .{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) }, }, + .decls = &.{}, }); var packed_untagged: PackedUntagged = .{ .signed = -1 }; _ = &packed_untagged; try testing.expectEqual(@as(i32, -1), packed_untagged.signed); try testing.expectEqual(~@as(u32, 0), packed_untagged.unsigned); - const Tag = @Type(.{ - .@"enum" = .{ - .tag_type = u1, - .fields = &.{ - .{ .name = "signed", .value = 0 }, - .{ .name = "unsigned", .value = 1 }, - }, - .decls = &.{}, - .is_exhaustive = true, + const Tag = @Enum(.{ + .tag_type = u1, + .fields = &.{ + .{ .name = "signed", .value = 0 }, + .{ .name = "unsigned", .value = 1 }, }, + .decls = &.{}, + .is_exhaustive = true, }); - const Tagged = @Type(.{ - .@"union" = .{ - .layout = .auto, - .tag_type = Tag, - .fields = &.{ - .{ .name = "signed", .type = i32, .alignment = @alignOf(i32) }, - .{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) }, - }, - .decls = &.{}, + const Tagged = @Union(.{ + .layout = .auto, + .tag_type = Tag, + .fields = &.{ + .{ .name = "signed", .type = i32, .alignment = @alignOf(i32) }, + .{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) }, }, + .decls = &.{}, }); var tagged = Tagged{ .signed = -1 }; try testing.expectEqual(Tag.signed, @as(Tag, tagged)); @@ -474,113 +312,70 @@ test "Type.Union" { } test "Type.Union from Type.Enum" { - const Tag = @Type(.{ - .@"enum" = .{ - .tag_type = u0, - .fields = &.{ - .{ .name = "working_as_expected", .value = 0 }, - }, - .decls = &.{}, - .is_exhaustive = true, + const Tag = @Enum(.{ + .tag_type = u0, + .fields = &.{ + .{ .name = "working_as_expected", .value = 0 }, }, + .decls = &.{}, + .is_exhaustive = true, }); - const T = @Type(.{ - .@"union" = .{ - .layout = .auto, - .tag_type = Tag, - .fields = &.{ - .{ .name = "working_as_expected", .type = u32, .alignment = @alignOf(u32) }, - }, - .decls = &.{}, + const T = @Union(.{ + .layout = .auto, + .tag_type = Tag, + .fields = &.{ + .{ .name = "working_as_expected", .type = u32, .alignment = @alignOf(u32) }, }, + .decls = &.{}, }); _ = @typeInfo(T).@"union"; } test "Type.Union from regular enum" { const E = enum { working_as_expected }; - const T = @Type(.{ - .@"union" = .{ - .layout = .auto, - .tag_type = E, - .fields = &.{ - .{ .name = "working_as_expected", .type = u32, .alignment = @alignOf(u32) }, - }, - .decls = &.{}, + const T = @Union(.{ + .layout = .auto, + .tag_type = E, + .fields = &.{ + .{ .name = "working_as_expected", .type = u32, .alignment = @alignOf(u32) }, }, + .decls = &.{}, }); _ = @typeInfo(T).@"union"; } test "Type.Union from empty regular enum" { const E = enum {}; - const U = @Type(.{ - .@"union" = .{ - .layout = .auto, - .tag_type = E, - .fields = &.{}, - .decls = &.{}, - }, + const U = @Union(.{ + .layout = .auto, + .tag_type = E, + .fields = &.{}, + .decls = &.{}, }); try testing.expectEqual(@sizeOf(U), 0); } test "Type.Union from empty Type.Enum" { - const E = @Type(.{ - .@"enum" = .{ - .tag_type = u0, - .fields = &.{}, - .decls = &.{}, - .is_exhaustive = true, - }, + const E = @Enum(.{ + .tag_type = u0, + .fields = &.{}, + .decls = &.{}, + .is_exhaustive = true, }); - const U = @Type(.{ - .@"union" = .{ - .layout = .auto, - .tag_type = E, - .fields = &.{}, - .decls = &.{}, - }, + const U = @Union(.{ + .layout = .auto, + .tag_type = E, + .fields = &.{}, + .decls = &.{}, }); try testing.expectEqual(@sizeOf(U), 0); } -test "Type.Fn" { - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - - const some_opaque = opaque {}; - const some_ptr = *some_opaque; - const T = fn (c_int, some_ptr) callconv(.c) void; - - { - const fn_info = std.builtin.Type{ .@"fn" = .{ - .calling_convention = .c, - .is_generic = false, - .is_var_args = false, - .return_type = void, - .params = &.{ - .{ .is_generic = false, .is_noalias = false, .type = c_int }, - .{ .is_generic = false, .is_noalias = false, .type = some_ptr }, - }, - } }; - - const fn_type = @Type(fn_info); - try std.testing.expectEqual(T, fn_type); - } - - { - const fn_info = @typeInfo(T); - const fn_type = @Type(fn_info); - try std.testing.expectEqual(T, fn_type); - } -} - test "reified struct field name from optional payload" { comptime { const m_name: ?[1:0]u8 = "a".*; if (m_name) |*name| { - const T = @Type(.{ .@"struct" = .{ + const T = @Struct(.{ .layout = .auto, .fields = &.{.{ .name = name, @@ -591,7 +386,7 @@ test "reified struct field name from optional payload" { }}, .decls = &.{}, .is_tuple = false, - } }); + }); const t: T = .{ .a = 123 }; try std.testing.expect(t.a == 123); } @@ -601,19 +396,17 @@ test "reified struct field name from optional payload" { test "reified union uses @alignOf" { const S = struct { fn CreateUnion(comptime T: type) type { - return @Type(.{ - .@"union" = .{ - .layout = .auto, - .tag_type = null, - .fields = &[_]std.builtin.Type.UnionField{ - .{ - .name = "field", - .type = T, - .alignment = @alignOf(T), - }, + return @Union(.{ + .layout = .auto, + .tag_type = null, + .fields = &[_]std.builtin.Type.UnionField{ + .{ + .name = "field", + .type = T, + .alignment = @alignOf(T), }, - .decls = &.{}, }, + .decls = &.{}, }); } }; @@ -623,21 +416,19 @@ test "reified union uses @alignOf" { test "reified struct uses @alignOf" { const S = struct { fn NamespacedGlobals(comptime modules: anytype) type { - return @Type(.{ - .@"struct" = .{ - .layout = .auto, - .is_tuple = false, - .fields = &.{ - .{ - .name = "globals", - .type = modules.mach.globals, - .default_value_ptr = null, - .is_comptime = false, - .alignment = @alignOf(modules.mach.globals), - }, + return @Struct(.{ + .layout = .auto, + .is_tuple = false, + .fields = &.{ + .{ + .name = "globals", + .type = modules.mach.globals, + .default_value_ptr = null, + .is_comptime = false, + .alignment = @alignOf(modules.mach.globals), }, - .decls = &.{}, }, + .decls = &.{}, }); } }; @@ -648,55 +439,20 @@ test "reified struct uses @alignOf" { }); } -test "reified error set initialized with field pointer" { - const S = struct { - const info = .{ - .args = [_]Type.Error{ - .{ .name = "bar" }, - }, - }; - const Foo = @Type(.{ - .error_set = &info.args, - }); - }; - try testing.expect(S.Foo == error{bar}); -} -test "reified function type params initialized with field pointer" { - const S = struct { - const fn_info = .{ - .params = [_]Type.Fn.Param{ - .{ .is_generic = false, .is_noalias = false, .type = u8 }, - }, - }; - const Bar = @Type(.{ - .@"fn" = .{ - .calling_convention = .auto, - .is_generic = false, - .is_var_args = false, - .return_type = void, - .params = &fn_info.params, - }, - }); - }; - try testing.expect(@typeInfo(S.Bar) == .@"fn"); -} - test "empty struct assigned to reified struct field" { const S = struct { fn NamespacedComponents(comptime modules: anytype) type { - return @Type(.{ - .@"struct" = .{ - .layout = .auto, - .is_tuple = false, - .fields = &.{.{ - .name = "components", - .type = @TypeOf(modules.components), - .default_value_ptr = null, - .is_comptime = false, - .alignment = @alignOf(@TypeOf(modules.components)), - }}, - .decls = &.{}, - }, + return @Struct(.{ + .layout = .auto, + .is_tuple = false, + .fields = &.{.{ + .name = "components", + .type = @TypeOf(modules.components), + .default_value_ptr = null, + .is_comptime = false, + .alignment = @alignOf(@TypeOf(modules.components)), + }}, + .decls = &.{}, }); } @@ -713,16 +469,6 @@ test "empty struct assigned to reified struct field" { }); } -test "@Type should resolve its children types" { - const sparse = enum(u2) { a, b, c }; - const dense = enum(u2) { a, b, c, d }; - - comptime var sparse_info = @typeInfo(anyerror!sparse); - sparse_info.error_union.payload = dense; - const B = @Type(sparse_info); - try testing.expectEqual(anyerror!dense, B); -} - test "struct field names sliced at comptime from larger string" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO @@ -746,13 +492,11 @@ test "struct field names sliced at comptime from larger string" { }}; } - const T = @Type(.{ - .@"struct" = .{ - .layout = .auto, - .is_tuple = false, - .fields = fields, - .decls = &.{}, - }, + const T = @Struct(.{ + .layout = .auto, + .is_tuple = false, + .fields = fields, + .decls = &.{}, }); const gen_fields = @typeInfo(T).@"struct".fields; @@ -766,10 +510,7 @@ test "struct field names sliced at comptime from larger string" { test "matching captures causes opaque equivalence" { const S = struct { fn UnsignedId(comptime I: type) type { - const U = @Type(.{ .int = .{ - .signedness = .unsigned, - .bits = @typeInfo(I).int.bits, - } }); + const U = @Int(.unsigned, @typeInfo(I).int.bits); return opaque { fn id(x: U) U { return x; @@ -794,12 +535,12 @@ test "reify enum where fields refers to part of array" { .{ .name = "bar", .value = 1 }, undefined, }; - const E = @Type(.{ .@"enum" = .{ + const E = @Enum(.{ .tag_type = u8, .fields = fields[0..2], .decls = &.{}, .is_exhaustive = true, - } }); + }); var a: E = undefined; var b: E = undefined; a = .foo; diff --git a/test/behavior/union.zig b/test/behavior/union.zig index 53322697af20..1c8890611b97 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -2235,14 +2235,8 @@ test "matching captures causes union equivalence" { fn SignedUnsigned(comptime I: type) type { const bits = @typeInfo(I).int.bits; return union { - u: @Type(.{ .int = .{ - .signedness = .unsigned, - .bits = bits, - } }), - i: @Type(.{ .int = .{ - .signedness = .signed, - .bits = bits, - } }), + u: @Int(.unsigned, bits), + i: @Int(.signed, bits), }; } }; diff --git a/test/behavior/x86_64/math.zig b/test/behavior/x86_64/math.zig index 5f0473e0d575..5662a09c7776 100644 --- a/test/behavior/x86_64/math.zig +++ b/test/behavior/x86_64/math.zig @@ -36,34 +36,28 @@ pub fn ChangeScalar(comptime Type: type, comptime NewScalar: type) type { } pub fn AsSignedness(comptime Type: type, comptime signedness: std.builtin.Signedness) type { return switch (@typeInfo(Scalar(Type))) { - .int => |int| ChangeScalar(Type, @Type(.{ .int = .{ - .signedness = signedness, - .bits = int.bits, - } })), + .int => |int| ChangeScalar(Type, @Int(signedness, int.bits)), .float => Type, else => @compileError(@typeName(Type)), }; } pub fn AddOneBit(comptime Type: type) type { return ChangeScalar(Type, switch (@typeInfo(Scalar(Type))) { - .int => |int| @Type(.{ .int = .{ .signedness = int.signedness, .bits = 1 + int.bits } }), + .int => |int| @Int(int.signedness, 1 + int.bits), .float => Scalar(Type), else => @compileError(@typeName(Type)), }); } pub fn DoubleBits(comptime Type: type) type { return ChangeScalar(Type, switch (@typeInfo(Scalar(Type))) { - .int => |int| @Type(.{ .int = .{ .signedness = int.signedness, .bits = int.bits * 2 } }), + .int => |int| @Int(int.signedness, int.bits * 2), .float => Scalar(Type), else => @compileError(@typeName(Type)), }); } pub fn RoundBitsUp(comptime Type: type, comptime multiple: u16) type { return ChangeScalar(Type, switch (@typeInfo(Scalar(Type))) { - .int => |int| @Type(.{ .int = .{ - .signedness = int.signedness, - .bits = std.mem.alignForward(u16, int.bits, multiple), - } }), + .int => |int| @Int(int.signedness, std.mem.alignForward(u16, int.bits, multiple)), .float => Scalar(Type), else => @compileError(@typeName(Type)), }); @@ -83,10 +77,7 @@ pub fn splat(comptime Type: type, scalar: Scalar(Type)) Type { pub fn sign(rhs: anytype) ChangeScalar(@TypeOf(rhs), bool) { const Int = ChangeScalar(@TypeOf(rhs), switch (@typeInfo(Scalar(@TypeOf(rhs)))) { .int, .comptime_int => Scalar(@TypeOf(rhs)), - .float => |float| @Type(.{ .int = .{ - .signedness = .signed, - .bits = float.bits, - } }), + .float => |float| @Int(.signed, float.bits), else => @compileError(@typeName(@TypeOf(rhs))), }); return @as(Int, @bitCast(rhs)) < splat(Int, 0); diff --git a/test/cases/compile_errors/@import_zon_opt_in_err.zig b/test/cases/compile_errors/@import_zon_opt_in_err.zig index b7322a43b421..b5b7b4a17219 100644 --- a/test/cases/compile_errors/@import_zon_opt_in_err.zig +++ b/test/cases/compile_errors/@import_zon_opt_in_err.zig @@ -70,7 +70,7 @@ export fn testVector() void { // tmp.zig:22:29: note: imported here // vec2.zon:1:2: error: expected type '?tmp.Enum' // tmp.zig:28:30: note: imported here -// vec2.zon:1:2: error: expected type '?@Type(.enum_literal)' +// vec2.zon:1:2: error: expected type '?@TypeOf(.enum_literal)' // tmp.zig:33:39: note: imported here // vec2.zon:1:2: error: expected type '?[1]u8' // tmp.zig:38:31: note: imported here diff --git a/test/cases/compile_errors/attempt_to_cast_enum_literal_to_error.zig b/test/cases/compile_errors/attempt_to_cast_enum_literal_to_error.zig index e0d0a411b4ec..cc740d9038f0 100644 --- a/test/cases/compile_errors/attempt_to_cast_enum_literal_to_error.zig +++ b/test/cases/compile_errors/attempt_to_cast_enum_literal_to_error.zig @@ -8,4 +8,4 @@ export fn entry() void { // backend=stage2 // target=native // -// :3:10: error: expected type 'error{Hi}', found '@Type(.enum_literal)' +// :3:10: error: expected type 'error{Hi}', found '@TypeOf(.enum_literal)' diff --git a/test/cases/compile_errors/attempt_to_create_17_bit_float_type.zig b/test/cases/compile_errors/attempt_to_create_17_bit_float_type.zig deleted file mode 100644 index 1f39222fd743..000000000000 --- a/test/cases/compile_errors/attempt_to_create_17_bit_float_type.zig +++ /dev/null @@ -1,10 +0,0 @@ -const builtin = @import("std").builtin; -comptime { - _ = @Type(.{ .float = .{ .bits = 17 } }); -} - -// error -// backend=stage2 -// target=native -// -// :3:9: error: 17-bit float unsupported diff --git a/test/cases/compile_errors/enum_with_declarations_unavailable_for_reify_type.zig b/test/cases/compile_errors/enum_with_declarations_unavailable_for_reify_type.zig index 56f32c768186..62e0d889e598 100644 --- a/test/cases/compile_errors/enum_with_declarations_unavailable_for_reify_type.zig +++ b/test/cases/compile_errors/enum_with_declarations_unavailable_for_reify_type.zig @@ -1,8 +1,8 @@ export fn entry() void { - _ = @Type(@typeInfo(enum { + _ = @Enum(@typeInfo(enum { foo, pub const bar = 1; - })); + }).@"enum"); } // error diff --git a/test/cases/compile_errors/error_set_decl_literal.zig b/test/cases/compile_errors/error_set_decl_literal.zig index abb22f189fd8..b825c09ae5a4 100644 --- a/test/cases/compile_errors/error_set_decl_literal.zig +++ b/test/cases/compile_errors/error_set_decl_literal.zig @@ -6,4 +6,4 @@ export fn entry() void { // error // -// :3:19: error: expected type 'error{Foo}', found '@Type(.enum_literal)' +// :3:19: error: expected type 'error{Foo}', found '@TypeOf(.enum_literal)' diff --git a/test/cases/compile_errors/invalid_pointer_with_reify_type.zig b/test/cases/compile_errors/invalid_pointer_with_reify_type.zig index c1f622c1a57d..6de867706857 100644 --- a/test/cases/compile_errors/invalid_pointer_with_reify_type.zig +++ b/test/cases/compile_errors/invalid_pointer_with_reify_type.zig @@ -1,5 +1,5 @@ export fn entry() void { - _ = @Type(.{ .pointer = .{ + _ = @Pointer(.{ .size = .one, .is_const = false, .is_volatile = false, @@ -8,7 +8,7 @@ export fn entry() void { .child = u8, .is_allowzero = false, .sentinel_ptr = &@as(u8, 0), - } }); + }); } // error diff --git a/test/cases/compile_errors/nested_vectors.zig b/test/cases/compile_errors/nested_vectors.zig index 62798d028943..92c7a01b833a 100644 --- a/test/cases/compile_errors/nested_vectors.zig +++ b/test/cases/compile_errors/nested_vectors.zig @@ -1,6 +1,6 @@ export fn entry() void { const V1 = @Vector(4, u8); - const V2 = @Type(.{ .vector = .{ .len = 4, .child = V1 } }); + const V2 = @Vector(4, V1); const v: V2 = undefined; _ = v; } @@ -9,4 +9,4 @@ export fn entry() void { // backend=stage2 // target=native // -// :3:16: error: expected integer, float, bool, or pointer for the vector element type; found '@Vector(4, u8)' +// :3:27: error: expected integer, float, bool, or pointer for the vector element type; found '@Vector(4, u8)' diff --git a/test/cases/compile_errors/non_scalar_sentinel.zig b/test/cases/compile_errors/non_scalar_sentinel.zig index c2d8bced8d7b..ad4f31f28686 100644 --- a/test/cases/compile_errors/non_scalar_sentinel.zig +++ b/test/cases/compile_errors/non_scalar_sentinel.zig @@ -11,34 +11,6 @@ comptime { _ = [*:sentinel]S; } -comptime { - _ = @Type(.{ .array = .{ .child = S, .len = 0, .sentinel_ptr = &sentinel } }); -} -comptime { - _ = @Type(.{ .pointer = .{ - .size = .slice, - .is_const = false, - .is_volatile = false, - .alignment = @alignOf(S), - .address_space = .generic, - .child = S, - .is_allowzero = false, - .sentinel_ptr = &sentinel, - } }); -} -comptime { - _ = @Type(.{ .pointer = .{ - .size = .many, - .is_const = false, - .is_volatile = false, - .alignment = @alignOf(S), - .address_space = .generic, - .child = S, - .is_allowzero = false, - .sentinel_ptr = &sentinel, - } }); -} - // error // // :5:12: error: non-scalar sentinel type 'tmp.S' @@ -47,9 +19,3 @@ comptime { // :1:11: note: struct declared here // :11:12: error: non-scalar sentinel type 'tmp.S' // :1:11: note: struct declared here -// :15:9: error: non-scalar sentinel type 'tmp.S' -// :1:11: note: struct declared here -// :18:9: error: non-scalar sentinel type 'tmp.S' -// :1:11: note: struct declared here -// :30:9: error: non-scalar sentinel type 'tmp.S' -// :1:11: note: struct declared here diff --git a/test/cases/compile_errors/packed_struct_field_alignment_unavailable_for_reify_type.zig b/test/cases/compile_errors/packed_struct_field_alignment_unavailable_for_reify_type.zig index 20fb548d838f..68574a0e95c9 100644 --- a/test/cases/compile_errors/packed_struct_field_alignment_unavailable_for_reify_type.zig +++ b/test/cases/compile_errors/packed_struct_field_alignment_unavailable_for_reify_type.zig @@ -1,7 +1,7 @@ export fn entry() void { - _ = @Type(.{ .@"struct" = .{ .layout = .@"packed", .fields = &.{ + _ = @Struct(.{ .layout = .@"packed", .fields = &.{ .{ .name = "one", .type = u4, .default_value_ptr = null, .is_comptime = false, .alignment = 2 }, - }, .decls = &.{}, .is_tuple = false } }); + }, .decls = &.{}, .is_tuple = false }); } // error diff --git a/test/cases/compile_errors/reified_enum_field_value_overflow.zig b/test/cases/compile_errors/reified_enum_field_value_overflow.zig index fd230a70d9ee..558d6313e46e 100644 --- a/test/cases/compile_errors/reified_enum_field_value_overflow.zig +++ b/test/cases/compile_errors/reified_enum_field_value_overflow.zig @@ -1,5 +1,5 @@ comptime { - const E = @Type(.{ .@"enum" = .{ + const E = @Enum(.{ .tag_type = u1, .fields = &.{ .{ .name = "f0", .value = 0 }, @@ -8,7 +8,7 @@ comptime { }, .decls = &.{}, .is_exhaustive = true, - } }); + }); _ = E; } diff --git a/test/cases/compile_errors/reify_enum_with_duplicate_field.zig b/test/cases/compile_errors/reify_enum_with_duplicate_field.zig index 2d1b93247f5c..675083698e1d 100644 --- a/test/cases/compile_errors/reify_enum_with_duplicate_field.zig +++ b/test/cases/compile_errors/reify_enum_with_duplicate_field.zig @@ -1,14 +1,12 @@ export fn entry() void { - _ = @Type(.{ - .@"enum" = .{ - .tag_type = u32, - .fields = &.{ - .{ .name = "A", .value = 0 }, - .{ .name = "A", .value = 1 }, - }, - .decls = &.{}, - .is_exhaustive = false, + _ = @Enum(.{ + .tag_type = u32, + .fields = &.{ + .{ .name = "A", .value = 0 }, + .{ .name = "A", .value = 1 }, }, + .decls = &.{}, + .is_exhaustive = false, }); } diff --git a/test/cases/compile_errors/reify_enum_with_duplicate_tag_value.zig b/test/cases/compile_errors/reify_enum_with_duplicate_tag_value.zig index cb4aee13b88b..23eb40f387fc 100644 --- a/test/cases/compile_errors/reify_enum_with_duplicate_tag_value.zig +++ b/test/cases/compile_errors/reify_enum_with_duplicate_tag_value.zig @@ -1,14 +1,12 @@ export fn entry() void { - _ = @Type(.{ - .@"enum" = .{ - .tag_type = u32, - .fields = &.{ - .{ .name = "A", .value = 10 }, - .{ .name = "B", .value = 10 }, - }, - .decls = &.{}, - .is_exhaustive = false, + _ = @Enum(.{ + .tag_type = u32, + .fields = &.{ + .{ .name = "A", .value = 10 }, + .{ .name = "B", .value = 10 }, }, + .decls = &.{}, + .is_exhaustive = false, }); } diff --git a/test/cases/compile_errors/reify_struct.zig b/test/cases/compile_errors/reify_struct.zig index 12d445082cd3..c6ccb7d887bd 100644 --- a/test/cases/compile_errors/reify_struct.zig +++ b/test/cases/compile_errors/reify_struct.zig @@ -1,5 +1,5 @@ comptime { - @Type(.{ .@"struct" = .{ + @Struct(.{ .layout = .auto, .fields = &.{.{ .name = "foo", @@ -10,10 +10,10 @@ comptime { }}, .decls = &.{}, .is_tuple = true, - } }); + }); } comptime { - @Type(.{ .@"struct" = .{ + @Struct(.{ .layout = .auto, .fields = &.{.{ .name = "3", @@ -24,10 +24,10 @@ comptime { }}, .decls = &.{}, .is_tuple = true, - } }); + }); } comptime { - @Type(.{ .@"struct" = .{ + @Struct(.{ .layout = .auto, .fields = &.{.{ .name = "0", @@ -38,10 +38,10 @@ comptime { }}, .decls = &.{}, .is_tuple = true, - } }); + }); } comptime { - @Type(.{ .@"struct" = .{ + @Struct(.{ .layout = .@"extern", .fields = &.{.{ .name = "0", @@ -52,10 +52,10 @@ comptime { }}, .decls = &.{}, .is_tuple = false, - } }); + }); } comptime { - @Type(.{ .@"struct" = .{ + @Struct(.{ .layout = .@"packed", .fields = &.{.{ .name = "0", @@ -66,7 +66,7 @@ comptime { }}, .decls = &.{}, .is_tuple = false, - } }); + }); } // error diff --git a/test/cases/compile_errors/reify_type.Fn_with_is_generic_true.zig b/test/cases/compile_errors/reify_type.Fn_with_is_generic_true.zig deleted file mode 100644 index 4b838fbdd69e..000000000000 --- a/test/cases/compile_errors/reify_type.Fn_with_is_generic_true.zig +++ /dev/null @@ -1,18 +0,0 @@ -const Foo = @Type(.{ - .@"fn" = .{ - .calling_convention = .auto, - .is_generic = true, - .is_var_args = false, - .return_type = u0, - .params = &.{}, - }, -}); -comptime { - _ = Foo; -} - -// error -// backend=stage2 -// target=native -// -// :1:13: error: Type.Fn.is_generic must be false for @Type diff --git a/test/cases/compile_errors/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig b/test/cases/compile_errors/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig deleted file mode 100644 index e72dc41b6ea8..000000000000 --- a/test/cases/compile_errors/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig +++ /dev/null @@ -1,18 +0,0 @@ -const Foo = @Type(.{ - .@"fn" = .{ - .calling_convention = .auto, - .is_generic = false, - .is_var_args = true, - .return_type = u0, - .params = &.{}, - }, -}); -comptime { - _ = Foo; -} - -// error -// target=x86_64-linux -// -// :1:13: error: variadic function does not support 'auto' calling convention -// :1:13: note: supported calling conventions: 'x86_64_sysv', 'x86_64_win' diff --git a/test/cases/compile_errors/reify_type.Fn_with_return_type_null.zig b/test/cases/compile_errors/reify_type.Fn_with_return_type_null.zig deleted file mode 100644 index 9dc21ca91e75..000000000000 --- a/test/cases/compile_errors/reify_type.Fn_with_return_type_null.zig +++ /dev/null @@ -1,18 +0,0 @@ -const Foo = @Type(.{ - .@"fn" = .{ - .calling_convention = .auto, - .is_generic = false, - .is_var_args = false, - .return_type = null, - .params = &.{}, - }, -}); -comptime { - _ = Foo; -} - -// error -// backend=stage2 -// target=native -// -// :1:13: error: Type.Fn.return_type must be non-null for @Type diff --git a/test/cases/compile_errors/reify_type_for_exhaustive_enum_with_non-integer_tag_type.zig b/test/cases/compile_errors/reify_type_for_exhaustive_enum_with_non-integer_tag_type.zig index a62b068975d3..43772104419a 100644 --- a/test/cases/compile_errors/reify_type_for_exhaustive_enum_with_non-integer_tag_type.zig +++ b/test/cases/compile_errors/reify_type_for_exhaustive_enum_with_non-integer_tag_type.zig @@ -1,10 +1,8 @@ -const Tag = @Type(.{ - .@"enum" = .{ - .tag_type = bool, - .fields = &.{}, - .decls = &.{}, - .is_exhaustive = false, - }, +const Tag = @Enum(.{ + .tag_type = bool, + .fields = &.{}, + .decls = &.{}, + .is_exhaustive = false, }); export fn entry() void { _ = @as(Tag, @enumFromInt(0)); diff --git a/test/cases/compile_errors/reify_type_for_exhaustive_enum_with_undefined_tag_type.zig b/test/cases/compile_errors/reify_type_for_exhaustive_enum_with_undefined_tag_type.zig index 2bf144b52d4c..016152888e0e 100644 --- a/test/cases/compile_errors/reify_type_for_exhaustive_enum_with_undefined_tag_type.zig +++ b/test/cases/compile_errors/reify_type_for_exhaustive_enum_with_undefined_tag_type.zig @@ -1,10 +1,8 @@ -const Tag = @Type(.{ - .@"enum" = .{ - .tag_type = undefined, - .fields = &.{}, - .decls = &.{}, - .is_exhaustive = false, - }, +const Tag = @Enum(.{ + .tag_type = undefined, + .fields = &.{}, + .decls = &.{}, + .is_exhaustive = false, }); export fn entry() void { _ = @as(Tag, @enumFromInt(0)); diff --git a/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_enum_field.zig b/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_enum_field.zig index 49e7a63a481a..cca6dc302508 100644 --- a/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_enum_field.zig +++ b/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_enum_field.zig @@ -1,25 +1,21 @@ -const Tag = @Type(.{ - .@"enum" = .{ - .tag_type = u2, - .fields = &.{ - .{ .name = "signed", .value = 0 }, - .{ .name = "unsigned", .value = 1 }, - .{ .name = "arst", .value = 2 }, - }, - .decls = &.{}, - .is_exhaustive = true, +const Tag = @Enum(.{ + .tag_type = u2, + .fields = &.{ + .{ .name = "signed", .value = 0 }, + .{ .name = "unsigned", .value = 1 }, + .{ .name = "arst", .value = 2 }, }, + .decls = &.{}, + .is_exhaustive = true, }); -const Tagged = @Type(.{ - .@"union" = .{ - .layout = .auto, - .tag_type = Tag, - .fields = &.{ - .{ .name = "signed", .type = i32, .alignment = @alignOf(i32) }, - .{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) }, - }, - .decls = &.{}, +const Tagged = @Union(.{ + .layout = .auto, + .tag_type = Tag, + .fields = &.{ + .{ .name = "signed", .type = i32, .alignment = @alignOf(i32) }, + .{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) }, }, + .decls = &.{}, }); export fn entry() void { var tagged = Tagged{ .signed = -1 }; @@ -30,6 +26,6 @@ export fn entry() void { // backend=stage2 // target=native // -// :13:16: error: enum fields missing in union +// :11:16: error: enum fields missing in union // :1:13: note: field 'arst' missing, declared here // :1:13: note: enum declared here diff --git a/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_union_field.zig b/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_union_field.zig index 9692936db701..459b715a36df 100644 --- a/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_union_field.zig +++ b/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_union_field.zig @@ -1,25 +1,21 @@ -const Tag = @Type(.{ - .@"enum" = .{ - .tag_type = u1, - .fields = &.{ - .{ .name = "signed", .value = 0 }, - .{ .name = "unsigned", .value = 1 }, - }, - .decls = &.{}, - .is_exhaustive = true, +const Tag = @Enum(.{ + .tag_type = u1, + .fields = &.{ + .{ .name = "signed", .value = 0 }, + .{ .name = "unsigned", .value = 1 }, }, + .decls = &.{}, + .is_exhaustive = true, }); -const Tagged = @Type(.{ - .@"union" = .{ - .layout = .auto, - .tag_type = Tag, - .fields = &.{ - .{ .name = "signed", .type = i32, .alignment = @alignOf(i32) }, - .{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) }, - .{ .name = "arst", .type = f32, .alignment = @alignOf(f32) }, - }, - .decls = &.{}, +const Tagged = @Union(.{ + .layout = .auto, + .tag_type = Tag, + .fields = &.{ + .{ .name = "signed", .type = i32, .alignment = @alignOf(i32) }, + .{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) }, + .{ .name = "arst", .type = f32, .alignment = @alignOf(f32) }, }, + .decls = &.{}, }); export fn entry() void { var tagged = Tagged{ .signed = -1 }; @@ -30,5 +26,5 @@ export fn entry() void { // backend=stage2 // target=native // -// :12:16: error: no field named 'arst' in enum 'tmp.Tag' +// :10:16: error: no field named 'arst' in enum 'tmp.Tag' // :1:13: note: enum declared here diff --git a/test/cases/compile_errors/reify_type_for_tagged_union_with_no_enum_fields.zig b/test/cases/compile_errors/reify_type_for_tagged_union_with_no_enum_fields.zig index 992db883776d..7b0ab7add937 100644 --- a/test/cases/compile_errors/reify_type_for_tagged_union_with_no_enum_fields.zig +++ b/test/cases/compile_errors/reify_type_for_tagged_union_with_no_enum_fields.zig @@ -1,21 +1,17 @@ -const Tag = @Type(.{ - .@"enum" = .{ - .tag_type = u0, - .fields = &.{}, - .decls = &.{}, - .is_exhaustive = true, - }, +const Tag = @Enum(.{ + .tag_type = u0, + .fields = &.{}, + .decls = &.{}, + .is_exhaustive = true, }); -const Tagged = @Type(.{ - .@"union" = .{ - .layout = .auto, - .tag_type = Tag, - .fields = &.{ - .{ .name = "signed", .type = i32, .alignment = @alignOf(i32) }, - .{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) }, - }, - .decls = &.{}, +const Tagged = @Union(.{ + .layout = .auto, + .tag_type = Tag, + .fields = &.{ + .{ .name = "signed", .type = i32, .alignment = @alignOf(i32) }, + .{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) }, }, + .decls = &.{}, }); export fn entry() void { const tagged: Tagged = undefined; @@ -26,5 +22,5 @@ export fn entry() void { // backend=stage2 // target=native // -// :9:16: error: no field named 'signed' in enum 'tmp.Tag' +// :7:16: error: no field named 'signed' in enum 'tmp.Tag' // :1:13: note: enum declared here diff --git a/test/cases/compile_errors/reify_type_for_tagged_union_with_no_union_fields.zig b/test/cases/compile_errors/reify_type_for_tagged_union_with_no_union_fields.zig index eb8a9ec2b020..34404396705a 100644 --- a/test/cases/compile_errors/reify_type_for_tagged_union_with_no_union_fields.zig +++ b/test/cases/compile_errors/reify_type_for_tagged_union_with_no_union_fields.zig @@ -1,21 +1,17 @@ -const Tag = @Type(.{ - .@"enum" = .{ - .tag_type = u1, - .fields = &.{ - .{ .name = "signed", .value = 0 }, - .{ .name = "unsigned", .value = 1 }, - }, - .decls = &.{}, - .is_exhaustive = true, +const Tag = @Enum(.{ + .tag_type = u1, + .fields = &.{ + .{ .name = "signed", .value = 0 }, + .{ .name = "unsigned", .value = 1 }, }, + .decls = &.{}, + .is_exhaustive = true, }); -const Tagged = @Type(.{ - .@"union" = .{ - .layout = .auto, - .tag_type = Tag, - .fields = &.{}, - .decls = &.{}, - }, +const Tagged = @Union(.{ + .layout = .auto, + .tag_type = Tag, + .fields = &.{}, + .decls = &.{}, }); export fn entry() void { const tagged: Tagged = undefined; @@ -26,7 +22,7 @@ export fn entry() void { // backend=stage2 // target=native // -// :12:16: error: enum fields missing in union +// :10:16: error: enum fields missing in union // :1:13: note: field 'signed' missing, declared here // :1:13: note: field 'unsigned' missing, declared here // :1:13: note: enum declared here diff --git a/test/cases/compile_errors/reify_type_for_union_with_opaque_field.zig b/test/cases/compile_errors/reify_type_for_union_with_opaque_field.zig index 845c11acfbf8..36df0907e4d1 100644 --- a/test/cases/compile_errors/reify_type_for_union_with_opaque_field.zig +++ b/test/cases/compile_errors/reify_type_for_union_with_opaque_field.zig @@ -1,12 +1,10 @@ -const Untagged = @Type(.{ - .@"union" = .{ - .layout = .auto, - .tag_type = null, - .fields = &.{ - .{ .name = "foo", .type = opaque {}, .alignment = 1 }, - }, - .decls = &.{}, +const Untagged = @Union(.{ + .layout = .auto, + .tag_type = null, + .fields = &.{ + .{ .name = "foo", .type = opaque {}, .alignment = 1 }, }, + .decls = &.{}, }); export fn entry() usize { return @sizeOf(Untagged); @@ -17,4 +15,4 @@ export fn entry() usize { // target=native // // :1:18: error: opaque types have unknown size and therefore cannot be directly embedded in unions -// :6:39: note: opaque declared here +// :5:35: note: opaque declared here diff --git a/test/cases/compile_errors/reify_type_union_payload_is_undefined.zig b/test/cases/compile_errors/reify_type_union_payload_is_undefined.zig index 8d80a3353d9a..efdc2e8c906c 100644 --- a/test/cases/compile_errors/reify_type_union_payload_is_undefined.zig +++ b/test/cases/compile_errors/reify_type_union_payload_is_undefined.zig @@ -1,10 +1,8 @@ -const Foo = @Type(.{ - .@"struct" = undefined, -}); +const Foo = @Struct(undefined); comptime { _ = Foo; } // error // -// :1:20: error: use of undefined value here causes illegal behavior +// :1:21: error: use of undefined value here causes illegal behavior diff --git a/test/cases/compile_errors/reify_type_with_Type.Int.zig b/test/cases/compile_errors/reify_type_with_Type.Int.zig deleted file mode 100644 index bd98912a0311..000000000000 --- a/test/cases/compile_errors/reify_type_with_Type.Int.zig +++ /dev/null @@ -1,15 +0,0 @@ -const builtin = @import("std").builtin; -export fn entry() void { - _ = @Type(builtin.Type.Int{ - .signedness = .signed, - .bits = 8, - }); -} - -// error -// backend=stage2 -// target=native -// -// :3:31: error: expected type 'builtin.Type', found 'builtin.Type.Int' -// :?:?: note: struct declared here -// :?:?: note: union declared here diff --git a/test/cases/compile_errors/reify_type_with_invalid_field_alignment.zig b/test/cases/compile_errors/reify_type_with_invalid_field_alignment.zig index 0fcb4ba7fc73..f5186d8482ff 100644 --- a/test/cases/compile_errors/reify_type_with_invalid_field_alignment.zig +++ b/test/cases/compile_errors/reify_type_with_invalid_field_alignment.zig @@ -1,48 +1,29 @@ comptime { - _ = @Type(.{ - .@"union" = .{ - .layout = .auto, - .tag_type = null, - .fields = &.{ - .{ .name = "foo", .type = usize, .alignment = 3 }, - }, - .decls = &.{}, + _ = @Union(.{ + .layout = .auto, + .tag_type = null, + .fields = &.{ + .{ .name = "foo", .type = usize, .alignment = 3 }, }, + .decls = &.{}, }); } comptime { - _ = @Type(.{ - .@"struct" = .{ - .layout = .auto, - .fields = &.{.{ - .name = "0", - .type = u32, - .default_value_ptr = null, - .is_comptime = true, - .alignment = 5, - }}, - .decls = &.{}, - .is_tuple = false, - }, - }); -} -comptime { - _ = @Type(.{ - .pointer = .{ - .size = .many, - .is_const = true, - .is_volatile = false, - .alignment = 7, - .address_space = .generic, - .child = u8, - .is_allowzero = false, - .sentinel_ptr = null, - }, + _ = @Struct(.{ + .layout = .auto, + .fields = &.{.{ + .name = "0", + .type = u32, + .default_value_ptr = null, + .is_comptime = true, + .alignment = 5, + }}, + .decls = &.{}, + .is_tuple = false, }); } // error // // :2:9: error: alignment value '3' is not a power of two or zero -// :14:9: error: alignment value '5' is not a power of two or zero -// :30:9: error: alignment value '7' is not a power of two or zero +// :12:9: error: alignment value '5' is not a power of two or zero diff --git a/test/cases/compile_errors/reify_type_with_undefined.zig b/test/cases/compile_errors/reify_type_with_undefined.zig index 5c476c94aa30..ae59562d1293 100644 --- a/test/cases/compile_errors/reify_type_with_undefined.zig +++ b/test/cases/compile_errors/reify_type_with_undefined.zig @@ -1,31 +1,23 @@ comptime { - _ = @Type(.{ .array = .{ .len = 0, .child = u8, .sentinel_ptr = undefined } }); -} -comptime { - _ = @Type(.{ - .@"struct" = .{ - .fields = undefined, - .decls = undefined, - .is_tuple = false, - .layout = .auto, - }, + _ = @Struct(.{ + .fields = undefined, + .decls = undefined, + .is_tuple = false, + .layout = .auto, }); } comptime { const std = @import("std"); const fields: [1]std.builtin.Type.StructField = undefined; - _ = @Type(.{ - .@"struct" = .{ - .layout = .auto, - .fields = &fields, - .decls = &.{}, - .is_tuple = false, - }, + _ = @Struct(.{ + .layout = .auto, + .fields = &fields, + .decls = &.{}, + .is_tuple = false, }); } // error // -// :2:16: error: use of undefined value here causes illegal behavior -// :5:16: error: use of undefined value here causes illegal behavior -// :17:16: error: use of undefined value here causes illegal behavior +// :2:18: error: use of undefined value here causes illegal behavior +// :12:18: error: use of undefined value here causes illegal behavior diff --git a/test/cases/compile_errors/runtime_condition_comptime_type_in_destructure.zig b/test/cases/compile_errors/runtime_condition_comptime_type_in_destructure.zig index 27b13e215029..a6624d03ed65 100644 --- a/test/cases/compile_errors/runtime_condition_comptime_type_in_destructure.zig +++ b/test/cases/compile_errors/runtime_condition_comptime_type_in_destructure.zig @@ -7,4 +7,4 @@ export fn foobar() void { // error // -// :4:5: error: value with comptime-only type '@Type(.enum_literal)' depends on runtime control flow +// :4:5: error: value with comptime-only type '@TypeOf(.enum_literal)' depends on runtime control flow diff --git a/test/cases/compile_errors/stage1/obj/generic_function_returning_opaque_type.zig b/test/cases/compile_errors/stage1/obj/generic_function_returning_opaque_type.zig index 247c1a49bf8a..52649368f7fd 100644 --- a/test/cases/compile_errors/stage1/obj/generic_function_returning_opaque_type.zig +++ b/test/cases/compile_errors/stage1/obj/generic_function_returning_opaque_type.zig @@ -19,7 +19,7 @@ export fn baz() void { // tmp.zig:6:16: error: call to generic function with Opaque return type 'FooType' not allowed // tmp.zig:2:1: note: function declared here // tmp.zig:1:1: note: type declared here -// tmp.zig:9:16: error: call to generic function with Null return type '@Type(.Null)' not allowed +// tmp.zig:9:16: error: call to generic function with Null return type '@TypeOf(null)' not allowed // tmp.zig:2:1: note: function declared here -// tmp.zig:12:16: error: call to generic function with Undefined return type '@Type(.Undefined)' not allowed +// tmp.zig:12:16: error: call to generic function with Undefined return type '@TypeOf(undefined)' not allowed // tmp.zig:2:1: note: function declared here diff --git a/test/cases/compile_errors/struct_with_declarations_unavailable_for_reify_type.zig b/test/cases/compile_errors/struct_with_declarations_unavailable_for_reify_type.zig index c3964b30e38b..65124626922b 100644 --- a/test/cases/compile_errors/struct_with_declarations_unavailable_for_reify_type.zig +++ b/test/cases/compile_errors/struct_with_declarations_unavailable_for_reify_type.zig @@ -1,7 +1,7 @@ export fn entry() void { - _ = @Type(@typeInfo(struct { + _ = @Struct(@typeInfo(struct { pub const foo = 1; - })); + }).@"struct"); } // error diff --git a/test/cases/compile_errors/tagName_on_undef_enum_literal.zig b/test/cases/compile_errors/tagName_on_undef_enum_literal.zig index 900aef9d7c6c..a85dc04bb790 100644 --- a/test/cases/compile_errors/tagName_on_undef_enum_literal.zig +++ b/test/cases/compile_errors/tagName_on_undef_enum_literal.zig @@ -1,5 +1,5 @@ comptime { - const undef: @Type(.enum_literal) = undefined; + const undef: @TypeOf(.enum_literal) = undefined; _ = @tagName(undef); } diff --git a/test/cases/compile_errors/wrong_type_for_reify_type.zig b/test/cases/compile_errors/wrong_type_for_reify_type.zig index b88f6563b510..8f653143ae3b 100644 --- a/test/cases/compile_errors/wrong_type_for_reify_type.zig +++ b/test/cases/compile_errors/wrong_type_for_reify_type.zig @@ -1,10 +1,22 @@ -export fn entry() void { - _ = @Type(0); +export fn entryE() void { + _ = @Enum(0); +} + +export fn entryS() void { + _ = @Struct(0); +} + +export fn entryU() void { + _ = @Union(0); } // error // backend=stage2 // target=native // -// :2:15: error: expected type 'builtin.Type', found 'comptime_int' -// :?:?: note: union declared here +// :2:15: error: expected type 'builtin.Type.Enum', found 'comptime_int' +// :?:?: note: struct declared here +// :6:17: error: expected type 'builtin.Type.Struct', found 'comptime_int' +// :?:?: note: struct declared here +// :10:16: error: expected type 'builtin.Type.Union', found 'comptime_int' +// :?:?: note: struct declared here diff --git a/test/standalone/simple/issue_7030.zig b/test/standalone/simple/issue_7030.zig index eb7aa6538716..1739075bd9e7 100644 --- a/test/standalone/simple/issue_7030.zig +++ b/test/standalone/simple/issue_7030.zig @@ -6,7 +6,7 @@ pub const std_options: std.Options = .{ pub fn log( comptime message_level: std.log.Level, - comptime scope: @Type(.enum_literal), + comptime scope: @TypeOf(.enum_literal), comptime format: []const u8, args: anytype, ) void { diff --git a/test/standalone/simple/std_enums_big_enums.zig b/test/standalone/simple/std_enums_big_enums.zig index de6cfe3ec75e..9a3f0cfa5035 100644 --- a/test/standalone/simple/std_enums_big_enums.zig +++ b/test/standalone/simple/std_enums_big_enums.zig @@ -3,7 +3,7 @@ const std = @import("std"); // big enums should not hit the eval branch quota pub fn main() void { const big = struct { - const Big = @Type(.{ .@"enum" = .{ + const Big = @Enum(.{ .tag_type = u16, .fields = make_fields: { @setEvalBranchQuota(500000); @@ -16,7 +16,7 @@ pub fn main() void { }, .decls = &.{}, .is_exhaustive = true, - } }); + }); }; var set = std.enums.EnumSet(big.Big).init(.{});