all: replace all @Type usages

Co-authored-by: Matthew Lugg <mlugg@mlugg.co.uk>
This commit is contained in:
Ali Cheraghi 2025-04-30 18:42:23 +03:30 committed by Matthew Lugg
parent ce0df033cf
commit dec1163fbb
No known key found for this signature in database
GPG key ID: 3F5B7DCCBF4AF02E
108 changed files with 629 additions and 1891 deletions

View file

@ -11,7 +11,7 @@ pub const std_options: std.Options = .{
fn myLogFn( fn myLogFn(
comptime level: std.log.Level, comptime level: std.log.Level,
comptime scope: @Type(.enum_literal), comptime scope: @EnumLiteral(),
comptime format: []const u8, comptime format: []const u8,
args: anytype, args: anytype,
) void { ) void {

View file

@ -41,7 +41,7 @@ test "coercion between unions and enums" {
try expect(u_4.tag() == 1); try expect(u_4.tag() == 1);
// The following example is invalid. // The following example is invalid.
// error: coercion from enum '@TypeOf(.enum_literal)' to union 'test_coerce_unions_enum.U2' must initialize 'f32' field 'b' // error: coercion from enum '@EnumLiteral()' to union 'test_coerce_unions_enum.U2' must initialize 'f32' field 'b'
//var u_5: U2 = .b; //var u_5: U2 = .b;
//try expect(u_5.tag() == 2); //try expect(u_5.tag() == 2);
} }

View file

@ -49,7 +49,7 @@ pub fn panic(msg: []const u8, st: ?*std.builtin.StackTrace, addr: ?usize) noretu
fn logFn( fn logFn(
comptime message_level: log.Level, comptime message_level: log.Level,
comptime scope: @TypeOf(.enum_literal), comptime scope: @EnumLiteral(),
comptime format: []const u8, comptime format: []const u8,
args: anytype, args: anytype,
) void { ) void {

View file

@ -717,23 +717,13 @@ pub const Tag = std.meta.DeclEnum(attributes);
pub const Arguments = blk: { pub const Arguments = blk: {
const decls = @typeInfo(attributes).@"struct".decls; const decls = @typeInfo(attributes).@"struct".decls;
var union_fields: [decls.len]ZigType.UnionField = undefined; var names: [decls.len][]const u8 = undefined;
for (decls, &union_fields) |decl, *field| { var types: [decls.len]type = undefined;
field.* = .{ for (decls, &names, &types) |decl, *name, *T| {
.name = decl.name, name.* = decl.name;
.type = @field(attributes, decl.name), T.* = @field(attributes, decl.name);
.alignment = @alignOf(@field(attributes, decl.name)),
};
} }
break :blk @Union(.auto, null, &names, &types, &@splat(.{}));
break :blk @Type(.{
.@"union" = .{
.layout = .auto,
.tag_type = null,
.fields = &union_fields,
.decls = &.{},
},
});
}; };
pub fn ArgumentsForTag(comptime tag: Tag) type { pub fn ArgumentsForTag(comptime tag: Tag) type {

View file

@ -59,7 +59,7 @@ fn serializeFloat(comptime T: type, value: T, w: *std.Io.Writer) !void {
else => { else => {
const size = @bitSizeOf(T); const size = @bitSizeOf(T);
const storage_unit = std.meta.intToEnum(StorageUnit, size) catch unreachable; const storage_unit = std.meta.intToEnum(StorageUnit, size) catch unreachable;
const IntTy = @Type(.{ .int = .{ .signedness = .unsigned, .bits = size } }); const IntTy = @Int(.unsigned, size);
const int_val: IntTy = @bitCast(value); const int_val: IntTy = @bitCast(value);
return serializeInt(int_val, storage_unit, w); return serializeInt(int_val, storage_unit, w);
}, },

View file

@ -179,12 +179,13 @@ pub const UnsupportedCodePage = enum(u16) {
pub const CodePage = blk: { pub const CodePage = blk: {
const fields = @typeInfo(SupportedCodePage).@"enum".fields ++ @typeInfo(UnsupportedCodePage).@"enum".fields; const fields = @typeInfo(SupportedCodePage).@"enum".fields ++ @typeInfo(UnsupportedCodePage).@"enum".fields;
break :blk @Type(.{ .@"enum" = .{ var field_names: [fields.len][]const u8 = undefined;
.tag_type = u16, var field_values: [fields.len]u16 = undefined;
.decls = &.{}, for (fields, &field_names, &field_values) |field, *name, *val| {
.fields = fields, name.* = field.name;
.is_exhaustive = true, val.* = field.value;
} }); }
break :blk @Enum(u16, .exhaustive, &field_names, &field_values);
}; };
pub fn isSupported(code_page: CodePage) bool { pub fn isSupported(code_page: CodePage) bool {

View file

@ -862,20 +862,23 @@ pub const ErrorDetails = struct {
pub const ErrorDetailsWithoutCodePage = blk: { pub const ErrorDetailsWithoutCodePage = blk: {
const details_info = @typeInfo(ErrorDetails); const details_info = @typeInfo(ErrorDetails);
const fields = details_info.@"struct".fields; const fields = details_info.@"struct".fields;
var fields_without_codepage: [fields.len - 1]std.builtin.Type.StructField = undefined; var field_names: [fields.len - 1][]const u8 = undefined;
var field_types: [fields.len - 1]type = undefined;
var field_attrs: [fields.len - 1]std.builtin.Type.StructField.Attributes = undefined;
var i: usize = 0; var i: usize = 0;
for (fields) |field| { for (fields) |field| {
if (std.mem.eql(u8, field.name, "code_page")) continue; if (std.mem.eql(u8, field.name, "code_page")) continue;
fields_without_codepage[i] = field; field_names[i] = field.name;
field_types[i] = field.type;
field_attrs[i] = .{
.@"comptime" = field.is_comptime,
.@"align" = field.alignment,
.default_value_ptr = field.default_value_ptr,
};
i += 1; i += 1;
} }
std.debug.assert(i == fields_without_codepage.len); std.debug.assert(i == fields.len - 1);
break :blk @Type(.{ .@"struct" = .{ break :blk @Struct(.auto, null, &field_names, &field_types, &field_attrs);
.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 { fn cellCount(code_page: SupportedCodePage, source: []const u8, start_index: usize, end_index: usize) usize {

View file

@ -298,7 +298,7 @@ fn mainTerminal() void {
pub fn log( pub fn log(
comptime message_level: std.log.Level, comptime message_level: std.log.Level,
comptime scope: @Type(.enum_literal), comptime scope: @EnumLiteral(),
comptime format: []const u8, comptime format: []const u8,
args: anytype, args: anytype,
) void { ) void {

View file

@ -290,10 +290,7 @@ pub fn normalize(comptime T: type, significand: *std.meta.Int(.unsigned, @typeIn
pub inline fn fneg(a: anytype) @TypeOf(a) { pub inline fn fneg(a: anytype) @TypeOf(a) {
const F = @TypeOf(a); const F = @TypeOf(a);
const bits = @typeInfo(F).float.bits; const bits = @typeInfo(F).float.bits;
const U = @Type(.{ .int = .{ const U = @Int(.unsigned, bits);
.signedness = .unsigned,
.bits = bits,
} });
const sign_bit_mask = @as(U, 1) << (bits - 1); const sign_bit_mask = @as(U, 1) << (bits - 1);
const negated = @as(U, @bitCast(a)) ^ sign_bit_mask; const negated = @as(U, @bitCast(a)) ^ sign_bit_mask;
return @bitCast(negated); return @bitCast(negated);

View file

@ -66,17 +66,17 @@ pub inline fn floatFromBigInt(comptime T: type, comptime signedness: std.builtin
switch (x.len) { switch (x.len) {
0 => return 0, 0 => return 0,
inline 1...4 => |limbs_len| return @floatFromInt(@as( 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].*), @bitCast(x[0..limbs_len].*),
)), )),
else => {}, else => {},
} }
// sign implicit fraction round sticky // sign implicit fraction round sticky
const I = comptime @Type(.{ .int = .{ const I = comptime @Int(
.signedness = signedness, signedness,
.bits = @as(u16, @intFromBool(signedness == .signed)) + 1 + math.floatFractionalBits(T) + 1 + 1, @as(u16, @intFromBool(signedness == .signed)) + 1 + math.floatFractionalBits(T) + 1 + 1,
} }); );
const clrsb = clrsb: { const clrsb = clrsb: {
var clsb: usize = 0; var clsb: usize = 0;

View file

@ -56,7 +56,7 @@ pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, resul
0 => return, 0 => return,
inline 1...4 => |limbs_len| { inline 1...4 => |limbs_len| {
result[0..limbs_len].* = @bitCast(@as( result[0..limbs_len].* = @bitCast(@as(
@Type(.{ .int = .{ .signedness = signedness, .bits = 32 * limbs_len } }), @Int(signedness, 32 * limbs_len),
@intFromFloat(a), @intFromFloat(a),
)); ));
return; return;
@ -66,10 +66,7 @@ pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, resul
// sign implicit fraction // sign implicit fraction
const significand_bits = 1 + math.floatFractionalBits(@TypeOf(a)); const significand_bits = 1 + math.floatFractionalBits(@TypeOf(a));
const I = @Type(comptime .{ .int = .{ const I = @Int(signedness, @as(u16, @intFromBool(signedness == .signed)) + significand_bits);
.signedness = signedness,
.bits = @as(u16, @intFromBool(signedness == .signed)) + significand_bits,
} });
const parts = math.frexp(a); const parts = math.frexp(a);
const significand_bits_adjusted_to_handle_smin = @as(i32, significand_bits) + const significand_bits_adjusted_to_handle_smin = @as(i32, significand_bits) +

View file

@ -159,7 +159,7 @@ inline fn copyFixedLength(
else if (len > @sizeOf(usize)) else if (len > @sizeOf(usize))
@Vector(len, u8) @Vector(len, u8)
else else
@Type(.{ .int = .{ .signedness = .unsigned, .bits = len * 8 } }); @Int(.unsigned, len * 8);
const loop_count = @divExact(len, @sizeOf(T)); const loop_count = @divExact(len, @sizeOf(T));

View file

@ -41,7 +41,7 @@ pub fn panic(msg: []const u8, st: ?*std.builtin.StackTrace, addr: ?usize) noretu
fn logFn( fn logFn(
comptime message_level: log.Level, comptime message_level: log.Level,
comptime scope: @TypeOf(.enum_literal), comptime scope: @EnumLiteral(),
comptime format: []const u8, comptime format: []const u8,
args: anytype, args: anytype,
) void { ) void {

View file

@ -15,7 +15,7 @@ pub const std_options = std.Options{
fn logOverride( fn logOverride(
comptime level: std.log.Level, comptime level: std.log.Level,
comptime scope: @Type(.enum_literal), comptime scope: @EnumLiteral(),
comptime format: []const u8, comptime format: []const u8,
args: anytype, args: anytype,
) void { ) void {

View file

@ -416,7 +416,7 @@ fn createChildOnly(
fn userInputOptionsFromArgs(arena: Allocator, args: anytype) UserInputOptionsMap { fn userInputOptionsFromArgs(arena: Allocator, args: anytype) UserInputOptionsMap {
var map = UserInputOptionsMap.init(arena); var map = UserInputOptionsMap.init(arena);
inline for (@typeInfo(@TypeOf(args)).@"struct".fields) |field| { inline for (@typeInfo(@TypeOf(args)).@"struct".fields) |field| {
if (field.type == @Type(.null)) continue; if (field.type == @TypeOf(null)) continue;
addUserInputOptionFromArg(arena, &map, field, field.type, @field(args, field.name)); addUserInputOptionFromArg(arena, &map, field, field.type, @field(args, field.name));
} }
return map; return map;
@ -526,16 +526,11 @@ fn addUserInputOptionFromArg(
.pointer => |ptr_info| switch (ptr_info.size) { .pointer => |ptr_info| switch (ptr_info.size) {
.one => switch (@typeInfo(ptr_info.child)) { .one => switch (@typeInfo(ptr_info.child)) {
.array => |array_info| { .array => |array_info| {
comptime var slice_info = ptr_info;
slice_info.size = .slice;
slice_info.is_const = true;
slice_info.child = array_info.child;
slice_info.sentinel_ptr = null;
addUserInputOptionFromArg( addUserInputOptionFromArg(
arena, arena,
map, map,
field, field,
@Type(.{ .pointer = slice_info }), @Pointer(.slice, .{ .@"const" = true }, array_info.child, null),
maybe_value orelse null, maybe_value orelse null,
); );
return; return;
@ -553,14 +548,11 @@ fn addUserInputOptionFromArg(
}) catch @panic("OOM"); }) catch @panic("OOM");
}, },
else => { else => {
comptime var slice_info = ptr_info;
slice_info.is_const = true;
slice_info.sentinel_ptr = null;
addUserInputOptionFromArg( addUserInputOptionFromArg(
arena, arena,
map, map,
field, field,
@Type(.{ .pointer = slice_info }), @Pointer(ptr_info.size, .{ .@"const" = true }, ptr_info.child, null),
maybe_value orelse null, maybe_value orelse null,
); );
return; return;

View file

@ -528,23 +528,7 @@ pub fn Poller(comptime StreamEnum: type) type {
/// Given an enum, returns a struct with fields of that enum, each field /// Given an enum, returns a struct with fields of that enum, each field
/// representing an I/O stream for polling. /// representing an I/O stream for polling.
pub fn PollFiles(comptime StreamEnum: type) type { pub fn PollFiles(comptime StreamEnum: type) type {
const enum_fields = @typeInfo(StreamEnum).@"enum".fields; return @Struct(.auto, null, std.meta.fieldNames(StreamEnum), &@splat(std.fs.File), &@splat(.{}));
var struct_fields: [enum_fields.len]std.builtin.Type.StructField = undefined;
for (&struct_fields, enum_fields) |*struct_field, enum_field| {
struct_field.* = .{
.name = enum_field.name,
.type = std.fs.File,
.default_value_ptr = null,
.is_comptime = false,
.alignment = @alignOf(std.fs.File),
};
}
return @Type(.{ .@"struct" = .{
.layout = .auto,
.fields = &struct_fields,
.decls = &.{},
.is_tuple = false,
} });
} }
test { test {
@ -1625,22 +1609,14 @@ pub fn sleep(io: Io, duration: Duration, clock: Clock) SleepError!void {
/// fields, each field type the future's result. /// fields, each field type the future's result.
pub fn SelectUnion(S: type) type { pub fn SelectUnion(S: type) type {
const struct_fields = @typeInfo(S).@"struct".fields; const struct_fields = @typeInfo(S).@"struct".fields;
var fields: [struct_fields.len]std.builtin.Type.UnionField = undefined; var names: [struct_fields.len][]const u8 = undefined;
for (&fields, struct_fields) |*union_field, struct_field| { var types: [struct_fields.len]type = undefined;
const F = @typeInfo(struct_field.type).pointer.child; for (struct_fields, &names, &types) |struct_field, *union_field_name, *UnionFieldType| {
const Result = @TypeOf(@as(F, undefined).result); const FieldFuture = @typeInfo(struct_field.type).pointer.child;
union_field.* = .{ union_field_name.* = struct_field.name;
.name = struct_field.name, UnionFieldType.* = @FieldType(FieldFuture, "result");
.type = Result,
.alignment = struct_field.alignment,
};
} }
return @Type(.{ .@"union" = .{ return @Union(.auto, std.meta.FieldEnum(S), &names, &types, &@splat(.{}));
.layout = .auto,
.tag_type = std.meta.FieldEnum(S),
.fields = &fields,
.decls = &.{},
} });
} }
/// `s` is a struct with every field a `*Future(T)`, where `T` can be any type, /// `s` is a struct with every field a `*Future(T)`, where `T` can be any type,

View file

@ -1273,20 +1273,17 @@ pub const TakeLeb128Error = Error || error{Overflow};
/// Read a single LEB128 value as type T, or `error.Overflow` if the value cannot fit. /// 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 { pub fn takeLeb128(r: *Reader, comptime Result: type) TakeLeb128Error!Result {
const result_info = @typeInfo(Result).int; const result_info = @typeInfo(Result).int;
return std.math.cast(Result, try r.takeMultipleOf7Leb128(@Type(.{ .int = .{ return std.math.cast(Result, try r.takeMultipleOf7Leb128(@Int(
.signedness = result_info.signedness, result_info.signedness,
.bits = std.mem.alignForwardAnyAlign(u16, result_info.bits, 7), std.mem.alignForwardAnyAlign(u16, result_info.bits, 7),
} }))) orelse error.Overflow; ))) orelse error.Overflow;
} }
fn takeMultipleOf7Leb128(r: *Reader, comptime Result: type) TakeLeb128Error!Result { fn takeMultipleOf7Leb128(r: *Reader, comptime Result: type) TakeLeb128Error!Result {
const result_info = @typeInfo(Result).int; const result_info = @typeInfo(Result).int;
comptime assert(result_info.bits % 7 == 0); comptime assert(result_info.bits % 7 == 0);
var remaining_bits: std.math.Log2IntCeil(Result) = result_info.bits; var remaining_bits: std.math.Log2IntCeil(Result) = result_info.bits;
const UnsignedResult = @Type(.{ .int = .{ const UnsignedResult = @Int(.unsigned, result_info.bits);
.signedness = .unsigned,
.bits = result_info.bits,
} });
var result: UnsignedResult = 0; var result: UnsignedResult = 0;
var fits = true; var fits = true;
while (true) { while (true) {

View file

@ -1890,7 +1890,7 @@ pub fn writeUleb128(w: *Writer, value: anytype) Error!void {
try w.writeLeb128(switch (@typeInfo(@TypeOf(value))) { try w.writeLeb128(switch (@typeInfo(@TypeOf(value))) {
.comptime_int => @as(std.math.IntFittingRange(0, @abs(value)), value), .comptime_int => @as(std.math.IntFittingRange(0, @abs(value)), value),
.int => |value_info| switch (value_info.signedness) { .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, .unsigned => value,
}, },
else => comptime unreachable, else => comptime unreachable,
@ -1903,7 +1903,7 @@ pub fn writeSleb128(w: *Writer, value: anytype) Error!void {
.comptime_int => @as(std.math.IntFittingRange(@min(value, -1), @max(0, value)), value), .comptime_int => @as(std.math.IntFittingRange(@min(value, -1), @max(0, value)), value),
.int => |value_info| switch (value_info.signedness) { .int => |value_info| switch (value_info.signedness) {
.signed => value, .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, else => comptime unreachable,
}); });
@ -1912,10 +1912,10 @@ pub fn writeSleb128(w: *Writer, value: anytype) Error!void {
/// Write a single integer as LEB128 to the given writer. /// Write a single integer as LEB128 to the given writer.
pub fn writeLeb128(w: *Writer, value: anytype) Error!void { pub fn writeLeb128(w: *Writer, value: anytype) Error!void {
const value_info = @typeInfo(@TypeOf(value)).int; const value_info = @typeInfo(@TypeOf(value)).int;
try w.writeMultipleOf7Leb128(@as(@Type(.{ .int = .{ try w.writeMultipleOf7Leb128(@as(@Int(
.signedness = value_info.signedness, value_info.signedness,
.bits = @max(std.mem.alignForwardAnyAlign(u16, value_info.bits, 7), 7), @max(std.mem.alignForwardAnyAlign(u16, value_info.bits, 7), 7),
} }), value)); ), value));
} }
fn writeMultipleOf7Leb128(w: *Writer, value: anytype) Error!void { fn writeMultipleOf7Leb128(w: *Writer, value: anytype) Error!void {
@ -1929,10 +1929,10 @@ fn writeMultipleOf7Leb128(w: *Writer, value: anytype) Error!void {
.unsigned => remaining > std.math.maxInt(u7), .unsigned => remaining > std.math.maxInt(u7),
}; };
byte.* = .{ byte.* = .{
.bits = @bitCast(@as(@Type(.{ .int = .{ .bits = @bitCast(@as(
.signedness = value_info.signedness, @Int(value_info.signedness, 7),
.bits = 7, @truncate(remaining),
} }), @truncate(remaining))), )),
.more = more, .more = more,
}; };
if (value_info.bits > 7) remaining >>= 7; if (value_info.bits > 7) remaining >>= 7;

View file

@ -94,12 +94,12 @@ pub fn deserialize(comptime HashResult: type, str: []const u8) Error!HashResult
if (kvSplit(field)) |opt_version| { if (kvSplit(field)) |opt_version| {
if (mem.eql(u8, opt_version.key, version_param_name)) { if (mem.eql(u8, opt_version.key, version_param_name)) {
if (@hasField(HashResult, "alg_version")) { if (@hasField(HashResult, "alg_version")) {
const value_type_info = switch (@typeInfo(@TypeOf(out.alg_version))) { const ValueType = switch (@typeInfo(@TypeOf(out.alg_version))) {
.optional => |opt| @typeInfo(opt.child), .optional => |opt| opt.child,
else => |t| t, else => @TypeOf(out.alg_version),
}; };
out.alg_version = fmt.parseUnsigned( out.alg_version = fmt.parseUnsigned(
@Type(value_type_info), ValueType,
opt_version.value, opt_version.value,
10, 10,
) catch return Error.InvalidEncoding; ) catch return Error.InvalidEncoding;

View file

@ -606,7 +606,7 @@ pub fn array(
const elem_size = @divExact(@bitSizeOf(Elem), 8); const elem_size = @divExact(@bitSizeOf(Elem), 8);
var arr: [len_size + elem_size * elems.len]u8 = undefined; var arr: [len_size + elem_size * elems.len]u8 = undefined;
std.mem.writeInt(Len, arr[0..len_size], @intCast(elem_size * elems.len), .big); 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| { for (0.., @as([elems.len]Elem, elems)) |index, elem| {
std.mem.writeInt( std.mem.writeInt(
ElemInt, ElemInt,

View file

@ -33,22 +33,8 @@ pub fn fromInt(comptime E: type, integer: anytype) ?E {
/// default, which may be undefined. /// default, which may be undefined.
pub fn EnumFieldStruct(comptime E: type, comptime Data: type, comptime field_default: ?Data) type { pub fn EnumFieldStruct(comptime E: type, comptime Data: type, comptime field_default: ?Data) type {
@setEvalBranchQuota(@typeInfo(E).@"enum".fields.len + eval_branch_quota_cushion); @setEvalBranchQuota(@typeInfo(E).@"enum".fields.len + eval_branch_quota_cushion);
var struct_fields: [@typeInfo(E).@"enum".fields.len]std.builtin.Type.StructField = undefined; const default_ptr: ?*const anyopaque = if (field_default) |d| @ptrCast(&d) else null;
for (&struct_fields, @typeInfo(E).@"enum".fields) |*struct_field, enum_field| { return @Struct(.auto, null, std.meta.fieldNames(E), &@splat(Data), &@splat(.{ .default_value_ptr = default_ptr }));
struct_field.* = .{
.name = enum_field.name,
.type = Data,
.default_value_ptr = if (field_default) |d| @as(?*const anyopaque, @ptrCast(&d)) else null,
.is_comptime = false,
.alignment = if (@sizeOf(Data) > 0) @alignOf(Data) else 0,
};
}
return @Type(.{ .@"struct" = .{
.layout = .auto,
.fields = &struct_fields,
.decls = &.{},
.is_tuple = false,
} });
} }
/// Looks up the supplied fields in the given enum type. /// Looks up the supplied fields in the given enum type.
@ -1532,19 +1518,15 @@ test "EnumIndexer empty" {
test "EnumIndexer large dense unsorted" { test "EnumIndexer large dense unsorted" {
@setEvalBranchQuota(500_000); // many `comptimePrint`s @setEvalBranchQuota(500_000); // many `comptimePrint`s
// Make an enum with 500 fields with values in *descending* order. // Make an enum with 500 fields with values in *descending* order.
const E = @Type(.{ .@"enum" = .{ const E = @Enum(u32, .exhaustive, names: {
.tag_type = u32, var names: [500][]const u8 = undefined;
.fields = comptime fields: { for (&names, 0..) |*name, i| name.* = std.fmt.comptimePrint("f{d}", .{i});
var fields: [500]EnumField = undefined; break :names &names;
for (&fields, 0..) |*f, i| f.* = .{ }, vals: {
.name = std.fmt.comptimePrint("f{d}", .{i}), var vals: [500]u32 = undefined;
.value = 500 - i, for (&vals, 0..) |*val, i| val.* = 500 - i;
}; break :vals &vals;
break :fields &fields; });
},
.decls = &.{},
.is_exhaustive = true,
} });
const Indexer = EnumIndexer(E); const Indexer = EnumIndexer(E);
try testing.expectEqual(E.f0, Indexer.keyForIndex(499)); try testing.expectEqual(E.f0, Indexer.keyForIndex(499));
try testing.expectEqual(E.f499, Indexer.keyForIndex(0)); try testing.expectEqual(E.f499, Indexer.keyForIndex(0));

View file

@ -279,7 +279,7 @@ pub fn Alt(
/// Helper for calling alternate format methods besides one named "format". /// Helper for calling alternate format methods besides one named "format".
pub fn alt( pub fn alt(
context: anytype, context: anytype,
comptime func_name: @TypeOf(.enum_literal), comptime func_name: @EnumLiteral(),
) Alt(@TypeOf(context), @field(@TypeOf(context), @tagName(func_name))) { ) Alt(@TypeOf(context), @field(@TypeOf(context), @tagName(func_name))) {
return .{ .data = context }; return .{ .data = context };
} }

View file

@ -61,7 +61,7 @@ pub fn render(buf: []u8, value: anytype, options: Options) Error![]const u8 {
const T = @TypeOf(v); const T = @TypeOf(v);
comptime std.debug.assert(@typeInfo(T) == .float); 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 DT = if (@bitSizeOf(T) <= 64) u64 else u128;
const tables = switch (DT) { const tables = switch (DT) {
@ -1516,7 +1516,7 @@ const FLOAT128_POW5_INV_ERRORS: [154]u64 = .{
const builtin = @import("builtin"); const builtin = @import("builtin");
fn check(comptime T: type, value: T, comptime expected: []const u8) !void { 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; var buf: [6000]u8 = undefined;
const value_bits: I = @bitCast(value); const value_bits: I = @bitCast(value);

View file

@ -42,7 +42,7 @@ pub fn int(input: anytype) @TypeOf(input) {
const info = @typeInfo(@TypeOf(input)).int; const info = @typeInfo(@TypeOf(input)).int;
const bits = info.bits; const bits = info.bits;
// Convert input to unsigned integer (easier to deal with) // 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); const u_input: Uint = @bitCast(input);
if (bits > 256) @compileError("bit widths > 256 are unsupported, use std.hash.autoHash functionality."); 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 // For bit widths that don't have a dedicated function, use a heuristic

View file

@ -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! // Help the optimizer see that hashing an int is easy by inlining!
// TODO Check if the situation is better after #561 is resolved. // TODO Check if the situation is better after #561 is resolved.
.int => |int| switch (int.signedness) { .int => |int| switch (int.signedness) {
.signed => hash(hasher, @as(@Type(.{ .int = .{ .signed => hash(hasher, @as(@Int(.unsigned, int.bits), @bitCast(key)), strat),
.bits = int.bits,
.signedness = .unsigned,
} }), @bitCast(key)), strat),
.unsigned => { .unsigned => {
if (std.meta.hasUniqueRepresentation(Key)) { if (std.meta.hasUniqueRepresentation(Key)) {
@call(.always_inline, Hasher.update, .{ hasher, std.mem.asBytes(&key) }); @call(.always_inline, Hasher.update, .{ hasher, std.mem.asBytes(&key) });

View file

@ -57,13 +57,13 @@ pub const default_level: Level = switch (builtin.mode) {
}; };
pub const ScopeLevel = struct { pub const ScopeLevel = struct {
scope: @Type(.enum_literal), scope: @EnumLiteral(),
level: Level, level: Level,
}; };
fn log( fn log(
comptime level: Level, comptime level: Level,
comptime scope: @Type(.enum_literal), comptime scope: @EnumLiteral(),
comptime format: []const u8, comptime format: []const u8,
args: anytype, args: anytype,
) void { ) void {
@ -73,7 +73,7 @@ fn log(
} }
/// Determine if a specific log message level and scope combination are enabled for logging. /// Determine if a specific log message level and scope combination are enabled for logging.
pub fn logEnabled(comptime level: Level, comptime scope: @Type(.enum_literal)) bool { pub fn logEnabled(comptime level: Level, comptime scope: @EnumLiteral()) bool {
inline for (std.options.log_scope_levels) |scope_level| { inline for (std.options.log_scope_levels) |scope_level| {
if (scope_level.scope == scope) return @intFromEnum(level) <= @intFromEnum(scope_level.level); if (scope_level.scope == scope) return @intFromEnum(level) <= @intFromEnum(scope_level.level);
} }
@ -87,7 +87,7 @@ pub fn logEnabled(comptime level: Level, comptime scope: @Type(.enum_literal)) b
/// function returns. /// function returns.
pub fn defaultLog( pub fn defaultLog(
comptime level: Level, comptime level: Level,
comptime scope: @Type(.enum_literal), comptime scope: @EnumLiteral(),
comptime format: []const u8, comptime format: []const u8,
args: anytype, args: anytype,
) void { ) void {
@ -115,7 +115,7 @@ pub fn defaultLog(
/// Returns a scoped logging namespace that logs all messages using the scope /// Returns a scoped logging namespace that logs all messages using the scope
/// provided here. /// provided here.
pub fn scoped(comptime scope: @Type(.enum_literal)) type { pub fn scoped(comptime scope: @EnumLiteral()) type {
return struct { return struct {
/// Log an error message. This log level is intended to be used /// Log an error message. This log level is intended to be used
/// when something has gone wrong. This might be recoverable or might /// when something has gone wrong. This might be recoverable or might

View file

@ -450,12 +450,7 @@ pub fn wrap(x: anytype, r: anytype) @TypeOf(x) {
// in the rare usecase of r not being comptime_int or float, // in the rare usecase of r not being comptime_int or float,
// take the penalty of having an intermediary type conversion, // take the penalty of having an intermediary type conversion,
// otherwise the alternative is to unwind iteratively to avoid overflow // otherwise the alternative is to unwind iteratively to avoid overflow
const R = comptime do: { const R = @Int(.signed, info_r.int.bits + 1);
var info = info_r;
info.int.bits += 1;
info.int.signedness = .signed;
break :do @Type(info);
};
const radius: if (info_r.int.signedness == .signed) @TypeOf(r) else R = r; 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 return @intCast(@mod(x - radius, 2 * @as(R, r)) - r); // provably impossible to overflow
}, },
@ -799,14 +794,14 @@ pub fn Log2IntCeil(comptime T: type) type {
pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) type { pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) type {
assert(from <= to); assert(from <= to);
const signedness: std.builtin.Signedness = if (from < 0) .signed else .unsigned; const signedness: std.builtin.Signedness = if (from < 0) .signed else .unsigned;
return @Type(.{ .int = .{ return @Int(
.signedness = signedness, signedness,
.bits = @as(u16, @intFromBool(signedness == .signed)) + @as(u16, @intFromBool(signedness == .signed)) +
switch (if (from < 0) @max(@abs(from) - 1, to) else to) { switch (if (from < 0) @max(@abs(from) - 1, to) else to) {
0 => 0, 0 => 0,
else => |pos_max| 1 + log2(pos_max), else => |pos_max| 1 + log2(pos_max),
}, },
} }); );
} }
test IntFittingRange { test IntFittingRange {
@ -1107,9 +1102,14 @@ test cast {
pub const AlignCastError = error{UnalignedMemory}; pub const AlignCastError = error{UnalignedMemory};
fn AlignCastResult(comptime alignment: Alignment, comptime Ptr: type) type { fn AlignCastResult(comptime alignment: Alignment, comptime Ptr: type) type {
var ptr_info = @typeInfo(Ptr); const orig = @typeInfo(Ptr).pointer;
ptr_info.pointer.alignment = alignment.toByteUnits(); return @Pointer(orig.size, .{
return @Type(ptr_info); .@"const" = orig.is_const,
.@"volatile" = orig.is_volatile,
.@"allowzero" = orig.is_allowzero,
.@"align" = alignment.toByteUnits(),
.@"addrspace" = orig.address_space,
}, orig.child, orig.sentinel());
} }
/// Align cast a pointer but return an error if it's the wrong alignment /// Align cast a pointer but return an error if it's the wrong alignment

View file

@ -2787,11 +2787,11 @@ test "bitNotWrap more than two limbs" {
const bits = @bitSizeOf(Limb) * 4 + 2; const bits = @bitSizeOf(Limb) * 4 + 2;
try res.bitNotWrap(&a, .unsigned, bits); 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 testing.expectEqual((try res.toInt(Unsigned)), ~@as(Unsigned, maxInt(Limb)));
try res.bitNotWrap(&a, .signed, bits); 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))); try testing.expectEqual((try res.toInt(Signed)), ~@as(Signed, maxInt(Limb)));
} }

View file

@ -14,22 +14,10 @@ pub fn FloatRepr(comptime Float: type) type {
exponent: BiasedExponent, exponent: BiasedExponent,
sign: std.math.Sign, sign: std.math.Sign,
pub const StoredMantissa = @Type(.{ .int = .{ pub const StoredMantissa = @Int(.unsigned, floatMantissaBits(Float));
.signedness = .unsigned, pub const Mantissa = @Int(.unsigned, 1 + fractional_bits);
.bits = floatMantissaBits(Float), pub const Exponent = @Int(.signed, exponent_bits);
} }); pub const BiasedExponent = enum(@Int(.unsigned, exponent_bits)) {
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,
} })) {
denormal = 0, denormal = 0,
min_normal = 1, min_normal = 1,
zero = (1 << (exponent_bits - 1)) - 1, zero = (1 << (exponent_bits - 1)) - 1,
@ -56,14 +44,8 @@ pub fn FloatRepr(comptime Float: type) type {
fraction: Fraction, fraction: Fraction,
exponent: Normalized.Exponent, exponent: Normalized.Exponent,
pub const Fraction = @Type(.{ .int = .{ pub const Fraction = @Int(.unsigned, fractional_bits);
.signedness = .unsigned, pub const Exponent = @Int(.signed, 1 + exponent_bits);
.bits = fractional_bits,
} });
pub const Exponent = @Type(.{ .int = .{
.signedness = .signed,
.bits = 1 + exponent_bits,
} });
/// This currently truncates denormal values, which needs to be fixed before this can be used to /// This currently truncates denormal values, which needs to be fixed before this can be used to
/// produce a rounded value. /// produce a rounded value.
@ -122,7 +104,7 @@ inline fn mantissaOne(comptime T: type) comptime_int {
/// Creates floating point type T from an unbiased exponent and raw mantissa. /// 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 { 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)); const biased_exponent = @as(TBits, exponent + floatExponentMax(T));
return @as(T, @bitCast((biased_exponent << floatMantissaBits(T)) | @as(TBits, mantissa))); return @as(T, @bitCast((biased_exponent << floatMantissaBits(T)) | @as(TBits, mantissa)));
} }
@ -209,7 +191,7 @@ pub inline fn floatEps(comptime T: type) T {
pub inline fn floatEpsAt(comptime T: type, x: T) T { pub inline fn floatEpsAt(comptime T: type, x: T) T {
switch (@typeInfo(T)) { switch (@typeInfo(T)) {
.float => |F| { .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 u: U = @bitCast(x);
const y: T = @bitCast(u ^ 1); const y: T = @bitCast(u ^ 1);
return @abs(x - y); return @abs(x - y);

View file

@ -33,10 +33,7 @@ pub fn log2(x: anytype) @TypeOf(x) {
return result; return result;
}, },
.int => |int_info| math.log2_int(switch (int_info.signedness) { .int => |int_info| math.log2_int(switch (int_info.signedness) {
.signed => @Type(.{ .int = .{ .signed => @Int(.unsigned, int_info.bits -| 1),
.signedness = .unsigned,
.bits = int_info.bits -| 1,
} }),
.unsigned => T, .unsigned => T,
}, @intCast(x)), }, @intCast(x)),
else => @compileError("log2 not implemented for " ++ @typeName(T)), else => @compileError("log2 not implemented for " ++ @typeName(T)),

View file

@ -65,7 +65,7 @@ test "log_int" {
// Test all unsigned integers with 2, 3, ..., 64 bits. // Test all unsigned integers with 2, 3, ..., 64 bits.
// We cannot test 0 or 1 bits since base must be > 1. // We cannot test 0 or 1 bits since base must be > 1.
inline for (2..64 + 1) |bits| { 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) // for base = 2, 3, ..., min(maxInt(T),1024)
var base: T = 1; var base: T = 1;

View file

@ -6,10 +6,7 @@ const expect = std.testing.expect;
pub fn signbit(x: anytype) bool { pub fn signbit(x: anytype) bool {
return switch (@typeInfo(@TypeOf(x))) { return switch (@typeInfo(@TypeOf(x))) {
.int, .comptime_int => x, .int, .comptime_int => x,
.float => |float| @as(@Type(.{ .int = .{ .float => |float| @as(@Int(.signed, float.bits), @bitCast(x)),
.signedness = .signed,
.bits = float.bits,
} }), @bitCast(x)),
.comptime_float => @as(i128, @bitCast(@as(f128, x))), // any float type will do .comptime_float => @as(i128, @bitCast(@as(f128, x))), // any float type will do
else => @compileError("std.math.signbit does not support " ++ @typeName(@TypeOf(x))), else => @compileError("std.math.signbit does not support " ++ @typeName(@TypeOf(x))),
} < 0; } < 0;

View file

@ -80,7 +80,7 @@ test sqrt_int {
/// Returns the return type `sqrt` will return given an operand of type `T`. /// Returns the return type `sqrt` will return given an operand of type `T`.
pub fn Sqrt(comptime T: type) type { pub fn Sqrt(comptime T: type) type {
return switch (@typeInfo(T)) { 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, else => T,
}; };
} }

View file

@ -846,17 +846,18 @@ fn Span(comptime T: type) type {
return ?Span(optional_info.child); return ?Span(optional_info.child);
}, },
.pointer => |ptr_info| { .pointer => |ptr_info| {
var new_ptr_info = ptr_info; const new_sentinel: ?ptr_info.child = switch (ptr_info.size) {
switch (ptr_info.size) {
.c => {
new_ptr_info.sentinel_ptr = &@as(ptr_info.child, 0);
new_ptr_info.is_allowzero = false;
},
.many => if (ptr_info.sentinel() == null) @compileError("invalid type given to std.mem.span: " ++ @typeName(T)),
.one, .slice => @compileError("invalid type given to std.mem.span: " ++ @typeName(T)), .one, .slice => @compileError("invalid type given to std.mem.span: " ++ @typeName(T)),
} .many => ptr_info.sentinel() orelse @compileError("invalid type given to std.mem.span: " ++ @typeName(T)),
new_ptr_info.size = .slice; .c => 0,
return @Type(.{ .pointer = new_ptr_info }); };
return @Pointer(.slice, .{
.@"const" = ptr_info.is_const,
.@"volatile" = ptr_info.is_volatile,
.@"allowzero" = ptr_info.is_allowzero and ptr_info.size != .c,
.@"align" = ptr_info.alignment,
.@"addrspace" = ptr_info.address_space,
}, ptr_info.child, new_sentinel);
}, },
else => {}, else => {},
} }
@ -910,45 +911,18 @@ fn SliceTo(comptime T: type, comptime end: std.meta.Elem(T)) type {
return ?SliceTo(optional_info.child, end); return ?SliceTo(optional_info.child, end);
}, },
.pointer => |ptr_info| { .pointer => |ptr_info| {
var new_ptr_info = ptr_info; const Elem = std.meta.Elem(T);
new_ptr_info.size = .slice; const have_sentinel: bool = switch (ptr_info.size) {
switch (ptr_info.size) { .one, .slice, .many => if (std.meta.sentinel(T)) |s| s == end else false,
.one => switch (@typeInfo(ptr_info.child)) { .c => false,
.array => |array_info| { };
new_ptr_info.child = array_info.child; return @Pointer(.slice, .{
// The return type must only be sentinel terminated if we are guaranteed .@"const" = ptr_info.is_const,
// to find the value searched for, which is only the case if it matches .@"volatile" = ptr_info.is_volatile,
// the sentinel of the type passed. .@"allowzero" = ptr_info.is_allowzero and ptr_info.size != .c,
if (array_info.sentinel()) |s| { .@"align" = ptr_info.alignment,
if (end == s) { .@"addrspace" = ptr_info.address_space,
new_ptr_info.sentinel_ptr = &end; }, Elem, if (have_sentinel) end else null);
} else {
new_ptr_info.sentinel_ptr = null;
}
}
},
else => {},
},
.many, .slice => {
// The return type must only be sentinel terminated if we are guaranteed
// to find the value searched for, which is only the case if it matches
// the sentinel of the type passed.
if (ptr_info.sentinel()) |s| {
if (end == s) {
new_ptr_info.sentinel_ptr = &end;
} else {
new_ptr_info.sentinel_ptr = null;
}
}
},
.c => {
new_ptr_info.sentinel_ptr = &end;
// C pointers are always allowzero, but we don't want the return type to be.
assert(new_ptr_info.is_allowzero);
new_ptr_info.is_allowzero = false;
},
}
return @Type(.{ .pointer = new_ptr_info });
}, },
else => {}, else => {},
} }
@ -3951,38 +3925,25 @@ test reverse {
} }
} }
fn ReverseIterator(comptime T: type) type { fn ReverseIterator(comptime T: type) type {
const Pointer = blk: { const ptr = switch (@typeInfo(T)) {
switch (@typeInfo(T)) { .pointer => |ptr| ptr,
.pointer => |ptr_info| switch (ptr_info.size) { else => @compileError("expected slice or pointer to array, found '" ++ @typeName(T) ++ "'"),
.one => switch (@typeInfo(ptr_info.child)) {
.array => |array_info| {
var new_ptr_info = ptr_info;
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 });
},
else => {},
},
.slice => {
var new_ptr_info = ptr_info;
new_ptr_info.size = .many;
break :blk @Type(.{ .pointer = new_ptr_info });
},
else => {},
},
else => {},
}
@compileError("expected slice or pointer to array, found '" ++ @typeName(T) ++ "'");
}; };
const Element = std.meta.Elem(Pointer); switch (ptr.size) {
const ElementPointer = @Type(.{ .pointer = ptr: { .slice => {},
var ptr = @typeInfo(Pointer).pointer; .one => if (@typeInfo(ptr.child) != .array) @compileError("expected slice or pointer to array, found '" ++ @typeName(T) ++ "'"),
ptr.size = .one; .many, .c => @compileError("expected slice or pointer to array, found '" ++ @typeName(T) ++ "'"),
ptr.child = Element; }
ptr.sentinel_ptr = null; const Element = std.meta.Elem(T);
break :ptr ptr; const attrs: std.builtin.Type.Pointer.Attributes = .{
} }); .@"const" = ptr.is_const,
.@"volatile" = ptr.is_volatile,
.@"allowzero" = ptr.is_allowzero,
.@"align" = ptr.alignment,
.@"addrspace" = ptr.address_space,
};
const Pointer = @Pointer(.many, attrs, Element, std.meta.sentinel(T));
const ElementPointer = @Pointer(.one, attrs, Element, null);
return struct { return struct {
ptr: Pointer, ptr: Pointer,
index: usize, index: usize,
@ -4342,19 +4303,14 @@ fn CopyPtrAttrs(
comptime size: std.builtin.Type.Pointer.Size, comptime size: std.builtin.Type.Pointer.Size,
comptime child: type, comptime child: type,
) type { ) type {
const info = @typeInfo(source).pointer; const ptr = @typeInfo(source).pointer;
return @Type(.{ return @Pointer(size, .{
.pointer = .{ .@"const" = ptr.is_const,
.size = size, .@"volatile" = ptr.is_volatile,
.is_const = info.is_const, .@"allowzero" = ptr.is_allowzero,
.is_volatile = info.is_volatile, .@"align" = ptr.alignment,
.is_allowzero = info.is_allowzero, .@"addrspace" = ptr.address_space,
.alignment = info.alignment, }, child, null);
.address_space = info.address_space,
.child = child,
.sentinel_ptr = null,
},
});
} }
fn AsBytesReturnType(comptime P: type) type { fn AsBytesReturnType(comptime P: type) type {
@ -4936,19 +4892,14 @@ test "freeing empty string with null-terminated sentinel" {
/// Returns a slice with the given new alignment, /// Returns a slice with the given new alignment,
/// all other pointer attributes copied from `AttributeSource`. /// all other pointer attributes copied from `AttributeSource`.
fn AlignedSlice(comptime AttributeSource: type, comptime new_alignment: usize) type { fn AlignedSlice(comptime AttributeSource: type, comptime new_alignment: usize) type {
const info = @typeInfo(AttributeSource).pointer; const ptr = @typeInfo(AttributeSource).pointer;
return @Type(.{ return @Pointer(.slice, .{
.pointer = .{ .@"const" = ptr.is_const,
.size = .slice, .@"volatile" = ptr.is_volatile,
.is_const = info.is_const, .@"allowzero" = ptr.is_allowzero,
.is_volatile = info.is_volatile, .@"align" = new_alignment,
.is_allowzero = info.is_allowzero, .@"addrspace" = ptr.address_space,
.alignment = new_alignment, }, ptr.child, null);
.address_space = info.address_space,
.child = info.child,
.sentinel_ptr = null,
},
});
} }
/// Returns the largest slice in the given bytes that conforms to the new alignment, /// Returns the largest slice in the given bytes that conforms to the new alignment,

View file

@ -171,58 +171,34 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
switch (@typeInfo(T)) { switch (@typeInfo(T)) {
.pointer => |info| switch (info.size) { .pointer => |info| switch (info.size) {
.one => switch (@typeInfo(info.child)) { .one => switch (@typeInfo(info.child)) {
.array => |array_info| return @Type(.{ .array => |array_info| return @Pointer(.one, .{
.pointer = .{ .@"const" = info.is_const,
.size = info.size, .@"volatile" = info.is_volatile,
.is_const = info.is_const, .@"allowzero" = info.is_allowzero,
.is_volatile = info.is_volatile, .@"align" = info.alignment,
.alignment = info.alignment, .@"addrspace" = info.address_space,
.address_space = info.address_space, }, [array_info.len:sentinel_val]array_info.child, null),
.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 => {}, else => {},
}, },
.many, .slice => return @Type(.{ .many, .slice => |size| return @Pointer(size, .{
.pointer = .{ .@"const" = info.is_const,
.size = info.size, .@"volatile" = info.is_volatile,
.is_const = info.is_const, .@"allowzero" = info.is_allowzero,
.is_volatile = info.is_volatile, .@"align" = info.alignment,
.alignment = info.alignment, .@"addrspace" = info.address_space,
.address_space = info.address_space, }, info.child, sentinel_val),
.child = info.child,
.is_allowzero = info.is_allowzero,
.sentinel_ptr = @as(?*const anyopaque, @ptrCast(&sentinel_val)),
},
}),
else => {}, else => {},
}, },
.optional => |info| switch (@typeInfo(info.child)) { .optional => |info| switch (@typeInfo(info.child)) {
.pointer => |ptr_info| switch (ptr_info.size) { .pointer => |ptr_info| switch (ptr_info.size) {
.many => return @Type(.{ .many => return ?@Pointer(.many, .{
.optional = .{ .@"const" = ptr_info.is_const,
.child = @Type(.{ .@"volatile" = ptr_info.is_volatile,
.pointer = .{ .@"allowzero" = ptr_info.is_allowzero,
.size = ptr_info.size, .@"align" = ptr_info.alignment,
.is_const = ptr_info.is_const, .@"addrspace" = ptr_info.address_space,
.is_volatile = ptr_info.is_volatile,
.alignment = ptr_info.alignment,
.address_space = ptr_info.address_space,
.child = ptr_info.child, .child = ptr_info.child,
.is_allowzero = ptr_info.is_allowzero, }, ptr_info.child, sentinel_val),
.sentinel_ptr = @as(?*const anyopaque, @ptrCast(&sentinel_val)),
},
}),
},
}),
else => {}, else => {},
}, },
else => {}, else => {},
@ -487,46 +463,22 @@ test tags {
/// Returns an enum with a variant named after each field of `T`. /// Returns an enum with a variant named after each field of `T`.
pub fn FieldEnum(comptime T: type) type { pub fn FieldEnum(comptime T: type) type {
const field_infos = fields(T); const field_names = fieldNames(T);
if (field_infos.len == 0) { switch (@typeInfo(T)) {
return @Type(.{ .@"union" => |@"union"| if (@"union".tag_type) |EnumTag| {
.@"enum" = .{ for (std.enums.values(EnumTag), 0..) |v, i| {
.tag_type = u0,
.fields = &.{},
.decls = &.{},
.is_exhaustive = true,
},
});
}
if (@typeInfo(T) == .@"union") {
if (@typeInfo(T).@"union".tag_type) |tag_type| {
for (std.enums.values(tag_type), 0..) |v, i| {
if (@intFromEnum(v) != i) break; // enum values not consecutive if (@intFromEnum(v) != i) break; // enum values not consecutive
if (!std.mem.eql(u8, @tagName(v), field_infos[i].name)) break; // fields out of order if (!std.mem.eql(u8, @tagName(v), field_names[i])) break; // fields out of order
} else { } else {
return tag_type; return EnumTag;
}
} }
},
else => {},
} }
var enumFields: [field_infos.len]std.builtin.Type.EnumField = undefined; const IntTag = std.math.IntFittingRange(0, field_names.len -| 1);
var decls = [_]std.builtin.Type.Declaration{}; return @Enum(IntTag, .exhaustive, field_names, &std.simd.iota(IntTag, field_names.len));
inline for (field_infos, 0..) |field, i| {
enumFields[i] = .{
.name = field.name,
.value = i,
};
}
return @Type(.{
.@"enum" = .{
.tag_type = std.math.IntFittingRange(0, field_infos.len - 1),
.fields = &enumFields,
.decls = &decls,
.is_exhaustive = true,
},
});
} }
fn expectEqualEnum(expected: anytype, actual: @TypeOf(expected)) !void { fn expectEqualEnum(expected: anytype, actual: @TypeOf(expected)) !void {
@ -583,20 +535,11 @@ test FieldEnum {
} }
pub fn DeclEnum(comptime T: type) type { pub fn DeclEnum(comptime T: type) type {
const fieldInfos = std.meta.declarations(T); const decls = declarations(T);
var enumDecls: [fieldInfos.len]std.builtin.Type.EnumField = undefined; var names: [decls.len][]const u8 = undefined;
var decls = [_]std.builtin.Type.Declaration{}; for (&names, decls) |*name, decl| name.* = decl.name;
inline for (fieldInfos, 0..) |field, i| { const IntTag = std.math.IntFittingRange(0, decls.len -| 1);
enumDecls[i] = .{ .name = field.name, .value = i }; return @Enum(IntTag, .exhaustive, &names, &std.simd.iota(IntTag, decls.len));
}
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,
},
});
} }
test DeclEnum { test DeclEnum {
@ -868,25 +811,26 @@ 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 { pub fn Int(comptime signedness: std.builtin.Signedness, comptime bit_count: u16) type {
return @Type(.{ return @Int(signedness, bit_count);
.int = .{
.signedness = signedness,
.bits = bit_count,
},
});
} }
pub fn Float(comptime bit_count: u8) type { pub fn Float(comptime bit_count: u8) type {
return @Type(.{ return switch (bit_count) {
.float = .{ .bits = bit_count }, 16 => f16,
}); 32 => f32,
64 => f64,
80 => f80,
128 => f128,
else => @compileError("invalid float bit count"),
};
} }
test Float { test Float {
try testing.expectEqual(f16, Float(16)); try testing.expectEqual(f16, Float(16));
try testing.expectEqual(f32, Float(32)); try testing.expectEqual(f32, Float(32));
try testing.expectEqual(f64, Float(64)); try testing.expectEqual(f64, Float(64));
try testing.expectEqual(f80, Float(80));
try testing.expectEqual(f128, Float(128)); try testing.expectEqual(f128, Float(128));
} }
@ -912,42 +856,14 @@ pub fn ArgsTuple(comptime Function: type) type {
argument_field_list[i] = T; argument_field_list[i] = T;
} }
return CreateUniqueTuple(argument_field_list.len, argument_field_list); return Tuple(&argument_field_list);
} }
/// For a given anonymous list of types, returns a new tuple type /// Deprecated; use `@Tuple` instead.
/// with those types as fields.
/// ///
/// Examples: /// To be removed after Zig 0.16.0 releases.
/// - `Tuple(&[_]type {})` `tuple { }`
/// - `Tuple(&[_]type {f32})` `tuple { f32 }`
/// - `Tuple(&[_]type {f32,u32})` `tuple { f32, u32 }`
pub fn Tuple(comptime types: []const type) type { pub fn Tuple(comptime types: []const type) type {
return CreateUniqueTuple(types.len, types[0..types.len].*); return @Tuple(types);
}
fn CreateUniqueTuple(comptime N: comptime_int, comptime types: [N]type) type {
var tuple_fields: [types.len]std.builtin.Type.StructField = undefined;
inline for (types, 0..) |T, i| {
@setEvalBranchQuota(10_000);
var num_buf: [128]u8 = undefined;
tuple_fields[i] = .{
.name = std.fmt.bufPrintSentinel(&num_buf, "{d}", .{i}, 0) catch unreachable,
.type = T,
.default_value_ptr = null,
.is_comptime = false,
.alignment = @alignOf(T),
};
}
return @Type(.{
.@"struct" = .{
.is_tuple = true,
.layout = .auto,
.decls = &.{},
.fields = &tuple_fields,
},
});
} }
const TupleTester = struct { const TupleTester = struct {

View file

@ -20,24 +20,16 @@ pub fn TrailerFlags(comptime Fields: type) type {
pub const ActiveFields = std.enums.EnumFieldStruct(FieldEnum, bool, false); pub const ActiveFields = std.enums.EnumFieldStruct(FieldEnum, bool, false);
pub const FieldValues = blk: { pub const FieldValues = blk: {
var fields: [bit_count]Type.StructField = undefined; var field_names: [bit_count][]const u8 = undefined;
for (@typeInfo(Fields).@"struct".fields, 0..) |struct_field, i| { var field_types: [bit_count]type = undefined;
fields[i] = Type.StructField{ var field_attrs: [bit_count]std.builtin.Type.StructField.Attributes = undefined;
.name = struct_field.name, for (@typeInfo(Fields).@"struct".fields, &field_names, &field_types, &field_attrs) |field, *new_name, *NewType, *new_attrs| {
.type = ?struct_field.type, new_name.* = field.name;
.default_value_ptr = &@as(?struct_field.type, null), NewType.* = ?field.type;
.is_comptime = false, const default: ?field.type = null;
.alignment = @alignOf(?struct_field.type), new_attrs.* = .{ .default_value_ptr = &default };
};
} }
break :blk @Type(.{ break :blk @Struct(.auto, null, &field_names, &field_types, &field_attrs);
.@"struct" = .{
.layout = .auto,
.fields = &fields,
.decls = &.{},
.is_tuple = false,
},
});
}; };
pub const Self = @This(); pub const Self = @This();

View file

@ -32,12 +32,17 @@ pub fn MultiArrayList(comptime T: type) type {
const Elem = switch (@typeInfo(T)) { const Elem = switch (@typeInfo(T)) {
.@"struct" => T, .@"struct" => T,
.@"union" => |u| struct { .@"union" => |u| struct {
pub const Bare = @Type(.{ .@"union" = .{ pub const Bare = Bare: {
.layout = u.layout, var field_names: [u.fields.len][]const u8 = undefined;
.tag_type = null, var field_types: [u.fields.len]type = undefined;
.fields = u.fields, var field_attrs: [u.fields.len]std.builtin.Type.UnionField.Attributes = undefined;
.decls = &.{}, for (u.fields, &field_names, &field_types, &field_attrs) |field, *name, *Type, *attrs| {
} }); name.* = field.name;
Type.* = field.type;
attrs.* = .{ .@"align" = field.alignment };
}
break :Bare @Union(u.layout, null, &field_names, &field_types, &field_attrs);
};
pub const Tag = pub const Tag =
u.tag_type orelse @compileError("MultiArrayList does not support untagged unions"); u.tag_type orelse @compileError("MultiArrayList does not support untagged unions");
tags: Tag, tags: Tag,
@ -609,20 +614,18 @@ pub fn MultiArrayList(comptime T: type) type {
} }
const Entry = entry: { const Entry = entry: {
var entry_fields: [fields.len]std.builtin.Type.StructField = undefined; var field_names: [fields.len][]const u8 = undefined;
for (&entry_fields, sizes.fields) |*entry_field, i| entry_field.* = .{ var field_types: [fields.len]type = undefined;
.name = fields[i].name ++ "_ptr", var field_attrs: [fields.len]std.builtin.Type.StructField.Attributes = undefined;
.type = *fields[i].type, for (sizes.fields, &field_names, &field_types, &field_attrs) |i, *name, *Type, *attrs| {
.default_value_ptr = null, name.* = fields[i].name ++ "_ptr";
.is_comptime = fields[i].is_comptime, Type.* = *fields[i].type;
.alignment = fields[i].alignment, attrs.* = .{
.@"comptime" = fields[i].is_comptime,
.@"align" = fields[i].alignment,
}; };
break :entry @Type(.{ .@"struct" = .{ }
.layout = .@"extern", break :entry @Struct(.@"extern", null, &field_names, &field_types, &field_attrs);
.fields = &entry_fields,
.decls = &.{},
.is_tuple = false,
} });
}; };
/// This function is used in the debugger pretty formatters in tools/ to fetch the /// 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. /// child field order and entry type to facilitate fancy debug printing for this type.
@ -1023,23 +1026,9 @@ test "struct with many fields" {
const ManyFields = struct { const ManyFields = struct {
fn Type(count: comptime_int) type { fn Type(count: comptime_int) type {
@setEvalBranchQuota(50000); @setEvalBranchQuota(50000);
var fields: [count]std.builtin.Type.StructField = undefined; var field_names: [count][]const u8 = undefined;
for (0..count) |i| { for (&field_names, 0..) |*n, i| n.* = std.fmt.comptimePrint("a{d}", .{i});
fields[i] = .{ return @Struct(.@"extern", null, &field_names, &@splat(u32), &@splat(.{}));
.name = std.fmt.comptimePrint("a{}", .{i}),
.type = u32,
.default_value_ptr = null,
.is_comptime = false,
.alignment = @alignOf(u32),
};
}
const info: std.builtin.Type = .{ .@"struct" = .{
.layout = .auto,
.fields = &fields,
.decls = &.{},
.is_tuple = false,
} };
return @Type(info);
} }
fn doTest(ally: std.mem.Allocator, count: comptime_int) !void { fn doTest(ally: std.mem.Allocator, count: comptime_int) !void {

View file

@ -124,7 +124,7 @@ pub const Options = struct {
logFn: fn ( logFn: fn (
comptime message_level: log.Level, comptime message_level: log.Level,
comptime scope: @TypeOf(.enum_literal), comptime scope: @EnumLiteral(),
comptime format: []const u8, comptime format: []const u8,
args: anytype, args: anytype,
) void = log.defaultLog, ) void = log.defaultLog,

View file

@ -81,23 +81,15 @@ fn ToUnsigned(comptime T: type) type {
} }
/// Constructs a [*c] pointer with the const and volatile annotations /// Constructs a [*c] pointer with the const and volatile annotations
/// from SelfType for pointing to a C flexible array of ElementType. /// from Self for pointing to a C flexible array of Element.
pub fn FlexibleArrayType(comptime SelfType: type, comptime ElementType: type) type { pub fn FlexibleArrayType(comptime Self: type, comptime Element: type) type {
switch (@typeInfo(SelfType)) { return switch (@typeInfo(Self)) {
.pointer => |ptr| { .pointer => |ptr| @Pointer(.c, .{
return @Type(.{ .pointer = .{ .@"const" = ptr.is_const,
.size = .c, .@"volatile" = ptr.is_volatile,
.is_const = ptr.is_const, }, Element, null),
.is_volatile = ptr.is_volatile, else => |info| @compileError("Invalid self type \"" ++ @tagName(info) ++ "\" for flexible array getter: " ++ @typeName(Self)),
.alignment = @alignOf(ElementType), };
.address_space = .generic,
.child = ElementType,
.is_allowzero = true,
.sentinel_ptr = null,
} });
},
else => |info| @compileError("Invalid self type \"" ++ @tagName(info) ++ "\" for flexible array getter: " ++ @typeName(SelfType)),
}
} }
/// Promote the type of an integer literal until it fits as C would. /// Promote the type of an integer literal until it fits as C would.
@ -219,7 +211,7 @@ fn castInt(comptime DestType: type, target: anytype) DestType {
const dest = @typeInfo(DestType).int; const dest = @typeInfo(DestType).int;
const source = @typeInfo(@TypeOf(target)).int; const source = @typeInfo(@TypeOf(target)).int;
const Int = @Type(.{ .int = .{ .bits = dest.bits, .signedness = source.signedness } }); const Int = @Int(source.signedness, dest.bits);
if (dest.bits < source.bits) if (dest.bits < source.bits)
return @as(DestType, @bitCast(@as(Int, @truncate(target)))) return @as(DestType, @bitCast(@as(Int, @truncate(target))))

View file

@ -8614,39 +8614,18 @@ pub const Metadata = packed struct(u32) {
nodes: anytype, nodes: anytype,
w: *Writer, w: *Writer,
) !void { ) !void {
comptime var fmt_str: []const u8 = "";
const names = comptime std.meta.fieldNames(@TypeOf(nodes)); const names = comptime std.meta.fieldNames(@TypeOf(nodes));
comptime var fields: [2 + names.len]std.builtin.Type.StructField = undefined;
inline for (fields[0..2], .{ "distinct", "node" }) |*field, name| { comptime var fmt_str: []const u8 = "{[distinct]s}{[node]s}(";
fmt_str = fmt_str ++ "{[" ++ name ++ "]s}"; inline for (names) |name| fmt_str = fmt_str ++ "{[" ++ name ++ "]f}";
field.* = .{
.name = name,
.type = []const u8,
.default_value_ptr = null,
.is_comptime = false,
.alignment = @alignOf([]const u8),
};
}
fmt_str = fmt_str ++ "(";
inline for (fields[2..], names) |*field, name| {
fmt_str = fmt_str ++ "{[" ++ name ++ "]f}";
const T = std.fmt.Alt(FormatData, format);
field.* = .{
.name = name,
.type = T,
.default_value_ptr = null,
.is_comptime = false,
.alignment = @alignOf(T),
};
}
fmt_str = fmt_str ++ ")\n"; fmt_str = fmt_str ++ ")\n";
var fmt_args: @Type(.{ .@"struct" = .{ const field_names = @as([]const []const u8, &.{ "distinct", "node" }) ++ names;
.layout = .auto, comptime var field_types: [2 + names.len]type = undefined;
.fields = &fields, @memset(field_types[0..2], []const u8);
.decls = &.{}, @memset(field_types[2..], std.fmt.Alt(FormatData, format));
.is_tuple = false,
} }) = undefined; var fmt_args: @Struct(.auto, null, field_names, &field_types, &@splat(.{})) = undefined;
fmt_args.distinct = @tagName(distinct); fmt_args.distinct = @tagName(distinct);
fmt_args.node = @tagName(node); fmt_args.node = @tagName(node);
inline for (names) |name| @field(fmt_args, name) = try formatter.fmt( inline for (names) |name| @field(fmt_args, name) = try formatter.fmt(

View file

@ -1153,23 +1153,17 @@ const Local = struct {
fn PtrArrayElem(comptime len: usize) type { fn PtrArrayElem(comptime len: usize) type {
const elem_info = @typeInfo(Elem).@"struct"; const elem_info = @typeInfo(Elem).@"struct";
const elem_fields = elem_info.fields; const elem_fields = elem_info.fields;
var new_fields: [elem_fields.len]std.builtin.Type.StructField = undefined; var new_names: [elem_fields.len][]const u8 = undefined;
for (&new_fields, elem_fields) |*new_field, elem_field| { var new_types: [elem_fields.len]type = undefined;
const T = *[len]elem_field.type; for (elem_fields, &new_names, &new_types) |elem_field, *new_name, *NewType| {
new_field.* = .{ new_name.* = elem_field.name;
.name = elem_field.name, NewType.* = *[len]elem_field.type;
.type = T, }
.default_value_ptr = null, if (elem_info.is_tuple) {
.is_comptime = false, return @Tuple(&new_types);
.alignment = @alignOf(T), } else {
}; return @Struct(.auto, null, &new_names, &new_types, &@splat(.{}));
} }
return @Type(.{ .@"struct" = .{
.layout = .auto,
.fields = &new_fields,
.decls = &.{},
.is_tuple = elem_info.is_tuple,
} });
} }
fn PtrElem(comptime opts: struct { fn PtrElem(comptime opts: struct {
size: std.builtin.Type.Pointer.Size, size: std.builtin.Type.Pointer.Size,
@ -1177,32 +1171,17 @@ const Local = struct {
}) type { }) type {
const elem_info = @typeInfo(Elem).@"struct"; const elem_info = @typeInfo(Elem).@"struct";
const elem_fields = elem_info.fields; const elem_fields = elem_info.fields;
var new_fields: [elem_fields.len]std.builtin.Type.StructField = undefined; var new_names: [elem_fields.len][]const u8 = undefined;
for (&new_fields, elem_fields) |*new_field, elem_field| { var new_types: [elem_fields.len]type = undefined;
const T = @Type(.{ .pointer = .{ for (elem_fields, &new_names, &new_types) |elem_field, *new_name, *NewType| {
.size = opts.size, new_name.* = elem_field.name;
.is_const = opts.is_const, NewType.* = @Pointer(opts.size, .{ .@"const" = opts.is_const }, elem_field.type, null);
.is_volatile = false, }
.alignment = @alignOf(elem_field.type), if (elem_info.is_tuple) {
.address_space = .generic, return @Tuple(&new_types);
.child = elem_field.type, } else {
.is_allowzero = false, return @Struct(.auto, null, &new_names, &new_types, &@splat(.{}));
.sentinel_ptr = null,
} });
new_field.* = .{
.name = elem_field.name,
.type = T,
.default_value_ptr = null,
.is_comptime = false,
.alignment = @alignOf(T),
};
} }
return @Type(.{ .@"struct" = .{
.layout = .auto,
.fields = &new_fields,
.decls = &.{},
.is_tuple = elem_info.is_tuple,
} });
} }
pub fn addOne(mutable: Mutable) Allocator.Error!PtrElem(.{ .size = .one }) { pub fn addOne(mutable: Mutable) Allocator.Error!PtrElem(.{ .size = .one }) {

View file

@ -23904,7 +23904,7 @@ fn analyzeShuffle(
const b_src = block.builtinCallArgSrc(src_node, 2); const b_src = block.builtinCallArgSrc(src_node, 2);
const mask_src = block.builtinCallArgSrc(src_node, 3); 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. // this is 0, because it is an error to index into this vector.
const a_len: u32 = switch (sema.typeOf(a_uncoerced).zigTypeTag(zcu)) { const a_len: u32 = switch (sema.typeOf(a_uncoerced).zigTypeTag(zcu)) {
.array, .vector => @intCast(sema.typeOf(a_uncoerced).arrayLen(zcu)), .array, .vector => @intCast(sema.typeOf(a_uncoerced).arrayLen(zcu)),
@ -23916,7 +23916,7 @@ fn analyzeShuffle(
const a_ty = try pt.vectorType(.{ .len = a_len, .child = elem_ty.toIntern() }); 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); 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)) { const b_len: u32 = switch (sema.typeOf(b_uncoerced).zigTypeTag(zcu)) {
.array, .vector => @intCast(sema.typeOf(b_uncoerced).arrayLen(zcu)), .array, .vector => @intCast(sema.typeOf(b_uncoerced).arrayLen(zcu)),
.undefined => 0, .undefined => 0,

View file

@ -120,23 +120,13 @@ const matchers = matchers: {
); );
var symbols: Symbols: { var symbols: Symbols: {
const symbols = @typeInfo(@TypeOf(instruction.symbols)).@"struct".fields; const symbols = @typeInfo(@TypeOf(instruction.symbols)).@"struct".fields;
var symbol_fields: [symbols.len]std.builtin.Type.StructField = undefined; var field_names: [symbols.len][]const u8 = undefined;
for (&symbol_fields, symbols) |*symbol_field, symbol| { var field_types: [symbols.len]type = undefined;
const Storage = zonCast(SymbolSpec, @field(instruction.symbols, symbol.name), .{}).Storage(); for (symbols, &field_names, &field_types) |symbol, *field_name, *FieldType| {
symbol_field.* = .{ field_name.* = symbol.name;
.name = symbol.name, FieldType.* = zonCast(SymbolSpec, @field(instruction.symbols, symbol.name), .{}).Storage();
.type = Storage,
.default_value_ptr = null,
.is_comptime = false,
.alignment = @alignOf(Storage),
};
} }
break :Symbols @Type(.{ .@"struct" = .{ break :Symbols @Struct(.auto, null, &field_names, &field_types, &@splat(.{}));
.layout = .auto,
.fields = &symbol_fields,
.decls = &.{},
.is_tuple = false,
} });
} = undefined; } = undefined;
const Symbol = std.meta.FieldEnum(@TypeOf(instruction.symbols)); const Symbol = std.meta.FieldEnum(@TypeOf(instruction.symbols));
comptime var unused_symbols: std.enums.EnumSet(Symbol) = .initFull(); comptime var unused_symbols: std.enums.EnumSet(Symbol) = .initFull();
@ -334,7 +324,7 @@ const SymbolSpec = union(enum) {
.reg => aarch64.encoding.Register, .reg => aarch64.encoding.Register,
.arrangement => aarch64.encoding.Register.Arrangement, .arrangement => aarch64.encoding.Register.Arrangement,
.systemreg => aarch64.encoding.Register.System, .systemreg => aarch64.encoding.Register.System,
.imm => |imm_spec| @Type(.{ .int = imm_spec.type }), .imm => |imm_spec| @Int(imm_spec.type.signedness, imm_spec.type.bits),
.fimm => f16, .fimm => f16,
.extend => Instruction.DataProcessingRegister.AddSubtractExtendedRegister.Option, .extend => Instruction.DataProcessingRegister.AddSubtractExtendedRegister.Option,
.shift => Instruction.DataProcessingRegister.Shift.Op, .shift => Instruction.DataProcessingRegister.Shift.Op,
@ -413,13 +403,13 @@ const SymbolSpec = union(enum) {
return systemreg; return systemreg;
}, },
.imm => |imm_spec| { .imm => |imm_spec| {
const imm = std.fmt.parseInt(@Type(.{ .int = .{ const imm = std.fmt.parseInt(@Int(
.signedness = imm_spec.type.signedness, imm_spec.type.signedness,
.bits = switch (imm_spec.adjust) { switch (imm_spec.adjust) {
.none, .neg_wrap => imm_spec.type.bits, .none, .neg_wrap => imm_spec.type.bits,
.dec => imm_spec.type.bits + 1, .dec => imm_spec.type.bits + 1,
}, },
} }), token, 0) catch { ), token, 0) catch {
log.debug("invalid immediate: \"{f}\"", .{std.zig.fmtString(token)}); log.debug("invalid immediate: \"{f}\"", .{std.zig.fmtString(token)});
return null; return null;
}; };

View file

@ -8928,12 +8928,16 @@ pub const Value = struct {
constant: Constant, constant: Constant,
pub const Tag = @typeInfo(Parent).@"union".tag_type.?; pub const Tag = @typeInfo(Parent).@"union".tag_type.?;
pub const Payload = @Type(.{ .@"union" = .{ pub const Payload = Payload: {
.layout = .auto, const fields = @typeInfo(Parent).@"union".fields;
.tag_type = null, var types: [fields.len]type = undefined;
.fields = @typeInfo(Parent).@"union".fields, var names: [fields.len][]const u8 = undefined;
.decls = &.{}, for (fields, &types, &names) |f, *ty, *name| {
} }); ty.* = f.type;
name.* = f.name;
}
break :Payload @Union(.auto, null, &names, &types, &@splat(.{}));
};
}; };
pub const Location = union(enum(u1)) { pub const Location = union(enum(u1)) {
@ -8949,12 +8953,16 @@ pub const Value = struct {
}, },
pub const Tag = @typeInfo(Location).@"union".tag_type.?; pub const Tag = @typeInfo(Location).@"union".tag_type.?;
pub const Payload = @Type(.{ .@"union" = .{ pub const Payload = Payload: {
.layout = .auto, const fields = @typeInfo(Location).@"union".fields;
.tag_type = null, var types: [fields.len]type = undefined;
.fields = @typeInfo(Location).@"union".fields, var names: [fields.len][]const u8 = undefined;
.decls = &.{}, for (fields, &types, &names) |f, *ty, *name| {
} }); ty.* = f.type;
name.* = f.name;
}
break :Payload @Union(.auto, null, &names, &types, &@splat(.{}));
};
}; };
pub const Indirect = packed struct(u32) { pub const Indirect = packed struct(u32) {
@ -11210,7 +11218,7 @@ pub const Value = struct {
.storage = .{ .u64 = switch (size) { .storage = .{ .u64 = switch (size) {
else => unreachable, else => unreachable,
inline 1...8 => |ct_size| std.mem.readInt( inline 1...8 => |ct_size| std.mem.readInt(
@Type(.{ .int = .{ .signedness = .unsigned, .bits = 8 * ct_size } }), @Int(.unsigned, 8 * ct_size),
buffer[@intCast(offset)..][0..ct_size], buffer[@intCast(offset)..][0..ct_size],
isel.target.cpu.arch.endian(), isel.target.cpu.arch.endian(),
), ),
@ -11438,7 +11446,7 @@ fn writeKeyToMemory(isel: *Select, constant_key: InternPool.Key, buffer: []u8) e
switch (buffer.len) { switch (buffer.len) {
else => unreachable, else => unreachable,
inline 1...4 => |size| std.mem.writeInt( inline 1...4 => |size| std.mem.writeInt(
@Type(.{ .int = .{ .signedness = .unsigned, .bits = 8 * size } }), @Int(.unsigned, 8 * size),
buffer[0..size], buffer[0..size],
@intCast(error_int), @intCast(error_int),
isel.target.cpu.arch.endian(), isel.target.cpu.arch.endian(),

View file

@ -189867,9 +189867,7 @@ const Select = struct {
} }
fn adjustedImm(op: Select.Operand, comptime SignedImm: type, s: *const Select) SignedImm { fn adjustedImm(op: Select.Operand, comptime SignedImm: type, s: *const Select) SignedImm {
const UnsignedImm = @Type(.{ const UnsignedImm = @Int(.unsigned, @typeInfo(SignedImm).int.bits);
.int = .{ .signedness = .unsigned, .bits = @typeInfo(SignedImm).int.bits },
});
const lhs: SignedImm = lhs: switch (op.flags.adjust.lhs) { const lhs: SignedImm = lhs: switch (op.flags.adjust.lhs) {
.none => 0, .none => 0,
.ptr_size => @divExact(s.cg.target.ptrBitWidth(), 8), .ptr_size => @divExact(s.cg.target.ptrBitWidth(), 8),
@ -189934,10 +189932,10 @@ const Select = struct {
const RefImm = switch (size) { const RefImm = switch (size) {
else => comptime unreachable, else => comptime unreachable,
.none => Imm, .none => Imm,
.byte, .word, .dword, .qword => @Type(comptime .{ .int = .{ .byte, .word, .dword, .qword => @Int(
.signedness = @typeInfo(Imm).int.signedness, @typeInfo(Imm).int.signedness,
.bits = size.bitSize(undefined), size.bitSize(undefined),
} }), ),
}; };
break :lhs @bitCast(@as(Imm, @intCast(@as(RefImm, switch (adjust) { break :lhs @bitCast(@as(Imm, @intCast(@as(RefImm, switch (adjust) {
else => comptime unreachable, else => comptime unreachable,

View file

@ -708,7 +708,7 @@ pub fn emitMir(emit: *Emit) Error!void {
switch (reloc.source_length) { switch (reloc.source_length) {
else => unreachable, else => unreachable,
inline 1, 4 => |source_length| std.mem.writeInt( 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], inst_bytes[reloc.source_offset..][0..source_length],
@intCast(disp), @intCast(disp),
.little, .little,

View file

@ -51,10 +51,7 @@ pub const Diags = struct {
const Int = blk: { const Int = blk: {
const bits = @typeInfo(@This()).@"struct".fields.len; const bits = @typeInfo(@This()).@"struct".fields.len;
break :blk @Type(.{ .int = .{ break :blk @Int(.unsigned, bits);
.signedness = .unsigned,
.bits = bits,
} });
}; };
pub fn anySet(ef: Flags) bool { pub fn anySet(ef: Flags) bool {

View file

@ -5130,25 +5130,23 @@ pub fn resolveRelocs(dwarf: *Dwarf) RelocError!void {
fn DeclValEnum(comptime T: type) type { fn DeclValEnum(comptime T: type) type {
const decls = @typeInfo(T).@"struct".decls; const decls = @typeInfo(T).@"struct".decls;
@setEvalBranchQuota(7 * decls.len); @setEvalBranchQuota(10 * decls.len);
var fields: [decls.len]std.builtin.Type.EnumField = undefined; var field_names: [decls.len][]const u8 = undefined;
var fields_len = 0; var fields_len = 0;
var min_value: ?comptime_int = null; var min_value: ?comptime_int = null;
var max_value: ?comptime_int = null; var max_value: ?comptime_int = null;
for (decls) |decl| { for (decls) |decl| {
if (std.mem.startsWith(u8, decl.name, "HP_") or std.mem.endsWith(u8, decl.name, "_user")) continue; if (std.mem.startsWith(u8, decl.name, "HP_") or std.mem.endsWith(u8, decl.name, "_user")) continue;
const value = @field(T, decl.name); const value = @field(T, decl.name);
fields[fields_len] = .{ .name = decl.name, .value = value }; field_names[fields_len] = decl.name;
fields_len += 1; fields_len += 1;
if (min_value == null or min_value.? > value) min_value = value; if (min_value == null or min_value.? > value) min_value = value;
if (max_value == null or max_value.? < value) max_value = value; if (max_value == null or max_value.? < value) max_value = value;
} }
return @Type(.{ .@"enum" = .{ const TagInt = std.math.IntFittingRange(min_value orelse 0, max_value orelse 0);
.tag_type = std.math.IntFittingRange(min_value orelse 0, max_value orelse 0), var field_vals: [fields_len]TagInt = undefined;
.fields = fields[0..fields_len], for (field_names[0..fields_len], &field_vals) |name, *val| val.* = @field(T, name);
.decls = &.{}, return @Enum(TagInt, .exhaustive, field_names[0..fields_len], &field_vals);
.is_exhaustive = true,
} });
} }
const AbbrevCode = enum { const AbbrevCode = enum {
@ -6382,10 +6380,12 @@ fn freeCommonEntry(
fn writeInt(dwarf: *Dwarf, buf: []u8, int: u64) void { fn writeInt(dwarf: *Dwarf, buf: []u8, int: u64) void {
switch (buf.len) { switch (buf.len) {
inline 0...8 => |len| std.mem.writeInt(@Type(.{ .int = .{ inline 0...8 => |len| std.mem.writeInt(
.signedness = .unsigned, @Int(.unsigned, len * 8),
.bits = len * 8, buf[0..len],
} }), buf[0..len], @intCast(int), dwarf.endian), @intCast(int),
dwarf.endian,
),
else => unreachable, else => unreachable,
} }
} }

View file

@ -108,10 +108,7 @@ pub const Node = extern struct {
has_content: bool, has_content: bool,
/// Whether a moved event on this node bubbles down to children. /// Whether a moved event on this node bubbles down to children.
bubbles_moved: bool, bubbles_moved: bool,
unused: @Type(.{ .int = .{ unused: @Int(.unsigned, 32 - @bitSizeOf(std.mem.Alignment) - 6) = 0,
.signedness = .unsigned,
.bits = 32 - @bitSizeOf(std.mem.Alignment) - 6,
} }) = 0,
}; };
pub const Location = union(enum(u1)) { pub const Location = union(enum(u1)) {
@ -122,19 +119,14 @@ pub const Node = extern struct {
}, },
large: extern struct { large: extern struct {
index: usize, index: usize,
unused: @Type(.{ .int = .{ unused: @Int(.unsigned, 64 - @bitSizeOf(usize)) = 0,
.signedness = .unsigned,
.bits = 64 - @bitSizeOf(usize),
} }) = 0,
}, },
pub const Tag = @typeInfo(Location).@"union".tag_type.?; pub const Tag = @typeInfo(Location).@"union".tag_type.?;
pub const Payload = @Type(.{ .@"union" = .{ pub const Payload = extern union {
.layout = .@"extern", small: @FieldType(Location, "small"),
.tag_type = null, large: @FieldType(Location, "large"),
.fields = @typeInfo(Location).@"union".fields, };
.decls = &.{},
} });
pub fn resolve(loc: Location, mf: *const MappedFile) [2]u64 { pub fn resolve(loc: Location, mf: *const MappedFile) [2]u64 {
return switch (loc) { return switch (loc) {

View file

@ -136,7 +136,7 @@ var log_scopes: std.ArrayList([]const u8) = .empty;
pub fn log( pub fn log(
comptime level: std.log.Level, comptime level: std.log.Level,
comptime scope: @Type(.enum_literal), comptime scope: @EnumLiteral(),
comptime format: []const u8, comptime format: []const u8,
args: anytype, args: anytype,
) void { ) void {

View file

@ -1264,12 +1264,9 @@ test "reference to inferred local variable works as expected" {
try expect(crasher_local.lets_crash != a.lets_crash); try expect(crasher_local.lets_crash != a.lets_crash);
} }
test "@Type returned from block" { test "@Int returned from block" {
const T = comptime b: { const T = comptime b: {
break :b @Type(.{ .int = .{ break :b @Int(.unsigned, 8);
.signedness = .unsigned,
.bits = 8,
} });
}; };
try std.testing.expect(T == u8); try std.testing.expect(T == u8);
} }

View file

@ -119,21 +119,12 @@ test "Saturating Shift Left where lhs is of a computed type" {
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
const S = struct { 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 { pub fn FixedPoint(comptime ValueType: type) type {
return struct { return struct {
value: ValueType, value: ValueType,
exponent: ShiftType, 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() { pub fn shiftExponent(self: @This(), shift: ShiftType) @This() {
const shiftAbs = @abs(shift); const shiftAbs = @abs(shift);

View file

@ -355,7 +355,7 @@ test "inline call doesn't re-evaluate non generic struct" {
try comptime @call(.always_inline, S.foo, ArgTuple{.{ .a = 123, .b = 45 }}); 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 S = struct {
const E = std.meta.FieldEnum(struct { const E = std.meta.FieldEnum(struct {
prev_pos: bool, prev_pos: bool,

View file

@ -2446,9 +2446,14 @@ test "peer type resolution: pointer attributes are combined correctly" {
}; };
const NonAllowZero = comptime blk: { const NonAllowZero = comptime blk: {
var ti = @typeInfo(@TypeOf(r1, r2, r3, r4)); const ptr = @typeInfo(@TypeOf(r1, r2, r3, r4)).pointer;
ti.pointer.is_allowzero = false; break :blk @Pointer(ptr.size, .{
break :blk @Type(ti); .@"const" = ptr.is_const,
.@"volatile" = ptr.is_volatile,
.@"allowzero" = false,
.@"align" = ptr.alignment,
.@"addrspace" = ptr.address_space,
}, ptr.child, ptr.sentinel());
}; };
try expectEqualSlices(u8, std.mem.span(@volatileCast(@as(NonAllowZero, @ptrCast(r1)))), "foo"); try expectEqualSlices(u8, std.mem.span(@volatileCast(@as(NonAllowZero, @ptrCast(r1)))), "foo");
try expectEqualSlices(u8, std.mem.span(@volatileCast(@as(NonAllowZero, @ptrCast(r2)))), "bar"); try expectEqualSlices(u8, std.mem.span(@volatileCast(@as(NonAllowZero, @ptrCast(r2)))), "bar");

View file

@ -1283,10 +1283,7 @@ test "Non-exhaustive enum backed by comptime_int" {
test "matching captures causes enum equivalence" { test "matching captures causes enum equivalence" {
const S = struct { const S = struct {
fn Nonexhaustive(comptime I: type) type { fn Nonexhaustive(comptime I: type) type {
const UTag = @Type(.{ .int = .{ const UTag = @Int(.unsigned, @typeInfo(I).int.bits);
.signedness = .unsigned,
.bits = @typeInfo(I).int.bits,
} });
return enum(UTag) { _ }; return enum(UTag) { _ };
} }
}; };

View file

@ -556,10 +556,10 @@ test "lazy values passed to anytype parameter" {
test "pass and return comptime-only types" { test "pass and return comptime-only types" {
const S = struct { const S = struct {
fn returnNull(comptime x: @Type(.null)) @Type(.null) { fn returnNull(comptime x: @TypeOf(null)) @TypeOf(null) {
return x; return x;
} }
fn returnUndefined(comptime x: @Type(.undefined)) @Type(.undefined) { fn returnUndefined(comptime x: @TypeOf(undefined)) @TypeOf(undefined) {
return x; return x;
} }
}; };

View file

@ -263,15 +263,7 @@ test "generic function instantiation turns into comptime call" {
pub fn FieldEnum(comptime T: type) type { pub fn FieldEnum(comptime T: type) type {
_ = T; _ = T;
var enumFields: [1]std.builtin.Type.EnumField = .{.{ .name = "A", .value = 0 }}; return @Enum(u0, .exhaustive, &.{"A"}, &.{0});
return @Type(.{
.@"enum" = .{
.tag_type = u0,
.fields = &enumFields,
.decls = &.{},
.is_exhaustive = true,
},
});
} }
}; };
try S.doTheTest(); try S.doTheTest();

View file

@ -338,14 +338,14 @@ test "peer type resolution with @TypeOf doesn't trigger dependency loop check" {
test "@sizeOf reified union zero-size payload fields" { test "@sizeOf reified union zero-size payload fields" {
comptime { comptime {
try std.testing.expect(0 == @sizeOf(@Type(@typeInfo(union {})))); try std.testing.expect(0 == @sizeOf(@Union(.auto, null, &.{}, &.{}, &.{})));
try std.testing.expect(0 == @sizeOf(@Type(@typeInfo(union { a: void })))); try std.testing.expect(0 == @sizeOf(@Union(.auto, null, &.{"a"}, &.{void}, &.{.{}})));
if (builtin.mode == .Debug or builtin.mode == .ReleaseSafe) { 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(@Union(.auto, null, &.{ "a", "b" }, &.{ void, void }, &.{ .{}, .{} })));
try std.testing.expect(1 == @sizeOf(@Type(@typeInfo(union { a: void, b: void, c: void })))); try std.testing.expect(1 == @sizeOf(@Union(.auto, null, &.{ "a", "b", "c" }, &.{ void, void, void }, &.{ .{}, .{}, .{} })));
} else { } else {
try std.testing.expect(0 == @sizeOf(@Type(@typeInfo(union { a: void, b: void })))); try std.testing.expect(0 == @sizeOf(@Union(.auto, null, &.{ "a", "b" }, &.{ void, void }, &.{ .{}, .{} })));
try std.testing.expect(0 == @sizeOf(@Type(@typeInfo(union { a: void, b: void, c: void })))); try std.testing.expect(0 == @sizeOf(@Union(.auto, null, &.{ "a", "b", "c" }, &.{ void, void, void }, &.{ .{}, .{}, .{} })));
} }
} }
} }

View file

@ -2034,10 +2034,7 @@ test "matching captures causes struct equivalence" {
fn UnsignedWrapper(comptime I: type) type { fn UnsignedWrapper(comptime I: type) type {
const bits = @typeInfo(I).int.bits; const bits = @typeInfo(I).int.bits;
return struct { return struct {
x: @Type(.{ .int = .{ x: @Int(.unsigned, bits),
.signedness = .unsigned,
.bits = bits,
} }),
}; };
} }
}; };

View file

@ -843,7 +843,8 @@ test "switch capture peer type resolution for in-memory coercible payloads" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
const T1 = c_int; 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); comptime assert(T1 != T2);
@ -865,7 +866,8 @@ test "switch pointer capture peer type resolution" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
const T1 = c_int; 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); comptime assert(T1 != T2);

View file

@ -230,10 +230,7 @@ test "switch loop on larger than pointer integer" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
var entry: @Type(.{ .int = .{ var entry: @Int(.unsigned, @bitSizeOf(usize) + 1) = undefined;
.signedness = .unsigned,
.bits = @bitSizeOf(usize) + 1,
} }) = undefined;
entry = 0; entry = 0;
loop: switch (entry) { loop: switch (entry) {
0 => { 0 => {

View file

@ -130,29 +130,7 @@ test "array-like initializer for tuple types" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const T = @Type(.{ const T = @Tuple(&.{ i32, u8 });
.@"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 S = struct { const S = struct {
fn doTheTest() !void { fn doTheTest() !void {
var obj: T = .{ -1234, 128 }; var obj: T = .{ -1234, 128 };
@ -320,20 +298,7 @@ test "zero sized struct in tuple handled correctly" {
const Self = @This(); const Self = @This();
const Inner = struct {}; const Inner = struct {};
data: @Type(.{ data: @Tuple(&.{Inner}),
.@"struct" = .{
.is_tuple = true,
.layout = .auto,
.decls = &.{},
.fields = &.{.{
.name = "0",
.type = Inner,
.default_value_ptr = null,
.is_comptime = false,
.alignment = @alignOf(Inner),
}},
},
}),
pub fn do(this: Self) usize { pub fn do(this: Self) usize {
return @sizeOf(@TypeOf(this)); return @sizeOf(@TypeOf(this));
@ -470,12 +435,7 @@ test "coerce anon tuple to tuple" {
} }
test "empty tuple type" { test "empty tuple type" {
const S = @Type(.{ .@"struct" = .{ const S = @Tuple(&.{});
.layout = .auto,
.fields = &.{},
.decls = &.{},
.is_tuple = true,
} });
const s: S = .{}; const s: S = .{};
try expect(s.len == 0); try expect(s.len == 0);
@ -616,18 +576,7 @@ test "OPV tuple fields aren't comptime" {
const t_info = @typeInfo(T); const t_info = @typeInfo(T);
try expect(!t_info.@"struct".fields[0].is_comptime); try expect(!t_info.@"struct".fields[0].is_comptime);
const T2 = @Type(.{ .@"struct" = .{ const T2 = @Tuple(&.{void});
.layout = .auto,
.fields = &.{.{
.name = "0",
.type = void,
.default_value_ptr = null,
.is_comptime = false,
.alignment = @alignOf(void),
}},
.decls = &.{},
.is_tuple = true,
} });
const t2_info = @typeInfo(T2); const t2_info = @typeInfo(T2);
try expect(!t2_info.@"struct".fields[0].is_comptime); try expect(!t2_info.@"struct".fields[0].is_comptime);
} }

View file

@ -4,63 +4,17 @@ const Type = std.builtin.Type;
const testing = std.testing; const testing = std.testing;
const assert = std.debug.assert; 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" { test "Type.Int" {
try testing.expect(u1 == @Type(.{ .int = .{ .signedness = .unsigned, .bits = 1 } })); try testing.expect(u1 == @Int(.unsigned, 1));
try testing.expect(i1 == @Type(.{ .int = .{ .signedness = .signed, .bits = 1 } })); try testing.expect(i1 == @Int(.signed, 1));
try testing.expect(u8 == @Type(.{ .int = .{ .signedness = .unsigned, .bits = 8 } })); try testing.expect(u8 == @Int(.unsigned, 8));
try testing.expect(i8 == @Type(.{ .int = .{ .signedness = .signed, .bits = 8 } })); try testing.expect(i8 == @Int(.signed, 8));
try testing.expect(u64 == @Type(.{ .int = .{ .signedness = .unsigned, .bits = 64 } })); try testing.expect(u64 == @Int(.unsigned, 64));
try testing.expect(i64 == @Type(.{ .int = .{ .signedness = .signed, .bits = 64 } })); try testing.expect(i64 == @Int(.signed, 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),
});
} }
test "Type.Pointer" { test "Type.Pointer" {
try testTypes(&[_]type{ inline for (&[_]type{
// One Value Pointer Types // One Value Pointer Types
*u8, *const u8, *u8, *const u8,
*volatile u8, *const volatile u8, *volatile u8, *const volatile u8,
@ -101,62 +55,30 @@ test "Type.Pointer" {
[*c]align(4) volatile u8, [*c]align(4) const volatile u8, [*c]align(4) volatile u8, [*c]align(4) const volatile u8,
[*c]align(8) u8, [*c]align(8) const u8, [*c]align(8) u8, [*c]align(8) const u8,
[*c]align(8) volatile u8, [*c]align(8) const volatile u8, [*c]align(8) volatile u8, [*c]align(8) const volatile u8,
}); }) |testType| {
const ptr = @typeInfo(testType).pointer;
try testing.expect(testType == @Pointer(ptr.size, .{
.@"const" = ptr.is_const,
.@"volatile" = ptr.is_volatile,
.@"allowzero" = ptr.is_allowzero,
.@"align" = ptr.alignment,
.@"addrspace" = ptr.address_space,
}, ptr.child, ptr.sentinel()));
}
} }
test "Type.Float" { test "@Pointer create slice without sentinel" {
try testing.expect(f16 == @Type(.{ .float = .{ .bits = 16 } })); const Slice = @Pointer(.slice, .{ .@"const" = true, .@"align" = 8 }, ?*i32, null);
try testing.expect(f32 == @Type(.{ .float = .{ .bits = 32 } })); try testing.expect(Slice == []align(8) const ?*i32);
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" { test "@Pointer create slice with null sentinel" {
try testing.expect([123]u8 == @Type(.{ const Slice = @Pointer(.slice, .{ .@"const" = true, .@"align" = 8 }, ?*i32, @as(?*i32, null));
.array = .{ try testing.expect(Slice == [:null]align(8) const ?*i32);
.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 });
} }
test "@Type create slice with null sentinel" { test "@Pointer on @typeInfo round-trips sentinels" {
const Slice = @Type(.{ inline for (&[_]type{
.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,
[*:0]u8, [*:0]const u8, [*:0]u8, [*:0]const u8,
[*:0]volatile u8, [*:0]const volatile u8, [*:0]volatile u8, [*:0]const volatile u8,
[*:0]align(4) u8, [*:0]align(4) const u8, [*:0]align(4) u8, [*:0]align(4) const u8,
@ -179,24 +101,16 @@ test "@Type picks up the sentinel value from Type" {
[:0]allowzero align(4) u8, [:0]allowzero align(4) const u8, [:0]allowzero align(4) u8, [:0]allowzero align(4) const u8,
[:0]allowzero align(4) volatile u8, [:0]allowzero align(4) const volatile 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, [:4]allowzero align(4) volatile u8, [:4]allowzero align(4) const volatile u8,
}); }) |TestType| {
} const ptr = @typeInfo(TestType).pointer;
try testing.expect(TestType == @Pointer(ptr.size, .{
test "Type.Optional" { .@"const" = ptr.is_const,
try testTypes(&[_]type{ .@"volatile" = ptr.is_volatile,
?u8, .@"allowzero" = ptr.is_allowzero,
?*u8, .@"align" = ptr.alignment,
?[]u8, .@"addrspace" = ptr.address_space,
?[*]u8, }, ptr.child, ptr.sentinel()));
?[*c]u8, }
});
}
test "Type.ErrorUnion" {
try testTypes(&[_]type{
error{}!void,
error{Error}!void,
});
} }
test "Type.Opaque" { test "Type.Opaque" {
@ -205,11 +119,7 @@ test "Type.Opaque" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const Opaque = @Type(.{ const Opaque = opaque {};
.@"opaque" = .{
.decls = &.{},
},
});
try testing.expect(Opaque != opaque {}); try testing.expect(Opaque != opaque {});
try testing.expectEqualSlices( try testing.expectEqualSlices(
Type.Declaration, Type.Declaration,
@ -218,52 +128,17 @@ test "Type.Opaque" {
); );
} }
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;
}
try testTypes(&[_]type{
anyframe,
anyframe->u8,
anyframe->anyframe->u8,
});
}
fn add(a: i32, b: i32) i32 { fn add(a: i32, b: i32) i32 {
return a + b; 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" { test "Type.Struct" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const A = @Type(@typeInfo(struct { x: u8, y: u32 })); const A = @Struct(.auto, null, &.{ "x", "y" }, &.{ u8, u32 }, &@splat(.{}));
const infoA = @typeInfo(A).@"struct"; const infoA = @typeInfo(A).@"struct";
try testing.expectEqual(Type.ContainerLayout.auto, infoA.layout); try testing.expectEqual(Type.ContainerLayout.auto, infoA.layout);
try testing.expectEqualSlices(u8, "x", infoA.fields[0].name); try testing.expectEqualSlices(u8, "x", infoA.fields[0].name);
@ -281,7 +156,13 @@ test "Type.Struct" {
a.y += 1; a.y += 1;
try testing.expectEqual(@as(u32, 2), a.y); try testing.expectEqual(@as(u32, 2), a.y);
const B = @Type(@typeInfo(extern struct { x: u8, y: u32 = 5 })); const B = @Struct(
.@"extern",
null,
&.{ "x", "y" },
&.{ u8, u32 },
&.{ .{}, .{ .default_value_ptr = &@as(u32, 5) } },
);
const infoB = @typeInfo(B).@"struct"; const infoB = @typeInfo(B).@"struct";
try testing.expectEqual(Type.ContainerLayout.@"extern", infoB.layout); try testing.expectEqual(Type.ContainerLayout.@"extern", infoB.layout);
try testing.expectEqualSlices(u8, "x", infoB.fields[0].name); try testing.expectEqualSlices(u8, "x", infoB.fields[0].name);
@ -293,7 +174,16 @@ test "Type.Struct" {
try testing.expectEqual(@as(usize, 0), infoB.decls.len); try testing.expectEqual(@as(usize, 0), infoB.decls.len);
try testing.expectEqual(@as(bool, false), infoB.is_tuple); try testing.expectEqual(@as(bool, false), infoB.is_tuple);
const C = @Type(@typeInfo(packed struct { x: u8 = 3, y: u32 = 5 })); const C = @Struct(
.@"packed",
null,
&.{ "x", "y" },
&.{ u8, u32 },
&.{
.{ .default_value_ptr = &@as(u8, 3) },
.{ .default_value_ptr = &@as(u32, 5) },
},
);
const infoC = @typeInfo(C).@"struct"; const infoC = @typeInfo(C).@"struct";
try testing.expectEqual(Type.ContainerLayout.@"packed", infoC.layout); try testing.expectEqual(Type.ContainerLayout.@"packed", infoC.layout);
try testing.expectEqualSlices(u8, "x", infoC.fields[0].name); try testing.expectEqualSlices(u8, "x", infoC.fields[0].name);
@ -305,76 +195,23 @@ test "Type.Struct" {
try testing.expectEqual(@as(usize, 0), infoC.decls.len); try testing.expectEqual(@as(usize, 0), infoC.decls.len);
try testing.expectEqual(@as(bool, false), infoC.is_tuple); try testing.expectEqual(@as(bool, false), infoC.is_tuple);
// anon structs
const D = @Type(@typeInfo(@TypeOf(.{ .x = 3, .y = 5 })));
const infoD = @typeInfo(D).@"struct";
try testing.expectEqual(Type.ContainerLayout.auto, infoD.layout);
try testing.expectEqualSlices(u8, "x", infoD.fields[0].name);
try testing.expectEqual(comptime_int, infoD.fields[0].type);
try testing.expectEqual(@as(comptime_int, 3), infoD.fields[0].defaultValue().?);
try testing.expectEqualSlices(u8, "y", infoD.fields[1].name);
try testing.expectEqual(comptime_int, infoD.fields[1].type);
try testing.expectEqual(@as(comptime_int, 5), infoD.fields[1].defaultValue().?);
try testing.expectEqual(@as(usize, 0), infoD.decls.len);
try testing.expectEqual(@as(bool, false), infoD.is_tuple);
// tuples
const E = @Type(@typeInfo(@TypeOf(.{ 1, 2 })));
const infoE = @typeInfo(E).@"struct";
try testing.expectEqual(Type.ContainerLayout.auto, infoE.layout);
try testing.expectEqualSlices(u8, "0", infoE.fields[0].name);
try testing.expectEqual(comptime_int, infoE.fields[0].type);
try testing.expectEqual(@as(comptime_int, 1), infoE.fields[0].defaultValue().?);
try testing.expectEqualSlices(u8, "1", infoE.fields[1].name);
try testing.expectEqual(comptime_int, infoE.fields[1].type);
try testing.expectEqual(@as(comptime_int, 2), infoE.fields[1].defaultValue().?);
try testing.expectEqual(@as(usize, 0), infoE.decls.len);
try testing.expectEqual(@as(bool, true), infoE.is_tuple);
// empty struct // empty struct
const F = @Type(@typeInfo(struct {})); const F = @Struct(.auto, null, &.{}, &.{}, &.{});
const infoF = @typeInfo(F).@"struct"; const infoF = @typeInfo(F).@"struct";
try testing.expectEqual(Type.ContainerLayout.auto, infoF.layout); try testing.expectEqual(Type.ContainerLayout.auto, infoF.layout);
try testing.expect(infoF.fields.len == 0); try testing.expect(infoF.fields.len == 0);
try testing.expectEqual(@as(bool, false), infoF.is_tuple); try testing.expectEqual(@as(bool, false), infoF.is_tuple);
// empty tuple
const G = @Type(@typeInfo(@TypeOf(.{})));
const infoG = @typeInfo(G).@"struct";
try testing.expectEqual(Type.ContainerLayout.auto, infoG.layout);
try testing.expect(infoG.fields.len == 0);
try testing.expectEqual(@as(bool, true), infoG.is_tuple);
} }
test "Type.Enum" { test "Type.Enum" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const Foo = @Type(.{ const Foo = @Enum(u8, .exhaustive, &.{ "a", "b" }, &.{ 1, 5 });
.@"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(true, @typeInfo(Foo).@"enum".is_exhaustive);
try testing.expectEqual(@as(u8, 1), @intFromEnum(Foo.a)); try testing.expectEqual(@as(u8, 1), @intFromEnum(Foo.a));
try testing.expectEqual(@as(u8, 5), @intFromEnum(Foo.b)); try testing.expectEqual(@as(u8, 5), @intFromEnum(Foo.b));
const Bar = @Type(.{ const Bar = @Enum(u32, .nonexhaustive, &.{ "a", "b" }, &.{ 1, 5 });
.@"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(false, @typeInfo(Bar).@"enum".is_exhaustive);
try testing.expectEqual(@as(u32, 1), @intFromEnum(Bar.a)); try testing.expectEqual(@as(u32, 1), @intFromEnum(Bar.a));
try testing.expectEqual(@as(u32, 5), @intFromEnum(Bar.b)); try testing.expectEqual(@as(u32, 5), @intFromEnum(Bar.b));
@ -382,12 +219,7 @@ test "Type.Enum" {
{ // from https://github.com/ziglang/zig/issues/19985 { // from https://github.com/ziglang/zig/issues/19985
{ // enum with single field can be initialized. { // enum with single field can be initialized.
const E = @Type(.{ .@"enum" = .{ const E = @Enum(u0, .exhaustive, &.{"foo"}, &.{0});
.tag_type = u0,
.is_exhaustive = true,
.fields = &.{.{ .name = "foo", .value = 0 }},
.decls = &.{},
} });
const s: struct { E } = .{.foo}; const s: struct { E } = .{.foo};
try testing.expectEqual(.foo, s[0]); try testing.expectEqual(.foo, s[0]);
} }
@ -411,60 +243,20 @@ test "Type.Union" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
const Untagged = @Type(.{ const Untagged = @Union(.@"extern", null, &.{ "int", "float" }, &.{ i32, f32 }, &.{ .{}, .{} });
.@"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 }; var untagged = Untagged{ .int = 1 };
untagged.float = 2.0; untagged.float = 2.0;
untagged.int = 3; untagged.int = 3;
try testing.expectEqual(@as(i32, 3), untagged.int); try testing.expectEqual(@as(i32, 3), untagged.int);
const PackedUntagged = @Type(.{ const PackedUntagged = @Union(.@"packed", null, &.{ "signed", "unsigned" }, &.{ i32, u32 }, &.{ .{}, .{} });
.@"union" = .{
.layout = .@"packed",
.tag_type = null,
.fields = &.{
.{ .name = "signed", .type = i32, .alignment = 0 },
.{ .name = "unsigned", .type = u32, .alignment = 0 },
},
.decls = &.{},
},
});
var packed_untagged: PackedUntagged = .{ .signed = -1 }; var packed_untagged: PackedUntagged = .{ .signed = -1 };
_ = &packed_untagged; _ = &packed_untagged;
try testing.expectEqual(@as(i32, -1), packed_untagged.signed); try testing.expectEqual(@as(i32, -1), packed_untagged.signed);
try testing.expectEqual(~@as(u32, 0), packed_untagged.unsigned); try testing.expectEqual(~@as(u32, 0), packed_untagged.unsigned);
const Tag = @Type(.{ const Tag = @Enum(u1, .exhaustive, &.{ "signed", "unsigned" }, &.{ 0, 1 });
.@"enum" = .{ const Tagged = @Union(.auto, Tag, &.{ "signed", "unsigned" }, &.{ i32, u32 }, &.{ .{}, .{} });
.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 = &.{},
},
});
var tagged = Tagged{ .signed = -1 }; var tagged = Tagged{ .signed = -1 };
try testing.expectEqual(Tag.signed, @as(Tag, tagged)); try testing.expectEqual(Tag.signed, @as(Tag, tagged));
tagged = .{ .unsigned = 1 }; tagged = .{ .unsigned = 1 };
@ -472,74 +264,26 @@ test "Type.Union" {
} }
test "Type.Union from Type.Enum" { test "Type.Union from Type.Enum" {
const Tag = @Type(.{ const Tag = @Enum(u0, .exhaustive, &.{"working_as_expected"}, &.{0});
.@"enum" = .{ const T = @Union(.auto, Tag, &.{"working_as_expected"}, &.{u32}, &.{.{}});
.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 = &.{},
},
});
_ = @typeInfo(T).@"union"; _ = @typeInfo(T).@"union";
} }
test "Type.Union from regular enum" { test "Type.Union from regular enum" {
const E = enum { working_as_expected }; const E = enum { working_as_expected };
const T = @Type(.{ const T = @Union(.auto, E, &.{"working_as_expected"}, &.{u32}, &.{.{}});
.@"union" = .{
.layout = .auto,
.tag_type = E,
.fields = &.{
.{ .name = "working_as_expected", .type = u32, .alignment = @alignOf(u32) },
},
.decls = &.{},
},
});
_ = @typeInfo(T).@"union"; _ = @typeInfo(T).@"union";
} }
test "Type.Union from empty regular enum" { test "Type.Union from empty regular enum" {
const E = enum {}; const E = enum {};
const U = @Type(.{ const U = @Union(.auto, E, &.{}, &.{}, &.{});
.@"union" = .{
.layout = .auto,
.tag_type = E,
.fields = &.{},
.decls = &.{},
},
});
try testing.expectEqual(@sizeOf(U), 0); try testing.expectEqual(@sizeOf(U), 0);
} }
test "Type.Union from empty Type.Enum" { test "Type.Union from empty Type.Enum" {
const E = @Type(.{ const E = @Enum(u0, .exhaustive, &.{}, &.{});
.@"enum" = .{ const U = @Union(.auto, E, &.{}, &.{}, &.{});
.tag_type = u0,
.fields = &.{},
.decls = &.{},
.is_exhaustive = true,
},
});
const U = @Type(.{
.@"union" = .{
.layout = .auto,
.tag_type = E,
.fields = &.{},
.decls = &.{},
},
});
try testing.expectEqual(@sizeOf(U), 0); try testing.expectEqual(@sizeOf(U), 0);
} }
@ -548,47 +292,22 @@ test "Type.Fn" {
const some_opaque = opaque {}; const some_opaque = opaque {};
const some_ptr = *some_opaque; const some_ptr = *some_opaque;
const T = fn (c_int, some_ptr) callconv(.c) void;
{ const A = @Fn(&.{ c_int, some_ptr }, &@splat(.{}), void, .{ .@"callconv" = .c });
const fn_info = std.builtin.Type{ .@"fn" = .{ comptime assert(A == fn (c_int, some_ptr) callconv(.c) void);
.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); const B = @Fn(&.{ c_int, some_ptr, u32 }, &.{ .{}, .{ .@"noalias" = true }, .{} }, u64, .{});
try std.testing.expectEqual(T, fn_type); comptime assert(B == fn (c_int, noalias some_ptr, u32) u64);
}
{ const C = @Fn(&.{?[*]u8}, &.{.{}}, *const anyopaque, .{ .@"callconv" = .c, .varargs = true });
const fn_info = @typeInfo(T); comptime assert(C == fn (?[*]u8, ...) callconv(.c) *const anyopaque);
const fn_type = @Type(fn_info);
try std.testing.expectEqual(T, fn_type);
}
} }
test "reified struct field name from optional payload" { test "reified struct field name from optional payload" {
comptime { comptime {
const m_name: ?[1:0]u8 = "a".*; const m_name: ?[1:0]u8 = "a".*;
if (m_name) |*name| { if (m_name) |*name| {
const T = @Type(.{ .@"struct" = .{ const T = @Struct(.auto, null, &.{name}, &.{u8}, &.{.{}});
.layout = .auto,
.fields = &.{.{
.name = name,
.type = u8,
.default_value_ptr = null,
.is_comptime = false,
.alignment = 1,
}},
.decls = &.{},
.is_tuple = false,
} });
const t: T = .{ .a = 123 }; const t: T = .{ .a = 123 };
try std.testing.expect(t.a == 123); try std.testing.expect(t.a == 123);
} }
@ -598,20 +317,7 @@ test "reified struct field name from optional payload" {
test "reified union uses @alignOf" { test "reified union uses @alignOf" {
const S = struct { const S = struct {
fn CreateUnion(comptime T: type) type { fn CreateUnion(comptime T: type) type {
return @Type(.{ return @Union(.auto, null, &.{"field"}, &.{T}, &.{.{}});
.@"union" = .{
.layout = .auto,
.tag_type = null,
.fields = &[_]std.builtin.Type.UnionField{
.{
.name = "field",
.type = T,
.alignment = @alignOf(T),
},
},
.decls = &.{},
},
});
} }
}; };
_ = S.CreateUnion(struct {}); _ = S.CreateUnion(struct {});
@ -620,22 +326,13 @@ test "reified union uses @alignOf" {
test "reified struct uses @alignOf" { test "reified struct uses @alignOf" {
const S = struct { const S = struct {
fn NamespacedGlobals(comptime modules: anytype) type { fn NamespacedGlobals(comptime modules: anytype) type {
return @Type(.{ return @Struct(
.@"struct" = .{ .auto,
.layout = .auto, null,
.is_tuple = false, &.{"globals"},
.fields = &.{ &.{modules.mach.globals},
.{ &.{.{ .@"align" = @alignOf(modules.mach.globals) }},
.name = "globals", );
.type = modules.mach.globals,
.default_value_ptr = null,
.is_comptime = false,
.alignment = @alignOf(modules.mach.globals),
},
},
.decls = &.{},
},
});
} }
}; };
_ = S.NamespacedGlobals(.{ _ = S.NamespacedGlobals(.{
@ -645,56 +342,10 @@ 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" { test "empty struct assigned to reified struct field" {
const S = struct { const S = struct {
fn NamespacedComponents(comptime modules: anytype) type { fn NamespacedComponents(comptime modules: anytype) type {
return @Type(.{ return @Struct(.auto, null, &.{"components"}, &.{@TypeOf(modules.components)}, &.{.{}});
.@"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 = &.{},
},
});
} }
fn namespacedComponents(comptime modules: anytype) NamespacedComponents(modules) { fn namespacedComponents(comptime modules: anytype) NamespacedComponents(modules) {
@ -710,16 +361,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" { test "struct field names sliced at comptime from larger string" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
@ -729,28 +370,14 @@ test "struct field names sliced at comptime from larger string" {
\\f3 \\f3
; ;
comptime { comptime {
var fields: []const Type.StructField = &[0]Type.StructField{}; var field_names: []const []const u8 = &.{};
var it = std.mem.tokenizeScalar(u8, text, '\n'); var it = std.mem.tokenizeScalar(u8, text, '\n');
while (it.next()) |name| { while (it.next()) |name| {
fields = fields ++ &[_]Type.StructField{.{ field_names = field_names ++ @as([]const []const u8, &.{name});
.alignment = @alignOf(usize),
.name = name ++ "",
.type = usize,
.default_value_ptr = null,
.is_comptime = false,
}};
} }
const T = @Type(.{ const T = @Struct(.auto, null, field_names, &@splat(usize), &@splat(.{}));
.@"struct" = .{
.layout = .auto,
.is_tuple = false,
.fields = fields,
.decls = &.{},
},
});
const gen_fields = @typeInfo(T).@"struct".fields; const gen_fields = @typeInfo(T).@"struct".fields;
try testing.expectEqual(3, gen_fields.len); try testing.expectEqual(3, gen_fields.len);
try testing.expectEqualStrings("f1", gen_fields[0].name); try testing.expectEqualStrings("f1", gen_fields[0].name);
@ -762,10 +389,7 @@ test "struct field names sliced at comptime from larger string" {
test "matching captures causes opaque equivalence" { test "matching captures causes opaque equivalence" {
const S = struct { const S = struct {
fn UnsignedId(comptime I: type) type { fn UnsignedId(comptime I: type) type {
const U = @Type(.{ .int = .{ const U = @Int(.unsigned, @typeInfo(I).int.bits);
.signedness = .unsigned,
.bits = @typeInfo(I).int.bits,
} });
return opaque { return opaque {
fn id(x: U) U { fn id(x: U) U {
return x; return x;
@ -785,17 +409,9 @@ test "matching captures causes opaque equivalence" {
} }
test "reify enum where fields refers to part of array" { test "reify enum where fields refers to part of array" {
const fields: [3]std.builtin.Type.EnumField = .{ const field_names: [3][]const u8 = .{ "foo", "bar", undefined };
.{ .name = "foo", .value = 0 }, const field_values: [3]u8 = .{ undefined, 0, 1 };
.{ .name = "bar", .value = 1 }, const E = @Enum(u8, .exhaustive, field_names[0..2], field_values[1..3]);
undefined,
};
const E = @Type(.{ .@"enum" = .{
.tag_type = u8,
.fields = fields[0..2],
.decls = &.{},
.is_exhaustive = true,
} });
var a: E = undefined; var a: E = undefined;
var b: E = undefined; var b: E = undefined;
a = .foo; a = .foo;

View file

@ -2198,14 +2198,8 @@ test "matching captures causes union equivalence" {
fn SignedUnsigned(comptime I: type) type { fn SignedUnsigned(comptime I: type) type {
const bits = @typeInfo(I).int.bits; const bits = @typeInfo(I).int.bits;
return union { return union {
u: @Type(.{ .int = .{ u: @Int(.unsigned, bits),
.signedness = .unsigned, i: @Int(.signed, bits),
.bits = bits,
} }),
i: @Type(.{ .int = .{
.signedness = .signed,
.bits = bits,
} }),
}; };
} }
}; };

View file

@ -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 { pub fn AsSignedness(comptime Type: type, comptime signedness: std.builtin.Signedness) type {
return switch (@typeInfo(Scalar(Type))) { return switch (@typeInfo(Scalar(Type))) {
.int => |int| ChangeScalar(Type, @Type(.{ .int = .{ .int => |int| ChangeScalar(Type, @Int(signedness, int.bits)),
.signedness = signedness,
.bits = int.bits,
} })),
.float => Type, .float => Type,
else => @compileError(@typeName(Type)), else => @compileError(@typeName(Type)),
}; };
} }
pub fn AddOneBit(comptime Type: type) type { pub fn AddOneBit(comptime Type: type) type {
return ChangeScalar(Type, switch (@typeInfo(Scalar(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), .float => Scalar(Type),
else => @compileError(@typeName(Type)), else => @compileError(@typeName(Type)),
}); });
} }
pub fn DoubleBits(comptime Type: type) type { pub fn DoubleBits(comptime Type: type) type {
return ChangeScalar(Type, switch (@typeInfo(Scalar(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), .float => Scalar(Type),
else => @compileError(@typeName(Type)), else => @compileError(@typeName(Type)),
}); });
} }
pub fn RoundBitsUp(comptime Type: type, comptime multiple: u16) type { pub fn RoundBitsUp(comptime Type: type, comptime multiple: u16) type {
return ChangeScalar(Type, switch (@typeInfo(Scalar(Type))) { return ChangeScalar(Type, switch (@typeInfo(Scalar(Type))) {
.int => |int| @Type(.{ .int = .{ .int => |int| @Int(int.signedness, std.mem.alignForward(u16, int.bits, multiple)),
.signedness = int.signedness,
.bits = std.mem.alignForward(u16, int.bits, multiple),
} }),
.float => Scalar(Type), .float => Scalar(Type),
else => @compileError(@typeName(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) { pub fn sign(rhs: anytype) ChangeScalar(@TypeOf(rhs), bool) {
const Int = ChangeScalar(@TypeOf(rhs), switch (@typeInfo(Scalar(@TypeOf(rhs)))) { const Int = ChangeScalar(@TypeOf(rhs), switch (@typeInfo(Scalar(@TypeOf(rhs)))) {
.int, .comptime_int => Scalar(@TypeOf(rhs)), .int, .comptime_int => Scalar(@TypeOf(rhs)),
.float => |float| @Type(.{ .int = .{ .float => |float| @Int(.signed, float.bits),
.signedness = .signed,
.bits = float.bits,
} }),
else => @compileError(@typeName(@TypeOf(rhs))), else => @compileError(@typeName(@TypeOf(rhs))),
}); });
return @as(Int, @bitCast(rhs)) < splat(Int, 0); return @as(Int, @bitCast(rhs)) < splat(Int, 0);

View file

@ -116,7 +116,7 @@ export fn testMutablePointer() void {
// tmp.zig:85:26: note: ZON does not allow nested optionals // tmp.zig:85:26: note: ZON does not allow nested optionals
// tmp.zig:90:29: error: type '*i32' is not available in ZON // tmp.zig:90:29: error: type '*i32' is not available in ZON
// tmp.zig:90:29: note: ZON does not allow mutable pointers // tmp.zig:90:29: note: ZON does not allow mutable pointers
// neg_inf.zon:1:1: error: expected type '@Type(.enum_literal)' // neg_inf.zon:1:1: error: expected type '@EnumLiteral()'
// tmp.zig:37:38: note: imported here // tmp.zig:37:38: note: imported here
// neg_inf.zon:1:1: error: expected type '?u8' // neg_inf.zon:1:1: error: expected type '?u8'
// tmp.zig:57:28: note: imported here // tmp.zig:57:28: note: imported here

View file

@ -70,7 +70,7 @@ export fn testVector() void {
// tmp.zig:22:29: note: imported here // tmp.zig:22:29: note: imported here
// vec2.zon:1:2: error: expected type '?tmp.Enum' // vec2.zon:1:2: error: expected type '?tmp.Enum'
// tmp.zig:28:30: note: imported here // tmp.zig:28:30: note: imported here
// vec2.zon:1:2: error: expected type '?@Type(.enum_literal)' // vec2.zon:1:2: error: expected type '?@EnumLiteral()'
// tmp.zig:33:39: note: imported here // tmp.zig:33:39: note: imported here
// vec2.zon:1:2: error: expected type '?[1]u8' // vec2.zon:1:2: error: expected type '?[1]u8'
// tmp.zig:38:31: note: imported here // tmp.zig:38:31: note: imported here

View file

@ -38,31 +38,11 @@ export fn i() void {
} }
export fn j() void { export fn j() void {
_ = @Type(.{ .@"struct" = .{ _ = @Struct(.auto, null, &.{"test"}, &.{u32}, &.{.{ .@"align" = 0 }});
.layout = .auto,
.fields = &.{.{
.name = "test",
.type = u32,
.default_value_ptr = null,
.is_comptime = false,
.alignment = 0,
}},
.decls = &.{},
.is_tuple = false,
} });
} }
export fn k() void { export fn k() void {
_ = @Type(.{ .pointer = .{ _ = @Pointer(.one, .{ .@"align" = 0 }, u32, null);
.size = .one,
.is_const = false,
.is_volatile = false,
.alignment = 0,
.address_space = .generic,
.child = u32,
.is_allowzero = false,
.sentinel_ptr = null,
} });
} }
// error // error
@ -76,5 +56,5 @@ export fn k() void {
// :29:17: error: alignment must be >= 1 // :29:17: error: alignment must be >= 1
// :33:35: error: alignment must be >= 1 // :33:35: error: alignment must be >= 1
// :37:34: error: alignment must be >= 1 // :37:34: error: alignment must be >= 1
// :41:9: error: alignment must be >= 1 // :41:51: error: alignment must be >= 1
// :56:9: error: alignment must be >= 1 // :45:25: error: alignment must be >= 1

View file

@ -6,4 +6,4 @@ export fn entry() void {
// error // error
// //
// :3:10: error: expected type 'error{Hi}', found '@Type(.enum_literal)' // :3:10: error: expected type 'error{Hi}', found '@EnumLiteral()'

View file

@ -1,8 +0,0 @@
const builtin = @import("std").builtin;
comptime {
_ = @Type(.{ .float = .{ .bits = 17 } });
}
// error
//
// :3:9: error: 17-bit float unsupported

View file

@ -1,10 +0,0 @@
export fn entry() void {
_ = @Type(@typeInfo(enum {
foo,
pub const bar = 1;
}));
}
// error
//
// :2:9: error: reified enums must have no decls

View file

@ -6,4 +6,4 @@ export fn entry() void {
// error // error
// //
// :3:19: error: expected type 'error{Foo}', found '@Type(.enum_literal)' // :3:19: error: expected type 'error{Foo}', found '@EnumLiteral()'

View file

@ -9,40 +9,13 @@ export fn c() void {
} }
export fn d() void { export fn d() void {
_ = @Type(.{ .pointer = .{ _ = @Pointer(.slice, .{}, anyopaque, null);
.size = .slice,
.is_const = false,
.is_volatile = false,
.alignment = 1,
.address_space = .generic,
.child = anyopaque,
.is_allowzero = false,
.sentinel_ptr = null,
} });
} }
export fn e() void { export fn e() void {
_ = @Type(.{ .pointer = .{ _ = @Pointer(.many, .{}, anyopaque, null);
.size = .many,
.is_const = false,
.is_volatile = false,
.alignment = 1,
.address_space = .generic,
.child = anyopaque,
.is_allowzero = false,
.sentinel_ptr = null,
} });
} }
export fn f() void { export fn f() void {
_ = @Type(.{ .pointer = .{ _ = @Pointer(.c, .{}, anyopaque, null);
.size = .c,
.is_const = false,
.is_volatile = false,
.alignment = 1,
.address_space = .generic,
.child = anyopaque,
.is_allowzero = false,
.sentinel_ptr = null,
} });
} }
// error // error
@ -51,5 +24,5 @@ export fn f() void {
// :5:12: error: indexable pointer to opaque type 'anyopaque' not allowed // :5:12: error: indexable pointer to opaque type 'anyopaque' not allowed
// :8:13: error: indexable pointer to opaque type 'anyopaque' not allowed // :8:13: error: indexable pointer to opaque type 'anyopaque' not allowed
// :12:9: error: indexable pointer to opaque type 'anyopaque' not allowed // :12:9: error: indexable pointer to opaque type 'anyopaque' not allowed
// :24:9: error: indexable pointer to opaque type 'anyopaque' not allowed // :15:9: error: indexable pointer to opaque type 'anyopaque' not allowed
// :36:9: error: indexable pointer to opaque type 'anyopaque' not allowed // :18:9: error: indexable pointer to opaque type 'anyopaque' not allowed

View file

@ -1,16 +1,7 @@
export fn entry() void { export fn entry() void {
_ = @Type(.{ .pointer = .{ _ = @Pointer(.one, .{}, u8, 0);
.size = .one,
.is_const = false,
.is_volatile = false,
.alignment = 1,
.address_space = .generic,
.child = u8,
.is_allowzero = false,
.sentinel_ptr = &@as(u8, 0),
} });
} }
// error // error
// //
// :2:9: error: sentinels are only allowed on slices and unknown-length pointers // :2:33: error: sentinels are only allowed on slices and unknown-length pointers

View file

@ -36,4 +36,4 @@ const Union = union { foo: void };
// :13:29: error: expected number, found 'tmp.Union' // :13:29: error: expected number, found 'tmp.Union'
// :19:15: note: union declared here // :19:15: note: union declared here
// :14:61: error: expected number, found 'fn () u8' // :14:61: error: expected number, found 'fn () u8'
// :15:25: error: expected number, found '@Type(.enum_literal)' // :15:25: error: expected number, found '@EnumLiteral()'

View file

@ -1,10 +1,10 @@
export fn entry() void { export fn entry() void {
const V1 = @Vector(4, u8); const V1 = @Vector(4, u8);
const V2 = @Type(.{ .vector = .{ .len = 4, .child = V1 } }); const V2 = @Vector(4, V1);
const v: V2 = undefined; const v: V2 = undefined;
_ = v; _ = v;
} }
// error // error
// //
// :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)'

View file

@ -14,4 +14,4 @@ export fn entry() usize {
// //
// :6:12: error: unable to resolve comptime value // :6:12: error: unable to resolve comptime value
// :2:12: note: called at comptime from here // :2:12: note: called at comptime from here
// :1:13: note: struct fields must be comptime-known // :1:13: note: types must be comptime-known

View file

@ -12,31 +12,10 @@ comptime {
} }
comptime { comptime {
_ = @Type(.{ .array = .{ .child = S, .len = 0, .sentinel_ptr = &sentinel } }); _ = @Pointer(.slice, .{}, S, sentinel);
} }
comptime { comptime {
_ = @Type(.{ .pointer = .{ _ = @Pointer(.many, .{}, S, sentinel);
.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 // error
@ -47,9 +26,7 @@ comptime {
// :1:11: note: struct declared here // :1:11: note: struct declared here
// :11:12: error: non-scalar sentinel type 'tmp.S' // :11:12: error: non-scalar sentinel type 'tmp.S'
// :1:11: note: struct declared here // :1:11: note: struct declared here
// :15:9: error: non-scalar sentinel type 'tmp.S' // :15:34: error: non-scalar sentinel type 'tmp.S'
// :1:11: note: struct declared here // :1:11: note: struct declared here
// :18:9: error: non-scalar sentinel type 'tmp.S' // :18:33: 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 // :1:11: note: struct declared here

View file

@ -1,17 +1,8 @@
comptime { comptime {
const E = @Type(.{ .@"enum" = .{ const E = @Enum(u1, .exhaustive, &.{ "f0", "f1", "f2" }, &.{ 0, 1, 2 });
.tag_type = u1,
.fields = &.{
.{ .name = "f0", .value = 0 },
.{ .name = "f1", .value = 1 },
.{ .name = "f2", .value = 2 },
},
.decls = &.{},
.is_exhaustive = true,
} });
_ = E; _ = E;
} }
// error // error
// //
// :2:15: error: field 'f2' with enumeration value '2' is too large for backing int type 'u1' // :2:72: error: type 'u1' cannot represent integer value '2'

View file

@ -1,18 +1,8 @@
export fn entry() void { export fn entry() void {
_ = @Type(.{ _ = @Enum(u32, .nonexhaustive, &.{ "A", "A" }, &.{ 0, 1 });
.@"enum" = .{
.tag_type = u32,
.fields = &.{
.{ .name = "A", .value = 0 },
.{ .name = "A", .value = 1 },
},
.decls = &.{},
.is_exhaustive = false,
},
});
} }
// error // error
// //
// :2:9: error: duplicate enum field 'A' // :2:36: error: duplicate enum field 'A'
// :2:9: note: other field here // :2:36: note: other field here

View file

@ -1,18 +1,8 @@
export fn entry() void { export fn entry() void {
_ = @Type(.{ _ = @Enum(u32, .nonexhaustive, &.{ "A", "B" }, &.{ 10, 10 });
.@"enum" = .{
.tag_type = u32,
.fields = &.{
.{ .name = "A", .value = 10 },
.{ .name = "B", .value = 10 },
},
.decls = &.{},
.is_exhaustive = false,
},
});
} }
// error // error
// //
// :2:9: error: enum tag value 10 already taken // :2:52: error: enum tag value 10 already taken
// :2:9: note: other enum tag value here // :2:52: note: other enum tag value here

View file

@ -1,79 +1,16 @@
comptime { comptime {
@Type(.{ .@"struct" = .{ @Struct(.auto, null, &.{"foo"}, &.{u32}, &.{.{ .@"comptime" = true }});
.layout = .auto,
.fields = &.{.{
.name = "foo",
.type = u32,
.default_value_ptr = null,
.is_comptime = false,
.alignment = 4,
}},
.decls = &.{},
.is_tuple = true,
} });
} }
comptime { comptime {
@Type(.{ .@"struct" = .{ @Struct(.@"extern", null, &.{"foo"}, &.{u32}, &.{.{ .@"comptime" = true, .default_value_ptr = &@as(u32, 10) }});
.layout = .auto,
.fields = &.{.{
.name = "3",
.type = u32,
.default_value_ptr = null,
.is_comptime = false,
.alignment = 4,
}},
.decls = &.{},
.is_tuple = true,
} });
} }
comptime { comptime {
@Type(.{ .@"struct" = .{ @Struct(.@"packed", null, &.{"foo"}, &.{u32}, &.{.{ .@"align" = 4 }});
.layout = .auto,
.fields = &.{.{
.name = "0",
.type = u32,
.default_value_ptr = null,
.is_comptime = true,
.alignment = 4,
}},
.decls = &.{},
.is_tuple = true,
} });
}
comptime {
@Type(.{ .@"struct" = .{
.layout = .@"extern",
.fields = &.{.{
.name = "0",
.type = u32,
.default_value_ptr = null,
.is_comptime = true,
.alignment = 4,
}},
.decls = &.{},
.is_tuple = false,
} });
}
comptime {
@Type(.{ .@"struct" = .{
.layout = .@"packed",
.fields = &.{.{
.name = "0",
.type = u32,
.default_value_ptr = null,
.is_comptime = true,
.alignment = 4,
}},
.decls = &.{},
.is_tuple = false,
} });
} }
// error // error
// //
// :2:5: error: tuple cannot have non-numeric field 'foo' // :2:46: error: comptime field without default initialization value
// :16:5: error: tuple field name '3' does not match field index 0 // :5:51: error: extern struct fields cannot be marked comptime
// :30:5: error: comptime field without default initialization value // :8:51: error: packed struct fields cannot be aligned
// :44:5: error: extern struct fields cannot be marked comptime
// :58:5: error: alignment of a packed struct field must be set to 0

View file

@ -1,16 +0,0 @@
const Foo = @Type(.{
.@"fn" = .{
.calling_convention = .auto,
.is_generic = true,
.is_var_args = false,
.return_type = u0,
.params = &.{},
},
});
comptime {
_ = Foo;
}
// error
//
// :1:13: error: Type.Fn.is_generic must be false for @Type

View file

@ -1,18 +1,9 @@
const Foo = @Type(.{
.@"fn" = .{
.calling_convention = .auto,
.is_generic = false,
.is_var_args = true,
.return_type = u0,
.params = &.{},
},
});
comptime { comptime {
_ = Foo; _ = @Fn(&.{u32}, &.{.{}}, u8, .{ .varargs = true });
} }
// error // error
// target=x86_64-linux // target=x86_64-linux
// //
// :1:13: error: variadic function does not support 'auto' calling convention // :2:36: error: variadic function does not support 'auto' calling convention
// :1:13: note: supported calling conventions: 'x86_64_sysv', 'x86_64_x32', 'x86_64_win' // :2:36: note: supported calling conventions: 'x86_64_sysv', 'x86_64_x32', 'x86_64_win'

View file

@ -1,16 +0,0 @@
const Foo = @Type(.{
.@"fn" = .{
.calling_convention = .auto,
.is_generic = false,
.is_var_args = false,
.return_type = null,
.params = &.{},
},
});
comptime {
_ = Foo;
}
// error
//
// :1:13: error: Type.Fn.return_type must be non-null for @Type

View file

@ -1,15 +1,8 @@
const Tag = @Type(.{ const Tag = @Enum(bool, .nonexhaustive, &.{}, &.{});
.@"enum" = .{
.tag_type = bool,
.fields = &.{},
.decls = &.{},
.is_exhaustive = false,
},
});
export fn entry() void { export fn entry() void {
_ = @as(Tag, @enumFromInt(0)); _ = @as(Tag, @enumFromInt(0));
} }
// error // error
// //
// :1:13: error: Type.Enum.tag_type must be an integer type // :1:19: error: tag type must be an integer type

View file

@ -1,15 +1,8 @@
const Tag = @Type(.{ const Tag = @Enum(undefined, .exhaustive, &.{}, &.{});
.@"enum" = .{
.tag_type = undefined,
.fields = &.{},
.decls = &.{},
.is_exhaustive = false,
},
});
export fn entry() void { export fn entry() void {
_ = @as(Tag, @enumFromInt(0)); _ = @as(Tag, @enumFromInt(0));
} }
// error // error
// //
// :1:20: error: use of undefined value here causes illegal behavior // :1:19: error: use of undefined value here causes illegal behavior

View file

@ -1,26 +1,5 @@
const Tag = @Type(.{ const Tag = @Enum(u2, .exhaustive, &.{ "signed", "unsigned" }, &.{ 0, 1 });
.@"enum" = .{ const Extern = @Union(.@"extern", Tag, &.{ "signed", "unsigned" }, &.{ i32, u32 }, &@splat(.{}));
.tag_type = u2,
.fields = &.{
.{ .name = "signed", .value = 0 },
.{ .name = "unsigned", .value = 1 },
},
.decls = &.{},
.is_exhaustive = true,
},
});
const Extern = @Type(.{
.@"union" = .{
.layout = .@"extern",
.tag_type = Tag,
.fields = &.{
.{ .name = "signed", .type = i32, .alignment = @alignOf(i32) },
.{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) },
},
.decls = &.{},
},
});
export fn entry() void { export fn entry() void {
const tagged: Extern = .{ .signed = -1 }; const tagged: Extern = .{ .signed = -1 };
@ -29,4 +8,4 @@ export fn entry() void {
// error // error
// //
// :13:16: error: extern union does not support enum tag type // :2:35: error: extern union does not support enum tag type

View file

@ -1,26 +1,5 @@
const Tag = @Type(.{ const Tag = @Enum(u2, .exhaustive, &.{ "signed", "unsigned" }, &.{ 0, 1 });
.@"enum" = .{ const Packed = @Union(.@"packed", Tag, &.{ "signed", "unsigned" }, &.{ i32, u32 }, &@splat(.{}));
.tag_type = u2,
.fields = &.{
.{ .name = "signed", .value = 0 },
.{ .name = "unsigned", .value = 1 },
},
.decls = &.{},
.is_exhaustive = true,
},
});
const Packed = @Type(.{
.@"union" = .{
.layout = .@"packed",
.tag_type = Tag,
.fields = &.{
.{ .name = "signed", .type = i32, .alignment = @alignOf(i32) },
.{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) },
},
.decls = &.{},
},
});
export fn entry() void { export fn entry() void {
const tagged: Packed = .{ .signed = -1 }; const tagged: Packed = .{ .signed = -1 };
@ -29,4 +8,4 @@ export fn entry() void {
// error // error
// //
// :13:16: error: packed union does not support enum tag type // :2:35: error: packed union does not support enum tag type

View file

@ -1,26 +1,5 @@
const Tag = @Type(.{ const Tag = @Enum(u2, .exhaustive, &.{ "signed", "unsigned", "arst" }, &.{ 0, 1, 2 });
.@"enum" = .{ const Tagged = @Union(.auto, Tag, &.{ "signed", "unsigned" }, &.{ i32, u32 }, &@splat(.{}));
.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 = &.{},
},
});
export fn entry() void { export fn entry() void {
var tagged = Tagged{ .signed = -1 }; var tagged = Tagged{ .signed = -1 };
tagged = .{ .unsigned = 1 }; tagged = .{ .unsigned = 1 };
@ -28,6 +7,6 @@ export fn entry() void {
// error // error
// //
// :13:16: error: enum fields missing in union // :2:35: error: 1 enum fields missing in union
// :1:13: note: field 'arst' missing, declared here // :1:13: note: field 'arst' missing, declared here
// :1:13: note: enum declared here // :1:13: note: enum declared here

View file

@ -1,26 +1,5 @@
const Tag = @Type(.{ const Tag = @Enum(u1, .exhaustive, &.{ "signed", "unsigned" }, &.{ 0, 1 });
.@"enum" = .{ const Tagged = @Union(.auto, Tag, &.{ "signed", "unsigned", "arst" }, &.{ i32, u32, f32 }, &@splat(.{}));
.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 = &.{},
},
});
export fn entry() void { export fn entry() void {
var tagged = Tagged{ .signed = -1 }; var tagged = Tagged{ .signed = -1 };
tagged = .{ .unsigned = 1 }; tagged = .{ .unsigned = 1 };
@ -28,5 +7,5 @@ export fn entry() void {
// error // error
// //
// :12:16: error: no field named 'arst' in enum 'tmp.Tag' // :2:35: error: no field named 'arst' in enum 'tmp.Tag'
// :1:13: note: enum declared here // :1:13: note: enum declared here

View file

@ -1,22 +1,5 @@
const Tag = @Type(.{ const Tag = @Enum(u0, .exhaustive, &.{}, &.{});
.@"enum" = .{ const Tagged = @Union(.auto, Tag, &.{ "signed", "unsigned" }, &.{ i32, u32 }, &@splat(.{}));
.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 = &.{},
},
});
export fn entry() void { export fn entry() void {
const tagged: Tagged = undefined; const tagged: Tagged = undefined;
_ = tagged; _ = tagged;
@ -24,5 +7,5 @@ export fn entry() void {
// error // error
// //
// :9:16: error: no field named 'signed' in enum 'tmp.Tag' // :2:35: error: no field named 'signed' in enum 'tmp.Tag'
// :1:13: note: enum declared here // :1:13: note: enum declared here

View file

@ -1,22 +1,5 @@
const Tag = @Type(.{ const Tag = @Enum(u1, .exhaustive, &.{ "signed", "unsigned" }, &.{ 0, 1 });
.@"enum" = .{ const Tagged = @Union(.auto, Tag, &.{}, &.{}, &.{});
.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 = &.{},
},
});
export fn entry() void { export fn entry() void {
const tagged: Tagged = undefined; const tagged: Tagged = undefined;
_ = tagged; _ = tagged;
@ -24,7 +7,7 @@ export fn entry() void {
// error // error
// //
// :12:16: error: enum fields missing in union // :2:35: error: 2 enum fields missing in union
// :1:13: note: field 'signed' missing, declared here // :1:13: note: field 'signed' missing, declared here
// :1:13: note: field 'unsigned' missing, declared here // :1:13: note: field 'unsigned' missing, declared here
// :1:13: note: enum declared here // :1:13: note: enum declared here

View file

@ -1,18 +1,9 @@
const Untagged = @Type(.{ const Untagged = @Union(.auto, null, &.{"foo"}, &.{opaque {}}, &.{.{}});
.@"union" = .{
.layout = .auto,
.tag_type = null,
.fields = &.{
.{ .name = "foo", .type = opaque {}, .alignment = 1 },
},
.decls = &.{},
},
});
export fn entry() usize { export fn entry() usize {
return @sizeOf(Untagged); return @sizeOf(Untagged);
} }
// error // error
// //
// :1:18: error: opaque types have unknown size and therefore cannot be directly embedded in unions // :1:49: error: opaque types have unknown size and therefore cannot be directly embedded in unions
// :6:39: note: opaque declared here // :1:52: note: opaque declared here

View file

@ -1,10 +0,0 @@
const Foo = @Type(.{
.@"struct" = undefined,
});
comptime {
_ = Foo;
}
// error
//
// :1:20: error: use of undefined value here causes illegal behavior

View file

@ -1,13 +0,0 @@
const builtin = @import("std").builtin;
export fn entry() void {
_ = @Type(builtin.Type.Int{
.signedness = .signed,
.bits = 8,
});
}
// error
//
// :3:31: error: expected type 'builtin.Type', found 'builtin.Type.Int'
// :?:?: note: struct declared here
// :?:?: note: union declared here

View file

@ -1,48 +1,15 @@
comptime { comptime {
_ = @Type(.{ _ = @Union(.auto, null, &.{"foo"}, &.{usize}, &.{.{ .@"align" = 3 }});
.@"union" = .{
.layout = .auto,
.tag_type = null,
.fields = &.{
.{ .name = "foo", .type = usize, .alignment = 3 },
},
.decls = &.{},
},
});
} }
comptime { comptime {
_ = @Type(.{ _ = @Struct(.auto, null, &.{"a"}, &.{u32}, &.{.{ .@"comptime" = true, .@"align" = 5 }});
.@"struct" = .{
.layout = .auto,
.fields = &.{.{
.name = "0",
.type = u32,
.default_value_ptr = null,
.is_comptime = true,
.alignment = 5,
}},
.decls = &.{},
.is_tuple = false,
},
});
} }
comptime { comptime {
_ = @Type(.{ _ = @Pointer(.many, .{ .@"align" = 7 }, u8, null);
.pointer = .{
.size = .many,
.is_const = true,
.is_volatile = false,
.alignment = 7,
.address_space = .generic,
.child = u8,
.is_allowzero = false,
.sentinel_ptr = null,
},
});
} }
// error // error
// //
// :2:9: error: alignment value '3' is not a power of two // :2:51: error: alignment value '3' is not a power of two
// :14:9: error: alignment value '5' is not a power of two // :5:48: error: alignment value '5' is not a power of two
// :30:9: error: alignment value '7' is not a power of two // :8:26: error: alignment value '7' is not a power of two

View file

@ -1,31 +1,11 @@
comptime { comptime {
_ = @Type(.{ .array = .{ .len = 0, .child = u8, .sentinel_ptr = undefined } }); _ = @Struct(.auto, null, &.{}, &.{}, undefined);
} }
comptime { comptime {
_ = @Type(.{ _ = @Struct(.auto, null, &.{"foo"}, &.{undefined}, &.{.{}});
.@"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,
},
});
} }
// error // error
// //
// :2:16: error: use of undefined value here causes illegal behavior // :2:42: error: use of undefined value here causes illegal behavior
// :5:16: error: use of undefined value here causes illegal behavior // :5:41: error: use of undefined value here causes illegal behavior
// :17:16: error: use of undefined value here causes illegal behavior

View file

@ -7,4 +7,4 @@ export fn foobar() void {
// error // 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 '@EnumLiteral()' depends on runtime control flow

View file

@ -1,9 +0,0 @@
export fn entry() void {
_ = @Type(@typeInfo(struct {
pub const foo = 1;
}));
}
// error
//
// :2:9: error: reified structs must have no decls

Some files were not shown because too many files have changed in this diff Show more