authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-11-23 07:50:29+00:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-11-23 07:50:29+00:00
log6d543bcf94b2deefa918cb29de93fc32a10d4abf
treed6d90938858a7479b682a3b97c98cb3ab67cd4df
parent0a9f666ea62829607d782dc0cac5d10099def180
parentdec1163fbb892f276179ae74b51007c656157d99
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #23733 from alichraghi/bp

replace @Type with individual type-creating builtins

122 files changed, 2665 insertions(+), 3322 deletions(-)

doc/langref.html.in+74-40
...@@ -638,7 +638,7 @@...@@ -638,7 +638,7 @@
638 {#syntax#}i7{#endsyntax#} refers to a signed 7-bit integer. The maximum allowed bit-width of an638 {#syntax#}i7{#endsyntax#} refers to a signed 7-bit integer. The maximum allowed bit-width of an
639 integer type is {#syntax#}65535{#endsyntax#}.639 integer type is {#syntax#}65535{#endsyntax#}.
640 </p>640 </p>
641 {#see_also|Integers|Floats|void|Errors|@Type#}641 {#see_also|Integers|Floats|void|Errors|@Int#}
642 {#header_close#}642 {#header_close#}
643 {#header_open|Primitive Values#}643 {#header_open|Primitive Values#}
644 <div class="table-wrapper">644 <div class="table-wrapper">
...@@ -3723,9 +3723,9 @@ void do_a_thing(struct Foo *foo) {...@@ -3723,9 +3723,9 @@ void do_a_thing(struct Foo *foo) {
3723 <td>{#syntax#}x{#endsyntax#} is a {#syntax#}@FieldType(T, "a"){#endsyntax#}</td>3723 <td>{#syntax#}x{#endsyntax#} is a {#syntax#}@FieldType(T, "a"){#endsyntax#}</td>
3724 </tr>3724 </tr>
3725 <tr>3725 <tr>
3726 <th scope="row">{#syntax#}@Type(x){#endsyntax#}</th>3726 <th scope="row">{#syntax#}@Int(x, y){#endsyntax#}</th>
3727 <td>-</td>3727 <td>-</td>
3728 <td>{#syntax#}x{#endsyntax#} is a {#syntax#}std.builtin.Type{#endsyntax#}</td>3728 <td>{#syntax#}x{#endsyntax#} is a {#syntax#}std.builtin.Signedness{#endsyntax#}, {#syntax#}y{#endsyntax#} is a {#syntax#}u16{#endsyntax#}</td>
3729 </tr>3729 </tr>
3730 <tr>3730 <tr>
3731 <th scope="row">{#syntax#}@typeInfo(x){#endsyntax#}</th>3731 <th scope="row">{#syntax#}@typeInfo(x){#endsyntax#}</th>
...@@ -3839,9 +3839,9 @@ void do_a_thing(struct Foo *foo) {...@@ -3839,9 +3839,9 @@ void do_a_thing(struct Foo *foo) {
3839 <td>{#syntax#}x{#endsyntax#} has no result location (typed initializers do not propagate result locations)</td>3839 <td>{#syntax#}x{#endsyntax#} has no result location (typed initializers do not propagate result locations)</td>
3840 </tr>3840 </tr>
3841 <tr>3841 <tr>
3842 <th scope="row">{#syntax#}@Type(x){#endsyntax#}</th>3842 <th scope="row">{#syntax#}@Int(x, y){#endsyntax#}</th>
3843 <td>{#syntax#}ptr{#endsyntax#}</td>3843 <td>-</td>
3844 <td>{#syntax#}x{#endsyntax#} has no result location</td>3844 <td>{#syntax#}x{#endsyntax#} and {#syntax#}y{#endsyntax#} do not have result locations</td>
3845 </tr>3845 </tr>
3846 <tr>3846 <tr>
3847 <th scope="row">{#syntax#}@typeInfo(x){#endsyntax#}</th>3847 <th scope="row">{#syntax#}@typeInfo(x){#endsyntax#}</th>
...@@ -5755,41 +5755,75 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val...@@ -5755,41 +5755,75 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
5755 </p>5755 </p>
5756 {#header_close#}5756 {#header_close#}
57575757
5758 {#header_open|@Type#}5758 {#header_open|@EnumLiteral#}
5759 <pre>{#syntax#}@Type(comptime info: std.builtin.Type) type{#endsyntax#}</pre>5759 <pre>{#syntax#}@EnumLiteral() type{#endsyntax#}</pre>
5760 <p>5760 <p>Returns the comptime-only "enum literal" type. This is the type of uncoerced {#link|Enum Literals#}. Values of this type can coerce to any {#link|enum#} with a matching field.</p>
5761 This function is the inverse of {#link|@typeInfo#}. It reifies type information5761 {#header_close#}
5762 into a {#syntax#}type{#endsyntax#}.5762
5763 </p>5763 {#header_open|@Int#}
5764 <p>5764 <pre>{#syntax#}@Int(comptime signedness: std.builtin.Signedness, comptime bits: u16) type{#endsyntax#}</pre>
5765 It is available for the following types:5765 <p>Returns an integer type with the given signedness and bit width.</p>
5766 </p>5766 <p>For instance, {#syntax#}@Int(.unsigned, 18){#endsyntax#} returns the type {#syntax#}u18{#endsyntax#}.</p>
5767 <ul>
5768 <li>{#syntax#}type{#endsyntax#}</li>
5769 <li>{#syntax#}noreturn{#endsyntax#}</li>
5770 <li>{#syntax#}void{#endsyntax#}</li>
5771 <li>{#syntax#}bool{#endsyntax#}</li>
5772 <li>{#link|Integers#} - The maximum bit count for an integer type is {#syntax#}65535{#endsyntax#}.</li>
5773 <li>{#link|Floats#}</li>
5774 <li>{#link|Pointers#}</li>
5775 <li>{#syntax#}comptime_int{#endsyntax#}</li>
5776 <li>{#syntax#}comptime_float{#endsyntax#}</li>
5777 <li>{#syntax#}@TypeOf(undefined){#endsyntax#}</li>
5778 <li>{#syntax#}@TypeOf(null){#endsyntax#}</li>
5779 <li>{#link|Arrays#}</li>
5780 <li>{#link|Optionals#}</li>
5781 <li>{#link|Error Set Type#}</li>
5782 <li>{#link|Error Union Type#}</li>
5783 <li>{#link|Vectors#}</li>
5784 <li>{#link|opaque#}</li>
5785 <li>{#syntax#}anyframe{#endsyntax#}</li>
5786 <li>{#link|struct#}</li>
5787 <li>{#link|enum#}</li>
5788 <li>{#link|Enum Literals#}</li>
5789 <li>{#link|union#}</li>
5790 <li>{#link|Functions#}</li>
5791 </ul>
5792 {#header_close#}5767 {#header_close#}
5768
5769 {#header_open|@Tuple#}
5770 <pre>{#syntax#}@Tuple(comptime field_types: []const type) type{#endsyntax#}</pre>
5771 <p>Returns a {#link|tuple|Tuples#} type with the given field types.</p>
5772 {#header_close#}
5773
5774 {#header_open|@Pointer#}
5775 <pre>{#syntax#}@Pointer(
5776 comptime size: std.builtin.Type.Pointer.Size,
5777 comptime attrs: std.builtin.Type.Pointer.Attributes,
5778 comptime Element: type,
5779 comptime sentinel: ?Element,
5780) type{#endsyntax#}</pre>
5781 <p>Returns a {#link|pointer|Pointers#} type with the properties specified by the arguments.</p>
5782 {#header_close#}
5783
5784 {#header_open|@Fn#}
5785 <pre>{#syntax#}@Fn(
5786 comptime param_types: []const type,
5787 comptime param_attrs: *const [param_types.len]std.builtin.Type.Fn.Param.Attributes,
5788 comptime ReturnType: type,
5789 comptime attrs: std.builtin.Type.Fn.Attributes,
5790) type{#endsyntax#}</pre>
5791 <p>Returns a {#link|function|Functions#} type with the properties specified by the arguments.</p>
5792 {#header_close#}
5793
5794 {#header_open|@Struct#}
5795 <pre>{#syntax#}@Struct(
5796 comptime layout: std.builtin.Type.ContainerLayout,
5797 comptime BackingInt: ?type,
5798 comptime field_names: []const []const u8,
5799 comptime field_types: *const [field_names.len]type,
5800 comptime field_attrs: *const [field_names.len]std.builtin.Type.StructField.Attributes,
5801) type{#endsyntax#}</pre>
5802 <p>Returns a {#link|struct#} type with the properties specified by the arguments.</p>
5803 {#header_close#}
5804
5805 {#header_open|@Union#}
5806 <pre>{#syntax#}@Union(
5807 comptime layout: std.builtin.Type.ContainerLayout,
5808 /// Either the integer tag type, or the integer backing type, depending on `layout`.
5809 comptime ArgType: ?type,
5810 comptime field_names: []const []const u8,
5811 comptime field_types: *const [field_names.len]type,
5812 comptime field_attrs: *const [field_names.len]std.builtin.Type.UnionField.Attributes,
5813) type{#endsyntax#}</pre>
5814 <p>Returns a {#link|union#} type with the properties specified by the arguments.</p>
5815 {#header_close#}
5816
5817 {#header_open|@Enum#}
5818 <pre>{#syntax#}@Enum(
5819 comptime TagInt: type,
5820 comptime mode: std.builtin.Type.Enum.Mode,
5821 comptime field_names: []const []const u8,
5822 comptime field_values: *const [field_names.len]TagInt,
5823) type{#endsyntax#}</pre>
5824 <p>Returns an {#link|enum#} type with the properties specified by the arguments.</p>
5825 {#header_close#}
5826
5793 {#header_open|@typeInfo#}5827 {#header_open|@typeInfo#}
5794 <pre>{#syntax#}@typeInfo(comptime T: type) std.builtin.Type{#endsyntax#}</pre>5828 <pre>{#syntax#}@typeInfo(comptime T: type) std.builtin.Type{#endsyntax#}</pre>
5795 <p>5829 <p>
doc/langref/std_options.zig+1-1
...@@ -11,7 +11,7 @@ pub const std_options: std.Options = .{...@@ -11,7 +11,7 @@ pub const std_options: std.Options = .{
1111
12fn myLogFn(12fn myLogFn(
13 comptime level: std.log.Level,13 comptime level: std.log.Level,
14 comptime scope: @Type(.enum_literal),14 comptime scope: @EnumLiteral(),
15 comptime format: []const u8,15 comptime format: []const u8,
16 args: anytype,16 args: anytype,
17) void {17) void {
doc/langref/test_coerce_unions_enums.zig+1-1
...@@ -41,7 +41,7 @@ test "coercion between unions and enums" {...@@ -41,7 +41,7 @@ test "coercion between unions and enums" {
41 try expect(u_4.tag() == 1);41 try expect(u_4.tag() == 1);
4242
43 // The following example is invalid.43 // The following example is invalid.
44 // error: coercion from enum '@TypeOf(.enum_literal)' to union 'test_coerce_unions_enum.U2' must initialize 'f32' field 'b'44 // error: coercion from enum '@EnumLiteral()' to union 'test_coerce_unions_enum.U2' must initialize 'f32' field 'b'
45 //var u_5: U2 = .b;45 //var u_5: U2 = .b;
46 //try expect(u_5.tag() == 2);46 //try expect(u_5.tag() == 2);
47}47}
lib/build-web/main.zig+1-1
...@@ -49,7 +49,7 @@ pub fn panic(msg: []const u8, st: ?*std.builtin.StackTrace, addr: ?usize) noretu...@@ -49,7 +49,7 @@ pub fn panic(msg: []const u8, st: ?*std.builtin.StackTrace, addr: ?usize) noretu
4949
50fn logFn(50fn logFn(
51 comptime message_level: log.Level,51 comptime message_level: log.Level,
52 comptime scope: @TypeOf(.enum_literal),52 comptime scope: @EnumLiteral(),
53 comptime format: []const u8,53 comptime format: []const u8,
54 args: anytype,54 args: anytype,
55) void {55) void {
lib/compiler/aro/aro/Attribute.zig+6-16
...@@ -717,23 +717,13 @@ pub const Tag = std.meta.DeclEnum(attributes);...@@ -717,23 +717,13 @@ pub const Tag = std.meta.DeclEnum(attributes);
717717
718pub const Arguments = blk: {718pub const Arguments = blk: {
719 const decls = @typeInfo(attributes).@"struct".decls;719 const decls = @typeInfo(attributes).@"struct".decls;
720 var union_fields: [decls.len]ZigType.UnionField = undefined;720 var names: [decls.len][]const u8 = undefined;
721 for (decls, &union_fields) |decl, *field| {721 var types: [decls.len]type = undefined;
722 field.* = .{722 for (decls, &names, &types) |decl, *name, *T| {
723 .name = decl.name,723 name.* = decl.name;
724 .type = @field(attributes, decl.name),724 T.* = @field(attributes, decl.name);
725 .alignment = @alignOf(@field(attributes, decl.name)),
726 };
727 }725 }
728726 break :blk @Union(.auto, null, &names, &types, &@splat(.{}));
729 break :blk @Type(.{
730 .@"union" = .{
731 .layout = .auto,
732 .tag_type = null,
733 .fields = &union_fields,
734 .decls = &.{},
735 },
736 });
737};727};
738728
739pub fn ArgumentsForTag(comptime tag: Tag) type {729pub fn ArgumentsForTag(comptime tag: Tag) type {
lib/compiler/aro/assembly_backend/x86_64.zig+1-1
...@@ -59,7 +59,7 @@ fn serializeFloat(comptime T: type, value: T, w: *std.Io.Writer) !void {...@@ -59,7 +59,7 @@ fn serializeFloat(comptime T: type, value: T, w: *std.Io.Writer) !void {
59 else => {59 else => {
60 const size = @bitSizeOf(T);60 const size = @bitSizeOf(T);
61 const storage_unit = std.meta.intToEnum(StorageUnit, size) catch unreachable;61 const storage_unit = std.meta.intToEnum(StorageUnit, size) catch unreachable;
62 const IntTy = @Type(.{ .int = .{ .signedness = .unsigned, .bits = size } });62 const IntTy = @Int(.unsigned, size);
63 const int_val: IntTy = @bitCast(value);63 const int_val: IntTy = @bitCast(value);
64 return serializeInt(int_val, storage_unit, w);64 return serializeInt(int_val, storage_unit, w);
65 },65 },
lib/compiler/resinator/code_pages.zig+7-6
...@@ -179,12 +179,13 @@ pub const UnsupportedCodePage = enum(u16) {...@@ -179,12 +179,13 @@ pub const UnsupportedCodePage = enum(u16) {
179179
180pub const CodePage = blk: {180pub const CodePage = blk: {
181 const fields = @typeInfo(SupportedCodePage).@"enum".fields ++ @typeInfo(UnsupportedCodePage).@"enum".fields;181 const fields = @typeInfo(SupportedCodePage).@"enum".fields ++ @typeInfo(UnsupportedCodePage).@"enum".fields;
182 break :blk @Type(.{ .@"enum" = .{182 var field_names: [fields.len][]const u8 = undefined;
183 .tag_type = u16,183 var field_values: [fields.len]u16 = undefined;
184 .decls = &.{},184 for (fields, &field_names, &field_values) |field, *name, *val| {
185 .fields = fields,185 name.* = field.name;
186 .is_exhaustive = true,186 val.* = field.value;
187 } });187 }
188 break :blk @Enum(u16, .exhaustive, &field_names, &field_values);
188};189};
189190
190pub fn isSupported(code_page: CodePage) bool {191pub fn isSupported(code_page: CodePage) bool {
lib/compiler/resinator/errors.zig+12-9
...@@ -862,20 +862,23 @@ pub const ErrorDetails = struct {...@@ -862,20 +862,23 @@ pub const ErrorDetails = struct {
862pub const ErrorDetailsWithoutCodePage = blk: {862pub const ErrorDetailsWithoutCodePage = blk: {
863 const details_info = @typeInfo(ErrorDetails);863 const details_info = @typeInfo(ErrorDetails);
864 const fields = details_info.@"struct".fields;864 const fields = details_info.@"struct".fields;
865 var fields_without_codepage: [fields.len - 1]std.builtin.Type.StructField = undefined;865 var field_names: [fields.len - 1][]const u8 = undefined;
866 var field_types: [fields.len - 1]type = undefined;
867 var field_attrs: [fields.len - 1]std.builtin.Type.StructField.Attributes = undefined;
866 var i: usize = 0;868 var i: usize = 0;
867 for (fields) |field| {869 for (fields) |field| {
868 if (std.mem.eql(u8, field.name, "code_page")) continue;870 if (std.mem.eql(u8, field.name, "code_page")) continue;
869 fields_without_codepage[i] = field;871 field_names[i] = field.name;
872 field_types[i] = field.type;
873 field_attrs[i] = .{
874 .@"comptime" = field.is_comptime,
875 .@"align" = field.alignment,
876 .default_value_ptr = field.default_value_ptr,
877 };
870 i += 1;878 i += 1;
871 }879 }
872 std.debug.assert(i == fields_without_codepage.len);880 std.debug.assert(i == fields.len - 1);
873 break :blk @Type(.{ .@"struct" = .{881 break :blk @Struct(.auto, null, &field_names, &field_types, &field_attrs);
874 .layout = .auto,
875 .fields = &fields_without_codepage,
876 .decls = &.{},
877 .is_tuple = false,
878 } });
879};882};
880883
881fn cellCount(code_page: SupportedCodePage, source: []const u8, start_index: usize, end_index: usize) usize {884fn cellCount(code_page: SupportedCodePage, source: []const u8, start_index: usize, end_index: usize) usize {
lib/compiler/test_runner.zig+1-1
...@@ -298,7 +298,7 @@ fn mainTerminal() void {...@@ -298,7 +298,7 @@ fn mainTerminal() void {
298298
299pub fn log(299pub fn log(
300 comptime message_level: std.log.Level,300 comptime message_level: std.log.Level,
301 comptime scope: @Type(.enum_literal),301 comptime scope: @EnumLiteral(),
302 comptime format: []const u8,302 comptime format: []const u8,
303 args: anytype,303 args: anytype,
304) void {304) void {
lib/compiler_rt/common.zig+1-4
...@@ -290,10 +290,7 @@ pub fn normalize(comptime T: type, significand: *std.meta.Int(.unsigned, @typeIn...@@ -290,10 +290,7 @@ pub fn normalize(comptime T: type, significand: *std.meta.Int(.unsigned, @typeIn
290pub inline fn fneg(a: anytype) @TypeOf(a) {290pub inline fn fneg(a: anytype) @TypeOf(a) {
291 const F = @TypeOf(a);291 const F = @TypeOf(a);
292 const bits = @typeInfo(F).float.bits;292 const bits = @typeInfo(F).float.bits;
293 const U = @Type(.{ .int = .{293 const U = @Int(.unsigned, bits);
294 .signedness = .unsigned,
295 .bits = bits,
296 } });
297 const sign_bit_mask = @as(U, 1) << (bits - 1);294 const sign_bit_mask = @as(U, 1) << (bits - 1);
298 const negated = @as(U, @bitCast(a)) ^ sign_bit_mask;295 const negated = @as(U, @bitCast(a)) ^ sign_bit_mask;
299 return @bitCast(negated);296 return @bitCast(negated);
lib/compiler_rt/float_from_int.zig+5-5
...@@ -66,17 +66,17 @@ pub inline fn floatFromBigInt(comptime T: type, comptime signedness: std.builtin...@@ -66,17 +66,17 @@ pub inline fn floatFromBigInt(comptime T: type, comptime signedness: std.builtin
66 switch (x.len) {66 switch (x.len) {
67 0 => return 0,67 0 => return 0,
68 inline 1...4 => |limbs_len| return @floatFromInt(@as(68 inline 1...4 => |limbs_len| return @floatFromInt(@as(
69 @Type(.{ .int = .{ .signedness = signedness, .bits = 32 * limbs_len } }),69 @Int(signedness, 32 * limbs_len),
70 @bitCast(x[0..limbs_len].*),70 @bitCast(x[0..limbs_len].*),
71 )),71 )),
72 else => {},72 else => {},
73 }73 }
7474
75 // sign implicit fraction round sticky75 // sign implicit fraction round sticky
76 const I = comptime @Type(.{ .int = .{76 const I = comptime @Int(
77 .signedness = signedness,77 signedness,
78 .bits = @as(u16, @intFromBool(signedness == .signed)) + 1 + math.floatFractionalBits(T) + 1 + 1,78 @as(u16, @intFromBool(signedness == .signed)) + 1 + math.floatFractionalBits(T) + 1 + 1,
79 } });79 );
8080
81 const clrsb = clrsb: {81 const clrsb = clrsb: {
82 var clsb: usize = 0;82 var clsb: usize = 0;
lib/compiler_rt/int_from_float.zig+2-5
...@@ -56,7 +56,7 @@ pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, resul...@@ -56,7 +56,7 @@ pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, resul
56 0 => return,56 0 => return,
57 inline 1...4 => |limbs_len| {57 inline 1...4 => |limbs_len| {
58 result[0..limbs_len].* = @bitCast(@as(58 result[0..limbs_len].* = @bitCast(@as(
59 @Type(.{ .int = .{ .signedness = signedness, .bits = 32 * limbs_len } }),59 @Int(signedness, 32 * limbs_len),
60 @intFromFloat(a),60 @intFromFloat(a),
61 ));61 ));
62 return;62 return;
...@@ -66,10 +66,7 @@ pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, resul...@@ -66,10 +66,7 @@ pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, resul
6666
67 // sign implicit fraction67 // sign implicit fraction
68 const significand_bits = 1 + math.floatFractionalBits(@TypeOf(a));68 const significand_bits = 1 + math.floatFractionalBits(@TypeOf(a));
69 const I = @Type(comptime .{ .int = .{69 const I = @Int(signedness, @as(u16, @intFromBool(signedness == .signed)) + significand_bits);
70 .signedness = signedness,
71 .bits = @as(u16, @intFromBool(signedness == .signed)) + significand_bits,
72 } });
7370
74 const parts = math.frexp(a);71 const parts = math.frexp(a);
75 const significand_bits_adjusted_to_handle_smin = @as(i32, significand_bits) +72 const significand_bits_adjusted_to_handle_smin = @as(i32, significand_bits) +
lib/compiler_rt/memcpy.zig+1-1
...@@ -159,7 +159,7 @@ inline fn copyFixedLength(...@@ -159,7 +159,7 @@ inline fn copyFixedLength(
159 else if (len > @sizeOf(usize))159 else if (len > @sizeOf(usize))
160 @Vector(len, u8)160 @Vector(len, u8)
161 else161 else
162 @Type(.{ .int = .{ .signedness = .unsigned, .bits = len * 8 } });162 @Int(.unsigned, len * 8);
163163
164 const loop_count = @divExact(len, @sizeOf(T));164 const loop_count = @divExact(len, @sizeOf(T));
165165
lib/docs/wasm/main.zig+1-1
...@@ -41,7 +41,7 @@ pub fn panic(msg: []const u8, st: ?*std.builtin.StackTrace, addr: ?usize) noretu...@@ -41,7 +41,7 @@ pub fn panic(msg: []const u8, st: ?*std.builtin.StackTrace, addr: ?usize) noretu
4141
42fn logFn(42fn logFn(
43 comptime message_level: log.Level,43 comptime message_level: log.Level,
44 comptime scope: @TypeOf(.enum_literal),44 comptime scope: @EnumLiteral(),
45 comptime format: []const u8,45 comptime format: []const u8,
46 args: anytype,46 args: anytype,
47) void {47) void {
lib/fuzzer.zig+1-1
...@@ -15,7 +15,7 @@ pub const std_options = std.Options{...@@ -15,7 +15,7 @@ pub const std_options = std.Options{
1515
16fn logOverride(16fn logOverride(
17 comptime level: std.log.Level,17 comptime level: std.log.Level,
18 comptime scope: @Type(.enum_literal),18 comptime scope: @EnumLiteral(),
19 comptime format: []const u8,19 comptime format: []const u8,
20 args: anytype,20 args: anytype,
21) void {21) void {
lib/std/Build.zig+3-11
...@@ -416,7 +416,7 @@ fn createChildOnly(...@@ -416,7 +416,7 @@ fn createChildOnly(
416fn userInputOptionsFromArgs(arena: Allocator, args: anytype) UserInputOptionsMap {416fn userInputOptionsFromArgs(arena: Allocator, args: anytype) UserInputOptionsMap {
417 var map = UserInputOptionsMap.init(arena);417 var map = UserInputOptionsMap.init(arena);
418 inline for (@typeInfo(@TypeOf(args)).@"struct".fields) |field| {418 inline for (@typeInfo(@TypeOf(args)).@"struct".fields) |field| {
419 if (field.type == @Type(.null)) continue;419 if (field.type == @TypeOf(null)) continue;
420 addUserInputOptionFromArg(arena, &map, field, field.type, @field(args, field.name));420 addUserInputOptionFromArg(arena, &map, field, field.type, @field(args, field.name));
421 }421 }
422 return map;422 return map;
...@@ -526,16 +526,11 @@ fn addUserInputOptionFromArg(...@@ -526,16 +526,11 @@ fn addUserInputOptionFromArg(
526 .pointer => |ptr_info| switch (ptr_info.size) {526 .pointer => |ptr_info| switch (ptr_info.size) {
527 .one => switch (@typeInfo(ptr_info.child)) {527 .one => switch (@typeInfo(ptr_info.child)) {
528 .array => |array_info| {528 .array => |array_info| {
529 comptime var slice_info = ptr_info;
530 slice_info.size = .slice;
531 slice_info.is_const = true;
532 slice_info.child = array_info.child;
533 slice_info.sentinel_ptr = null;
534 addUserInputOptionFromArg(529 addUserInputOptionFromArg(
535 arena,530 arena,
536 map,531 map,
537 field,532 field,
538 @Type(.{ .pointer = slice_info }),533 @Pointer(.slice, .{ .@"const" = true }, array_info.child, null),
539 maybe_value orelse null,534 maybe_value orelse null,
540 );535 );
541 return;536 return;
...@@ -553,14 +548,11 @@ fn addUserInputOptionFromArg(...@@ -553,14 +548,11 @@ fn addUserInputOptionFromArg(
553 }) catch @panic("OOM");548 }) catch @panic("OOM");
554 },549 },
555 else => {550 else => {
556 comptime var slice_info = ptr_info;
557 slice_info.is_const = true;
558 slice_info.sentinel_ptr = null;
559 addUserInputOptionFromArg(551 addUserInputOptionFromArg(
560 arena,552 arena,
561 map,553 map,
562 field,554 field,
563 @Type(.{ .pointer = slice_info }),555 @Pointer(ptr_info.size, .{ .@"const" = true }, ptr_info.child, null),
564 maybe_value orelse null,556 maybe_value orelse null,
565 );557 );
566 return;558 return;
lib/std/Io.zig+8-32
...@@ -528,23 +528,7 @@ pub fn Poller(comptime StreamEnum: type) type {...@@ -528,23 +528,7 @@ pub fn Poller(comptime StreamEnum: type) type {
528/// Given an enum, returns a struct with fields of that enum, each field528/// Given an enum, returns a struct with fields of that enum, each field
529/// representing an I/O stream for polling.529/// representing an I/O stream for polling.
530pub fn PollFiles(comptime StreamEnum: type) type {530pub fn PollFiles(comptime StreamEnum: type) type {
531 const enum_fields = @typeInfo(StreamEnum).@"enum".fields;531 return @Struct(.auto, null, std.meta.fieldNames(StreamEnum), &@splat(std.fs.File), &@splat(.{}));
532 var struct_fields: [enum_fields.len]std.builtin.Type.StructField = undefined;
533 for (&struct_fields, enum_fields) |*struct_field, enum_field| {
534 struct_field.* = .{
535 .name = enum_field.name,
536 .type = std.fs.File,
537 .default_value_ptr = null,
538 .is_comptime = false,
539 .alignment = @alignOf(std.fs.File),
540 };
541 }
542 return @Type(.{ .@"struct" = .{
543 .layout = .auto,
544 .fields = &struct_fields,
545 .decls = &.{},
546 .is_tuple = false,
547 } });
548}532}
549533
550test {534test {
...@@ -1625,22 +1609,14 @@ pub fn sleep(io: Io, duration: Duration, clock: Clock) SleepError!void {...@@ -1625,22 +1609,14 @@ pub fn sleep(io: Io, duration: Duration, clock: Clock) SleepError!void {
1625/// fields, each field type the future's result.1609/// fields, each field type the future's result.
1626pub fn SelectUnion(S: type) type {1610pub fn SelectUnion(S: type) type {
1627 const struct_fields = @typeInfo(S).@"struct".fields;1611 const struct_fields = @typeInfo(S).@"struct".fields;
1628 var fields: [struct_fields.len]std.builtin.Type.UnionField = undefined;1612 var names: [struct_fields.len][]const u8 = undefined;
1629 for (&fields, struct_fields) |*union_field, struct_field| {1613 var types: [struct_fields.len]type = undefined;
1630 const F = @typeInfo(struct_field.type).pointer.child;1614 for (struct_fields, &names, &types) |struct_field, *union_field_name, *UnionFieldType| {
1631 const Result = @TypeOf(@as(F, undefined).result);1615 const FieldFuture = @typeInfo(struct_field.type).pointer.child;
1632 union_field.* = .{1616 union_field_name.* = struct_field.name;
1633 .name = struct_field.name,1617 UnionFieldType.* = @FieldType(FieldFuture, "result");
1634 .type = Result,
1635 .alignment = struct_field.alignment,
1636 };
1637 }1618 }
1638 return @Type(.{ .@"union" = .{1619 return @Union(.auto, std.meta.FieldEnum(S), &names, &types, &@splat(.{}));
1639 .layout = .auto,
1640 .tag_type = std.meta.FieldEnum(S),
1641 .fields = &fields,
1642 .decls = &.{},
1643 } });
1644}1620}
16451621
1646/// `s` is a struct with every field a `*Future(T)`, where `T` can be any type,1622/// `s` is a struct with every field a `*Future(T)`, where `T` can be any type,
lib/std/Io/Reader.zig+5-8
...@@ -1273,20 +1273,17 @@ pub const TakeLeb128Error = Error || error{Overflow};...@@ -1273,20 +1273,17 @@ pub const TakeLeb128Error = Error || error{Overflow};
1273/// Read a single LEB128 value as type T, or `error.Overflow` if the value cannot fit.1273/// Read a single LEB128 value as type T, or `error.Overflow` if the value cannot fit.
1274pub fn takeLeb128(r: *Reader, comptime Result: type) TakeLeb128Error!Result {1274pub fn takeLeb128(r: *Reader, comptime Result: type) TakeLeb128Error!Result {
1275 const result_info = @typeInfo(Result).int;1275 const result_info = @typeInfo(Result).int;
1276 return std.math.cast(Result, try r.takeMultipleOf7Leb128(@Type(.{ .int = .{1276 return std.math.cast(Result, try r.takeMultipleOf7Leb128(@Int(
1277 .signedness = result_info.signedness,1277 result_info.signedness,
1278 .bits = std.mem.alignForwardAnyAlign(u16, result_info.bits, 7),1278 std.mem.alignForwardAnyAlign(u16, result_info.bits, 7),
1279 } }))) orelse error.Overflow;1279 ))) orelse error.Overflow;
1280}1280}
12811281
1282fn takeMultipleOf7Leb128(r: *Reader, comptime Result: type) TakeLeb128Error!Result {1282fn takeMultipleOf7Leb128(r: *Reader, comptime Result: type) TakeLeb128Error!Result {
1283 const result_info = @typeInfo(Result).int;1283 const result_info = @typeInfo(Result).int;
1284 comptime assert(result_info.bits % 7 == 0);1284 comptime assert(result_info.bits % 7 == 0);
1285 var remaining_bits: std.math.Log2IntCeil(Result) = result_info.bits;1285 var remaining_bits: std.math.Log2IntCeil(Result) = result_info.bits;
1286 const UnsignedResult = @Type(.{ .int = .{1286 const UnsignedResult = @Int(.unsigned, result_info.bits);
1287 .signedness = .unsigned,
1288 .bits = result_info.bits,
1289 } });
1290 var result: UnsignedResult = 0;1287 var result: UnsignedResult = 0;
1291 var fits = true;1288 var fits = true;
1292 while (true) {1289 while (true) {
lib/std/Io/Writer.zig+10-10
...@@ -1890,7 +1890,7 @@ pub fn writeUleb128(w: *Writer, value: anytype) Error!void {...@@ -1890,7 +1890,7 @@ pub fn writeUleb128(w: *Writer, value: anytype) Error!void {
1890 try w.writeLeb128(switch (@typeInfo(@TypeOf(value))) {1890 try w.writeLeb128(switch (@typeInfo(@TypeOf(value))) {
1891 .comptime_int => @as(std.math.IntFittingRange(0, @abs(value)), value),1891 .comptime_int => @as(std.math.IntFittingRange(0, @abs(value)), value),
1892 .int => |value_info| switch (value_info.signedness) {1892 .int => |value_info| switch (value_info.signedness) {
1893 .signed => @as(@Type(.{ .int = .{ .signedness = .unsigned, .bits = value_info.bits -| 1 } }), @intCast(value)),1893 .signed => @as(@Int(.unsigned, value_info.bits -| 1), @intCast(value)),
1894 .unsigned => value,1894 .unsigned => value,
1895 },1895 },
1896 else => comptime unreachable,1896 else => comptime unreachable,
...@@ -1903,7 +1903,7 @@ pub fn writeSleb128(w: *Writer, value: anytype) Error!void {...@@ -1903,7 +1903,7 @@ pub fn writeSleb128(w: *Writer, value: anytype) Error!void {
1903 .comptime_int => @as(std.math.IntFittingRange(@min(value, -1), @max(0, value)), value),1903 .comptime_int => @as(std.math.IntFittingRange(@min(value, -1), @max(0, value)), value),
1904 .int => |value_info| switch (value_info.signedness) {1904 .int => |value_info| switch (value_info.signedness) {
1905 .signed => value,1905 .signed => value,
1906 .unsigned => @as(@Type(.{ .int = .{ .signedness = .signed, .bits = value_info.bits + 1 } }), value),1906 .unsigned => @as(@Int(.signed, value_info.bits + 1), value),
1907 },1907 },
1908 else => comptime unreachable,1908 else => comptime unreachable,
1909 });1909 });
...@@ -1912,10 +1912,10 @@ pub fn writeSleb128(w: *Writer, value: anytype) Error!void {...@@ -1912,10 +1912,10 @@ pub fn writeSleb128(w: *Writer, value: anytype) Error!void {
1912/// Write a single integer as LEB128 to the given writer.1912/// Write a single integer as LEB128 to the given writer.
1913pub fn writeLeb128(w: *Writer, value: anytype) Error!void {1913pub fn writeLeb128(w: *Writer, value: anytype) Error!void {
1914 const value_info = @typeInfo(@TypeOf(value)).int;1914 const value_info = @typeInfo(@TypeOf(value)).int;
1915 try w.writeMultipleOf7Leb128(@as(@Type(.{ .int = .{1915 try w.writeMultipleOf7Leb128(@as(@Int(
1916 .signedness = value_info.signedness,1916 value_info.signedness,
1917 .bits = @max(std.mem.alignForwardAnyAlign(u16, value_info.bits, 7), 7),1917 @max(std.mem.alignForwardAnyAlign(u16, value_info.bits, 7), 7),
1918 } }), value));1918 ), value));
1919}1919}
19201920
1921fn writeMultipleOf7Leb128(w: *Writer, value: anytype) Error!void {1921fn writeMultipleOf7Leb128(w: *Writer, value: anytype) Error!void {
...@@ -1929,10 +1929,10 @@ fn writeMultipleOf7Leb128(w: *Writer, value: anytype) Error!void {...@@ -1929,10 +1929,10 @@ fn writeMultipleOf7Leb128(w: *Writer, value: anytype) Error!void {
1929 .unsigned => remaining > std.math.maxInt(u7),1929 .unsigned => remaining > std.math.maxInt(u7),
1930 };1930 };
1931 byte.* = .{1931 byte.* = .{
1932 .bits = @bitCast(@as(@Type(.{ .int = .{1932 .bits = @bitCast(@as(
1933 .signedness = value_info.signedness,1933 @Int(value_info.signedness, 7),
1934 .bits = 7,1934 @truncate(remaining),
1935 } }), @truncate(remaining))),1935 )),
1936 .more = more,1936 .more = more,
1937 };1937 };
1938 if (value_info.bits > 7) remaining >>= 7;1938 if (value_info.bits > 7) remaining >>= 7;
lib/std/builtin.zig+50-9
...@@ -548,19 +548,19 @@ pub const TypeId = std.meta.Tag(Type);...@@ -548,19 +548,19 @@ pub const TypeId = std.meta.Tag(Type);
548/// This data structure is used by the Zig language code generation and548/// This data structure is used by the Zig language code generation and
549/// therefore must be kept in sync with the compiler implementation.549/// therefore must be kept in sync with the compiler implementation.
550pub const Type = union(enum) {550pub const Type = union(enum) {
551 type: void,551 type,
552 void: void,552 void,
553 bool: void,553 bool,
554 noreturn: void,554 noreturn,
555 int: Int,555 int: Int,
556 float: Float,556 float: Float,
557 pointer: Pointer,557 pointer: Pointer,
558 array: Array,558 array: Array,
559 @"struct": Struct,559 @"struct": Struct,
560 comptime_float: void,560 comptime_float,
561 comptime_int: void,561 comptime_int,
562 undefined: void,562 undefined,
563 null: void,563 null,
564 optional: Optional,564 optional: Optional,
565 error_union: ErrorUnion,565 error_union: ErrorUnion,
566 error_set: ErrorSet,566 error_set: ErrorSet,
...@@ -571,7 +571,7 @@ pub const Type = union(enum) {...@@ -571,7 +571,7 @@ pub const Type = union(enum) {
571 frame: Frame,571 frame: Frame,
572 @"anyframe": AnyFrame,572 @"anyframe": AnyFrame,
573 vector: Vector,573 vector: Vector,
574 enum_literal: void,574 enum_literal,
575575
576 /// This data structure is used by the Zig language code generation and576 /// This data structure is used by the Zig language code generation and
577 /// therefore must be kept in sync with the compiler implementation.577 /// therefore must be kept in sync with the compiler implementation.
...@@ -619,6 +619,16 @@ pub const Type = union(enum) {...@@ -619,6 +619,16 @@ pub const Type = union(enum) {
619 slice,619 slice,
620 c,620 c,
621 };621 };
622
623 /// This data structure is used by the Zig language code generation and
624 /// therefore must be kept in sync with the compiler implementation.
625 pub const Attributes = struct {
626 @"const": bool = false,
627 @"volatile": bool = false,
628 @"allowzero": bool = false,
629 @"addrspace": ?AddressSpace = null,
630 @"align": ?usize = null,
631 };
622 };632 };
623633
624 /// This data structure is used by the Zig language code generation and634 /// This data structure is used by the Zig language code generation and
...@@ -668,6 +678,14 @@ pub const Type = union(enum) {...@@ -668,6 +678,14 @@ pub const Type = union(enum) {
668 const dp: *const sf.type = @ptrCast(@alignCast(sf.default_value_ptr orelse return null));678 const dp: *const sf.type = @ptrCast(@alignCast(sf.default_value_ptr orelse return null));
669 return dp.*;679 return dp.*;
670 }680 }
681
682 /// This data structure is used by the Zig language code generation and
683 /// therefore must be kept in sync with the compiler implementation.
684 pub const Attributes = struct {
685 @"comptime": bool = false,
686 @"align": ?usize = null,
687 default_value_ptr: ?*const anyopaque = null,
688 };
671 };689 };
672690
673 /// This data structure is used by the Zig language code generation and691 /// This data structure is used by the Zig language code generation and
...@@ -718,6 +736,10 @@ pub const Type = union(enum) {...@@ -718,6 +736,10 @@ pub const Type = union(enum) {
718 fields: []const EnumField,736 fields: []const EnumField,
719 decls: []const Declaration,737 decls: []const Declaration,
720 is_exhaustive: bool,738 is_exhaustive: bool,
739
740 /// This data structure is used by the Zig language code generation and
741 /// therefore must be kept in sync with the compiler implementation.
742 pub const Mode = enum { exhaustive, nonexhaustive };
721 };743 };
722744
723 /// This data structure is used by the Zig language code generation and745 /// This data structure is used by the Zig language code generation and
...@@ -726,6 +748,12 @@ pub const Type = union(enum) {...@@ -726,6 +748,12 @@ pub const Type = union(enum) {
726 name: [:0]const u8,748 name: [:0]const u8,
727 type: type,749 type: type,
728 alignment: comptime_int,750 alignment: comptime_int,
751
752 /// This data structure is used by the Zig language code generation and
753 /// therefore must be kept in sync with the compiler implementation.
754 pub const Attributes = struct {
755 @"align": ?usize = null,
756 };
729 };757 };
730758
731 /// This data structure is used by the Zig language code generation and759 /// This data structure is used by the Zig language code generation and
...@@ -753,6 +781,19 @@ pub const Type = union(enum) {...@@ -753,6 +781,19 @@ pub const Type = union(enum) {
753 is_generic: bool,781 is_generic: bool,
754 is_noalias: bool,782 is_noalias: bool,
755 type: ?type,783 type: ?type,
784
785 /// This data structure is used by the Zig language code generation and
786 /// therefore must be kept in sync with the compiler implementation.
787 pub const Attributes = struct {
788 @"noalias": bool = false,
789 };
790 };
791
792 /// This data structure is used by the Zig language code generation and
793 /// therefore must be kept in sync with the compiler implementation.
794 pub const Attributes = struct {
795 @"callconv": CallingConvention = .auto,
796 varargs: bool = false,
756 };797 };
757 };798 };
758799
lib/std/crypto/phc_encoding.zig+4-4
...@@ -94,12 +94,12 @@ pub fn deserialize(comptime HashResult: type, str: []const u8) Error!HashResult...@@ -94,12 +94,12 @@ pub fn deserialize(comptime HashResult: type, str: []const u8) Error!HashResult
94 if (kvSplit(field)) |opt_version| {94 if (kvSplit(field)) |opt_version| {
95 if (mem.eql(u8, opt_version.key, version_param_name)) {95 if (mem.eql(u8, opt_version.key, version_param_name)) {
96 if (@hasField(HashResult, "alg_version")) {96 if (@hasField(HashResult, "alg_version")) {
97 const value_type_info = switch (@typeInfo(@TypeOf(out.alg_version))) {97 const ValueType = switch (@typeInfo(@TypeOf(out.alg_version))) {
98 .optional => |opt| @typeInfo(opt.child),98 .optional => |opt| opt.child,
99 else => |t| t,99 else => @TypeOf(out.alg_version),
100 };100 };
101 out.alg_version = fmt.parseUnsigned(101 out.alg_version = fmt.parseUnsigned(
102 @Type(value_type_info),102 ValueType,
103 opt_version.value,103 opt_version.value,
104 10,104 10,
105 ) catch return Error.InvalidEncoding;105 ) catch return Error.InvalidEncoding;
lib/std/crypto/tls.zig+1-1
...@@ -606,7 +606,7 @@ pub fn array(...@@ -606,7 +606,7 @@ pub fn array(
606 const elem_size = @divExact(@bitSizeOf(Elem), 8);606 const elem_size = @divExact(@bitSizeOf(Elem), 8);
607 var arr: [len_size + elem_size * elems.len]u8 = undefined;607 var arr: [len_size + elem_size * elems.len]u8 = undefined;
608 std.mem.writeInt(Len, arr[0..len_size], @intCast(elem_size * elems.len), .big);608 std.mem.writeInt(Len, arr[0..len_size], @intCast(elem_size * elems.len), .big);
609 const ElemInt = @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(Elem) } });609 const ElemInt = @Int(.unsigned, @bitSizeOf(Elem));
610 for (0.., @as([elems.len]Elem, elems)) |index, elem| {610 for (0.., @as([elems.len]Elem, elems)) |index, elem| {
611 std.mem.writeInt(611 std.mem.writeInt(
612 ElemInt,612 ElemInt,
lib/std/enums.zig+11-29
...@@ -33,22 +33,8 @@ pub fn fromInt(comptime E: type, integer: anytype) ?E {...@@ -33,22 +33,8 @@ pub fn fromInt(comptime E: type, integer: anytype) ?E {
33/// default, which may be undefined.33/// default, which may be undefined.
34pub fn EnumFieldStruct(comptime E: type, comptime Data: type, comptime field_default: ?Data) type {34pub fn EnumFieldStruct(comptime E: type, comptime Data: type, comptime field_default: ?Data) type {
35 @setEvalBranchQuota(@typeInfo(E).@"enum".fields.len + eval_branch_quota_cushion);35 @setEvalBranchQuota(@typeInfo(E).@"enum".fields.len + eval_branch_quota_cushion);
36 var struct_fields: [@typeInfo(E).@"enum".fields.len]std.builtin.Type.StructField = undefined;36 const default_ptr: ?*const anyopaque = if (field_default) |d| @ptrCast(&d) else null;
37 for (&struct_fields, @typeInfo(E).@"enum".fields) |*struct_field, enum_field| {37 return @Struct(.auto, null, std.meta.fieldNames(E), &@splat(Data), &@splat(.{ .default_value_ptr = default_ptr }));
38 struct_field.* = .{
39 .name = enum_field.name,
40 .type = Data,
41 .default_value_ptr = if (field_default) |d| @as(?*const anyopaque, @ptrCast(&d)) else null,
42 .is_comptime = false,
43 .alignment = if (@sizeOf(Data) > 0) @alignOf(Data) else 0,
44 };
45 }
46 return @Type(.{ .@"struct" = .{
47 .layout = .auto,
48 .fields = &struct_fields,
49 .decls = &.{},
50 .is_tuple = false,
51 } });
52}38}
5339
54/// Looks up the supplied fields in the given enum type.40/// Looks up the supplied fields in the given enum type.
...@@ -1532,19 +1518,15 @@ test "EnumIndexer empty" {...@@ -1532,19 +1518,15 @@ test "EnumIndexer empty" {
1532test "EnumIndexer large dense unsorted" {1518test "EnumIndexer large dense unsorted" {
1533 @setEvalBranchQuota(500_000); // many `comptimePrint`s1519 @setEvalBranchQuota(500_000); // many `comptimePrint`s
1534 // Make an enum with 500 fields with values in *descending* order.1520 // Make an enum with 500 fields with values in *descending* order.
1535 const E = @Type(.{ .@"enum" = .{1521 const E = @Enum(u32, .exhaustive, names: {
1536 .tag_type = u32,1522 var names: [500][]const u8 = undefined;
1537 .fields = comptime fields: {1523 for (&names, 0..) |*name, i| name.* = std.fmt.comptimePrint("f{d}", .{i});
1538 var fields: [500]EnumField = undefined;1524 break :names &names;
1539 for (&fields, 0..) |*f, i| f.* = .{1525 }, vals: {
1540 .name = std.fmt.comptimePrint("f{d}", .{i}),1526 var vals: [500]u32 = undefined;
1541 .value = 500 - i,1527 for (&vals, 0..) |*val, i| val.* = 500 - i;
1542 };1528 break :vals &vals;
1543 break :fields &fields;1529 });
1544 },
1545 .decls = &.{},
1546 .is_exhaustive = true,
1547 } });
1548 const Indexer = EnumIndexer(E);1530 const Indexer = EnumIndexer(E);
1549 try testing.expectEqual(E.f0, Indexer.keyForIndex(499));1531 try testing.expectEqual(E.f0, Indexer.keyForIndex(499));
1550 try testing.expectEqual(E.f499, Indexer.keyForIndex(0));1532 try testing.expectEqual(E.f499, Indexer.keyForIndex(0));
lib/std/fmt.zig+1-1
...@@ -279,7 +279,7 @@ pub fn Alt(...@@ -279,7 +279,7 @@ pub fn Alt(
279/// Helper for calling alternate format methods besides one named "format".279/// Helper for calling alternate format methods besides one named "format".
280pub fn alt(280pub fn alt(
281 context: anytype,281 context: anytype,
282 comptime func_name: @TypeOf(.enum_literal),282 comptime func_name: @EnumLiteral(),
283) Alt(@TypeOf(context), @field(@TypeOf(context), @tagName(func_name))) {283) Alt(@TypeOf(context), @field(@TypeOf(context), @tagName(func_name))) {
284 return .{ .data = context };284 return .{ .data = context };
285}285}
lib/std/fmt/float.zig+2-2
...@@ -61,7 +61,7 @@ pub fn render(buf: []u8, value: anytype, options: Options) Error![]const u8 {...@@ -61,7 +61,7 @@ pub fn render(buf: []u8, value: anytype, options: Options) Error![]const u8 {
6161
62 const T = @TypeOf(v);62 const T = @TypeOf(v);
63 comptime std.debug.assert(@typeInfo(T) == .float);63 comptime std.debug.assert(@typeInfo(T) == .float);
64 const I = @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(T) } });64 const I = @Int(.unsigned, @bitSizeOf(T));
6565
66 const DT = if (@bitSizeOf(T) <= 64) u64 else u128;66 const DT = if (@bitSizeOf(T) <= 64) u64 else u128;
67 const tables = switch (DT) {67 const tables = switch (DT) {
...@@ -1516,7 +1516,7 @@ const FLOAT128_POW5_INV_ERRORS: [154]u64 = .{...@@ -1516,7 +1516,7 @@ const FLOAT128_POW5_INV_ERRORS: [154]u64 = .{
1516const builtin = @import("builtin");1516const builtin = @import("builtin");
15171517
1518fn check(comptime T: type, value: T, comptime expected: []const u8) !void {1518fn check(comptime T: type, value: T, comptime expected: []const u8) !void {
1519 const I = @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(T) } });1519 const I = @Int(.unsigned, @bitSizeOf(T));
15201520
1521 var buf: [6000]u8 = undefined;1521 var buf: [6000]u8 = undefined;
1522 const value_bits: I = @bitCast(value);1522 const value_bits: I = @bitCast(value);
lib/std/hash.zig+1-1
...@@ -42,7 +42,7 @@ pub fn int(input: anytype) @TypeOf(input) {...@@ -42,7 +42,7 @@ pub fn int(input: anytype) @TypeOf(input) {
42 const info = @typeInfo(@TypeOf(input)).int;42 const info = @typeInfo(@TypeOf(input)).int;
43 const bits = info.bits;43 const bits = info.bits;
44 // Convert input to unsigned integer (easier to deal with)44 // Convert input to unsigned integer (easier to deal with)
45 const Uint = @Type(.{ .int = .{ .bits = bits, .signedness = .unsigned } });45 const Uint = @Int(.unsigned, bits);
46 const u_input: Uint = @bitCast(input);46 const u_input: Uint = @bitCast(input);
47 if (bits > 256) @compileError("bit widths > 256 are unsupported, use std.hash.autoHash functionality.");47 if (bits > 256) @compileError("bit widths > 256 are unsupported, use std.hash.autoHash functionality.");
48 // For bit widths that don't have a dedicated function, use a heuristic48 // For bit widths that don't have a dedicated function, use a heuristic
lib/std/hash/auto_hash.zig+1-4
...@@ -91,10 +91,7 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {...@@ -91,10 +91,7 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {
91 // Help the optimizer see that hashing an int is easy by inlining!91 // Help the optimizer see that hashing an int is easy by inlining!
92 // TODO Check if the situation is better after #561 is resolved.92 // TODO Check if the situation is better after #561 is resolved.
93 .int => |int| switch (int.signedness) {93 .int => |int| switch (int.signedness) {
94 .signed => hash(hasher, @as(@Type(.{ .int = .{94 .signed => hash(hasher, @as(@Int(.unsigned, int.bits), @bitCast(key)), strat),
95 .bits = int.bits,
96 .signedness = .unsigned,
97 } }), @bitCast(key)), strat),
98 .unsigned => {95 .unsigned => {
99 if (std.meta.hasUniqueRepresentation(Key)) {96 if (std.meta.hasUniqueRepresentation(Key)) {
100 @call(.always_inline, Hasher.update, .{ hasher, std.mem.asBytes(&key) });97 @call(.always_inline, Hasher.update, .{ hasher, std.mem.asBytes(&key) });
lib/std/log.zig+5-5
...@@ -57,13 +57,13 @@ pub const default_level: Level = switch (builtin.mode) {...@@ -57,13 +57,13 @@ pub const default_level: Level = switch (builtin.mode) {
57};57};
5858
59pub const ScopeLevel = struct {59pub const ScopeLevel = struct {
60 scope: @Type(.enum_literal),60 scope: @EnumLiteral(),
61 level: Level,61 level: Level,
62};62};
6363
64fn log(64fn log(
65 comptime level: Level,65 comptime level: Level,
66 comptime scope: @Type(.enum_literal),66 comptime scope: @EnumLiteral(),
67 comptime format: []const u8,67 comptime format: []const u8,
68 args: anytype,68 args: anytype,
69) void {69) void {
...@@ -73,7 +73,7 @@ fn log(...@@ -73,7 +73,7 @@ fn log(
73}73}
7474
75/// Determine if a specific log message level and scope combination are enabled for logging.75/// Determine if a specific log message level and scope combination are enabled for logging.
76pub fn logEnabled(comptime level: Level, comptime scope: @Type(.enum_literal)) bool {76pub fn logEnabled(comptime level: Level, comptime scope: @EnumLiteral()) bool {
77 inline for (std.options.log_scope_levels) |scope_level| {77 inline for (std.options.log_scope_levels) |scope_level| {
78 if (scope_level.scope == scope) return @intFromEnum(level) <= @intFromEnum(scope_level.level);78 if (scope_level.scope == scope) return @intFromEnum(level) <= @intFromEnum(scope_level.level);
79 }79 }
...@@ -87,7 +87,7 @@ pub fn logEnabled(comptime level: Level, comptime scope: @Type(.enum_literal)) b...@@ -87,7 +87,7 @@ pub fn logEnabled(comptime level: Level, comptime scope: @Type(.enum_literal)) b
87/// function returns.87/// function returns.
88pub fn defaultLog(88pub fn defaultLog(
89 comptime level: Level,89 comptime level: Level,
90 comptime scope: @Type(.enum_literal),90 comptime scope: @EnumLiteral(),
91 comptime format: []const u8,91 comptime format: []const u8,
92 args: anytype,92 args: anytype,
93) void {93) void {
...@@ -115,7 +115,7 @@ pub fn defaultLog(...@@ -115,7 +115,7 @@ pub fn defaultLog(
115115
116/// Returns a scoped logging namespace that logs all messages using the scope116/// Returns a scoped logging namespace that logs all messages using the scope
117/// provided here.117/// provided here.
118pub fn scoped(comptime scope: @Type(.enum_literal)) type {118pub fn scoped(comptime scope: @EnumLiteral()) type {
119 return struct {119 return struct {
120 /// Log an error message. This log level is intended to be used120 /// Log an error message. This log level is intended to be used
121 /// when something has gone wrong. This might be recoverable or might121 /// when something has gone wrong. This might be recoverable or might
lib/std/math.zig+13-13
...@@ -450,12 +450,7 @@ pub fn wrap(x: anytype, r: anytype) @TypeOf(x) {...@@ -450,12 +450,7 @@ pub fn wrap(x: anytype, r: anytype) @TypeOf(x) {
450 // in the rare usecase of r not being comptime_int or float,450 // in the rare usecase of r not being comptime_int or float,
451 // take the penalty of having an intermediary type conversion,451 // take the penalty of having an intermediary type conversion,
452 // otherwise the alternative is to unwind iteratively to avoid overflow452 // otherwise the alternative is to unwind iteratively to avoid overflow
453 const R = comptime do: {453 const R = @Int(.signed, info_r.int.bits + 1);
454 var info = info_r;
455 info.int.bits += 1;
456 info.int.signedness = .signed;
457 break :do @Type(info);
458 };
459 const radius: if (info_r.int.signedness == .signed) @TypeOf(r) else R = r;454 const radius: if (info_r.int.signedness == .signed) @TypeOf(r) else R = r;
460 return @intCast(@mod(x - radius, 2 * @as(R, r)) - r); // provably impossible to overflow455 return @intCast(@mod(x - radius, 2 * @as(R, r)) - r); // provably impossible to overflow
461 },456 },
...@@ -799,14 +794,14 @@ pub fn Log2IntCeil(comptime T: type) type {...@@ -799,14 +794,14 @@ pub fn Log2IntCeil(comptime T: type) type {
799pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) type {794pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) type {
800 assert(from <= to);795 assert(from <= to);
801 const signedness: std.builtin.Signedness = if (from < 0) .signed else .unsigned;796 const signedness: std.builtin.Signedness = if (from < 0) .signed else .unsigned;
802 return @Type(.{ .int = .{797 return @Int(
803 .signedness = signedness,798 signedness,
804 .bits = @as(u16, @intFromBool(signedness == .signed)) +799 @as(u16, @intFromBool(signedness == .signed)) +
805 switch (if (from < 0) @max(@abs(from) - 1, to) else to) {800 switch (if (from < 0) @max(@abs(from) - 1, to) else to) {
806 0 => 0,801 0 => 0,
807 else => |pos_max| 1 + log2(pos_max),802 else => |pos_max| 1 + log2(pos_max),
808 },803 },
809 } });804 );
810}805}
811806
812test IntFittingRange {807test IntFittingRange {
...@@ -1107,9 +1102,14 @@ test cast {...@@ -1107,9 +1102,14 @@ test cast {
1107pub const AlignCastError = error{UnalignedMemory};1102pub const AlignCastError = error{UnalignedMemory};
11081103
1109fn AlignCastResult(comptime alignment: Alignment, comptime Ptr: type) type {1104fn AlignCastResult(comptime alignment: Alignment, comptime Ptr: type) type {
1110 var ptr_info = @typeInfo(Ptr);1105 const orig = @typeInfo(Ptr).pointer;
1111 ptr_info.pointer.alignment = alignment.toByteUnits();1106 return @Pointer(orig.size, .{
1112 return @Type(ptr_info);1107 .@"const" = orig.is_const,
1108 .@"volatile" = orig.is_volatile,
1109 .@"allowzero" = orig.is_allowzero,
1110 .@"align" = alignment.toByteUnits(),
1111 .@"addrspace" = orig.address_space,
1112 }, orig.child, orig.sentinel());
1113}1113}
11141114
1115/// Align cast a pointer but return an error if it's the wrong alignment1115/// Align cast a pointer but return an error if it's the wrong alignment
lib/std/math/big/int_test.zig+2-2
...@@ -2787,11 +2787,11 @@ test "bitNotWrap more than two limbs" {...@@ -2787,11 +2787,11 @@ test "bitNotWrap more than two limbs" {
2787 const bits = @bitSizeOf(Limb) * 4 + 2;2787 const bits = @bitSizeOf(Limb) * 4 + 2;
27882788
2789 try res.bitNotWrap(&a, .unsigned, bits);2789 try res.bitNotWrap(&a, .unsigned, bits);
2790 const Unsigned = @Type(.{ .int = .{ .signedness = .unsigned, .bits = bits } });2790 const Unsigned = @Int(.unsigned, bits);
2791 try testing.expectEqual((try res.toInt(Unsigned)), ~@as(Unsigned, maxInt(Limb)));2791 try testing.expectEqual((try res.toInt(Unsigned)), ~@as(Unsigned, maxInt(Limb)));
27922792
2793 try res.bitNotWrap(&a, .signed, bits);2793 try res.bitNotWrap(&a, .signed, bits);
2794 const Signed = @Type(.{ .int = .{ .signedness = .signed, .bits = bits } });2794 const Signed = @Int(.signed, bits);
2795 try testing.expectEqual((try res.toInt(Signed)), ~@as(Signed, maxInt(Limb)));2795 try testing.expectEqual((try res.toInt(Signed)), ~@as(Signed, maxInt(Limb)));
2796}2796}
27972797
lib/std/math/float.zig+8-26
...@@ -14,22 +14,10 @@ pub fn FloatRepr(comptime Float: type) type {...@@ -14,22 +14,10 @@ pub fn FloatRepr(comptime Float: type) type {
14 exponent: BiasedExponent,14 exponent: BiasedExponent,
15 sign: std.math.Sign,15 sign: std.math.Sign,
1616
17 pub const StoredMantissa = @Type(.{ .int = .{17 pub const StoredMantissa = @Int(.unsigned, floatMantissaBits(Float));
18 .signedness = .unsigned,18 pub const Mantissa = @Int(.unsigned, 1 + fractional_bits);
19 .bits = floatMantissaBits(Float),19 pub const Exponent = @Int(.signed, exponent_bits);
20 } });20 pub const BiasedExponent = enum(@Int(.unsigned, exponent_bits)) {
21 pub const Mantissa = @Type(.{ .int = .{
22 .signedness = .unsigned,
23 .bits = 1 + fractional_bits,
24 } });
25 pub const Exponent = @Type(.{ .int = .{
26 .signedness = .signed,
27 .bits = exponent_bits,
28 } });
29 pub const BiasedExponent = enum(@Type(.{ .int = .{
30 .signedness = .unsigned,
31 .bits = exponent_bits,
32 } })) {
33 denormal = 0,21 denormal = 0,
34 min_normal = 1,22 min_normal = 1,
35 zero = (1 << (exponent_bits - 1)) - 1,23 zero = (1 << (exponent_bits - 1)) - 1,
...@@ -56,14 +44,8 @@ pub fn FloatRepr(comptime Float: type) type {...@@ -56,14 +44,8 @@ pub fn FloatRepr(comptime Float: type) type {
56 fraction: Fraction,44 fraction: Fraction,
57 exponent: Normalized.Exponent,45 exponent: Normalized.Exponent,
5846
59 pub const Fraction = @Type(.{ .int = .{47 pub const Fraction = @Int(.unsigned, fractional_bits);
60 .signedness = .unsigned,48 pub const Exponent = @Int(.signed, 1 + exponent_bits);
61 .bits = fractional_bits,
62 } });
63 pub const Exponent = @Type(.{ .int = .{
64 .signedness = .signed,
65 .bits = 1 + exponent_bits,
66 } });
6749
68 /// This currently truncates denormal values, which needs to be fixed before this can be used to50 /// This currently truncates denormal values, which needs to be fixed before this can be used to
69 /// produce a rounded value.51 /// produce a rounded value.
...@@ -122,7 +104,7 @@ inline fn mantissaOne(comptime T: type) comptime_int {...@@ -122,7 +104,7 @@ inline fn mantissaOne(comptime T: type) comptime_int {
122104
123/// Creates floating point type T from an unbiased exponent and raw mantissa.105/// Creates floating point type T from an unbiased exponent and raw mantissa.
124inline fn reconstructFloat(comptime T: type, comptime exponent: comptime_int, comptime mantissa: comptime_int) T {106inline fn reconstructFloat(comptime T: type, comptime exponent: comptime_int, comptime mantissa: comptime_int) T {
125 const TBits = @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(T) } });107 const TBits = @Int(.unsigned, @bitSizeOf(T));
126 const biased_exponent = @as(TBits, exponent + floatExponentMax(T));108 const biased_exponent = @as(TBits, exponent + floatExponentMax(T));
127 return @as(T, @bitCast((biased_exponent << floatMantissaBits(T)) | @as(TBits, mantissa)));109 return @as(T, @bitCast((biased_exponent << floatMantissaBits(T)) | @as(TBits, mantissa)));
128}110}
...@@ -209,7 +191,7 @@ pub inline fn floatEps(comptime T: type) T {...@@ -209,7 +191,7 @@ pub inline fn floatEps(comptime T: type) T {
209pub inline fn floatEpsAt(comptime T: type, x: T) T {191pub inline fn floatEpsAt(comptime T: type, x: T) T {
210 switch (@typeInfo(T)) {192 switch (@typeInfo(T)) {
211 .float => |F| {193 .float => |F| {
212 const U: type = @Type(.{ .int = .{ .signedness = .unsigned, .bits = F.bits } });194 const U: type = @Int(.unsigned, F.bits);
213 const u: U = @bitCast(x);195 const u: U = @bitCast(x);
214 const y: T = @bitCast(u ^ 1);196 const y: T = @bitCast(u ^ 1);
215 return @abs(x - y);197 return @abs(x - y);
lib/std/math/log2.zig+1-4
...@@ -33,10 +33,7 @@ pub fn log2(x: anytype) @TypeOf(x) {...@@ -33,10 +33,7 @@ pub fn log2(x: anytype) @TypeOf(x) {
33 return result;33 return result;
34 },34 },
35 .int => |int_info| math.log2_int(switch (int_info.signedness) {35 .int => |int_info| math.log2_int(switch (int_info.signedness) {
36 .signed => @Type(.{ .int = .{36 .signed => @Int(.unsigned, int_info.bits -| 1),
37 .signedness = .unsigned,
38 .bits = int_info.bits -| 1,
39 } }),
40 .unsigned => T,37 .unsigned => T,
41 }, @intCast(x)),38 }, @intCast(x)),
42 else => @compileError("log2 not implemented for " ++ @typeName(T)),39 else => @compileError("log2 not implemented for " ++ @typeName(T)),
lib/std/math/log_int.zig+1-1
...@@ -65,7 +65,7 @@ test "log_int" {...@@ -65,7 +65,7 @@ test "log_int" {
65 // Test all unsigned integers with 2, 3, ..., 64 bits.65 // Test all unsigned integers with 2, 3, ..., 64 bits.
66 // We cannot test 0 or 1 bits since base must be > 1.66 // We cannot test 0 or 1 bits since base must be > 1.
67 inline for (2..64 + 1) |bits| {67 inline for (2..64 + 1) |bits| {
68 const T = @Type(.{ .int = .{ .signedness = .unsigned, .bits = @intCast(bits) } });68 const T = @Int(.unsigned, @intCast(bits));
6969
70 // for base = 2, 3, ..., min(maxInt(T),1024)70 // for base = 2, 3, ..., min(maxInt(T),1024)
71 var base: T = 1;71 var base: T = 1;
lib/std/math/signbit.zig+1-4
...@@ -6,10 +6,7 @@ const expect = std.testing.expect;...@@ -6,10 +6,7 @@ const expect = std.testing.expect;
6pub fn signbit(x: anytype) bool {6pub fn signbit(x: anytype) bool {
7 return switch (@typeInfo(@TypeOf(x))) {7 return switch (@typeInfo(@TypeOf(x))) {
8 .int, .comptime_int => x,8 .int, .comptime_int => x,
9 .float => |float| @as(@Type(.{ .int = .{9 .float => |float| @as(@Int(.signed, float.bits), @bitCast(x)),
10 .signedness = .signed,
11 .bits = float.bits,
12 } }), @bitCast(x)),
13 .comptime_float => @as(i128, @bitCast(@as(f128, x))), // any float type will do10 .comptime_float => @as(i128, @bitCast(@as(f128, x))), // any float type will do
14 else => @compileError("std.math.signbit does not support " ++ @typeName(@TypeOf(x))),11 else => @compileError("std.math.signbit does not support " ++ @typeName(@TypeOf(x))),
15 } < 0;12 } < 0;
lib/std/math/sqrt.zig+1-1
...@@ -80,7 +80,7 @@ test sqrt_int {...@@ -80,7 +80,7 @@ test sqrt_int {
80/// Returns the return type `sqrt` will return given an operand of type `T`.80/// Returns the return type `sqrt` will return given an operand of type `T`.
81pub fn Sqrt(comptime T: type) type {81pub fn Sqrt(comptime T: type) type {
82 return switch (@typeInfo(T)) {82 return switch (@typeInfo(T)) {
83 .int => |int| @Type(.{ .int = .{ .signedness = .unsigned, .bits = (int.bits + 1) / 2 } }),83 .int => |int| @Int(.unsigned, (int.bits + 1) / 2),
84 else => T,84 else => T,
85 };85 };
86}86}
lib/std/mem.zig+57-106
...@@ -846,17 +846,18 @@ fn Span(comptime T: type) type {...@@ -846,17 +846,18 @@ fn Span(comptime T: type) type {
846 return ?Span(optional_info.child);846 return ?Span(optional_info.child);
847 },847 },
848 .pointer => |ptr_info| {848 .pointer => |ptr_info| {
849 var new_ptr_info = ptr_info;849 const new_sentinel: ?ptr_info.child = switch (ptr_info.size) {
850 switch (ptr_info.size) {
851 .c => {
852 new_ptr_info.sentinel_ptr = &@as(ptr_info.child, 0);
853 new_ptr_info.is_allowzero = false;
854 },
855 .many => if (ptr_info.sentinel() == null) @compileError("invalid type given to std.mem.span: " ++ @typeName(T)),
856 .one, .slice => @compileError("invalid type given to std.mem.span: " ++ @typeName(T)),850 .one, .slice => @compileError("invalid type given to std.mem.span: " ++ @typeName(T)),
857 }851 .many => ptr_info.sentinel() orelse @compileError("invalid type given to std.mem.span: " ++ @typeName(T)),
858 new_ptr_info.size = .slice;852 .c => 0,
859 return @Type(.{ .pointer = new_ptr_info });853 };
854 return @Pointer(.slice, .{
855 .@"const" = ptr_info.is_const,
856 .@"volatile" = ptr_info.is_volatile,
857 .@"allowzero" = ptr_info.is_allowzero and ptr_info.size != .c,
858 .@"align" = ptr_info.alignment,
859 .@"addrspace" = ptr_info.address_space,
860 }, ptr_info.child, new_sentinel);
860 },861 },
861 else => {},862 else => {},
862 }863 }
...@@ -910,45 +911,18 @@ fn SliceTo(comptime T: type, comptime end: std.meta.Elem(T)) type {...@@ -910,45 +911,18 @@ fn SliceTo(comptime T: type, comptime end: std.meta.Elem(T)) type {
910 return ?SliceTo(optional_info.child, end);911 return ?SliceTo(optional_info.child, end);
911 },912 },
912 .pointer => |ptr_info| {913 .pointer => |ptr_info| {
913 var new_ptr_info = ptr_info;914 const Elem = std.meta.Elem(T);
914 new_ptr_info.size = .slice;915 const have_sentinel: bool = switch (ptr_info.size) {
915 switch (ptr_info.size) {916 .one, .slice, .many => if (std.meta.sentinel(T)) |s| s == end else false,
916 .one => switch (@typeInfo(ptr_info.child)) {917 .c => false,
917 .array => |array_info| {918 };
918 new_ptr_info.child = array_info.child;919 return @Pointer(.slice, .{
919 // The return type must only be sentinel terminated if we are guaranteed920 .@"const" = ptr_info.is_const,
920 // to find the value searched for, which is only the case if it matches921 .@"volatile" = ptr_info.is_volatile,
921 // the sentinel of the type passed.922 .@"allowzero" = ptr_info.is_allowzero and ptr_info.size != .c,
922 if (array_info.sentinel()) |s| {923 .@"align" = ptr_info.alignment,
923 if (end == s) {924 .@"addrspace" = ptr_info.address_space,
924 new_ptr_info.sentinel_ptr = &end;925 }, Elem, if (have_sentinel) end else null);
925 } else {
926 new_ptr_info.sentinel_ptr = null;
927 }
928 }
929 },
930 else => {},
931 },
932 .many, .slice => {
933 // The return type must only be sentinel terminated if we are guaranteed
934 // to find the value searched for, which is only the case if it matches
935 // the sentinel of the type passed.
936 if (ptr_info.sentinel()) |s| {
937 if (end == s) {
938 new_ptr_info.sentinel_ptr = &end;
939 } else {
940 new_ptr_info.sentinel_ptr = null;
941 }
942 }
943 },
944 .c => {
945 new_ptr_info.sentinel_ptr = &end;
946 // C pointers are always allowzero, but we don't want the return type to be.
947 assert(new_ptr_info.is_allowzero);
948 new_ptr_info.is_allowzero = false;
949 },
950 }
951 return @Type(.{ .pointer = new_ptr_info });
952 },926 },
953 else => {},927 else => {},
954 }928 }
...@@ -3951,38 +3925,25 @@ test reverse {...@@ -3951,38 +3925,25 @@ test reverse {
3951 }3925 }
3952}3926}
3953fn ReverseIterator(comptime T: type) type {3927fn ReverseIterator(comptime T: type) type {
3954 const Pointer = blk: {3928 const ptr = switch (@typeInfo(T)) {
3955 switch (@typeInfo(T)) {3929 .pointer => |ptr| ptr,
3956 .pointer => |ptr_info| switch (ptr_info.size) {3930 else => @compileError("expected slice or pointer to array, found '" ++ @typeName(T) ++ "'"),
3957 .one => switch (@typeInfo(ptr_info.child)) {
3958 .array => |array_info| {
3959 var new_ptr_info = ptr_info;
3960 new_ptr_info.size = .many;
3961 new_ptr_info.child = array_info.child;
3962 new_ptr_info.sentinel_ptr = array_info.sentinel_ptr;
3963 break :blk @Type(.{ .pointer = new_ptr_info });
3964 },
3965 else => {},
3966 },
3967 .slice => {
3968 var new_ptr_info = ptr_info;
3969 new_ptr_info.size = .many;
3970 break :blk @Type(.{ .pointer = new_ptr_info });
3971 },
3972 else => {},
3973 },
3974 else => {},
3975 }
3976 @compileError("expected slice or pointer to array, found '" ++ @typeName(T) ++ "'");
3977 };3931 };
3978 const Element = std.meta.Elem(Pointer);3932 switch (ptr.size) {
3979 const ElementPointer = @Type(.{ .pointer = ptr: {3933 .slice => {},
3980 var ptr = @typeInfo(Pointer).pointer;3934 .one => if (@typeInfo(ptr.child) != .array) @compileError("expected slice or pointer to array, found '" ++ @typeName(T) ++ "'"),
3981 ptr.size = .one;3935 .many, .c => @compileError("expected slice or pointer to array, found '" ++ @typeName(T) ++ "'"),
3982 ptr.child = Element;3936 }
3983 ptr.sentinel_ptr = null;3937 const Element = std.meta.Elem(T);
3984 break :ptr ptr;3938 const attrs: std.builtin.Type.Pointer.Attributes = .{
3985 } });3939 .@"const" = ptr.is_const,
3940 .@"volatile" = ptr.is_volatile,
3941 .@"allowzero" = ptr.is_allowzero,
3942 .@"align" = ptr.alignment,
3943 .@"addrspace" = ptr.address_space,
3944 };
3945 const Pointer = @Pointer(.many, attrs, Element, std.meta.sentinel(T));
3946 const ElementPointer = @Pointer(.one, attrs, Element, null);
3986 return struct {3947 return struct {
3987 ptr: Pointer,3948 ptr: Pointer,
3988 index: usize,3949 index: usize,
...@@ -4342,19 +4303,14 @@ fn CopyPtrAttrs(...@@ -4342,19 +4303,14 @@ fn CopyPtrAttrs(
4342 comptime size: std.builtin.Type.Pointer.Size,4303 comptime size: std.builtin.Type.Pointer.Size,
4343 comptime child: type,4304 comptime child: type,
4344) type {4305) type {
4345 const info = @typeInfo(source).pointer;4306 const ptr = @typeInfo(source).pointer;
4346 return @Type(.{4307 return @Pointer(size, .{
4347 .pointer = .{4308 .@"const" = ptr.is_const,
4348 .size = size,4309 .@"volatile" = ptr.is_volatile,
4349 .is_const = info.is_const,4310 .@"allowzero" = ptr.is_allowzero,
4350 .is_volatile = info.is_volatile,4311 .@"align" = ptr.alignment,
4351 .is_allowzero = info.is_allowzero,4312 .@"addrspace" = ptr.address_space,
4352 .alignment = info.alignment,4313 }, child, null);
4353 .address_space = info.address_space,
4354 .child = child,
4355 .sentinel_ptr = null,
4356 },
4357 });
4358}4314}
43594315
4360fn AsBytesReturnType(comptime P: type) type {4316fn AsBytesReturnType(comptime P: type) type {
...@@ -4936,19 +4892,14 @@ test "freeing empty string with null-terminated sentinel" {...@@ -4936,19 +4892,14 @@ test "freeing empty string with null-terminated sentinel" {
4936/// Returns a slice with the given new alignment,4892/// Returns a slice with the given new alignment,
4937/// all other pointer attributes copied from `AttributeSource`.4893/// all other pointer attributes copied from `AttributeSource`.
4938fn AlignedSlice(comptime AttributeSource: type, comptime new_alignment: usize) type {4894fn AlignedSlice(comptime AttributeSource: type, comptime new_alignment: usize) type {
4939 const info = @typeInfo(AttributeSource).pointer;4895 const ptr = @typeInfo(AttributeSource).pointer;
4940 return @Type(.{4896 return @Pointer(.slice, .{
4941 .pointer = .{4897 .@"const" = ptr.is_const,
4942 .size = .slice,4898 .@"volatile" = ptr.is_volatile,
4943 .is_const = info.is_const,4899 .@"allowzero" = ptr.is_allowzero,
4944 .is_volatile = info.is_volatile,4900 .@"align" = new_alignment,
4945 .is_allowzero = info.is_allowzero,4901 .@"addrspace" = ptr.address_space,
4946 .alignment = new_alignment,4902 }, ptr.child, null);
4947 .address_space = info.address_space,
4948 .child = info.child,
4949 .sentinel_ptr = null,
4950 },
4951 });
4952}4903}
49534904
4954/// Returns the largest slice in the given bytes that conforms to the new alignment,4905/// Returns the largest slice in the given bytes that conforms to the new alignment,
lib/std/meta.zig+52-136
...@@ -171,58 +171,34 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {...@@ -171,58 +171,34 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
171 switch (@typeInfo(T)) {171 switch (@typeInfo(T)) {
172 .pointer => |info| switch (info.size) {172 .pointer => |info| switch (info.size) {
173 .one => switch (@typeInfo(info.child)) {173 .one => switch (@typeInfo(info.child)) {
174 .array => |array_info| return @Type(.{174 .array => |array_info| return @Pointer(.one, .{
175 .pointer = .{175 .@"const" = info.is_const,
176 .size = info.size,176 .@"volatile" = info.is_volatile,
177 .is_const = info.is_const,177 .@"allowzero" = info.is_allowzero,
178 .is_volatile = info.is_volatile,178 .@"align" = info.alignment,
179 .alignment = info.alignment,179 .@"addrspace" = info.address_space,
180 .address_space = info.address_space,180 }, [array_info.len:sentinel_val]array_info.child, null),
181 .child = @Type(.{
182 .array = .{
183 .len = array_info.len,
184 .child = array_info.child,
185 .sentinel_ptr = @as(?*const anyopaque, @ptrCast(&sentinel_val)),
186 },
187 }),
188 .is_allowzero = info.is_allowzero,
189 .sentinel_ptr = info.sentinel_ptr,
190 },
191 }),
192 else => {},181 else => {},
193 },182 },
194 .many, .slice => return @Type(.{183 .many, .slice => |size| return @Pointer(size, .{
195 .pointer = .{184 .@"const" = info.is_const,
196 .size = info.size,185 .@"volatile" = info.is_volatile,
197 .is_const = info.is_const,186 .@"allowzero" = info.is_allowzero,
198 .is_volatile = info.is_volatile,187 .@"align" = info.alignment,
199 .alignment = info.alignment,188 .@"addrspace" = info.address_space,
200 .address_space = info.address_space,189 }, info.child, sentinel_val),
201 .child = info.child,
202 .is_allowzero = info.is_allowzero,
203 .sentinel_ptr = @as(?*const anyopaque, @ptrCast(&sentinel_val)),
204 },
205 }),
206 else => {},190 else => {},
207 },191 },
208 .optional => |info| switch (@typeInfo(info.child)) {192 .optional => |info| switch (@typeInfo(info.child)) {
209 .pointer => |ptr_info| switch (ptr_info.size) {193 .pointer => |ptr_info| switch (ptr_info.size) {
210 .many => return @Type(.{194 .many => return ?@Pointer(.many, .{
211 .optional = .{195 .@"const" = ptr_info.is_const,
212 .child = @Type(.{196 .@"volatile" = ptr_info.is_volatile,
213 .pointer = .{197 .@"allowzero" = ptr_info.is_allowzero,
214 .size = ptr_info.size,198 .@"align" = ptr_info.alignment,
215 .is_const = ptr_info.is_const,199 .@"addrspace" = ptr_info.address_space,
216 .is_volatile = ptr_info.is_volatile,200 .child = ptr_info.child,
217 .alignment = ptr_info.alignment,201 }, ptr_info.child, sentinel_val),
218 .address_space = ptr_info.address_space,
219 .child = ptr_info.child,
220 .is_allowzero = ptr_info.is_allowzero,
221 .sentinel_ptr = @as(?*const anyopaque, @ptrCast(&sentinel_val)),
222 },
223 }),
224 },
225 }),
226 else => {},202 else => {},
227 },203 },
228 else => {},204 else => {},
...@@ -487,46 +463,22 @@ test tags {...@@ -487,46 +463,22 @@ test tags {
487463
488/// Returns an enum with a variant named after each field of `T`.464/// Returns an enum with a variant named after each field of `T`.
489pub fn FieldEnum(comptime T: type) type {465pub fn FieldEnum(comptime T: type) type {
490 const field_infos = fields(T);466 const field_names = fieldNames(T);
491
492 if (field_infos.len == 0) {
493 return @Type(.{
494 .@"enum" = .{
495 .tag_type = u0,
496 .fields = &.{},
497 .decls = &.{},
498 .is_exhaustive = true,
499 },
500 });
501 }
502467
503 if (@typeInfo(T) == .@"union") {468 switch (@typeInfo(T)) {
504 if (@typeInfo(T).@"union".tag_type) |tag_type| {469 .@"union" => |@"union"| if (@"union".tag_type) |EnumTag| {
505 for (std.enums.values(tag_type), 0..) |v, i| {470 for (std.enums.values(EnumTag), 0..) |v, i| {
506 if (@intFromEnum(v) != i) break; // enum values not consecutive471 if (@intFromEnum(v) != i) break; // enum values not consecutive
507 if (!std.mem.eql(u8, @tagName(v), field_infos[i].name)) break; // fields out of order472 if (!std.mem.eql(u8, @tagName(v), field_names[i])) break; // fields out of order
508 } else {473 } else {
509 return tag_type;474 return EnumTag;
510 }475 }
511 }476 },
477 else => {},
512 }478 }
513479
514 var enumFields: [field_infos.len]std.builtin.Type.EnumField = undefined;480 const IntTag = std.math.IntFittingRange(0, field_names.len -| 1);
515 var decls = [_]std.builtin.Type.Declaration{};481 return @Enum(IntTag, .exhaustive, field_names, &std.simd.iota(IntTag, field_names.len));
516 inline for (field_infos, 0..) |field, i| {
517 enumFields[i] = .{
518 .name = field.name,
519 .value = i,
520 };
521 }
522 return @Type(.{
523 .@"enum" = .{
524 .tag_type = std.math.IntFittingRange(0, field_infos.len - 1),
525 .fields = &enumFields,
526 .decls = &decls,
527 .is_exhaustive = true,
528 },
529 });
530}482}
531483
532fn expectEqualEnum(expected: anytype, actual: @TypeOf(expected)) !void {484fn expectEqualEnum(expected: anytype, actual: @TypeOf(expected)) !void {
...@@ -583,20 +535,11 @@ test FieldEnum {...@@ -583,20 +535,11 @@ test FieldEnum {
583}535}
584536
585pub fn DeclEnum(comptime T: type) type {537pub fn DeclEnum(comptime T: type) type {
586 const fieldInfos = std.meta.declarations(T);538 const decls = declarations(T);
587 var enumDecls: [fieldInfos.len]std.builtin.Type.EnumField = undefined;539 var names: [decls.len][]const u8 = undefined;
588 var decls = [_]std.builtin.Type.Declaration{};540 for (&names, decls) |*name, decl| name.* = decl.name;
589 inline for (fieldInfos, 0..) |field, i| {541 const IntTag = std.math.IntFittingRange(0, decls.len -| 1);
590 enumDecls[i] = .{ .name = field.name, .value = i };542 return @Enum(IntTag, .exhaustive, &names, &std.simd.iota(IntTag, decls.len));
591 }
592 return @Type(.{
593 .@"enum" = .{
594 .tag_type = std.math.IntFittingRange(0, if (fieldInfos.len == 0) 0 else fieldInfos.len - 1),
595 .fields = &enumDecls,
596 .decls = &decls,
597 .is_exhaustive = true,
598 },
599 });
600}543}
601544
602test DeclEnum {545test DeclEnum {
...@@ -868,25 +811,26 @@ pub fn declList(comptime Namespace: type, comptime Decl: type) []const *const De...@@ -868,25 +811,26 @@ pub fn declList(comptime Namespace: type, comptime Decl: type) []const *const De
868 }811 }
869}812}
870813
814/// Deprecated: use @Int
871pub fn Int(comptime signedness: std.builtin.Signedness, comptime bit_count: u16) type {815pub fn Int(comptime signedness: std.builtin.Signedness, comptime bit_count: u16) type {
872 return @Type(.{816 return @Int(signedness, bit_count);
873 .int = .{
874 .signedness = signedness,
875 .bits = bit_count,
876 },
877 });
878}817}
879818
880pub fn Float(comptime bit_count: u8) type {819pub fn Float(comptime bit_count: u8) type {
881 return @Type(.{820 return switch (bit_count) {
882 .float = .{ .bits = bit_count },821 16 => f16,
883 });822 32 => f32,
823 64 => f64,
824 80 => f80,
825 128 => f128,
826 else => @compileError("invalid float bit count"),
827 };
884}828}
885
886test Float {829test Float {
887 try testing.expectEqual(f16, Float(16));830 try testing.expectEqual(f16, Float(16));
888 try testing.expectEqual(f32, Float(32));831 try testing.expectEqual(f32, Float(32));
889 try testing.expectEqual(f64, Float(64));832 try testing.expectEqual(f64, Float(64));
833 try testing.expectEqual(f80, Float(80));
890 try testing.expectEqual(f128, Float(128));834 try testing.expectEqual(f128, Float(128));
891}835}
892836
...@@ -912,42 +856,14 @@ pub fn ArgsTuple(comptime Function: type) type {...@@ -912,42 +856,14 @@ pub fn ArgsTuple(comptime Function: type) type {
912 argument_field_list[i] = T;856 argument_field_list[i] = T;
913 }857 }
914858
915 return CreateUniqueTuple(argument_field_list.len, argument_field_list);859 return Tuple(&argument_field_list);
916}860}
917861
918/// For a given anonymous list of types, returns a new tuple type862/// Deprecated; use `@Tuple` instead.
919/// with those types as fields.
920///863///
921/// Examples:864/// To be removed after Zig 0.16.0 releases.
922/// - `Tuple(&[_]type {})` ⇒ `tuple { }`
923/// - `Tuple(&[_]type {f32})` ⇒ `tuple { f32 }`
924/// - `Tuple(&[_]type {f32,u32})` ⇒ `tuple { f32, u32 }`
925pub fn Tuple(comptime types: []const type) type {865pub fn Tuple(comptime types: []const type) type {
926 return CreateUniqueTuple(types.len, types[0..types.len].*);866 return @Tuple(types);
927}
928
929fn CreateUniqueTuple(comptime N: comptime_int, comptime types: [N]type) type {
930 var tuple_fields: [types.len]std.builtin.Type.StructField = undefined;
931 inline for (types, 0..) |T, i| {
932 @setEvalBranchQuota(10_000);
933 var num_buf: [128]u8 = undefined;
934 tuple_fields[i] = .{
935 .name = std.fmt.bufPrintSentinel(&num_buf, "{d}", .{i}, 0) catch unreachable,
936 .type = T,
937 .default_value_ptr = null,
938 .is_comptime = false,
939 .alignment = @alignOf(T),
940 };
941 }
942
943 return @Type(.{
944 .@"struct" = .{
945 .is_tuple = true,
946 .layout = .auto,
947 .decls = &.{},
948 .fields = &tuple_fields,
949 },
950 });
951}867}
952868
953const TupleTester = struct {869const TupleTester = struct {
lib/std/meta/trailer_flags.zig+9-17
...@@ -20,24 +20,16 @@ pub fn TrailerFlags(comptime Fields: type) type {...@@ -20,24 +20,16 @@ pub fn TrailerFlags(comptime Fields: type) type {
2020
21 pub const ActiveFields = std.enums.EnumFieldStruct(FieldEnum, bool, false);21 pub const ActiveFields = std.enums.EnumFieldStruct(FieldEnum, bool, false);
22 pub const FieldValues = blk: {22 pub const FieldValues = blk: {
23 var fields: [bit_count]Type.StructField = undefined;23 var field_names: [bit_count][]const u8 = undefined;
24 for (@typeInfo(Fields).@"struct".fields, 0..) |struct_field, i| {24 var field_types: [bit_count]type = undefined;
25 fields[i] = Type.StructField{25 var field_attrs: [bit_count]std.builtin.Type.StructField.Attributes = undefined;
26 .name = struct_field.name,26 for (@typeInfo(Fields).@"struct".fields, &field_names, &field_types, &field_attrs) |field, *new_name, *NewType, *new_attrs| {
27 .type = ?struct_field.type,27 new_name.* = field.name;
28 .default_value_ptr = &@as(?struct_field.type, null),28 NewType.* = ?field.type;
29 .is_comptime = false,29 const default: ?field.type = null;
30 .alignment = @alignOf(?struct_field.type),30 new_attrs.* = .{ .default_value_ptr = &default };
31 };
32 }31 }
33 break :blk @Type(.{32 break :blk @Struct(.auto, null, &field_names, &field_types, &field_attrs);
34 .@"struct" = .{
35 .layout = .auto,
36 .fields = &fields,
37 .decls = &.{},
38 .is_tuple = false,
39 },
40 });
41 };33 };
4234
43 pub const Self = @This();35 pub const Self = @This();
lib/std/multi_array_list.zig+26-37
...@@ -32,12 +32,17 @@ pub fn MultiArrayList(comptime T: type) type {...@@ -32,12 +32,17 @@ pub fn MultiArrayList(comptime T: type) type {
32 const Elem = switch (@typeInfo(T)) {32 const Elem = switch (@typeInfo(T)) {
33 .@"struct" => T,33 .@"struct" => T,
34 .@"union" => |u| struct {34 .@"union" => |u| struct {
35 pub const Bare = @Type(.{ .@"union" = .{35 pub const Bare = Bare: {
36 .layout = u.layout,36 var field_names: [u.fields.len][]const u8 = undefined;
37 .tag_type = null,37 var field_types: [u.fields.len]type = undefined;
38 .fields = u.fields,38 var field_attrs: [u.fields.len]std.builtin.Type.UnionField.Attributes = undefined;
39 .decls = &.{},39 for (u.fields, &field_names, &field_types, &field_attrs) |field, *name, *Type, *attrs| {
40 } });40 name.* = field.name;
41 Type.* = field.type;
42 attrs.* = .{ .@"align" = field.alignment };
43 }
44 break :Bare @Union(u.layout, null, &field_names, &field_types, &field_attrs);
45 };
41 pub const Tag =46 pub const Tag =
42 u.tag_type orelse @compileError("MultiArrayList does not support untagged unions");47 u.tag_type orelse @compileError("MultiArrayList does not support untagged unions");
43 tags: Tag,48 tags: Tag,
...@@ -609,20 +614,18 @@ pub fn MultiArrayList(comptime T: type) type {...@@ -609,20 +614,18 @@ pub fn MultiArrayList(comptime T: type) type {
609 }614 }
610615
611 const Entry = entry: {616 const Entry = entry: {
612 var entry_fields: [fields.len]std.builtin.Type.StructField = undefined;617 var field_names: [fields.len][]const u8 = undefined;
613 for (&entry_fields, sizes.fields) |*entry_field, i| entry_field.* = .{618 var field_types: [fields.len]type = undefined;
614 .name = fields[i].name ++ "_ptr",619 var field_attrs: [fields.len]std.builtin.Type.StructField.Attributes = undefined;
615 .type = *fields[i].type,620 for (sizes.fields, &field_names, &field_types, &field_attrs) |i, *name, *Type, *attrs| {
616 .default_value_ptr = null,621 name.* = fields[i].name ++ "_ptr";
617 .is_comptime = fields[i].is_comptime,622 Type.* = *fields[i].type;
618 .alignment = fields[i].alignment,623 attrs.* = .{
619 };624 .@"comptime" = fields[i].is_comptime,
620 break :entry @Type(.{ .@"struct" = .{625 .@"align" = fields[i].alignment,
621 .layout = .@"extern",626 };
622 .fields = &entry_fields,627 }
623 .decls = &.{},628 break :entry @Struct(.@"extern", null, &field_names, &field_types, &field_attrs);
624 .is_tuple = false,
625 } });
626 };629 };
627 /// This function is used in the debugger pretty formatters in tools/ to fetch the630 /// This function is used in the debugger pretty formatters in tools/ to fetch the
628 /// child field order and entry type to facilitate fancy debug printing for this type.631 /// child field order and entry type to facilitate fancy debug printing for this type.
...@@ -1023,23 +1026,9 @@ test "struct with many fields" {...@@ -1023,23 +1026,9 @@ test "struct with many fields" {
1023 const ManyFields = struct {1026 const ManyFields = struct {
1024 fn Type(count: comptime_int) type {1027 fn Type(count: comptime_int) type {
1025 @setEvalBranchQuota(50000);1028 @setEvalBranchQuota(50000);
1026 var fields: [count]std.builtin.Type.StructField = undefined;1029 var field_names: [count][]const u8 = undefined;
1027 for (0..count) |i| {1030 for (&field_names, 0..) |*n, i| n.* = std.fmt.comptimePrint("a{d}", .{i});
1028 fields[i] = .{1031 return @Struct(.@"extern", null, &field_names, &@splat(u32), &@splat(.{}));
1029 .name = std.fmt.comptimePrint("a{}", .{i}),
1030 .type = u32,
1031 .default_value_ptr = null,
1032 .is_comptime = false,
1033 .alignment = @alignOf(u32),
1034 };
1035 }
1036 const info: std.builtin.Type = .{ .@"struct" = .{
1037 .layout = .auto,
1038 .fields = &fields,
1039 .decls = &.{},
1040 .is_tuple = false,
1041 } };
1042 return @Type(info);
1043 }1032 }
10441033
1045 fn doTest(ally: std.mem.Allocator, count: comptime_int) !void {1034 fn doTest(ally: std.mem.Allocator, count: comptime_int) !void {
lib/std/std.zig+1-1
...@@ -124,7 +124,7 @@ pub const Options = struct {...@@ -124,7 +124,7 @@ pub const Options = struct {
124124
125 logFn: fn (125 logFn: fn (
126 comptime message_level: log.Level,126 comptime message_level: log.Level,
127 comptime scope: @TypeOf(.enum_literal),127 comptime scope: @EnumLiteral(),
128 comptime format: []const u8,128 comptime format: []const u8,
129 args: anytype,129 args: anytype,
130 ) void = log.defaultLog,130 ) void = log.defaultLog,
lib/std/zig.zig+40-24
...@@ -773,7 +773,6 @@ pub const EnvVar = enum {...@@ -773,7 +773,6 @@ pub const EnvVar = enum {
773pub const SimpleComptimeReason = enum(u32) {773pub const SimpleComptimeReason = enum(u32) {
774 // Evaluating at comptime because a builtin operand must be comptime-known.774 // Evaluating at comptime because a builtin operand must be comptime-known.
775 // These messages all mention a specific builtin.775 // These messages all mention a specific builtin.
776 operand_Type,
777 operand_setEvalBranchQuota,776 operand_setEvalBranchQuota,
778 operand_setFloatMode,777 operand_setFloatMode,
779 operand_branchHint,778 operand_branchHint,
...@@ -809,25 +808,34 @@ pub const SimpleComptimeReason = enum(u32) {...@@ -809,25 +808,34 @@ pub const SimpleComptimeReason = enum(u32) {
809 // Evaluating at comptime because types must be comptime-known.808 // Evaluating at comptime because types must be comptime-known.
810 // Reasons other than `.type` are just more specific messages.809 // Reasons other than `.type` are just more specific messages.
811 type,810 type,
811 int_signedness,
812 int_bit_width,
812 array_sentinel,813 array_sentinel,
814 array_length,
815 pointer_size,
816 pointer_attrs,
813 pointer_sentinel,817 pointer_sentinel,
814 slice_sentinel,818 slice_sentinel,
815 array_length,
816 vector_length,819 vector_length,
817 error_set_contents,820 fn_ret_ty,
818 struct_fields,821 fn_param_types,
819 enum_fields,822 fn_param_attrs,
820 union_fields,823 fn_attrs,
821 function_ret_ty,824 struct_layout,
822 function_parameters,825 struct_field_names,
826 struct_field_types,
827 struct_field_attrs,
828 union_layout,
829 union_field_names,
830 union_field_types,
831 union_field_attrs,
832 tuple_field_types,
833 enum_field_names,
834 enum_field_values,
823835
824 // Evaluating at comptime because decl/field name must be comptime-known.836 // Evaluating at comptime because decl/field name must be comptime-known.
825 decl_name,837 decl_name,
826 field_name,838 field_name,
827 struct_field_name,
828 enum_field_name,
829 union_field_name,
830 tuple_field_name,
831 tuple_field_index,839 tuple_field_index,
832840
833 // Evaluating at comptime because it is an attribute of a global declaration.841 // Evaluating at comptime because it is an attribute of a global declaration.
...@@ -856,7 +864,6 @@ pub const SimpleComptimeReason = enum(u32) {...@@ -856,7 +864,6 @@ pub const SimpleComptimeReason = enum(u32) {
856 pub fn message(r: SimpleComptimeReason) []const u8 {864 pub fn message(r: SimpleComptimeReason) []const u8 {
857 return switch (r) {865 return switch (r) {
858 // zig fmt: off866 // zig fmt: off
859 .operand_Type => "operand to '@Type' must be comptime-known",
860 .operand_setEvalBranchQuota => "operand to '@setEvalBranchQuota' must be comptime-known",867 .operand_setEvalBranchQuota => "operand to '@setEvalBranchQuota' must be comptime-known",
861 .operand_setFloatMode => "operand to '@setFloatMode' must be comptime-known",868 .operand_setFloatMode => "operand to '@setFloatMode' must be comptime-known",
862 .operand_branchHint => "operand to '@branchHint' must be comptime-known",869 .operand_branchHint => "operand to '@branchHint' must be comptime-known",
...@@ -888,24 +895,33 @@ pub const SimpleComptimeReason = enum(u32) {...@@ -888,24 +895,33 @@ pub const SimpleComptimeReason = enum(u32) {
888 .clobber => "clobber must be comptime-known",895 .clobber => "clobber must be comptime-known",
889896
890 .type => "types must be comptime-known",897 .type => "types must be comptime-known",
898 .int_signedness => "integer signedness must be comptime-known",
899 .int_bit_width => "integer bit width must be comptime-known",
891 .array_sentinel => "array sentinel value must be comptime-known",900 .array_sentinel => "array sentinel value must be comptime-known",
901 .array_length => "array length must be comptime-known",
902 .pointer_size => "pointer size must be comptime-known",
903 .pointer_attrs => "pointer attributes must be comptime-known",
892 .pointer_sentinel => "pointer sentinel value must be comptime-known",904 .pointer_sentinel => "pointer sentinel value must be comptime-known",
893 .slice_sentinel => "slice sentinel value must be comptime-known",905 .slice_sentinel => "slice sentinel value must be comptime-known",
894 .array_length => "array length must be comptime-known",
895 .vector_length => "vector length must be comptime-known",906 .vector_length => "vector length must be comptime-known",
896 .error_set_contents => "error set contents must be comptime-known",907 .fn_ret_ty => "function return type must be comptime-known",
897 .struct_fields => "struct fields must be comptime-known",908 .fn_param_types => "function parameter types must be comptime-known",
898 .enum_fields => "enum fields must be comptime-known",909 .fn_param_attrs => "function parameter attributes must be comptime-known",
899 .union_fields => "union fields must be comptime-known",910 .fn_attrs => "function attributes must be comptime-known",
900 .function_ret_ty => "function return type must be comptime-known",911 .struct_layout => "struct layout must be comptime-known",
901 .function_parameters => "function parameters must be comptime-known",912 .struct_field_names => "struct field names must be comptime-known",
913 .struct_field_types => "struct field types must be comptime-known",
914 .struct_field_attrs => "struct field attributes must be comptime-known",
915 .union_layout => "union layout must be comptime-known",
916 .union_field_names => "union field names must be comptime-known",
917 .union_field_types => "union field types must be comptime-known",
918 .union_field_attrs => "union field attributes must be comptime-known",
919 .tuple_field_types => "tuple field types must be comptime-known",
920 .enum_field_names => "enum field names must be comptime-known",
921 .enum_field_values => "enum field values must be comptime-known",
902922
903 .decl_name => "declaration name must be comptime-known",923 .decl_name => "declaration name must be comptime-known",
904 .field_name => "field name must be comptime-known",924 .field_name => "field name must be comptime-known",
905 .struct_field_name => "struct field name must be comptime-known",
906 .enum_field_name => "enum field name must be comptime-known",
907 .union_field_name => "union field name must be comptime-known",
908 .tuple_field_name => "tuple field name must be comptime-known",
909 .tuple_field_index => "tuple field index must be comptime-known",925 .tuple_field_index => "tuple field index must be comptime-known",
910926
911 .container_var_init => "initializer of container-level variable must be comptime-known",927 .container_var_init => "initializer of container-level variable must be comptime-known",
lib/std/zig/AstGen.zig+150-46
...@@ -833,7 +833,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -833,7 +833,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
833 => {833 => {
834 var buf: [2]Ast.Node.Index = undefined;834 var buf: [2]Ast.Node.Index = undefined;
835 const params = tree.builtinCallParams(&buf, node).?;835 const params = tree.builtinCallParams(&buf, node).?;
836 return builtinCall(gz, scope, ri, node, params, false);836 return builtinCall(gz, scope, ri, node, params, false, .anon);
837 },837 },
838838
839 .call_one,839 .call_one,
...@@ -1194,14 +1194,20 @@ fn nameStratExpr(...@@ -1194,14 +1194,20 @@ fn nameStratExpr(
1194 },1194 },
1195 .builtin_call_two,1195 .builtin_call_two,
1196 .builtin_call_two_comma,1196 .builtin_call_two_comma,
1197 .builtin_call,
1198 .builtin_call_comma,
1197 => {1199 => {
1198 const builtin_token = tree.nodeMainToken(node);1200 const builtin_token = tree.nodeMainToken(node);
1199 const builtin_name = tree.tokenSlice(builtin_token);1201 const builtin_name = tree.tokenSlice(builtin_token);
1200 if (!std.mem.eql(u8, builtin_name, "@Type")) return null;1202 const info = BuiltinFn.list.get(builtin_name) orelse return null;
1201 var buf: [2]Ast.Node.Index = undefined;1203 switch (info.tag) {
1202 const params = tree.builtinCallParams(&buf, node).?;1204 .Enum, .Struct, .Union => {
1203 if (params.len != 1) return null; // let `builtinCall` error1205 var buf: [2]Ast.Node.Index = undefined;
1204 return try builtinReify(gz, scope, ri, node, params[0], name_strat);1206 const params = tree.builtinCallParams(&buf, node).?;
1207 return try builtinCall(gz, scope, ri, node, params, false, name_strat);
1208 },
1209 else => return null,
1210 }
1205 },1211 },
1206 else => return null,1212 else => return null,
1207 }1213 }
...@@ -1406,7 +1412,7 @@ fn fnProtoExprInner(...@@ -1406,7 +1412,7 @@ fn fnProtoExprInner(
1406 .none;1412 .none;
14071413
1408 const ret_ty_node = fn_proto.ast.return_type.unwrap().?;1414 const ret_ty_node = fn_proto.ast.return_type.unwrap().?;
1409 const ret_ty = try comptimeExpr(&block_scope, scope, coerced_type_ri, ret_ty_node, .function_ret_ty);1415 const ret_ty = try comptimeExpr(&block_scope, scope, coerced_type_ri, ret_ty_node, .fn_ret_ty);
14101416
1411 const result = try block_scope.addFunc(.{1417 const result = try block_scope.addFunc(.{
1412 .src_node = fn_proto.ast.proto_node,1418 .src_node = fn_proto.ast.proto_node,
...@@ -2629,7 +2635,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod...@@ -2629,7 +2635,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
2629 const params = tree.builtinCallParams(&buf, inner_node).?;2635 const params = tree.builtinCallParams(&buf, inner_node).?;
26302636
2631 try emitDbgNode(gz, inner_node);2637 try emitDbgNode(gz, inner_node);
2632 const result = try builtinCall(gz, scope, .{ .rl = .none }, inner_node, params, allow_branch_hint);2638 const result = try builtinCall(gz, scope, .{ .rl = .none }, inner_node, params, allow_branch_hint, .anon);
2633 noreturn_src_node = try addEnsureResult(gz, result, inner_node);2639 noreturn_src_node = try addEnsureResult(gz, result, inner_node);
2634 },2640 },
26352641
...@@ -2707,6 +2713,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2707,6 +2713,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2707 .elem_type,2713 .elem_type,
2708 .indexable_ptr_elem_type,2714 .indexable_ptr_elem_type,
2709 .splat_op_result_ty,2715 .splat_op_result_ty,
2716 .reify_int,
2710 .vector_type,2717 .vector_type,
2711 .indexable_ptr_len,2718 .indexable_ptr_len,
2712 .anyframe_type,2719 .anyframe_type,
...@@ -8942,7 +8949,7 @@ fn unionInit(...@@ -8942,7 +8949,7 @@ fn unionInit(
8942 params: []const Ast.Node.Index,8949 params: []const Ast.Node.Index,
8943) InnerError!Zir.Inst.Ref {8950) InnerError!Zir.Inst.Ref {
8944 const union_type = try typeExpr(gz, scope, params[0]);8951 const union_type = try typeExpr(gz, scope, params[0]);
8945 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .union_field_name);8952 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .union_field_names);
8946 const field_type = try gz.addPlNode(.field_type_ref, node, Zir.Inst.FieldTypeRef{8953 const field_type = try gz.addPlNode(.field_type_ref, node, Zir.Inst.FieldTypeRef{
8947 .container_type = union_type,8954 .container_type = union_type,
8948 .field_name = field_name,8955 .field_name = field_name,
...@@ -9210,6 +9217,7 @@ fn builtinCall(...@@ -9210,6 +9217,7 @@ fn builtinCall(
9210 node: Ast.Node.Index,9217 node: Ast.Node.Index,
9211 params: []const Ast.Node.Index,9218 params: []const Ast.Node.Index,
9212 allow_branch_hint: bool,9219 allow_branch_hint: bool,
9220 reify_name_strat: Zir.Inst.NameStrategy,
9213) InnerError!Zir.Inst.Ref {9221) InnerError!Zir.Inst.Ref {
9214 const astgen = gz.astgen;9222 const astgen = gz.astgen;
9215 const tree = astgen.tree;9223 const tree = astgen.tree;
...@@ -9443,9 +9451,140 @@ fn builtinCall(...@@ -9443,9 +9451,140 @@ fn builtinCall(
9443 return rvalue(gz, ri, try gz.addNodeExtended(.in_comptime, node), node);9451 return rvalue(gz, ri, try gz.addNodeExtended(.in_comptime, node), node);
9444 },9452 },
94459453
9446 .Type => {9454 .EnumLiteral => return rvalue(gz, ri, .enum_literal_type, node),
9447 return builtinReify(gz, scope, ri, node, params[0], .anon);9455 .Int => {
9456 const signedness_ty = try gz.addBuiltinValue(node, .signedness);
9457 const result = try gz.addPlNode(.reify_int, node, Zir.Inst.Bin{
9458 .lhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = signedness_ty } }, params[0], .int_signedness),
9459 .rhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, params[1], .int_bit_width),
9460 });
9461 return rvalue(gz, ri, result, node);
9462 },
9463 .Tuple => {
9464 const result = try gz.addExtendedPayload(.reify_tuple, Zir.Inst.UnNode{
9465 .node = gz.nodeIndexToRelative(node),
9466 .operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_type_type } }, params[0], .tuple_field_types),
9467 });
9468 return rvalue(gz, ri, result, node);
9469 },
9470 .Pointer => {
9471 const ptr_size_ty = try gz.addBuiltinValue(node, .pointer_size);
9472 const ptr_attrs_ty = try gz.addBuiltinValue(node, .pointer_attributes);
9473 const size = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = ptr_size_ty } }, params[0], .pointer_size);
9474 const attrs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = ptr_attrs_ty } }, params[1], .pointer_attrs);
9475 const elem_ty = try typeExpr(gz, scope, params[2]);
9476 const sentinel_ty = try gz.addExtendedPayload(.reify_pointer_sentinel_ty, Zir.Inst.UnNode{
9477 .node = gz.nodeIndexToRelative(params[2]),
9478 .operand = elem_ty,
9479 });
9480 const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = sentinel_ty } }, params[3], .pointer_sentinel);
9481 const result = try gz.addExtendedPayload(.reify_pointer, Zir.Inst.ReifyPointer{
9482 .node = gz.nodeIndexToRelative(node),
9483 .size = size,
9484 .attrs = attrs,
9485 .elem_ty = elem_ty,
9486 .sentinel = sentinel,
9487 });
9488 return rvalue(gz, ri, result, node);
9448 },9489 },
9490 .Fn => {
9491 const fn_attrs_ty = try gz.addBuiltinValue(node, .fn_attributes);
9492 const param_types = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_type_type } }, params[0], .fn_param_types);
9493 const param_attrs_ty = try gz.addExtendedPayloadSmall(
9494 .reify_slice_arg_ty,
9495 @intFromEnum(Zir.Inst.ReifySliceArgInfo.type_to_fn_param_attrs),
9496 Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(params[0]), .operand = param_types },
9497 );
9498 const param_attrs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = param_attrs_ty } }, params[1], .fn_param_attrs);
9499 const ret_ty = try comptimeExpr(gz, scope, coerced_type_ri, params[2], .fn_ret_ty);
9500 const fn_attrs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = fn_attrs_ty } }, params[3], .fn_attrs);
9501 const result = try gz.addExtendedPayload(.reify_fn, Zir.Inst.ReifyFn{
9502 .node = gz.nodeIndexToRelative(node),
9503 .param_types = param_types,
9504 .param_attrs = param_attrs,
9505 .ret_ty = ret_ty,
9506 .fn_attrs = fn_attrs,
9507 });
9508 return rvalue(gz, ri, result, node);
9509 },
9510 .Struct => {
9511 const container_layout_ty = try gz.addBuiltinValue(node, .container_layout);
9512 const layout = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = container_layout_ty } }, params[0], .struct_layout);
9513 const backing_ty = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .optional_type_type } }, params[1], .type);
9514 const field_names = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_slice_const_u8_type } }, params[2], .struct_field_names);
9515 const field_types_ty = try gz.addExtendedPayloadSmall(
9516 .reify_slice_arg_ty,
9517 @intFromEnum(Zir.Inst.ReifySliceArgInfo.string_to_struct_field_type),
9518 Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(params[2]), .operand = field_names },
9519 );
9520 const field_attrs_ty = try gz.addExtendedPayloadSmall(
9521 .reify_slice_arg_ty,
9522 @intFromEnum(Zir.Inst.ReifySliceArgInfo.string_to_struct_field_attrs),
9523 Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(params[2]), .operand = field_names },
9524 );
9525 const field_types = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_types_ty } }, params[3], .struct_field_types);
9526 const field_attrs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_attrs_ty } }, params[4], .struct_field_attrs);
9527 const result = try gz.addExtendedPayloadSmall(.reify_struct, @intFromEnum(reify_name_strat), Zir.Inst.ReifyStruct{
9528 .src_line = gz.astgen.source_line,
9529 .node = node,
9530 .layout = layout,
9531 .backing_ty = backing_ty,
9532 .field_names = field_names,
9533 .field_types = field_types,
9534 .field_attrs = field_attrs,
9535 });
9536 return rvalue(gz, ri, result, node);
9537 },
9538 .Union => {
9539 const container_layout_ty = try gz.addBuiltinValue(node, .container_layout);
9540 const layout = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = container_layout_ty } }, params[0], .union_layout);
9541 const arg_ty = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .optional_type_type } }, params[1], .type);
9542 const field_names = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_slice_const_u8_type } }, params[2], .union_field_names);
9543 const field_types_ty = try gz.addExtendedPayloadSmall(
9544 .reify_slice_arg_ty,
9545 @intFromEnum(Zir.Inst.ReifySliceArgInfo.string_to_union_field_type),
9546 Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(params[2]), .operand = field_names },
9547 );
9548 const field_attrs_ty = try gz.addExtendedPayloadSmall(
9549 .reify_slice_arg_ty,
9550 @intFromEnum(Zir.Inst.ReifySliceArgInfo.string_to_union_field_attrs),
9551 Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(params[2]), .operand = field_names },
9552 );
9553 const field_types = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_types_ty } }, params[3], .union_field_types);
9554 const field_attrs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_attrs_ty } }, params[4], .union_field_attrs);
9555 const result = try gz.addExtendedPayloadSmall(.reify_union, @intFromEnum(reify_name_strat), Zir.Inst.ReifyUnion{
9556 .src_line = gz.astgen.source_line,
9557 .node = node,
9558 .layout = layout,
9559 .arg_ty = arg_ty,
9560 .field_names = field_names,
9561 .field_types = field_types,
9562 .field_attrs = field_attrs,
9563 });
9564 return rvalue(gz, ri, result, node);
9565 },
9566 .Enum => {
9567 const enum_mode_ty = try gz.addBuiltinValue(node, .enum_mode);
9568 const tag_ty = try typeExpr(gz, scope, params[0]);
9569 const mode = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = enum_mode_ty } }, params[1], .type);
9570 const field_names = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_slice_const_u8_type } }, params[2], .enum_field_names);
9571 const field_values_ty = try gz.addExtendedPayload(.reify_enum_value_slice_ty, Zir.Inst.BinNode{
9572 .node = gz.nodeIndexToRelative(node),
9573 .lhs = tag_ty,
9574 .rhs = field_names,
9575 });
9576 const field_values = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_values_ty } }, params[3], .enum_field_values);
9577 const result = try gz.addExtendedPayloadSmall(.reify_enum, @intFromEnum(reify_name_strat), Zir.Inst.ReifyEnum{
9578 .src_line = gz.astgen.source_line,
9579 .node = node,
9580 .tag_ty = tag_ty,
9581 .mode = mode,
9582 .field_names = field_names,
9583 .field_values = field_values,
9584 });
9585 return rvalue(gz, ri, result, node);
9586 },
9587
9449 .panic => {9588 .panic => {
9450 try emitDbgNode(gz, node);9589 try emitDbgNode(gz, node);
9451 return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0], .panic);9590 return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0], .panic);
...@@ -9764,41 +9903,6 @@ fn builtinCall(...@@ -9764,41 +9903,6 @@ fn builtinCall(
9764 },9903 },
9765 }9904 }
9766}9905}
9767fn builtinReify(
9768 gz: *GenZir,
9769 scope: *Scope,
9770 ri: ResultInfo,
9771 node: Ast.Node.Index,
9772 arg_node: Ast.Node.Index,
9773 name_strat: Zir.Inst.NameStrategy,
9774) InnerError!Zir.Inst.Ref {
9775 const astgen = gz.astgen;
9776 const gpa = astgen.gpa;
9777
9778 const type_info_ty = try gz.addBuiltinValue(node, .type_info);
9779 const operand = try expr(gz, scope, .{ .rl = .{ .coerced_ty = type_info_ty } }, arg_node);
9780
9781 try gz.instructions.ensureUnusedCapacity(gpa, 1);
9782 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
9783
9784 const payload_index = try astgen.addExtra(Zir.Inst.Reify{
9785 .node = node, // Absolute node index -- see the definition of `Reify`.
9786 .operand = operand,
9787 .src_line = astgen.source_line,
9788 });
9789 const new_index: Zir.Inst.Index = @enumFromInt(astgen.instructions.len);
9790 astgen.instructions.appendAssumeCapacity(.{
9791 .tag = .extended,
9792 .data = .{ .extended = .{
9793 .opcode = .reify,
9794 .small = @intFromEnum(name_strat),
9795 .operand = payload_index,
9796 } },
9797 });
9798 gz.instructions.appendAssumeCapacity(new_index);
9799 const result = new_index.toRef();
9800 return rvalue(gz, ri, result, node);
9801}
98029906
9803fn hasDeclOrField(9907fn hasDeclOrField(
9804 gz: *GenZir,9908 gz: *GenZir,
lib/std/zig/AstRlAnnotate.zig+44-1
...@@ -866,6 +866,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast....@@ -866,6 +866,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
866 // These builtins take no args and do not consume the result pointer.866 // These builtins take no args and do not consume the result pointer.
867 .src,867 .src,
868 .This,868 .This,
869 .EnumLiteral,
869 .return_address,870 .return_address,
870 .error_return_trace,871 .error_return_trace,
871 .frame,872 .frame,
...@@ -906,7 +907,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast....@@ -906,7 +907,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
906 .embed_file,907 .embed_file,
907 .error_name,908 .error_name,
908 .set_runtime_safety,909 .set_runtime_safety,
909 .Type,910 .Tuple,
910 .c_undef,911 .c_undef,
911 .c_include,912 .c_include,
912 .wasm_memory_size,913 .wasm_memory_size,
...@@ -1058,6 +1059,48 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast....@@ -1058,6 +1059,48 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
1058 _ = try astrl.expr(args[3], block, ResultInfo.none);1059 _ = try astrl.expr(args[3], block, ResultInfo.none);
1059 return false;1060 return false;
1060 },1061 },
1062 .Int => {
1063 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1064 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1065 return false;
1066 },
1067 .Pointer => {
1068 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1069 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1070 _ = try astrl.expr(args[2], block, ResultInfo.type_only);
1071 _ = try astrl.expr(args[3], block, ResultInfo.type_only);
1072 return false;
1073 },
1074 .Fn => {
1075 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1076 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1077 _ = try astrl.expr(args[2], block, ResultInfo.type_only);
1078 _ = try astrl.expr(args[3], block, ResultInfo.type_only);
1079 return false;
1080 },
1081 .Struct => {
1082 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1083 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1084 _ = try astrl.expr(args[2], block, ResultInfo.type_only);
1085 _ = try astrl.expr(args[3], block, ResultInfo.type_only);
1086 _ = try astrl.expr(args[4], block, ResultInfo.type_only);
1087 return false;
1088 },
1089 .Union => {
1090 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1091 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1092 _ = try astrl.expr(args[2], block, ResultInfo.type_only);
1093 _ = try astrl.expr(args[3], block, ResultInfo.type_only);
1094 _ = try astrl.expr(args[4], block, ResultInfo.type_only);
1095 return false;
1096 },
1097 .Enum => {
1098 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1099 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1100 _ = try astrl.expr(args[2], block, ResultInfo.type_only);
1101 _ = try astrl.expr(args[3], block, ResultInfo.type_only);
1102 return false;
1103 },
1061 .Vector => {1104 .Vector => {
1062 _ = try astrl.expr(args[0], block, ResultInfo.type_only);1105 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1063 _ = try astrl.expr(args[1], block, ResultInfo.type_only);1106 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
lib/std/zig/BuiltinFn.zig+59-3
...@@ -110,7 +110,14 @@ pub const Tag = enum {...@@ -110,7 +110,14 @@ pub const Tag = enum {
110 This,110 This,
111 trap,111 trap,
112 truncate,112 truncate,
113 Type,113 EnumLiteral,
114 Int,
115 Tuple,
116 Pointer,
117 Fn,
118 Struct,
119 Union,
120 Enum,
114 type_info,121 type_info,
115 type_name,122 type_name,
116 TypeOf,123 TypeOf,
...@@ -937,12 +944,61 @@ pub const list = list: {...@@ -937,12 +944,61 @@ pub const list = list: {
937 },944 },
938 },945 },
939 .{946 .{
940 "@Type",947 "@EnumLiteral",
941 .{948 .{
942 .tag = .Type,949 .tag = .EnumLiteral,
950 .param_count = 0,
951 },
952 },
953 .{
954 "@Int",
955 .{
956 .tag = .Int,
957 .param_count = 2,
958 },
959 },
960 .{
961 "@Tuple",
962 .{
963 .tag = .Tuple,
943 .param_count = 1,964 .param_count = 1,
944 },965 },
945 },966 },
967 .{
968 "@Pointer",
969 .{
970 .tag = .Pointer,
971 .param_count = 4,
972 },
973 },
974 .{
975 "@Fn",
976 .{
977 .tag = .Fn,
978 .param_count = 4,
979 },
980 },
981 .{
982 "@Struct",
983 .{
984 .tag = .Struct,
985 .param_count = 5,
986 },
987 },
988 .{
989 "@Union",
990 .{
991 .tag = .Union,
992 .param_count = 5,
993 },
994 },
995 .{
996 "@Enum",
997 .{
998 .tag = .Enum,
999 .param_count = 4,
1000 },
1001 },
946 .{1002 .{
947 "@typeInfo",1003 "@typeInfo",
948 .{1004 .{
lib/std/zig/Zir.zig+131-8
...@@ -260,6 +260,10 @@ pub const Inst = struct {...@@ -260,6 +260,10 @@ pub const Inst = struct {
260 /// `[N:S]T` syntax. Source location is the array type expression node.260 /// `[N:S]T` syntax. Source location is the array type expression node.
261 /// Uses the `pl_node` union field. Payload is `ArrayTypeSentinel`.261 /// Uses the `pl_node` union field. Payload is `ArrayTypeSentinel`.
262 array_type_sentinel,262 array_type_sentinel,
263 /// `@Int` builtin.
264 /// Uses the `pl_node` union field with `Bin` payload.
265 /// lhs is signedness, rhs is bit count.
266 reify_int,
263 /// `@Vector` builtin.267 /// `@Vector` builtin.
264 /// Uses the `pl_node` union field with `Bin` payload.268 /// Uses the `pl_node` union field with `Bin` payload.
265 /// lhs is length, rhs is element type.269 /// lhs is length, rhs is element type.
...@@ -1112,6 +1116,7 @@ pub const Inst = struct {...@@ -1112,6 +1116,7 @@ pub const Inst = struct {
1112 .array_mul,1116 .array_mul,
1113 .array_type,1117 .array_type,
1114 .array_type_sentinel,1118 .array_type_sentinel,
1119 .reify_int,
1115 .vector_type,1120 .vector_type,
1116 .elem_type,1121 .elem_type,
1117 .indexable_ptr_elem_type,1122 .indexable_ptr_elem_type,
...@@ -1409,6 +1414,7 @@ pub const Inst = struct {...@@ -1409,6 +1414,7 @@ pub const Inst = struct {
1409 .array_mul,1414 .array_mul,
1410 .array_type,1415 .array_type,
1411 .array_type_sentinel,1416 .array_type_sentinel,
1417 .reify_int,
1412 .vector_type,1418 .vector_type,
1413 .elem_type,1419 .elem_type,
1414 .indexable_ptr_elem_type,1420 .indexable_ptr_elem_type,
...@@ -1644,6 +1650,7 @@ pub const Inst = struct {...@@ -1644,6 +1650,7 @@ pub const Inst = struct {
1644 .array_mul = .pl_node,1650 .array_mul = .pl_node,
1645 .array_type = .pl_node,1651 .array_type = .pl_node,
1646 .array_type_sentinel = .pl_node,1652 .array_type_sentinel = .pl_node,
1653 .reify_int = .pl_node,
1647 .vector_type = .pl_node,1654 .vector_type = .pl_node,
1648 .elem_type = .un_node,1655 .elem_type = .un_node,
1649 .indexable_ptr_elem_type = .un_node,1656 .indexable_ptr_elem_type = .un_node,
...@@ -2035,10 +2042,43 @@ pub const Inst = struct {...@@ -2035,10 +2042,43 @@ pub const Inst = struct {
2035 /// Implement builtin `@errorFromInt`.2042 /// Implement builtin `@errorFromInt`.
2036 /// `operand` is payload index to `UnNode`.2043 /// `operand` is payload index to `UnNode`.
2037 error_from_int,2044 error_from_int,
2038 /// Implement builtin `@Type`.2045 /// Given a comptime-known operand of type `[]const A`, returns the type `*const [operand.len]B`.
2039 /// `operand` is payload index to `Reify`.2046 /// The types `A` and `B` are determined from `ReifySliceArgInfo`.
2047 /// This instruction is used to provide result types to arguments of `@Fn`, `@Struct`, etc.
2048 /// `operand` is payload index to `UnNode`.
2049 /// `small` is a bitcast `ReifySliceArgInfo`.
2050 reify_slice_arg_ty,
2051 /// Like `reify_slice_arg_ty` for the specific case of `[]const []const u8` to `[]const TagInt`,
2052 /// as needed for `@Enum`.
2053 /// `operand` is payload index to `BinNode`. lhs is the type `TagInt`. rhs is the `[]const []const u8` value.
2054 /// `small` is unused.
2055 reify_enum_value_slice_ty,
2056 /// Given a comptime-known operand of type `type`, returns the type `?operand` if possible, otherwise `?noreturn`.
2057 /// Used for the final arg of `@Pointer` to allow reifying pointers to opaque types.
2058 /// `operand` is payload index to `UnNode`.
2059 /// `small` is unused.
2060 reify_pointer_sentinel_ty,
2061 /// Implements builtin `@Tuple`.
2062 /// `operand` is payload index to `UnNode`.
2063 reify_tuple,
2064 /// Implements builtin `@Pointer`.
2065 /// `operand` is payload index to `ReifyPointer`.
2066 reify_pointer,
2067 /// Implements builtin `@Fn`.
2068 /// `operand` is payload index to `ReifyFn`.
2069 reify_fn,
2070 /// Implements builtin `@Struct`.
2071 /// `operand` is payload index to `ReifyStruct`.
2072 /// `small` contains `NameStrategy`.
2073 reify_struct,
2074 /// Implements builtin `@Union`.
2075 /// `operand` is payload index to `ReifyUnion`.
2076 /// `small` contains `NameStrategy`.
2077 reify_union,
2078 /// Implements builtin `@Enum`.
2079 /// `operand` is payload index to `ReifyEnum`.
2040 /// `small` contains `NameStrategy`.2080 /// `small` contains `NameStrategy`.
2041 reify,2081 reify_enum,
2042 /// Implements the `@cmpxchgStrong` and `@cmpxchgWeak` builtins.2082 /// Implements the `@cmpxchgStrong` and `@cmpxchgWeak` builtins.
2043 /// `small` 0=>weak 1=>strong2083 /// `small` 0=>weak 1=>strong
2044 /// `operand` is payload index to `Cmpxchg`.2084 /// `operand` is payload index to `Cmpxchg`.
...@@ -2226,6 +2266,11 @@ pub const Inst = struct {...@@ -2226,6 +2266,11 @@ pub const Inst = struct {
2226 manyptr_const_u8_sentinel_0_type,2266 manyptr_const_u8_sentinel_0_type,
2227 slice_const_u8_type,2267 slice_const_u8_type,
2228 slice_const_u8_sentinel_0_type,2268 slice_const_u8_sentinel_0_type,
2269 manyptr_const_slice_const_u8_type,
2270 slice_const_slice_const_u8_type,
2271 optional_type_type,
2272 manyptr_const_type_type,
2273 slice_const_type_type,
2229 vector_8_i8_type,2274 vector_8_i8_type,
2230 vector_16_i8_type,2275 vector_16_i8_type,
2231 vector_32_i8_type,2276 vector_32_i8_type,
...@@ -3169,6 +3214,23 @@ pub const Inst = struct {...@@ -3169,6 +3214,23 @@ pub const Inst = struct {
3169 rhs: Ref,3214 rhs: Ref,
3170 };3215 };
31713216
3217 pub const ReifySliceArgInfo = enum(u16) {
3218 /// Input element type is `type`.
3219 /// Output element type is `std.builtin.Type.Fn.Param.Attributes`.
3220 type_to_fn_param_attrs,
3221 /// Input element type is `[]const u8`.
3222 /// Output element type is `type`.
3223 string_to_struct_field_type,
3224 /// Identical to `string_to_struct_field_type` aside from emitting slightly different error messages.
3225 string_to_union_field_type,
3226 /// Input element type is `[]const u8`.
3227 /// Output element type is `std.builtin.Type.StructField.Attributes`.
3228 string_to_struct_field_attrs,
3229 /// Input element type is `[]const u8`.
3230 /// Output element type is `std.builtin.Type.UnionField.Attributes`.
3231 string_to_union_field_attrs,
3232 };
3233
3172 pub const UnNode = struct {3234 pub const UnNode = struct {
3173 node: Ast.Node.Offset,3235 node: Ast.Node.Offset,
3174 operand: Ref,3236 operand: Ref,
...@@ -3179,12 +3241,55 @@ pub const Inst = struct {...@@ -3179,12 +3241,55 @@ pub const Inst = struct {
3179 index: u32,3241 index: u32,
3180 };3242 };
31813243
3182 pub const Reify = struct {3244 pub const ReifyPointer = struct {
3245 node: Ast.Node.Offset,
3246 size: Ref,
3247 attrs: Ref,
3248 elem_ty: Ref,
3249 sentinel: Ref,
3250 };
3251
3252 pub const ReifyFn = struct {
3253 node: Ast.Node.Offset,
3254 param_types: Ref,
3255 param_attrs: Ref,
3256 ret_ty: Ref,
3257 fn_attrs: Ref,
3258 };
3259
3260 pub const ReifyStruct = struct {
3261 src_line: u32,
3183 /// This node is absolute, because `reify` instructions are tracked across updates, and3262 /// This node is absolute, because `reify` instructions are tracked across updates, and
3184 /// this simplifies the logic for getting source locations for types.3263 /// this simplifies the logic for getting source locations for types.
3185 node: Ast.Node.Index,3264 node: Ast.Node.Index,
3186 operand: Ref,3265 layout: Ref,
3266 backing_ty: Ref,
3267 field_names: Ref,
3268 field_types: Ref,
3269 field_attrs: Ref,
3270 };
3271
3272 pub const ReifyUnion = struct {
3187 src_line: u32,3273 src_line: u32,
3274 /// This node is absolute, because `reify` instructions are tracked across updates, and
3275 /// this simplifies the logic for getting source locations for types.
3276 node: Ast.Node.Index,
3277 layout: Ref,
3278 arg_ty: Ref,
3279 field_names: Ref,
3280 field_types: Ref,
3281 field_attrs: Ref,
3282 };
3283
3284 pub const ReifyEnum = struct {
3285 src_line: u32,
3286 /// This node is absolute, because `reify` instructions are tracked across updates, and
3287 /// this simplifies the logic for getting source locations for types.
3288 node: Ast.Node.Index,
3289 tag_ty: Ref,
3290 mode: Ref,
3291 field_names: Ref,
3292 field_values: Ref,
3188 };3293 };
31893294
3190 /// Trailing:3295 /// Trailing:
...@@ -3496,14 +3601,19 @@ pub const Inst = struct {...@@ -3496,14 +3601,19 @@ pub const Inst = struct {
3496 calling_convention,3601 calling_convention,
3497 address_space,3602 address_space,
3498 float_mode,3603 float_mode,
3604 signedness,
3499 reduce_op,3605 reduce_op,
3500 call_modifier,3606 call_modifier,
3501 prefetch_options,3607 prefetch_options,
3502 export_options,3608 export_options,
3503 extern_options,3609 extern_options,
3504 type_info,
3505 branch_hint,3610 branch_hint,
3506 clobbers,3611 clobbers,
3612 pointer_size,
3613 pointer_attributes,
3614 fn_attributes,
3615 container_layout,
3616 enum_mode,
3507 // Values3617 // Values
3508 calling_convention_c,3618 calling_convention_c,
3509 calling_convention_inline,3619 calling_convention_inline,
...@@ -4190,6 +4300,7 @@ fn findTrackableInner(...@@ -4190,6 +4300,7 @@ fn findTrackableInner(
4190 .array_mul,4300 .array_mul,
4191 .array_type,4301 .array_type,
4192 .array_type_sentinel,4302 .array_type_sentinel,
4303 .reify_int,
4193 .vector_type,4304 .vector_type,
4194 .elem_type,4305 .elem_type,
4195 .indexable_ptr_elem_type,4306 .indexable_ptr_elem_type,
...@@ -4432,6 +4543,12 @@ fn findTrackableInner(...@@ -4432,6 +4543,12 @@ fn findTrackableInner(
4432 .select,4543 .select,
4433 .int_from_error,4544 .int_from_error,
4434 .error_from_int,4545 .error_from_int,
4546 .reify_slice_arg_ty,
4547 .reify_enum_value_slice_ty,
4548 .reify_pointer_sentinel_ty,
4549 .reify_tuple,
4550 .reify_pointer,
4551 .reify_fn,
4435 .cmpxchg,4552 .cmpxchg,
4436 .c_va_arg,4553 .c_va_arg,
4437 .c_va_copy,4554 .c_va_copy,
...@@ -4463,7 +4580,11 @@ fn findTrackableInner(...@@ -4463,7 +4580,11 @@ fn findTrackableInner(
4463 },4580 },
44644581
4465 // Reifications and opaque declarations need tracking, but have no body.4582 // Reifications and opaque declarations need tracking, but have no body.
4466 .reify, .opaque_decl => return contents.other.append(gpa, inst),4583 .reify_enum,
4584 .reify_struct,
4585 .reify_union,
4586 .opaque_decl,
4587 => return contents.other.append(gpa, inst),
44674588
4468 // Struct declarations need tracking and have bodies.4589 // Struct declarations need tracking and have bodies.
4469 .struct_decl => {4590 .struct_decl => {
...@@ -5246,7 +5367,9 @@ pub fn assertTrackable(zir: Zir, inst_idx: Zir.Inst.Index) void {...@@ -5246,7 +5367,9 @@ pub fn assertTrackable(zir: Zir, inst_idx: Zir.Inst.Index) void {
5246 .union_decl,5367 .union_decl,
5247 .enum_decl,5368 .enum_decl,
5248 .opaque_decl,5369 .opaque_decl,
5249 .reify,5370 .reify_enum,
5371 .reify_struct,
5372 .reify_union,
5250 => {}, // tracked in order, as the owner instructions of explicit container types5373 => {}, // tracked in order, as the owner instructions of explicit container types
5251 else => unreachable, // assertion failure; not trackable5374 else => unreachable, // assertion failure; not trackable
5252 },5375 },
lib/std/zig/c_translation/helpers.zig+10-18
...@@ -81,23 +81,15 @@ fn ToUnsigned(comptime T: type) type {...@@ -81,23 +81,15 @@ fn ToUnsigned(comptime T: type) type {
81}81}
8282
83/// Constructs a [*c] pointer with the const and volatile annotations83/// Constructs a [*c] pointer with the const and volatile annotations
84/// from SelfType for pointing to a C flexible array of ElementType.84/// from Self for pointing to a C flexible array of Element.
85pub fn FlexibleArrayType(comptime SelfType: type, comptime ElementType: type) type {85pub fn FlexibleArrayType(comptime Self: type, comptime Element: type) type {
86 switch (@typeInfo(SelfType)) {86 return switch (@typeInfo(Self)) {
87 .pointer => |ptr| {87 .pointer => |ptr| @Pointer(.c, .{
88 return @Type(.{ .pointer = .{88 .@"const" = ptr.is_const,
89 .size = .c,89 .@"volatile" = ptr.is_volatile,
90 .is_const = ptr.is_const,90 }, Element, null),
91 .is_volatile = ptr.is_volatile,91 else => |info| @compileError("Invalid self type \"" ++ @tagName(info) ++ "\" for flexible array getter: " ++ @typeName(Self)),
92 .alignment = @alignOf(ElementType),92 };
93 .address_space = .generic,
94 .child = ElementType,
95 .is_allowzero = true,
96 .sentinel_ptr = null,
97 } });
98 },
99 else => |info| @compileError("Invalid self type \"" ++ @tagName(info) ++ "\" for flexible array getter: " ++ @typeName(SelfType)),
100 }
101}93}
10294
103/// Promote the type of an integer literal until it fits as C would.95/// 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 {...@@ -219,7 +211,7 @@ fn castInt(comptime DestType: type, target: anytype) DestType {
219 const dest = @typeInfo(DestType).int;211 const dest = @typeInfo(DestType).int;
220 const source = @typeInfo(@TypeOf(target)).int;212 const source = @typeInfo(@TypeOf(target)).int;
221213
222 const Int = @Type(.{ .int = .{ .bits = dest.bits, .signedness = source.signedness } });214 const Int = @Int(source.signedness, dest.bits);
223215
224 if (dest.bits < source.bits)216 if (dest.bits < source.bits)
225 return @as(DestType, @bitCast(@as(Int, @truncate(target))))217 return @as(DestType, @bitCast(@as(Int, @truncate(target))))
lib/std/zig/llvm/Builder.zig+9-30
...@@ -8614,39 +8614,18 @@ pub const Metadata = packed struct(u32) {...@@ -8614,39 +8614,18 @@ pub const Metadata = packed struct(u32) {
8614 nodes: anytype,8614 nodes: anytype,
8615 w: *Writer,8615 w: *Writer,
8616 ) !void {8616 ) !void {
8617 comptime var fmt_str: []const u8 = "";
8618 const names = comptime std.meta.fieldNames(@TypeOf(nodes));8617 const names = comptime std.meta.fieldNames(@TypeOf(nodes));
8619 comptime var fields: [2 + names.len]std.builtin.Type.StructField = undefined;8618
8620 inline for (fields[0..2], .{ "distinct", "node" }) |*field, name| {8619 comptime var fmt_str: []const u8 = "{[distinct]s}{[node]s}(";
8621 fmt_str = fmt_str ++ "{[" ++ name ++ "]s}";8620 inline for (names) |name| fmt_str = fmt_str ++ "{[" ++ name ++ "]f}";
8622 field.* = .{
8623 .name = name,
8624 .type = []const u8,
8625 .default_value_ptr = null,
8626 .is_comptime = false,
8627 .alignment = @alignOf([]const u8),
8628 };
8629 }
8630 fmt_str = fmt_str ++ "(";
8631 inline for (fields[2..], names) |*field, name| {
8632 fmt_str = fmt_str ++ "{[" ++ name ++ "]f}";
8633 const T = std.fmt.Alt(FormatData, format);
8634 field.* = .{
8635 .name = name,
8636 .type = T,
8637 .default_value_ptr = null,
8638 .is_comptime = false,
8639 .alignment = @alignOf(T),
8640 };
8641 }
8642 fmt_str = fmt_str ++ ")\n";8621 fmt_str = fmt_str ++ ")\n";
86438622
8644 var fmt_args: @Type(.{ .@"struct" = .{8623 const field_names = @as([]const []const u8, &.{ "distinct", "node" }) ++ names;
8645 .layout = .auto,8624 comptime var field_types: [2 + names.len]type = undefined;
8646 .fields = &fields,8625 @memset(field_types[0..2], []const u8);
8647 .decls = &.{},8626 @memset(field_types[2..], std.fmt.Alt(FormatData, format));
8648 .is_tuple = false,8627
8649 } }) = undefined;8628 var fmt_args: @Struct(.auto, null, field_names, &field_types, &@splat(.{})) = undefined;
8650 fmt_args.distinct = @tagName(distinct);8629 fmt_args.distinct = @tagName(distinct);
8651 fmt_args.node = @tagName(node);8630 fmt_args.node = @tagName(node);
8652 inline for (names) |name| @field(fmt_args, name) = try formatter.fmt(8631 inline for (names) |name| @field(fmt_args, name) = try formatter.fmt(
src/Air.zig+5
...@@ -1062,6 +1062,11 @@ pub const Inst = struct {...@@ -1062,6 +1062,11 @@ pub const Inst = struct {
1062 manyptr_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.manyptr_const_u8_sentinel_0_type),1062 manyptr_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.manyptr_const_u8_sentinel_0_type),
1063 slice_const_u8_type = @intFromEnum(InternPool.Index.slice_const_u8_type),1063 slice_const_u8_type = @intFromEnum(InternPool.Index.slice_const_u8_type),
1064 slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type),1064 slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type),
1065 manyptr_const_slice_const_u8_type = @intFromEnum(InternPool.Index.manyptr_const_slice_const_u8_type),
1066 slice_const_slice_const_u8_type = @intFromEnum(InternPool.Index.slice_const_slice_const_u8_type),
1067 optional_type_type = @intFromEnum(InternPool.Index.optional_type_type),
1068 manyptr_const_type_type = @intFromEnum(InternPool.Index.manyptr_const_type_type),
1069 slice_const_type_type = @intFromEnum(InternPool.Index.slice_const_type_type),
1065 vector_8_i8_type = @intFromEnum(InternPool.Index.vector_8_i8_type),1070 vector_8_i8_type = @intFromEnum(InternPool.Index.vector_8_i8_type),
1066 vector_16_i8_type = @intFromEnum(InternPool.Index.vector_16_i8_type),1071 vector_16_i8_type = @intFromEnum(InternPool.Index.vector_16_i8_type),
1067 vector_32_i8_type = @intFromEnum(InternPool.Index.vector_32_i8_type),1072 vector_32_i8_type = @intFromEnum(InternPool.Index.vector_32_i8_type),
src/InternPool.zig+90-79
...@@ -1153,23 +1153,17 @@ const Local = struct {...@@ -1153,23 +1153,17 @@ const Local = struct {
1153 fn PtrArrayElem(comptime len: usize) type {1153 fn PtrArrayElem(comptime len: usize) type {
1154 const elem_info = @typeInfo(Elem).@"struct";1154 const elem_info = @typeInfo(Elem).@"struct";
1155 const elem_fields = elem_info.fields;1155 const elem_fields = elem_info.fields;
1156 var new_fields: [elem_fields.len]std.builtin.Type.StructField = undefined;1156 var new_names: [elem_fields.len][]const u8 = undefined;
1157 for (&new_fields, elem_fields) |*new_field, elem_field| {1157 var new_types: [elem_fields.len]type = undefined;
1158 const T = *[len]elem_field.type;1158 for (elem_fields, &new_names, &new_types) |elem_field, *new_name, *NewType| {
1159 new_field.* = .{1159 new_name.* = elem_field.name;
1160 .name = elem_field.name,1160 NewType.* = *[len]elem_field.type;
1161 .type = T,1161 }
1162 .default_value_ptr = null,1162 if (elem_info.is_tuple) {
1163 .is_comptime = false,1163 return @Tuple(&new_types);
1164 .alignment = @alignOf(T),1164 } else {
1165 };1165 return @Struct(.auto, null, &new_names, &new_types, &@splat(.{}));
1166 }1166 }
1167 return @Type(.{ .@"struct" = .{
1168 .layout = .auto,
1169 .fields = &new_fields,
1170 .decls = &.{},
1171 .is_tuple = elem_info.is_tuple,
1172 } });
1173 }1167 }
1174 fn PtrElem(comptime opts: struct {1168 fn PtrElem(comptime opts: struct {
1175 size: std.builtin.Type.Pointer.Size,1169 size: std.builtin.Type.Pointer.Size,
...@@ -1177,32 +1171,17 @@ const Local = struct {...@@ -1177,32 +1171,17 @@ const Local = struct {
1177 }) type {1171 }) type {
1178 const elem_info = @typeInfo(Elem).@"struct";1172 const elem_info = @typeInfo(Elem).@"struct";
1179 const elem_fields = elem_info.fields;1173 const elem_fields = elem_info.fields;
1180 var new_fields: [elem_fields.len]std.builtin.Type.StructField = undefined;1174 var new_names: [elem_fields.len][]const u8 = undefined;
1181 for (&new_fields, elem_fields) |*new_field, elem_field| {1175 var new_types: [elem_fields.len]type = undefined;
1182 const T = @Type(.{ .pointer = .{1176 for (elem_fields, &new_names, &new_types) |elem_field, *new_name, *NewType| {
1183 .size = opts.size,1177 new_name.* = elem_field.name;
1184 .is_const = opts.is_const,1178 NewType.* = @Pointer(opts.size, .{ .@"const" = opts.is_const }, elem_field.type, null);
1185 .is_volatile = false,1179 }
1186 .alignment = @alignOf(elem_field.type),1180 if (elem_info.is_tuple) {
1187 .address_space = .generic,1181 return @Tuple(&new_types);
1188 .child = elem_field.type,1182 } else {
1189 .is_allowzero = false,1183 return @Struct(.auto, null, &new_names, &new_types, &@splat(.{}));
1190 .sentinel_ptr = null,
1191 } });
1192 new_field.* = .{
1193 .name = elem_field.name,
1194 .type = T,
1195 .default_value_ptr = null,
1196 .is_comptime = false,
1197 .alignment = @alignOf(T),
1198 };
1199 }1184 }
1200 return @Type(.{ .@"struct" = .{
1201 .layout = .auto,
1202 .fields = &new_fields,
1203 .decls = &.{},
1204 .is_tuple = elem_info.is_tuple,
1205 } });
1206 }1185 }
12071186
1208 pub fn addOne(mutable: Mutable) Allocator.Error!PtrElem(.{ .size = .one }) {1187 pub fn addOne(mutable: Mutable) Allocator.Error!PtrElem(.{ .size = .one }) {
...@@ -2017,8 +1996,7 @@ pub const Key = union(enum) {...@@ -2017,8 +1996,7 @@ pub const Key = union(enum) {
2017 error_union_type: ErrorUnionType,1996 error_union_type: ErrorUnionType,
2018 simple_type: SimpleType,1997 simple_type: SimpleType,
2019 /// This represents a struct that has been explicitly declared in source code,1998 /// This represents a struct that has been explicitly declared in source code,
2020 /// or was created with `@Type`. It is unique and based on a declaration.1999 /// or was created with `@Struct`. It is unique and based on a declaration.
2021 /// It may be a tuple, if declared like this: `struct {A, B, C}`.
2022 struct_type: NamespaceType,2000 struct_type: NamespaceType,
2023 /// This is a tuple type. Tuples are logically similar to structs, but have some2001 /// This is a tuple type. Tuples are logically similar to structs, but have some
2024 /// important differences in semantics; they do not undergo staged type resolution,2002 /// important differences in semantics; they do not undergo staged type resolution,
...@@ -2175,7 +2153,7 @@ pub const Key = union(enum) {...@@ -2175,7 +2153,7 @@ pub const Key = union(enum) {
2175 /// The union for which this is a tag type.2153 /// The union for which this is a tag type.
2176 union_type: Index,2154 union_type: Index,
2177 },2155 },
2178 /// This type originates from a reification via `@Type`, or from an anonymous initialization.2156 /// This type originates from a reification via `@Enum`, `@Struct`, `@Union` or from an anonymous initialization.
2179 /// It is hashed based on its ZIR instruction index and fields, attributes, etc.2157 /// It is hashed based on its ZIR instruction index and fields, attributes, etc.
2180 /// To avoid making this key overly complex, the type-specific data is hashed by Sema.2158 /// To avoid making this key overly complex, the type-specific data is hashed by Sema.
2181 reified: struct {2159 reified: struct {
...@@ -4641,6 +4619,13 @@ pub const Index = enum(u32) {...@@ -4641,6 +4619,13 @@ pub const Index = enum(u32) {
4641 slice_const_u8_type,4619 slice_const_u8_type,
4642 slice_const_u8_sentinel_0_type,4620 slice_const_u8_sentinel_0_type,
46434621
4622 manyptr_const_slice_const_u8_type,
4623 slice_const_slice_const_u8_type,
4624
4625 optional_type_type,
4626 manyptr_const_type_type,
4627 slice_const_type_type,
4628
4644 vector_8_i8_type,4629 vector_8_i8_type,
4645 vector_16_i8_type,4630 vector_16_i8_type,
4646 vector_32_i8_type,4631 vector_32_i8_type,
...@@ -5201,6 +5186,45 @@ pub const static_keys: [static_len]Key = .{...@@ -5201,6 +5186,45 @@ pub const static_keys: [static_len]Key = .{
5201 },5186 },
5202 } },5187 } },
52035188
5189 // [*]const []const u8
5190 .{ .ptr_type = .{
5191 .child = .slice_const_u8_type,
5192 .flags = .{
5193 .size = .many,
5194 .is_const = true,
5195 },
5196 } },
5197
5198 // []const []const u8
5199 .{ .ptr_type = .{
5200 .child = .slice_const_u8_type,
5201 .flags = .{
5202 .size = .slice,
5203 .is_const = true,
5204 },
5205 } },
5206
5207 // ?type
5208 .{ .opt_type = .type_type },
5209
5210 // [*]const type
5211 .{ .ptr_type = .{
5212 .child = .type_type,
5213 .flags = .{
5214 .size = .many,
5215 .is_const = true,
5216 },
5217 } },
5218
5219 // []const type
5220 .{ .ptr_type = .{
5221 .child = .type_type,
5222 .flags = .{
5223 .size = .slice,
5224 .is_const = true,
5225 },
5226 } },
5227
5204 // @Vector(8, i8)5228 // @Vector(8, i8)
5205 .{ .vector_type = .{ .len = 8, .child = .i8_type } },5229 .{ .vector_type = .{ .len = 8, .child = .i8_type } },
5206 // @Vector(16, i8)5230 // @Vector(16, i8)
...@@ -10225,16 +10249,8 @@ pub fn getGeneratedTagEnumType(...@@ -10225,16 +10249,8 @@ pub fn getGeneratedTagEnumType(
10225}10249}
1022610250
10227pub const OpaqueTypeInit = struct {10251pub const OpaqueTypeInit = struct {
10228 key: union(enum) {10252 zir_index: TrackedInst.Index,
10229 declared: struct {10253 captures: []const CaptureValue,
10230 zir_index: TrackedInst.Index,
10231 captures: []const CaptureValue,
10232 },
10233 reified: struct {
10234 zir_index: TrackedInst.Index,
10235 // No type hash since reifid opaques have no data other than the `@Type` location
10236 },
10237 },
10238};10254};
1023910255
10240pub fn getOpaqueType(10256pub fn getOpaqueType(
...@@ -10243,16 +10259,10 @@ pub fn getOpaqueType(...@@ -10243,16 +10259,10 @@ pub fn getOpaqueType(
10243 tid: Zcu.PerThread.Id,10259 tid: Zcu.PerThread.Id,
10244 ini: OpaqueTypeInit,10260 ini: OpaqueTypeInit,
10245) Allocator.Error!WipNamespaceType.Result {10261) Allocator.Error!WipNamespaceType.Result {
10246 var gop = try ip.getOrPutKey(gpa, tid, .{ .opaque_type = switch (ini.key) {10262 var gop = try ip.getOrPutKey(gpa, tid, .{ .opaque_type = .{ .declared = .{
10247 .declared => |d| .{ .declared = .{10263 .zir_index = ini.zir_index,
10248 .zir_index = d.zir_index,10264 .captures = .{ .external = ini.captures },
10249 .captures = .{ .external = d.captures },10265 } } });
10250 } },
10251 .reified => |r| .{ .reified = .{
10252 .zir_index = r.zir_index,
10253 .type_hash = 0,
10254 } },
10255 } });
10256 defer gop.deinit();10266 defer gop.deinit();
10257 if (gop == .existing) return .{ .existing = gop.existing };10267 if (gop == .existing) return .{ .existing = gop.existing };
1025810268
...@@ -10261,30 +10271,19 @@ pub fn getOpaqueType(...@@ -10261,30 +10271,19 @@ pub fn getOpaqueType(
10261 const extra = local.getMutableExtra(gpa);10271 const extra = local.getMutableExtra(gpa);
10262 try items.ensureUnusedCapacity(1);10272 try items.ensureUnusedCapacity(1);
1026310273
10264 try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeOpaque).@"struct".fields.len + switch (ini.key) {10274 try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeOpaque).@"struct".fields.len + ini.captures.len);
10265 .declared => |d| d.captures.len,
10266 .reified => 0,
10267 });
10268 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeOpaque{10275 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeOpaque{
10269 .name = undefined, // set by `finish`10276 .name = undefined, // set by `finish`
10270 .name_nav = undefined, // set by `finish`10277 .name_nav = undefined, // set by `finish`
10271 .namespace = undefined, // set by `finish`10278 .namespace = undefined, // set by `finish`
10272 .zir_index = switch (ini.key) {10279 .zir_index = ini.zir_index,
10273 inline else => |x| x.zir_index,10280 .captures_len = @intCast(ini.captures.len),
10274 },
10275 .captures_len = switch (ini.key) {
10276 .declared => |d| @intCast(d.captures.len),
10277 .reified => std.math.maxInt(u32),
10278 },
10279 });10281 });
10280 items.appendAssumeCapacity(.{10282 items.appendAssumeCapacity(.{
10281 .tag = .type_opaque,10283 .tag = .type_opaque,
10282 .data = extra_index,10284 .data = extra_index,
10283 });10285 });
10284 switch (ini.key) {10286 extra.appendSliceAssumeCapacity(.{@ptrCast(ini.captures)});
10285 .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}),
10286 .reified => {},
10287 }
10288 return .{10287 return .{
10289 .wip = .{10288 .wip = .{
10290 .tid = tid,10289 .tid = tid,
...@@ -10555,6 +10554,8 @@ pub fn slicePtrType(ip: *const InternPool, index: Index) Index {...@@ -10555,6 +10554,8 @@ pub fn slicePtrType(ip: *const InternPool, index: Index) Index {
10555 switch (index) {10554 switch (index) {
10556 .slice_const_u8_type => return .manyptr_const_u8_type,10555 .slice_const_u8_type => return .manyptr_const_u8_type,
10557 .slice_const_u8_sentinel_0_type => return .manyptr_const_u8_sentinel_0_type,10556 .slice_const_u8_sentinel_0_type => return .manyptr_const_u8_sentinel_0_type,
10557 .slice_const_slice_const_u8_type => return .manyptr_const_slice_const_u8_type,
10558 .slice_const_type_type => return .manyptr_const_type_type,
10558 else => {},10559 else => {},
10559 }10560 }
10560 const item = index.unwrap(ip).getItem(ip);10561 const item = index.unwrap(ip).getItem(ip);
...@@ -12013,8 +12014,13 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {...@@ -12013,8 +12014,13 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
12013 .manyptr_u8_type,12014 .manyptr_u8_type,
12014 .manyptr_const_u8_type,12015 .manyptr_const_u8_type,
12015 .manyptr_const_u8_sentinel_0_type,12016 .manyptr_const_u8_sentinel_0_type,
12017 .manyptr_const_slice_const_u8_type,
12016 .slice_const_u8_type,12018 .slice_const_u8_type,
12017 .slice_const_u8_sentinel_0_type,12019 .slice_const_u8_sentinel_0_type,
12020 .slice_const_slice_const_u8_type,
12021 .optional_type_type,
12022 .manyptr_const_type_type,
12023 .slice_const_type_type,
12018 .vector_8_i8_type,12024 .vector_8_i8_type,
12019 .vector_16_i8_type,12025 .vector_16_i8_type,
12020 .vector_32_i8_type,12026 .vector_32_i8_type,
...@@ -12355,8 +12361,12 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId {...@@ -12355,8 +12361,12 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId {
12355 .manyptr_u8_type,12361 .manyptr_u8_type,
12356 .manyptr_const_u8_type,12362 .manyptr_const_u8_type,
12357 .manyptr_const_u8_sentinel_0_type,12363 .manyptr_const_u8_sentinel_0_type,
12364 .manyptr_const_slice_const_u8_type,
12358 .slice_const_u8_type,12365 .slice_const_u8_type,
12359 .slice_const_u8_sentinel_0_type,12366 .slice_const_u8_sentinel_0_type,
12367 .slice_const_slice_const_u8_type,
12368 .manyptr_const_type_type,
12369 .slice_const_type_type,
12360 => .pointer,12370 => .pointer,
1236112371
12362 .vector_8_i8_type,12372 .vector_8_i8_type,
...@@ -12408,6 +12418,7 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId {...@@ -12408,6 +12418,7 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId {
12408 .vector_8_f64_type,12418 .vector_8_f64_type,
12409 => .vector,12419 => .vector,
1241012420
12421 .optional_type_type => .optional,
12411 .optional_noreturn_type => .optional,12422 .optional_noreturn_type => .optional,
12412 .anyerror_void_error_union_type => .error_union,12423 .anyerror_void_error_union_type => .error_union,
12413 .empty_tuple_type => .@"struct",12424 .empty_tuple_type => .@"struct",
src/Sema.zig+1194-1243
...@@ -1167,6 +1167,7 @@ fn analyzeBodyInner(...@@ -1167,6 +1167,7 @@ fn analyzeBodyInner(
1167 .array_mul => try sema.zirArrayMul(block, inst),1167 .array_mul => try sema.zirArrayMul(block, inst),
1168 .array_type => try sema.zirArrayType(block, inst),1168 .array_type => try sema.zirArrayType(block, inst),
1169 .array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst),1169 .array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst),
1170 .reify_int => try sema.zirReifyInt(block, inst),
1170 .vector_type => try sema.zirVectorType(block, inst),1171 .vector_type => try sema.zirVectorType(block, inst),
1171 .as_node => try sema.zirAsNode(block, inst),1172 .as_node => try sema.zirAsNode(block, inst),
1172 .as_shift_operand => try sema.zirAsShiftOperand(block, inst),1173 .as_shift_operand => try sema.zirAsShiftOperand(block, inst),
...@@ -1411,7 +1412,6 @@ fn analyzeBodyInner(...@@ -1411,7 +1412,6 @@ fn analyzeBodyInner(
1411 .select => try sema.zirSelect( block, extended),1412 .select => try sema.zirSelect( block, extended),
1412 .int_from_error => try sema.zirIntFromError( block, extended),1413 .int_from_error => try sema.zirIntFromError( block, extended),
1413 .error_from_int => try sema.zirErrorFromInt( block, extended),1414 .error_from_int => try sema.zirErrorFromInt( block, extended),
1414 .reify => try sema.zirReify( block, extended, inst),
1415 .cmpxchg => try sema.zirCmpxchg( block, extended),1415 .cmpxchg => try sema.zirCmpxchg( block, extended),
1416 .c_va_arg => try sema.zirCVaArg( block, extended),1416 .c_va_arg => try sema.zirCVaArg( block, extended),
1417 .c_va_copy => try sema.zirCVaCopy( block, extended),1417 .c_va_copy => try sema.zirCVaCopy( block, extended),
...@@ -1424,6 +1424,16 @@ fn analyzeBodyInner(...@@ -1424,6 +1424,16 @@ fn analyzeBodyInner(
1424 .work_group_id => try sema.zirWorkItem( block, extended, extended.opcode),1424 .work_group_id => try sema.zirWorkItem( block, extended, extended.opcode),
1425 .in_comptime => try sema.zirInComptime( block),1425 .in_comptime => try sema.zirInComptime( block),
1426 .closure_get => try sema.zirClosureGet( block, extended),1426 .closure_get => try sema.zirClosureGet( block, extended),
1427
1428 .reify_slice_arg_ty => try sema.zirReifySliceArgTy( block, extended),
1429 .reify_enum_value_slice_ty => try sema.zirReifyEnumValueSliceTy(block, extended),
1430 .reify_pointer_sentinel_ty => try sema.zirReifyPointerSentinelTy(block, extended),
1431 .reify_tuple => try sema.zirReifyTuple( block, extended),
1432 .reify_pointer => try sema.zirReifyPointer( block, extended),
1433 .reify_fn => try sema.zirReifyFn( block, extended),
1434 .reify_struct => try sema.zirReifyStruct( block, extended, inst),
1435 .reify_union => try sema.zirReifyUnion( block, extended, inst),
1436 .reify_enum => try sema.zirReifyEnum( block, extended, inst),
1427 // zig fmt: on1437 // zig fmt: on
14281438
1429 .set_float_mode => {1439 .set_float_mode => {
...@@ -3517,10 +3527,8 @@ fn zirOpaqueDecl(...@@ -3517,10 +3527,8 @@ fn zirOpaqueDecl(
3517 extra_index += captures_len * 2;3527 extra_index += captures_len * 2;
35183528
3519 const opaque_init: InternPool.OpaqueTypeInit = .{3529 const opaque_init: InternPool.OpaqueTypeInit = .{
3520 .key = .{ .declared = .{3530 .zir_index = tracked_inst,
3521 .zir_index = tracked_inst,3531 .captures = captures,
3522 .captures = captures,
3523 } },
3524 };3532 };
3525 const wip_ty = switch (try ip.getOpaqueType(gpa, pt.tid, opaque_init)) {3533 const wip_ty = switch (try ip.getOpaqueType(gpa, pt.tid, opaque_init)) {
3526 .existing => |ty| {3534 .existing => |ty| {
...@@ -7386,7 +7394,7 @@ fn analyzeCall(...@@ -7386,7 +7394,7 @@ fn analyzeCall(
7386 const body = sema.code.bodySlice(extra.end, extra.data.type.body_len);7394 const body = sema.code.bodySlice(extra.end, extra.data.type.body_len);
73877395
7388 generic_block.comptime_reason = .{ .reason = .{7396 generic_block.comptime_reason = .{ .reason = .{
7389 .r = .{ .simple = .function_parameters },7397 .r = .{ .simple = .fn_param_types },
7390 .src = param_src,7398 .src = param_src,
7391 } };7399 } };
73927400
...@@ -7470,7 +7478,7 @@ fn analyzeCall(...@@ -7470,7 +7478,7 @@ fn analyzeCall(
7470 sema.inst_map = generic_inst_map;7478 sema.inst_map = generic_inst_map;
74717479
7472 generic_block.comptime_reason = .{ .reason = .{7480 generic_block.comptime_reason = .{ .reason = .{
7473 .r = .{ .simple = .function_ret_ty },7481 .r = .{ .simple = .fn_ret_ty },
7474 .src = func_ret_ty_src,7482 .src = func_ret_ty_src,
7475 } };7483 } };
74767484
...@@ -8927,7 +8935,7 @@ fn zirFunc(...@@ -8927,7 +8935,7 @@ fn zirFunc(
8927 const ret_ty_body = sema.code.bodySlice(extra_index, extra.data.ret_ty.body_len);8935 const ret_ty_body = sema.code.bodySlice(extra_index, extra.data.ret_ty.body_len);
8928 extra_index += ret_ty_body.len;8936 extra_index += ret_ty_body.len;
89298937
8930 const ret_ty_val = try sema.resolveGenericBody(block, ret_ty_src, ret_ty_body, inst, .type, .{ .simple = .function_ret_ty });8938 const ret_ty_val = try sema.resolveGenericBody(block, ret_ty_src, ret_ty_body, inst, .type, .{ .simple = .fn_ret_ty });
8931 break :blk ret_ty_val.toType();8939 break :blk ret_ty_val.toType();
8932 },8940 },
8933 };8941 };
...@@ -9171,6 +9179,181 @@ fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc:...@@ -9171,6 +9179,181 @@ fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc:
9171 }9179 }
9172}9180}
91739181
9182fn checkParamTypeCommon(
9183 sema: *Sema,
9184 block: *Block,
9185 param_idx: u32,
9186 param_ty: Type,
9187 param_is_noalias: bool,
9188 param_src: LazySrcLoc,
9189 cc: std.builtin.CallingConvention,
9190) CompileError!void {
9191 const pt = sema.pt;
9192 const zcu = pt.zcu;
9193 const target = zcu.getTarget();
9194
9195 if (!param_ty.isValidParamType(zcu)) {
9196 const opaque_str = if (param_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";
9197 return sema.fail(block, param_src, "parameter of {s}type '{f}' not allowed", .{
9198 opaque_str, param_ty.fmt(pt),
9199 });
9200 }
9201 if (!param_ty.isGenericPoison() and
9202 !target_util.fnCallConvAllowsZigTypes(cc) and
9203 !try sema.validateExternType(param_ty, .param_ty))
9204 {
9205 return sema.failWithOwnedErrorMsg(block, msg: {
9206 const msg = try sema.errMsg(param_src, "parameter of type '{f}' not allowed in function with calling convention '{s}'", .{
9207 param_ty.fmt(pt), @tagName(cc),
9208 });
9209 errdefer msg.destroy(sema.gpa);
9210
9211 try sema.explainWhyTypeIsNotExtern(msg, param_src, param_ty, .param_ty);
9212
9213 try sema.addDeclaredHereNote(msg, param_ty);
9214 break :msg msg;
9215 });
9216 }
9217 switch (cc) {
9218 .x86_64_interrupt, .x86_interrupt => {
9219 const err_code_size = target.ptrBitWidth();
9220 switch (param_idx) {
9221 0 => if (param_ty.zigTypeTag(zcu) != .pointer) return sema.fail(block, param_src, "first parameter of function with '{s}' calling convention must be a pointer type", .{@tagName(cc)}),
9222 1 => if (param_ty.bitSize(zcu) != err_code_size) return sema.fail(block, param_src, "second parameter of function with '{s}' calling convention must be a {d}-bit integer", .{ @tagName(cc), err_code_size }),
9223 else => return sema.fail(block, param_src, "'{s}' calling convention supports up to 2 parameters, found {d}", .{ @tagName(cc), param_idx + 1 }),
9224 }
9225 },
9226 .arc_interrupt,
9227 .arm_interrupt,
9228 .microblaze_interrupt,
9229 .mips64_interrupt,
9230 .mips_interrupt,
9231 .riscv64_interrupt,
9232 .riscv32_interrupt,
9233 .sh_interrupt,
9234 .avr_interrupt,
9235 .csky_interrupt,
9236 .m68k_interrupt,
9237 .msp430_interrupt,
9238 .avr_signal,
9239 => return sema.fail(block, param_src, "parameters are not allowed with '{s}' calling convention", .{@tagName(cc)}),
9240 else => {},
9241 }
9242 if (param_is_noalias and !param_ty.isGenericPoison() and !param_ty.isPtrAtRuntime(zcu) and !param_ty.isSliceAtRuntime(zcu)) {
9243 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});
9244 }
9245}
9246
9247fn checkReturnTypeAndCallConvCommon(
9248 sema: *Sema,
9249 block: *Block,
9250 bare_ret_ty: Type,
9251 ret_ty_src: LazySrcLoc,
9252 @"callconv": std.builtin.CallingConvention,
9253 callconv_src: LazySrcLoc,
9254 /// non-`null` only if the function is varargs.
9255 opt_varargs_src: ?LazySrcLoc,
9256 inferred_error_set: bool,
9257 is_noinline: bool,
9258) CompileError!void {
9259 const pt = sema.pt;
9260 const zcu = pt.zcu;
9261 const gpa = zcu.gpa;
9262 if (opt_varargs_src) |varargs_src| {
9263 try sema.checkCallConvSupportsVarArgs(block, varargs_src, @"callconv");
9264 }
9265 if (inferred_error_set and !bare_ret_ty.isGenericPoison()) {
9266 try sema.validateErrorUnionPayloadType(block, bare_ret_ty, ret_ty_src);
9267 }
9268 const ies_ret_ty_prefix: []const u8 = if (inferred_error_set) "!" else "";
9269 if (!bare_ret_ty.isValidReturnType(zcu)) {
9270 const opaque_str = if (bare_ret_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";
9271 return sema.fail(block, ret_ty_src, "{s}return type '{s}{f}' not allowed", .{
9272 opaque_str, ies_ret_ty_prefix, bare_ret_ty.fmt(pt),
9273 });
9274 }
9275 if (!bare_ret_ty.isGenericPoison() and
9276 !target_util.fnCallConvAllowsZigTypes(@"callconv") and
9277 (inferred_error_set or !try sema.validateExternType(bare_ret_ty, .ret_ty)))
9278 {
9279 return sema.failWithOwnedErrorMsg(block, msg: {
9280 const msg = try sema.errMsg(ret_ty_src, "return type '{s}{f}' not allowed in function with calling convention '{s}'", .{
9281 ies_ret_ty_prefix, bare_ret_ty.fmt(pt), @tagName(@"callconv"),
9282 });
9283 errdefer msg.destroy(gpa);
9284 if (!inferred_error_set) {
9285 try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src, bare_ret_ty, .ret_ty);
9286 try sema.addDeclaredHereNote(msg, bare_ret_ty);
9287 }
9288 break :msg msg;
9289 });
9290 }
9291 validate_incoming_stack_align: {
9292 const a: u64 = switch (@"callconv") {
9293 inline else => |payload| if (@TypeOf(payload) != void and @hasField(@TypeOf(payload), "incoming_stack_alignment"))
9294 payload.incoming_stack_alignment orelse break :validate_incoming_stack_align
9295 else
9296 break :validate_incoming_stack_align,
9297 };
9298 if (!std.math.isPowerOfTwo(a)) {
9299 return sema.fail(block, callconv_src, "calling convention incoming stack alignment '{d}' is not a power of two", .{a});
9300 }
9301 }
9302 switch (@"callconv") {
9303 .x86_64_interrupt,
9304 .x86_interrupt,
9305 .arm_interrupt,
9306 .mips64_interrupt,
9307 .mips_interrupt,
9308 .riscv64_interrupt,
9309 .riscv32_interrupt,
9310 .sh_interrupt,
9311 .arc_interrupt,
9312 .avr_interrupt,
9313 .csky_interrupt,
9314 .m68k_interrupt,
9315 .microblaze_interrupt,
9316 .msp430_interrupt,
9317 .avr_signal,
9318 => {
9319 const ret_ok = !inferred_error_set and switch (bare_ret_ty.toIntern()) {
9320 .void_type, .noreturn_type => true,
9321 else => false,
9322 };
9323 if (!ret_ok) {
9324 return sema.fail(block, ret_ty_src, "function with calling convention '{s}' must return 'void' or 'noreturn'", .{@tagName(@"callconv")});
9325 }
9326 },
9327 .@"inline" => if (is_noinline) {
9328 return sema.fail(block, callconv_src, "'noinline' function cannot have calling convention 'inline'", .{});
9329 },
9330 else => {},
9331 }
9332 switch (zcu.callconvSupported(@"callconv")) {
9333 .ok => {},
9334 .bad_arch => |allowed_archs| {
9335 const ArchListFormatter = struct {
9336 archs: []const std.Target.Cpu.Arch,
9337 pub fn format(formatter: @This(), w: *std.Io.Writer) std.Io.Writer.Error!void {
9338 for (formatter.archs, 0..) |arch, i| {
9339 if (i != 0)
9340 try w.writeAll(", ");
9341 try w.print("'{s}'", .{@tagName(arch)});
9342 }
9343 }
9344 };
9345 return sema.fail(block, callconv_src, "calling convention '{s}' only available on architectures {f}", .{
9346 @tagName(@"callconv"),
9347 ArchListFormatter{ .archs = allowed_archs },
9348 });
9349 },
9350 .bad_backend => |bad_backend| return sema.fail(block, callconv_src, "calling convention '{s}' not supported by compiler backend '{s}'", .{
9351 @tagName(@"callconv"),
9352 @tagName(bad_backend),
9353 }),
9354 }
9355}
9356
9174fn callConvIsCallable(cc: std.builtin.CallingConvention.Tag) bool {9357fn callConvIsCallable(cc: std.builtin.CallingConvention.Tag) bool {
9175 return switch (cc) {9358 return switch (cc) {
9176 .naked,9359 .naked,
...@@ -9259,7 +9442,6 @@ fn funcCommon(...@@ -9259,7 +9442,6 @@ fn funcCommon(
9259 const pt = sema.pt;9442 const pt = sema.pt;
9260 const zcu = pt.zcu;9443 const zcu = pt.zcu;
9261 const gpa = sema.gpa;9444 const gpa = sema.gpa;
9262 const target = zcu.getTarget();
9263 const ip = &zcu.intern_pool;9445 const ip = &zcu.intern_pool;
9264 const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = src_node_offset });9446 const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = src_node_offset });
9265 const cc_src = block.src(.{ .node_offset_fn_type_cc = src_node_offset });9447 const cc_src = block.src(.{ .node_offset_fn_type_cc = src_node_offset });
...@@ -9293,26 +9475,14 @@ fn funcCommon(...@@ -9293,26 +9475,14 @@ fn funcCommon(
9293 if (param_ty_generic and !target_util.fnCallConvAllowsZigTypes(cc)) {9475 if (param_ty_generic and !target_util.fnCallConvAllowsZigTypes(cc)) {
9294 return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});9476 return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});
9295 }9477 }
9296 if (!param_ty.isValidParamType(zcu)) {9478 try sema.checkParamTypeCommon(
9297 const opaque_str = if (param_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";9479 block,
9298 return sema.fail(block, param_src, "parameter of {s}type '{f}' not allowed", .{9480 @intCast(i),
9299 opaque_str, param_ty.fmt(pt),9481 param_ty,
9300 });9482 is_noalias,
9301 }9483 param_src,
9302 if (!param_ty_generic and !target_util.fnCallConvAllowsZigTypes(cc) and !try sema.validateExternType(param_ty, .param_ty)) {9484 cc,
9303 const msg = msg: {9485 );
9304 const msg = try sema.errMsg(param_src, "parameter of type '{f}' not allowed in function with calling convention '{s}'", .{
9305 param_ty.fmt(pt), @tagName(cc),
9306 });
9307 errdefer msg.destroy(sema.gpa);
9308
9309 try sema.explainWhyTypeIsNotExtern(msg, param_src, param_ty, .param_ty);
9310
9311 try sema.addDeclaredHereNote(msg, param_ty);
9312 break :msg msg;
9313 };
9314 return sema.failWithOwnedErrorMsg(block, msg);
9315 }
9316 if (param_ty_comptime and !param_is_comptime and has_body and !block.isComptime()) {9486 if (param_ty_comptime and !param_is_comptime and has_body and !block.isComptime()) {
9317 const msg = msg: {9487 const msg = msg: {
9318 const msg = try sema.errMsg(param_src, "parameter of type '{f}' must be declared comptime", .{9488 const msg = try sema.errMsg(param_src, "parameter of type '{f}' must be declared comptime", .{
...@@ -9327,209 +9497,40 @@ fn funcCommon(...@@ -9327,209 +9497,40 @@ fn funcCommon(
9327 };9497 };
9328 return sema.failWithOwnedErrorMsg(block, msg);9498 return sema.failWithOwnedErrorMsg(block, msg);
9329 }9499 }
9330 if (!param_ty_generic and is_noalias and
9331 !(param_ty.zigTypeTag(zcu) == .pointer or param_ty.isPtrLikeOptional(zcu)))
9332 {
9333 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});
9334 }
9335 switch (cc) {
9336 .x86_64_interrupt, .x86_interrupt => {
9337 const err_code_size = target.ptrBitWidth();
9338 switch (i) {
9339 0 => if (param_ty.zigTypeTag(zcu) != .pointer) return sema.fail(block, param_src, "first parameter of function with '{s}' calling convention must be a pointer type", .{@tagName(cc)}),
9340 1 => if (param_ty.bitSize(zcu) != err_code_size) return sema.fail(block, param_src, "second parameter of function with '{s}' calling convention must be a {d}-bit integer", .{ @tagName(cc), err_code_size }),
9341 else => return sema.fail(block, param_src, "'{s}' calling convention supports up to 2 parameters, found {d}", .{ @tagName(cc), i + 1 }),
9342 }
9343 },
9344 .arc_interrupt,
9345 .arm_interrupt,
9346 .microblaze_interrupt,
9347 .mips64_interrupt,
9348 .mips_interrupt,
9349 .riscv64_interrupt,
9350 .riscv32_interrupt,
9351 .sh_interrupt,
9352 .avr_interrupt,
9353 .csky_interrupt,
9354 .m68k_interrupt,
9355 .msp430_interrupt,
9356 .avr_signal,
9357 => return sema.fail(block, param_src, "parameters are not allowed with '{s}' calling convention", .{@tagName(cc)}),
9358 else => {},
9359 }
9360 }
9361
9362 if (var_args) {
9363 if (is_generic) {
9364 return sema.fail(block, func_src, "generic function cannot be variadic", .{});
9365 }
9366 const va_args_src = block.src(.{
9367 .fn_proto_param = .{
9368 .fn_proto_node_offset = src_node_offset,
9369 .param_index = @intCast(block.params.len), // va_arg must be the last parameter
9370 },
9371 });
9372 try sema.checkCallConvSupportsVarArgs(block, va_args_src, cc);
9373 }
9374
9375 const ret_poison = bare_return_type.isGenericPoison();
9376
9377 const param_types = block.params.items(.ty);
9378
9379 if (inferred_error_set) {
9380 assert(has_body);
9381 if (!ret_poison)
9382 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
9383 const func_index = try ip.getFuncDeclIes(gpa, pt.tid, .{
9384 .owner_nav = sema.owner.unwrap().nav_val,
9385
9386 .param_types = param_types,
9387 .noalias_bits = noalias_bits,
9388 .comptime_bits = comptime_bits,
9389 .bare_return_type = bare_return_type.toIntern(),
9390 .cc = cc,
9391 .is_var_args = var_args,
9392 .is_generic = is_generic,
9393 .is_noinline = is_noinline,
9394
9395 .zir_body_inst = try block.trackZir(func_inst),
9396 .lbrace_line = src_locs.lbrace_line,
9397 .rbrace_line = src_locs.rbrace_line,
9398 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
9399 .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)),
9400 });
9401 return finishFunc(
9402 sema,
9403 block,
9404 func_index,
9405 .none,
9406 ret_poison,
9407 bare_return_type,
9408 ret_ty_src,
9409 cc,
9410 ret_ty_requires_comptime,
9411 func_inst,
9412 cc_src,
9413 is_noinline,
9414 );
9415 }9500 }
94169501
9417 const func_ty = try ip.getFuncType(gpa, pt.tid, .{9502 if (var_args and is_generic) {
9418 .param_types = param_types,9503 return sema.fail(block, func_src, "generic function cannot be variadic", .{});
9419 .noalias_bits = noalias_bits,
9420 .comptime_bits = comptime_bits,
9421 .return_type = bare_return_type.toIntern(),
9422 .cc = cc,
9423 .is_var_args = var_args,
9424 .is_generic = is_generic,
9425 .is_noinline = is_noinline,
9426 });
9427
9428 if (has_body) {
9429 const func_index = try ip.getFuncDecl(gpa, pt.tid, .{
9430 .owner_nav = sema.owner.unwrap().nav_val,
9431 .ty = func_ty,
9432 .cc = cc,
9433 .is_noinline = is_noinline,
9434 .zir_body_inst = try block.trackZir(func_inst),
9435 .lbrace_line = src_locs.lbrace_line,
9436 .rbrace_line = src_locs.rbrace_line,
9437 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
9438 .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)),
9439 });
9440 return finishFunc(
9441 sema,
9442 block,
9443 func_index,
9444 func_ty,
9445 ret_poison,
9446 bare_return_type,
9447 ret_ty_src,
9448 cc,
9449 ret_ty_requires_comptime,
9450 func_inst,
9451 cc_src,
9452 is_noinline,
9453 );
9454 }9504 }
94559505
9456 return finishFunc(9506 try sema.checkReturnTypeAndCallConvCommon(
9457 sema,
9458 block,9507 block,
9459 .none,
9460 func_ty,
9461 ret_poison,
9462 bare_return_type,9508 bare_return_type,
9463 ret_ty_src,9509 ret_ty_src,
9464 cc,9510 cc,
9465 ret_ty_requires_comptime,
9466 func_inst,
9467 cc_src,9511 cc_src,
9512 if (var_args) block.src(.{ .fn_proto_param = .{
9513 .fn_proto_node_offset = src_node_offset,
9514 .param_index = @intCast(block.params.len),
9515 } }) else null,
9516 inferred_error_set,
9468 is_noinline,9517 is_noinline,
9469 );9518 );
9470}
9471
9472fn finishFunc(
9473 sema: *Sema,
9474 block: *Block,
9475 opt_func_index: InternPool.Index,
9476 func_ty: InternPool.Index,
9477 ret_poison: bool,
9478 bare_return_type: Type,
9479 ret_ty_src: LazySrcLoc,
9480 cc_resolved: std.builtin.CallingConvention,
9481 ret_ty_requires_comptime: bool,
9482 func_inst: Zir.Inst.Index,
9483 cc_src: LazySrcLoc,
9484 is_noinline: bool,
9485) CompileError!Air.Inst.Ref {
9486 const pt = sema.pt;
9487 const zcu = pt.zcu;
9488 const ip = &zcu.intern_pool;
9489 const gpa = sema.gpa;
9490
9491 const return_type: Type = if (opt_func_index == .none or ret_poison)
9492 bare_return_type
9493 else
9494 .fromInterned(ip.funcTypeReturnType(ip.typeOf(opt_func_index)));
9495
9496 if (!return_type.isValidReturnType(zcu)) {
9497 const opaque_str = if (return_type.zigTypeTag(zcu) == .@"opaque") "opaque " else "";
9498 return sema.fail(block, ret_ty_src, "{s}return type '{f}' not allowed", .{
9499 opaque_str, return_type.fmt(pt),
9500 });
9501 }
9502 if (!ret_poison and !target_util.fnCallConvAllowsZigTypes(cc_resolved) and
9503 !try sema.validateExternType(return_type, .ret_ty))
9504 {
9505 const msg = msg: {
9506 const msg = try sema.errMsg(ret_ty_src, "return type '{f}' not allowed in function with calling convention '{s}'", .{
9507 return_type.fmt(pt), @tagName(cc_resolved),
9508 });
9509 errdefer msg.destroy(gpa);
9510
9511 try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src, return_type, .ret_ty);
9512
9513 try sema.addDeclaredHereNote(msg, return_type);
9514 break :msg msg;
9515 };
9516 return sema.failWithOwnedErrorMsg(block, msg);
9517 }
95189519
9519 // If the return type is comptime-only but not dependent on parameters then9520 // If the return type is comptime-only but not dependent on parameters then
9520 // all parameter types also need to be comptime.9521 // all parameter types also need to be comptime.
9521 if (opt_func_index != .none and ret_ty_requires_comptime and !block.isComptime()) comptime_check: {9522 if (has_body and ret_ty_requires_comptime and !block.isComptime()) comptime_check: {
9522 for (block.params.items(.is_comptime)) |is_comptime| {9523 for (block.params.items(.is_comptime)) |is_comptime| {
9523 if (!is_comptime) break;9524 if (!is_comptime) break;
9524 } else break :comptime_check;9525 } else break :comptime_check;
95259526 const ies_ret_ty_prefix: []const u8 = if (inferred_error_set) "!" else "";
9526 const msg = try sema.errMsg(9527 const msg = try sema.errMsg(
9527 ret_ty_src,9528 ret_ty_src,
9528 "function with comptime-only return type '{f}' requires all parameters to be comptime",9529 "function with comptime-only return type '{s}{f}' requires all parameters to be comptime",
9529 .{return_type.fmt(pt)},9530 .{ ies_ret_ty_prefix, bare_return_type.fmt(pt) },
9530 );9531 );
9531 errdefer msg.destroy(sema.gpa);9532 errdefer msg.destroy(sema.gpa);
9532 try sema.explainWhyTypeIsComptime(msg, ret_ty_src, return_type);9533 try sema.explainWhyTypeIsComptime(msg, ret_ty_src, bare_return_type);
95339534
9534 const tags = sema.code.instructions.items(.tag);9535 const tags = sema.code.instructions.items(.tag);
9535 const data = sema.code.instructions.items(.data);9536 const data = sema.code.instructions.items(.data);
...@@ -9556,68 +9557,56 @@ fn finishFunc(...@@ -9556,68 +9557,56 @@ fn finishFunc(
9556 return sema.failWithOwnedErrorMsg(block, msg);9557 return sema.failWithOwnedErrorMsg(block, msg);
9557 }9558 }
95589559
9559 validate_incoming_stack_align: {9560 const param_types = block.params.items(.ty);
9560 const a: u64 = switch (cc_resolved) {
9561 inline else => |payload| if (@TypeOf(payload) != void and @hasField(@TypeOf(payload), "incoming_stack_alignment"))
9562 payload.incoming_stack_alignment orelse break :validate_incoming_stack_align
9563 else
9564 break :validate_incoming_stack_align,
9565 };
9566 if (!std.math.isPowerOfTwo(a)) {
9567 return sema.fail(block, cc_src, "calling convention incoming stack alignment '{d}' is not a power of two", .{a});
9568 }
9569 }
95709561
9571 switch (cc_resolved) {9562 if (inferred_error_set) {
9572 .x86_64_interrupt,9563 assert(has_body);
9573 .x86_interrupt,9564 return .fromIntern(try ip.getFuncDeclIes(gpa, pt.tid, .{
9574 .arm_interrupt,9565 .owner_nav = sema.owner.unwrap().nav_val,
9575 .mips64_interrupt,9566
9576 .mips_interrupt,9567 .param_types = param_types,
9577 .riscv64_interrupt,9568 .noalias_bits = noalias_bits,
9578 .riscv32_interrupt,9569 .comptime_bits = comptime_bits,
9579 .sh_interrupt,9570 .bare_return_type = bare_return_type.toIntern(),
9580 .arc_interrupt,9571 .cc = cc,
9581 .avr_interrupt,9572 .is_var_args = var_args,
9582 .csky_interrupt,9573 .is_generic = is_generic,
9583 .m68k_interrupt,9574 .is_noinline = is_noinline,
9584 .microblaze_interrupt,9575
9585 .msp430_interrupt,9576 .zir_body_inst = try block.trackZir(func_inst),
9586 .avr_signal,9577 .lbrace_line = src_locs.lbrace_line,
9587 => if (return_type.zigTypeTag(zcu) != .void and return_type.zigTypeTag(zcu) != .noreturn) {9578 .rbrace_line = src_locs.rbrace_line,
9588 return sema.fail(block, ret_ty_src, "function with calling convention '{s}' must return 'void' or 'noreturn'", .{@tagName(cc_resolved)});9579 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
9589 },9580 .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)),
9590 .@"inline" => if (is_noinline) {9581 }));
9591 return sema.fail(block, cc_src, "'noinline' function cannot have calling convention 'inline'", .{});
9592 },
9593 else => {},
9594 }9582 }
95959583
9596 switch (zcu.callconvSupported(cc_resolved)) {9584 const func_ty = try ip.getFuncType(gpa, pt.tid, .{
9597 .ok => {},9585 .param_types = param_types,
9598 .bad_arch => |allowed_archs| {9586 .noalias_bits = noalias_bits,
9599 const ArchListFormatter = struct {9587 .comptime_bits = comptime_bits,
9600 archs: []const std.Target.Cpu.Arch,9588 .return_type = bare_return_type.toIntern(),
9601 pub fn format(formatter: @This(), w: *std.Io.Writer) std.Io.Writer.Error!void {9589 .cc = cc,
9602 for (formatter.archs, 0..) |arch, i| {9590 .is_var_args = var_args,
9603 if (i != 0)9591 .is_generic = is_generic,
9604 try w.writeAll(", ");9592 .is_noinline = is_noinline,
9605 try w.print("'{s}'", .{@tagName(arch)});9593 });
9606 }9594
9607 }9595 if (has_body) {
9608 };9596 return .fromIntern(try ip.getFuncDecl(gpa, pt.tid, .{
9609 return sema.fail(block, cc_src, "calling convention '{s}' only available on architectures {f}", .{9597 .owner_nav = sema.owner.unwrap().nav_val,
9610 @tagName(cc_resolved),9598 .ty = func_ty,
9611 ArchListFormatter{ .archs = allowed_archs },9599 .cc = cc,
9612 });9600 .is_noinline = is_noinline,
9613 },9601 .zir_body_inst = try block.trackZir(func_inst),
9614 .bad_backend => |bad_backend| return sema.fail(block, cc_src, "calling convention '{s}' not supported by compiler backend '{s}'", .{9602 .lbrace_line = src_locs.lbrace_line,
9615 @tagName(cc_resolved),9603 .rbrace_line = src_locs.rbrace_line,
9616 @tagName(bad_backend),9604 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
9617 }),9605 .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)),
9606 }));
9618 }9607 }
96199608
9620 return Air.internedToRef(if (opt_func_index != .none) opt_func_index else func_ty);9609 return .fromIntern(func_ty);
9621}9610}
96229611
9623fn zirParam(9612fn zirParam(
...@@ -19395,7 +19384,7 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -19395,7 +19384,7 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
19395 if (union_ty.zigTypeTag(pt.zcu) != .@"union") {19384 if (union_ty.zigTypeTag(pt.zcu) != .@"union") {
19396 return sema.fail(block, ty_src, "expected union type, found '{f}'", .{union_ty.fmt(pt)});19385 return sema.fail(block, ty_src, "expected union type, found '{f}'", .{union_ty.fmt(pt)});
19397 }19386 }
19398 const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, .{ .simple = .union_field_name });19387 const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, .{ .simple = .union_field_names });
19399 const init = try sema.resolveInst(extra.init);19388 const init = try sema.resolveInst(extra.init);
19400 return sema.unionInit(block, init, init_src, union_ty, ty_src, field_name, field_src);19389 return sema.unionInit(block, init, init_src, union_ty, ty_src, field_name, field_src);
19401}19390}
...@@ -20553,589 +20542,529 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -20553,589 +20542,529 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20553 return block.addUnOp(.tag_name, casted_operand);20542 return block.addUnOp(.tag_name, casted_operand);
20554}20543}
2055520544
20556fn zirReify(20545fn zirReifyInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
20546 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
20547 const signedness_src = block.builtinCallArgSrc(inst_data.src_node, 0);
20548 const bits_src = block.builtinCallArgSrc(inst_data.src_node, 1);
20549 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
20550 const signedness = try sema.resolveBuiltinEnum(block, signedness_src, extra.lhs, .Signedness, .{ .simple = .int_signedness });
20551 const bits: u16 = @intCast(try sema.resolveInt(block, bits_src, extra.rhs, .u16, .{ .simple = .int_bit_width }));
20552 return .fromType(try sema.pt.intType(signedness, bits));
20553}
20554
20555fn zirReifySliceArgTy(
20557 sema: *Sema,20556 sema: *Sema,
20558 block: *Block,20557 block: *Block,
20559 extended: Zir.Inst.Extended.InstData,20558 extended: Zir.Inst.Extended.InstData,
20560 inst: Zir.Inst.Index,
20561) CompileError!Air.Inst.Ref {20559) CompileError!Air.Inst.Ref {
20562 const pt = sema.pt;20560 const pt = sema.pt;
20563 const zcu = pt.zcu;20561 const zcu = pt.zcu;
20564 const gpa = sema.gpa;20562
20565 const ip = &zcu.intern_pool;20563 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
20566 const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small);20564 const info: Zir.Inst.ReifySliceArgInfo = @enumFromInt(extended.small);
20567 const extra = sema.code.extraData(Zir.Inst.Reify, extended.operand).data;20565
20568 const tracked_inst = try block.trackZir(inst);20566 const src = block.nodeOffset(extra.node);
20569 const src: LazySrcLoc = .{20567
20570 .base_node_inst = tracked_inst,20568 const comptime_reason: std.zig.SimpleComptimeReason, const in_scalar_ty: Type, const out_scalar_ty: Type = switch (info) {
20571 .offset = LazySrcLoc.Offset.nodeOffset(.zero),20569 // zig fmt: off
20572 };20570 .type_to_fn_param_attrs => .{ .fn_param_attrs, .type, try sema.getBuiltinType(src, .@"Type.Fn.Param.Attributes") },
20573 const operand_src: LazySrcLoc = .{20571 .string_to_struct_field_type => .{ .struct_field_types, .slice_const_u8, .type },
20574 .base_node_inst = tracked_inst,20572 .string_to_union_field_type => .{ .union_field_types, .slice_const_u8, .type },
20575 .offset = .{20573 .string_to_struct_field_attrs => .{ .struct_field_attrs, .slice_const_u8, try sema.getBuiltinType(src, .@"Type.StructField.Attributes") },
20576 .node_offset_builtin_call_arg = .{20574 .string_to_union_field_attrs => .{ .union_field_attrs, .slice_const_u8, try sema.getBuiltinType(src, .@"Type.UnionField.Attributes") },
20577 .builtin_call_node = .zero, // `tracked_inst` is precisely the `reify` instruction, so offset is 020575 // zig fmt: on
20578 .arg_index = 0,
20579 },
20580 },
20581 };20576 };
20582 const type_info_ty = try sema.getBuiltinType(src, .Type);
20583 const uncasted_operand = try sema.resolveInst(extra.operand);
20584 const type_info = try sema.coerce(block, type_info_ty, uncasted_operand, operand_src);
20585 const val = try sema.resolveConstDefinedValue(block, operand_src, type_info, .{ .simple = .operand_Type });
20586 const union_val = ip.indexToKey(val.toIntern()).un;
20587 if (try sema.anyUndef(block, operand_src, Value.fromInterned(union_val.val))) {
20588 return sema.failWithUseOfUndef(block, operand_src, null);
20589 }
20590 const tag_index = type_info_ty.unionTagFieldIndex(Value.fromInterned(union_val.tag), zcu).?;
20591 switch (@as(std.builtin.TypeId, @enumFromInt(tag_index))) {
20592 .type => return .type_type,
20593 .void => return .void_type,
20594 .bool => return .bool_type,
20595 .noreturn => return .noreturn_type,
20596 .comptime_float => return .comptime_float_type,
20597 .comptime_int => return .comptime_int_type,
20598 .undefined => return .undefined_type,
20599 .null => return .null_type,
20600 .@"anyframe" => return sema.failWithUseOfAsync(block, src),
20601 .enum_literal => return .enum_literal_type,
20602 .int => {
20603 const int = try sema.interpretBuiltinType(block, operand_src, .fromInterned(union_val.val), std.builtin.Type.Int);
20604 const ty = try pt.intType(int.signedness, int.bits);
20605 return Air.internedToRef(ty.toIntern());
20606 },
20607 .vector => {
20608 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
20609 const len_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20610 ip,
20611 try ip.getOrPutString(gpa, pt.tid, "len", .no_embedded_nulls),
20612 ).?);
20613 const child_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20614 ip,
20615 try ip.getOrPutString(gpa, pt.tid, "child", .no_embedded_nulls),
20616 ).?);
20617
20618 const len: u32 = @intCast(try len_val.toUnsignedIntSema(pt));
20619 const child_ty = child_val.toType();
20620
20621 try sema.checkVectorElemType(block, src, child_ty);
20622
20623 const ty = try pt.vectorType(.{
20624 .len = len,
20625 .child = child_ty.toIntern(),
20626 });
20627 return Air.internedToRef(ty.toIntern());
20628 },
20629 .float => {
20630 const float = try sema.interpretBuiltinType(block, operand_src, .fromInterned(union_val.val), std.builtin.Type.Float);
20631
20632 const ty: Type = switch (float.bits) {
20633 16 => .f16,
20634 32 => .f32,
20635 64 => .f64,
20636 80 => .f80,
20637 128 => .f128,
20638 else => return sema.fail(block, src, "{d}-bit float unsupported", .{float.bits}),
20639 };
20640 return Air.internedToRef(ty.toIntern());
20641 },
20642 .pointer => {
20643 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
20644 const size_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20645 ip,
20646 try ip.getOrPutString(gpa, pt.tid, "size", .no_embedded_nulls),
20647 ).?);
20648 const is_const_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20649 ip,
20650 try ip.getOrPutString(gpa, pt.tid, "is_const", .no_embedded_nulls),
20651 ).?);
20652 const is_volatile_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20653 ip,
20654 try ip.getOrPutString(gpa, pt.tid, "is_volatile", .no_embedded_nulls),
20655 ).?);
20656 const alignment_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20657 ip,
20658 try ip.getOrPutString(gpa, pt.tid, "alignment", .no_embedded_nulls),
20659 ).?);
20660 const address_space_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20661 ip,
20662 try ip.getOrPutString(gpa, pt.tid, "address_space", .no_embedded_nulls),
20663 ).?);
20664 const child_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20665 ip,
20666 try ip.getOrPutString(gpa, pt.tid, "child", .no_embedded_nulls),
20667 ).?);
20668 const is_allowzero_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20669 ip,
20670 try ip.getOrPutString(gpa, pt.tid, "is_allowzero", .no_embedded_nulls),
20671 ).?);
20672 const sentinel_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20673 ip,
20674 try ip.getOrPutString(gpa, pt.tid, "sentinel_ptr", .no_embedded_nulls),
20675 ).?);
20676
20677 if (!try sema.intFitsInType(alignment_val, align_ty, null)) {
20678 return sema.fail(block, src, "alignment must fit in '{f}'", .{align_ty.fmt(pt)});
20679 }
20680 const alignment_val_int = try alignment_val.toUnsignedIntSema(pt);
20681 const abi_align = try sema.validateAlign(block, src, alignment_val_int);
20682
20683 const elem_ty = child_val.toType();
20684 if (abi_align != .none) {
20685 try elem_ty.resolveLayout(pt);
20686 }
20687
20688 const ptr_size = try sema.interpretBuiltinType(block, operand_src, size_val, std.builtin.Type.Pointer.Size);
20689
20690 const actual_sentinel: InternPool.Index = s: {
20691 if (!sentinel_val.isNull(zcu)) {
20692 if (ptr_size == .one or ptr_size == .c) {
20693 return sema.fail(block, src, "sentinels are only allowed on slices and unknown-length pointers", .{});
20694 }
20695 const sentinel_ptr_val = sentinel_val.optionalValue(zcu).?;
20696 const ptr_ty = try pt.singleMutPtrType(elem_ty);
20697 const sent_val = (try sema.pointerDeref(block, src, sentinel_ptr_val, ptr_ty)).?;
20698 try sema.checkSentinelType(block, src, elem_ty);
20699 if (sent_val.canMutateComptimeVarState(zcu)) {
20700 const sentinel_name = try ip.getOrPutString(gpa, pt.tid, "sentinel_ptr", .no_embedded_nulls);
20701 return sema.failWithContainsReferenceToComptimeVar(block, src, sentinel_name, "sentinel", sent_val);
20702 }
20703 break :s sent_val.toIntern();
20704 }
20705 break :s .none;
20706 };
2070720577
20708 if (elem_ty.zigTypeTag(zcu) == .noreturn) {20578 const operand_ty = try pt.ptrTypeSema(.{
20709 return sema.fail(block, src, "pointer to noreturn not allowed", .{});20579 .child = in_scalar_ty.toIntern(),
20710 } else if (elem_ty.zigTypeTag(zcu) == .@"fn") {20580 .flags = .{ .size = .slice, .is_const = true },
20711 if (ptr_size != .one) {20581 });
20712 return sema.fail(block, src, "function pointers must be single pointers", .{});
20713 }
20714 } else if (ptr_size != .one and elem_ty.zigTypeTag(zcu) == .@"opaque") {
20715 return sema.fail(block, src, "indexable pointer to opaque type '{f}' not allowed", .{elem_ty.fmt(pt)});
20716 } else if (ptr_size == .c) {
20717 if (!try sema.validateExternType(elem_ty, .other)) {
20718 const msg = msg: {
20719 const msg = try sema.errMsg(src, "C pointers cannot point to non-C-ABI-compatible type '{f}'", .{elem_ty.fmt(pt)});
20720 errdefer msg.destroy(gpa);
2072120582
20722 try sema.explainWhyTypeIsNotExtern(msg, src, elem_ty, .other);20583 const operand_uncoerced = try sema.resolveInst(extra.operand);
20584 const operand_coerced = try sema.coerce(block, operand_ty, operand_uncoerced, src);
20585 const operand_val = try sema.resolveConstDefinedValue(block, src, operand_coerced, .{ .simple = comptime_reason });
20586 const len_val: Value = .fromInterned(zcu.intern_pool.indexToKey(operand_val.toIntern()).slice.len);
20587 if (len_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, src, null);
20588 const len = try len_val.toUnsignedIntSema(pt);
2072320589
20724 try sema.addDeclaredHereNote(msg, elem_ty);20590 return .fromType(try pt.singleConstPtrType(try pt.arrayType(.{
20725 break :msg msg;20591 .len = len,
20726 };20592 .child = out_scalar_ty.toIntern(),
20727 return sema.failWithOwnedErrorMsg(block, msg);20593 })));
20728 }20594}
20729 }
2073020595
20731 const ty = try pt.ptrTypeSema(.{20596fn zirReifyEnumValueSliceTy(
20732 .child = elem_ty.toIntern(),20597 sema: *Sema,
20733 .sentinel = actual_sentinel,20598 block: *Block,
20734 .flags = .{20599 extended: Zir.Inst.Extended.InstData,
20735 .size = ptr_size,20600) CompileError!Air.Inst.Ref {
20736 .is_const = is_const_val.toBool(),20601 const pt = sema.pt;
20737 .is_volatile = is_volatile_val.toBool(),20602 const zcu = pt.zcu;
20738 .alignment = abi_align,
20739 .address_space = try sema.interpretBuiltinType(block, operand_src, address_space_val, std.builtin.AddressSpace),
20740 .is_allowzero = is_allowzero_val.toBool(),
20741 },
20742 });
20743 return Air.internedToRef(ty.toIntern());
20744 },
20745 .array => {
20746 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
20747 const len_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20748 ip,
20749 try ip.getOrPutString(gpa, pt.tid, "len", .no_embedded_nulls),
20750 ).?);
20751 const child_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20752 ip,
20753 try ip.getOrPutString(gpa, pt.tid, "child", .no_embedded_nulls),
20754 ).?);
20755 const sentinel_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20756 ip,
20757 try ip.getOrPutString(gpa, pt.tid, "sentinel_ptr", .no_embedded_nulls),
20758 ).?);
20759
20760 const len = try len_val.toUnsignedIntSema(pt);
20761 const child_ty = child_val.toType();
20762 const sentinel = if (sentinel_val.optionalValue(zcu)) |p| blk: {
20763 const ptr_ty = try pt.singleMutPtrType(child_ty);
20764 try sema.checkSentinelType(block, src, child_ty);
20765 const sentinel = (try sema.pointerDeref(block, src, p, ptr_ty)).?;
20766 if (sentinel.canMutateComptimeVarState(zcu)) {
20767 const sentinel_name = try ip.getOrPutString(gpa, pt.tid, "sentinel_ptr", .no_embedded_nulls);
20768 return sema.failWithContainsReferenceToComptimeVar(block, src, sentinel_name, "sentinel", sentinel);
20769 }
20770 break :blk sentinel;
20771 } else null;
20772
20773 const ty = try pt.arrayType(.{
20774 .len = len,
20775 .sentinel = if (sentinel) |s| s.toIntern() else .none,
20776 .child = child_ty.toIntern(),
20777 });
20778 return Air.internedToRef(ty.toIntern());
20779 },
20780 .optional => {
20781 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
20782 const child_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20783 ip,
20784 try ip.getOrPutString(gpa, pt.tid, "child", .no_embedded_nulls),
20785 ).?);
2078620603
20787 const child_ty = child_val.toType();20604 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
2078820605
20789 const ty = try pt.optionalType(child_ty.toIntern());20606 const int_tag_ty_src = block.builtinCallArgSrc(extra.node, 0);
20790 return Air.internedToRef(ty.toIntern());20607 const field_names_src = block.builtinCallArgSrc(extra.node, 2);
20791 },
20792 .error_union => {
20793 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
20794 const error_set_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20795 ip,
20796 try ip.getOrPutString(gpa, pt.tid, "error_set", .no_embedded_nulls),
20797 ).?);
20798 const payload_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20799 ip,
20800 try ip.getOrPutString(gpa, pt.tid, "payload", .no_embedded_nulls),
20801 ).?);
2080220608
20803 const error_set_ty = error_set_val.toType();20609 const int_tag_ty = try sema.resolveType(block, int_tag_ty_src, extra.lhs);
20804 const payload_ty = payload_val.toType();
2080520610
20806 if (error_set_ty.zigTypeTag(zcu) != .error_set) {20611 const operand_uncoerced = try sema.resolveInst(extra.rhs);
20807 return sema.fail(block, src, "Type.ErrorUnion.error_set must be an error set type", .{});20612 const operand_coerced = try sema.coerce(block, .slice_const_slice_const_u8, operand_uncoerced, field_names_src);
20808 }20613 const operand_val = try sema.resolveConstDefinedValue(block, field_names_src, operand_coerced, .{ .simple = .enum_field_names });
20614 const len_val: Value = .fromInterned(zcu.intern_pool.indexToKey(operand_val.toIntern()).slice.len);
20615 if (len_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, field_names_src, null);
20616 const len = try len_val.toUnsignedIntSema(pt);
2080920617
20810 const ty = try pt.errorUnionType(error_set_ty, payload_ty);20618 return .fromType(try pt.singleConstPtrType(try pt.arrayType(.{
20811 return Air.internedToRef(ty.toIntern());20619 .len = len,
20812 },20620 .child = int_tag_ty.toIntern(),
20813 .error_set => {20621 })));
20814 const payload_val = Value.fromInterned(union_val.val).optionalValue(zcu) orelse20622}
20815 return .anyerror_type;20623
20624fn zirReifyPointerSentinelTy(
20625 sema: *Sema,
20626 block: *Block,
20627 extended: Zir.Inst.Extended.InstData,
20628) CompileError!Air.Inst.Ref {
20629 const pt = sema.pt;
20630 const zcu = pt.zcu;
20631 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
20632 const src = block.nodeOffset(extra.node);
20633 const elem_ty = try sema.resolveType(block, src, extra.operand);
20634 return .fromType(switch (elem_ty.zigTypeTag(zcu)) {
20635 else => try pt.optionalType(elem_ty.toIntern()),
20636 // These types cannot be the child of an optional. To allow reifying pointers to them still,
20637 // we treat the "sentinel" argument to `@Pointer` as `?noreturn` instead of `?T`.
20638 .@"opaque", .null => .optional_noreturn,
20639 });
20640}
2081620641
20817 const names_val = try sema.derefSliceAsArray(block, src, payload_val, .{ .simple = .error_set_contents });20642fn zirReifyTuple(
20643 sema: *Sema,
20644 block: *Block,
20645 extended: Zir.Inst.Extended.InstData,
20646) CompileError!Air.Inst.Ref {
20647 const pt = sema.pt;
20648 const zcu = pt.zcu;
2081820649
20819 const len = try sema.usizeCast(block, src, names_val.typeOf(zcu).arrayLen(zcu));20650 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
20820 var names: InferredErrorSet.NameMap = .{};20651 const operand_src = block.builtinCallArgSrc(extra.node, 0);
20821 try names.ensureUnusedCapacity(sema.arena, len);
20822 for (0..len) |i| {
20823 const elem_val = try names_val.elemValue(pt, i);
20824 const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern()));
20825 const name_val = try elem_val.fieldValue(pt, elem_struct_type.nameIndex(
20826 ip,
20827 try ip.getOrPutString(gpa, pt.tid, "name", .no_embedded_nulls),
20828 ).?);
20829
20830 const name = try sema.sliceToIpString(block, src, name_val, .{ .simple = .error_set_contents });
20831 _ = try pt.getErrorValue(name);
20832 const gop = names.getOrPutAssumeCapacity(name);
20833 if (gop.found_existing) {
20834 return sema.fail(block, src, "duplicate error '{f}'", .{
20835 name.fmt(ip),
20836 });
20837 }
20838 }
2083920652
20840 const ty = try pt.errorSetFromUnsortedNames(names.keys());20653 const types_uncoerced = try sema.resolveInst(extra.operand);
20841 return Air.internedToRef(ty.toIntern());20654 const types_coerced = try sema.coerce(block, .slice_const_type, types_uncoerced, operand_src);
20842 },20655 const types_slice_val = try sema.resolveConstDefinedValue(block, operand_src, types_coerced, .{ .simple = .tuple_field_types });
20843 .@"struct" => {20656 const types_array_val = try sema.derefSliceAsArray(block, operand_src, types_slice_val, .{ .simple = .tuple_field_types });
20844 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));20657 const fields_len: u32 = @intCast(types_array_val.typeOf(zcu).arrayLen(zcu));
20845 const layout_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20846 ip,
20847 try ip.getOrPutString(gpa, pt.tid, "layout", .no_embedded_nulls),
20848 ).?);
20849 const backing_integer_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20850 ip,
20851 try ip.getOrPutString(gpa, pt.tid, "backing_integer", .no_embedded_nulls),
20852 ).?);
20853 const fields_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20854 ip,
20855 try ip.getOrPutString(gpa, pt.tid, "fields", .no_embedded_nulls),
20856 ).?);
20857 const decls_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20858 ip,
20859 try ip.getOrPutString(gpa, pt.tid, "decls", .no_embedded_nulls),
20860 ).?);
20861 const is_tuple_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20862 ip,
20863 try ip.getOrPutString(gpa, pt.tid, "is_tuple", .no_embedded_nulls),
20864 ).?);
20865
20866 const layout = try sema.interpretBuiltinType(block, operand_src, layout_val, std.builtin.Type.ContainerLayout);
20867
20868 // Decls
20869 if (try decls_val.sliceLen(pt) > 0) {
20870 return sema.fail(block, src, "reified structs must have no decls", .{});
20871 }
20872
20873 if (layout != .@"packed" and !backing_integer_val.isNull(zcu)) {
20874 return sema.fail(block, src, "non-packed struct does not support backing integer type", .{});
20875 }
20876
20877 const fields_arr = try sema.derefSliceAsArray(block, operand_src, fields_val, .{ .simple = .struct_fields });
20878
20879 if (is_tuple_val.toBool()) {
20880 switch (layout) {
20881 .@"extern" => return sema.fail(block, src, "extern tuples are not supported", .{}),
20882 .@"packed" => return sema.fail(block, src, "packed tuples are not supported", .{}),
20883 .auto => {},
20884 }
20885 return sema.reifyTuple(block, src, fields_arr);
20886 } else {
20887 return sema.reifyStruct(block, inst, src, layout, backing_integer_val, fields_arr, name_strategy);
20888 }
20889 },
20890 .@"enum" => {
20891 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
20892 const tag_type_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20893 ip,
20894 try ip.getOrPutString(gpa, pt.tid, "tag_type", .no_embedded_nulls),
20895 ).?);
20896 const fields_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20897 ip,
20898 try ip.getOrPutString(gpa, pt.tid, "fields", .no_embedded_nulls),
20899 ).?);
20900 const decls_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20901 ip,
20902 try ip.getOrPutString(gpa, pt.tid, "decls", .no_embedded_nulls),
20903 ).?);
20904 const is_exhaustive_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20905 ip,
20906 try ip.getOrPutString(gpa, pt.tid, "is_exhaustive", .no_embedded_nulls),
20907 ).?);
20908
20909 if (try decls_val.sliceLen(pt) > 0) {
20910 return sema.fail(block, src, "reified enums must have no decls", .{});
20911 }
20912
20913 const fields_arr = try sema.derefSliceAsArray(block, operand_src, fields_val, .{ .simple = .enum_fields });
20914
20915 return sema.reifyEnum(block, inst, src, tag_type_val.toType(), is_exhaustive_val.toBool(), fields_arr, name_strategy);
20916 },
20917 .@"opaque" => {
20918 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
20919 const decls_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20920 ip,
20921 try ip.getOrPutString(gpa, pt.tid, "decls", .no_embedded_nulls),
20922 ).?);
2092320658
20924 // Decls20659 const field_types = try sema.arena.alloc(InternPool.Index, fields_len);
20925 if (try decls_val.sliceLen(pt) > 0) {20660 for (field_types, 0..) |*field_ty, field_idx| {
20926 return sema.fail(block, src, "reified opaque must have no decls", .{});20661 const field_ty_val = try types_array_val.elemValue(pt, field_idx);
20927 }20662 if (field_ty_val.isUndef(zcu)) {
20663 return sema.failWithUseOfUndef(block, operand_src, null);
20664 }
20665 field_ty.* = field_ty_val.toIntern();
20666 }
2092820667
20929 const wip_ty = switch (try ip.getOpaqueType(gpa, pt.tid, .{20668 const field_values = try sema.arena.alloc(InternPool.Index, fields_len);
20930 .key = .{ .reified = .{20669 @memset(field_values, .none);
20931 .zir_index = try block.trackZir(inst),
20932 } },
20933 })) {
20934 .existing => |ty| {
20935 try sema.addTypeReferenceEntry(src, ty);
20936 return Air.internedToRef(ty);
20937 },
20938 .wip => |wip| wip,
20939 };
20940 errdefer wip_ty.cancel(ip, pt.tid);
2094120670
20942 const type_name = try sema.createTypeName(20671 return .fromIntern(try zcu.intern_pool.getTupleType(zcu.gpa, pt.tid, .{
20943 block,20672 .types = field_types,
20944 name_strategy,20673 .values = field_values,
20945 "opaque",20674 }));
20946 inst,20675}
20947 wip_ty.index,
20948 );
20949 wip_ty.setName(ip, type_name.name, type_name.nav);
2095020676
20951 const new_namespace_index = try pt.createNamespace(.{20677fn zirReifyPointer(
20952 .parent = block.namespace.toOptional(),20678 sema: *Sema,
20953 .owner_type = wip_ty.index,20679 block: *Block,
20954 .file_scope = block.getFileScopeIndex(zcu),20680 extended: Zir.Inst.Extended.InstData,
20955 .generation = zcu.generation,20681) CompileError!Air.Inst.Ref {
20956 });20682 const pt = sema.pt;
20683 const zcu = pt.zcu;
20684 const gpa = zcu.gpa;
20685 const ip = &zcu.intern_pool;
2095720686
20958 try sema.addTypeReferenceEntry(src, wip_ty.index);20687 const extra = sema.code.extraData(Zir.Inst.ReifyPointer, extended.operand).data;
20959 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);20688 const src = block.nodeOffset(extra.node);
20960 return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));20689 const size_src = block.builtinCallArgSrc(extra.node, 0);
20961 },20690 const attrs_src = block.builtinCallArgSrc(extra.node, 1);
20962 .@"union" => {20691 const elem_ty_src = block.builtinCallArgSrc(extra.node, 2);
20963 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));20692 const sentinel_src = block.builtinCallArgSrc(extra.node, 3);
20964 const layout_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(20693
20965 ip,20694 const size_ty = try sema.getBuiltinType(size_src, .@"Type.Pointer.Size");
20966 try ip.getOrPutString(gpa, pt.tid, "layout", .no_embedded_nulls),20695 const attrs_ty = try sema.getBuiltinType(attrs_src, .@"Type.Pointer.Attributes");
20967 ).?);20696
20968 const tag_type_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(20697 const size_uncoerced = try sema.resolveInst(extra.size);
20969 ip,20698 const size_coerced = try sema.coerce(block, size_ty, size_uncoerced, size_src);
20970 try ip.getOrPutString(gpa, pt.tid, "tag_type", .no_embedded_nulls),20699 const size_val = try sema.resolveConstDefinedValue(block, size_src, size_coerced, .{ .simple = .pointer_size });
20971 ).?);20700 const size = try sema.interpretBuiltinType(block, size_src, size_val, std.builtin.Type.Pointer.Size);
20972 const fields_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(20701
20973 ip,20702 const attrs_uncoerced = try sema.resolveInst(extra.attrs);
20974 try ip.getOrPutString(gpa, pt.tid, "fields", .no_embedded_nulls),20703 const attrs_coerced = try sema.coerce(block, attrs_ty, attrs_uncoerced, attrs_src);
20975 ).?);20704 const attrs_val = try sema.resolveConstDefinedValue(block, attrs_src, attrs_coerced, .{ .simple = .pointer_attrs });
20976 const decls_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(20705 const attrs = try sema.interpretBuiltinType(block, attrs_src, attrs_val, std.builtin.Type.Pointer.Attributes);
20977 ip,20706
20978 try ip.getOrPutString(gpa, pt.tid, "decls", .no_embedded_nulls),20707 const @"align": Alignment = if (attrs.@"align") |bytes| a: {
20979 ).?);20708 break :a try sema.validateAlign(block, attrs_src, bytes);
20709 } else .none;
2098020710
20981 if (try decls_val.sliceLen(pt) > 0) {20711 const elem_ty = try sema.resolveType(block, elem_ty_src, extra.elem_ty);
20982 return sema.fail(block, src, "reified unions must have no decls", .{});
20983 }
20984 const layout = try sema.interpretBuiltinType(block, operand_src, layout_val, std.builtin.Type.ContainerLayout);
2098520712
20986 const has_tag = tag_type_val.optionalValue(zcu) != null;20713 switch (elem_ty.zigTypeTag(zcu)) {
20714 .noreturn => return sema.fail(block, elem_ty_src, "pointer to noreturn not allowed", .{}),
20715 // This needs to be disallowed, because the sentinel parameter would otherwise have type
20716 // `?@TypeOf(null)`, which is not a valid type because you cannot differentiate between
20717 // constructing the "inner" null value and the "outer" null value.
20718 .null => return sema.fail(block, elem_ty_src, "cannot reify pointer to '@TypeOf(null)'", .{}),
20719 .@"fn" => switch (size) {
20720 .one => {},
20721 .many, .c, .slice => return sema.fail(block, src, "function pointers must be single pointers", .{}),
20722 },
20723 .@"opaque" => switch (size) {
20724 .one => {},
20725 .many, .c, .slice => return sema.fail(block, src, "indexable pointer to opaque type '{f}' not allowed", .{elem_ty.fmt(pt)}),
20726 },
20727 else => {},
20728 }
2098720729
20988 if (has_tag) {20730 if (size == .c and !try sema.validateExternType(elem_ty, .other)) {
20989 switch (layout) {20731 return sema.failWithOwnedErrorMsg(block, msg: {
20990 .@"extern" => return sema.fail(block, src, "extern union does not support enum tag type", .{}),20732 const msg = try sema.errMsg(src, "C pointers cannot point to non-C-ABI-compatible type '{f}'", .{elem_ty.fmt(pt)});
20991 .@"packed" => return sema.fail(block, src, "packed union does not support enum tag type", .{}),20733 errdefer msg.destroy(gpa);
20992 .auto => {},20734 try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src, elem_ty, .other);
20993 }20735 try sema.addDeclaredHereNote(msg, elem_ty);
20994 }20736 break :msg msg;
20737 });
20738 }
2099520739
20996 const fields_arr = try sema.derefSliceAsArray(block, operand_src, fields_val, .{ .simple = .union_fields });20740 const sentinel_ty = try pt.optionalType(elem_ty.toIntern());
20741 const sentinel_uncoerced = try sema.resolveInst(extra.sentinel);
20742 const sentinel_coerced = try sema.coerce(block, sentinel_ty, sentinel_uncoerced, sentinel_src);
20743 const sentinel_val = try sema.resolveConstDefinedValue(block, sentinel_src, sentinel_coerced, .{ .simple = .pointer_sentinel });
20744 const opt_sentinel = sentinel_val.optionalValue(zcu);
20745 if (opt_sentinel) |sentinel| {
20746 switch (size) {
20747 .many, .slice => {},
20748 .one, .c => return sema.fail(block, sentinel_src, "sentinels are only allowed on slices and unknown-length pointers", .{}),
20749 }
20750 try checkSentinelType(sema, block, sentinel_src, elem_ty);
20751 if (sentinel.canMutateComptimeVarState(zcu)) {
20752 const sentinel_name = try ip.getOrPutString(gpa, pt.tid, "sentinel", .no_embedded_nulls);
20753 return sema.failWithContainsReferenceToComptimeVar(block, sentinel_src, sentinel_name, "sentinel", sentinel);
20754 }
20755 }
2099720756
20998 return sema.reifyUnion(block, inst, src, layout, tag_type_val, fields_arr, name_strategy);20757 return .fromType(try pt.ptrTypeSema(.{
20758 .child = elem_ty.toIntern(),
20759 .sentinel = if (opt_sentinel) |s| s.toIntern() else .none,
20760 .flags = .{
20761 .size = size,
20762 .is_const = attrs.@"const",
20763 .is_volatile = attrs.@"volatile",
20764 .is_allowzero = attrs.@"allowzero",
20765 .address_space = attrs.@"addrspace" orelse as: {
20766 if (elem_ty.zigTypeTag(zcu) == .@"fn" and zcu.getTarget().cpu.arch == .avr) break :as .flash;
20767 break :as .generic;
20768 },
20769 .alignment = @"align",
20999 },20770 },
21000 .@"fn" => {20771 }));
21001 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));20772}
21002 const calling_convention_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
21003 ip,
21004 try ip.getOrPutString(gpa, pt.tid, "calling_convention", .no_embedded_nulls),
21005 ).?);
21006 const is_generic_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
21007 ip,
21008 try ip.getOrPutString(gpa, pt.tid, "is_generic", .no_embedded_nulls),
21009 ).?);
21010 const is_var_args_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
21011 ip,
21012 try ip.getOrPutString(gpa, pt.tid, "is_var_args", .no_embedded_nulls),
21013 ).?);
21014 const return_type_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
21015 ip,
21016 try ip.getOrPutString(gpa, pt.tid, "return_type", .no_embedded_nulls),
21017 ).?);
21018 const params_slice_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
21019 ip,
21020 try ip.getOrPutString(gpa, pt.tid, "params", .no_embedded_nulls),
21021 ).?);
21022
21023 const is_generic = is_generic_val.toBool();
21024 if (is_generic) {
21025 return sema.fail(block, src, "Type.Fn.is_generic must be false for @Type", .{});
21026 }
21027
21028 const is_var_args = is_var_args_val.toBool();
21029 const cc = try sema.analyzeValueAsCallconv(block, src, calling_convention_val);
21030 if (is_var_args) {
21031 try sema.checkCallConvSupportsVarArgs(block, src, cc);
21032 }
21033
21034 const return_type = return_type_val.optionalValue(zcu) orelse
21035 return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{});
21036
21037 const params_val = try sema.derefSliceAsArray(block, operand_src, params_slice_val, .{ .simple = .function_parameters });
21038
21039 const args_len = try sema.usizeCast(block, src, params_val.typeOf(zcu).arrayLen(zcu));
21040 const param_types = try sema.arena.alloc(InternPool.Index, args_len);
2104120773
21042 var noalias_bits: u32 = 0;20774fn zirReifyFn(
21043 for (param_types, 0..) |*param_type, i| {20775 sema: *Sema,
21044 const elem_val = try params_val.elemValue(pt, i);20776 block: *Block,
21045 const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern()));20777 extended: Zir.Inst.Extended.InstData,
21046 const param_is_generic_val = try elem_val.fieldValue(pt, elem_struct_type.nameIndex(20778) CompileError!Air.Inst.Ref {
21047 ip,20779 const pt = sema.pt;
21048 try ip.getOrPutString(gpa, pt.tid, "is_generic", .no_embedded_nulls),20780 const zcu = pt.zcu;
21049 ).?);20781 const gpa = zcu.gpa;
21050 const param_is_noalias_val = try elem_val.fieldValue(pt, elem_struct_type.nameIndex(20782 const ip = &zcu.intern_pool;
21051 ip,20783
21052 try ip.getOrPutString(gpa, pt.tid, "is_noalias", .no_embedded_nulls),20784 const extra = sema.code.extraData(Zir.Inst.ReifyFn, extended.operand).data;
21053 ).?);20785 const param_types_src = block.builtinCallArgSrc(extra.node, 0);
21054 const opt_param_type_val = try elem_val.fieldValue(pt, elem_struct_type.nameIndex(20786 const param_attrs_src = block.builtinCallArgSrc(extra.node, 1);
21055 ip,20787 const ret_ty_src = block.builtinCallArgSrc(extra.node, 2);
21056 try ip.getOrPutString(gpa, pt.tid, "type", .no_embedded_nulls),20788 const fn_attrs_src = block.builtinCallArgSrc(extra.node, 3);
21057 ).?);20789
2105820790 const single_param_attrs_ty = try sema.getBuiltinType(param_attrs_src, .@"Type.Fn.Param.Attributes");
21059 if (param_is_generic_val.toBool()) {20791 const fn_attrs_ty = try sema.getBuiltinType(fn_attrs_src, .@"Type.Fn.Attributes");
21060 return sema.fail(block, src, "Type.Fn.Param.is_generic must be false for @Type", .{});20792
21061 }20793 const param_types_uncoerced = try sema.resolveInst(extra.param_types);
2106220794 const param_types_coerced = try sema.coerce(block, .slice_const_type, param_types_uncoerced, param_types_src);
21063 const param_type_val = opt_param_type_val.optionalValue(zcu) orelse20795 const param_types_slice = try sema.resolveConstDefinedValue(block, param_types_src, param_types_coerced, .{ .simple = .fn_param_types });
21064 return sema.fail(block, src, "Type.Fn.Param.type must be non-null for @Type", .{});20796 const param_types_arr = try sema.derefSliceAsArray(block, param_types_src, param_types_slice, .{ .simple = .fn_param_types });
21065 param_type.* = param_type_val.toIntern();20797
2106620798 const params_len = param_types_arr.typeOf(zcu).arrayLen(zcu);
21067 if (param_is_noalias_val.toBool()) {20799
21068 if (!Type.fromInterned(param_type.*).isPtrAtRuntime(zcu)) {20800 const param_attrs_ty = try pt.singleConstPtrType(try pt.arrayType(.{
21069 return sema.fail(block, src, "non-pointer parameter declared noalias", .{});20801 .len = params_len,
21070 }20802 .child = single_param_attrs_ty.toIntern(),
21071 noalias_bits |= @as(u32, 1) << (std.math.cast(u5, i) orelse20803 }));
21072 return sema.fail(block, src, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));20804 const param_attrs_uncoerced = try sema.resolveInst(extra.param_attrs);
21073 }20805 const param_attrs_coerced = try sema.coerce(block, param_attrs_ty, param_attrs_uncoerced, param_attrs_src);
20806 const param_attrs_slice = try sema.resolveConstDefinedValue(block, param_attrs_src, param_attrs_coerced, .{ .simple = .fn_param_attrs });
20807 const param_attrs_arr = try sema.derefSliceAsArray(block, param_attrs_src, param_attrs_slice, .{ .simple = .fn_param_attrs });
20808
20809 const ret_ty = try sema.resolveType(block, ret_ty_src, extra.ret_ty);
20810
20811 const fn_attrs_uncoerced = try sema.resolveInst(extra.fn_attrs);
20812 const fn_attrs_coerced = try sema.coerce(block, fn_attrs_ty, fn_attrs_uncoerced, fn_attrs_src);
20813 const fn_attrs_val = try sema.resolveConstDefinedValue(block, fn_attrs_src, fn_attrs_coerced, .{ .simple = .fn_attrs });
20814 const fn_attrs = try sema.interpretBuiltinType(block, fn_attrs_src, fn_attrs_val, std.builtin.Type.Fn.Attributes);
20815
20816 var noalias_bits: u32 = 0;
20817 const param_types_ip = try sema.arena.alloc(InternPool.Index, @intCast(params_len));
20818 for (param_types_ip, 0..@intCast(params_len)) |*param_ty_ip, param_idx| {
20819 const param_ty: Type = (try param_types_arr.elemValue(pt, param_idx)).toType();
20820 const param_attrs = try sema.interpretBuiltinType(
20821 block,
20822 param_attrs_src,
20823 try param_attrs_arr.elemValue(pt, param_idx),
20824 std.builtin.Type.Fn.Param.Attributes,
20825 );
20826 try sema.checkParamTypeCommon(
20827 block,
20828 @intCast(param_idx),
20829 param_ty,
20830 param_attrs.@"noalias",
20831 param_types_src,
20832 fn_attrs.@"callconv",
20833 );
20834 if (try param_ty.comptimeOnlySema(pt)) {
20835 return sema.fail(block, param_attrs_src, "cannot reify function type with comptime-only parameter type '{f}'", .{param_ty.fmt(pt)});
20836 }
20837 if (param_attrs.@"noalias") {
20838 if (param_idx > 31) {
20839 return sema.fail(block, param_attrs_src, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{});
21074 }20840 }
20841 noalias_bits |= @as(u32, 1) << @intCast(param_idx);
20842 }
20843 param_ty_ip.* = param_ty.toIntern();
20844 }
2107520845
21076 const ty = try pt.funcType(.{20846 if (fn_attrs.varargs) {
21077 .param_types = param_types,20847 try sema.checkCallConvSupportsVarArgs(block, fn_attrs_src, fn_attrs.@"callconv");
21078 .noalias_bits = noalias_bits,
21079 .return_type = return_type.toIntern(),
21080 .cc = cc,
21081 .is_var_args = is_var_args,
21082 });
21083 return Air.internedToRef(ty.toIntern());
21084 },
21085 .frame => return sema.failWithUseOfAsync(block, src),
21086 }20848 }
20849
20850 try sema.checkReturnTypeAndCallConvCommon(
20851 block,
20852 ret_ty,
20853 ret_ty_src,
20854 fn_attrs.@"callconv",
20855 fn_attrs_src,
20856 if (fn_attrs.varargs) fn_attrs_src else null,
20857 false,
20858 false,
20859 );
20860 if (try ret_ty.comptimeOnlySema(pt)) {
20861 return sema.fail(block, param_attrs_src, "cannot reify function type with comptime-only return type '{f}'", .{ret_ty.fmt(pt)});
20862 }
20863
20864 return .fromIntern(try ip.getFuncType(gpa, pt.tid, .{
20865 .param_types = param_types_ip,
20866 .noalias_bits = noalias_bits,
20867 .comptime_bits = 0,
20868 .return_type = ret_ty.toIntern(),
20869 .cc = fn_attrs.@"callconv",
20870 .is_var_args = fn_attrs.varargs,
20871 .is_generic = false,
20872 .is_noinline = false,
20873 }));
21087}20874}
2108820875
21089fn reifyEnum(20876fn zirReifyStruct(
21090 sema: *Sema,20877 sema: *Sema,
21091 block: *Block,20878 block: *Block,
20879 extended: Zir.Inst.Extended.InstData,
21092 inst: Zir.Inst.Index,20880 inst: Zir.Inst.Index,
21093 src: LazySrcLoc,
21094 tag_ty: Type,
21095 is_exhaustive: bool,
21096 fields_val: Value,
21097 name_strategy: Zir.Inst.NameStrategy,
21098) CompileError!Air.Inst.Ref {20881) CompileError!Air.Inst.Ref {
21099 const pt = sema.pt;20882 const pt = sema.pt;
21100 const zcu = pt.zcu;20883 const zcu = pt.zcu;
21101 const gpa = sema.gpa;20884 const gpa = sema.gpa;
21102 const ip = &zcu.intern_pool;20885 const ip = &zcu.intern_pool;
2110320886
21104 // This logic must stay in sync with the structure of `std.builtin.Type.Enum` - search for `fieldValue`.20887 const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small);
20888 const extra = sema.code.extraData(Zir.Inst.ReifyStruct, extended.operand).data;
20889 const tracked_inst = try block.trackZir(inst);
20890 const src: LazySrcLoc = .{
20891 .base_node_inst = tracked_inst,
20892 .offset = .nodeOffset(.zero),
20893 };
20894
20895 const layout_src: LazySrcLoc = .{
20896 .base_node_inst = tracked_inst,
20897 .offset = .{ .node_offset_builtin_call_arg = .{
20898 .builtin_call_node = .zero,
20899 .arg_index = 0,
20900 } },
20901 };
20902 const backing_ty_src: LazySrcLoc = .{
20903 .base_node_inst = tracked_inst,
20904 .offset = .{ .node_offset_builtin_call_arg = .{
20905 .builtin_call_node = .zero,
20906 .arg_index = 1,
20907 } },
20908 };
20909 const field_names_src: LazySrcLoc = .{
20910 .base_node_inst = tracked_inst,
20911 .offset = .{ .node_offset_builtin_call_arg = .{
20912 .builtin_call_node = .zero,
20913 .arg_index = 2,
20914 } },
20915 };
20916 const field_types_src: LazySrcLoc = .{
20917 .base_node_inst = tracked_inst,
20918 .offset = .{ .node_offset_builtin_call_arg = .{
20919 .builtin_call_node = .zero,
20920 .arg_index = 3,
20921 } },
20922 };
20923 const field_attrs_src: LazySrcLoc = .{
20924 .base_node_inst = tracked_inst,
20925 .offset = .{ .node_offset_builtin_call_arg = .{
20926 .builtin_call_node = .zero,
20927 .arg_index = 4,
20928 } },
20929 };
20930
20931 const container_layout_ty = try sema.getBuiltinType(layout_src, .@"Type.ContainerLayout");
20932 const single_field_attrs_ty = try sema.getBuiltinType(field_attrs_src, .@"Type.StructField.Attributes");
20933
20934 const layout_uncoerced = try sema.resolveInst(extra.layout);
20935 const layout_coerced = try sema.coerce(block, container_layout_ty, layout_uncoerced, layout_src);
20936 const layout_val = try sema.resolveConstDefinedValue(block, layout_src, layout_coerced, .{ .simple = .struct_layout });
20937 const layout = try sema.interpretBuiltinType(block, layout_src, layout_val, std.builtin.Type.ContainerLayout);
20938
20939 const backing_int_ty_uncoerced = try sema.resolveInst(extra.backing_ty);
20940 const backing_int_ty_coerced = try sema.coerce(block, .optional_type, backing_int_ty_uncoerced, backing_ty_src);
20941 const backing_int_ty_val = try sema.resolveConstDefinedValue(block, backing_ty_src, backing_int_ty_coerced, .{ .simple = .type });
20942
20943 const field_names_uncoerced = try sema.resolveInst(extra.field_names);
20944 const field_names_coerced = try sema.coerce(block, .slice_const_slice_const_u8, field_names_uncoerced, field_names_src);
20945 const field_names_slice = try sema.resolveConstDefinedValue(block, field_names_src, field_names_coerced, .{ .simple = .struct_field_names });
20946 const field_names_arr = try sema.derefSliceAsArray(block, field_names_src, field_names_slice, .{ .simple = .struct_field_names });
20947
20948 const fields_len = try sema.usizeCast(block, src, field_names_arr.typeOf(zcu).arrayLen(zcu));
20949
20950 const field_types_ty = try pt.singleConstPtrType(try pt.arrayType(.{
20951 .len = fields_len,
20952 .child = .type_type,
20953 }));
20954 const field_attrs_ty = try pt.singleConstPtrType(try pt.arrayType(.{
20955 .len = fields_len,
20956 .child = single_field_attrs_ty.toIntern(),
20957 }));
20958
20959 const field_types_uncoerced = try sema.resolveInst(extra.field_types);
20960 const field_types_coerced = try sema.coerce(block, field_types_ty, field_types_uncoerced, field_types_src);
20961 const field_types_slice = try sema.resolveConstDefinedValue(block, field_types_src, field_types_coerced, .{ .simple = .struct_field_types });
20962 const field_types_arr = try sema.derefSliceAsArray(block, field_types_src, field_types_slice, .{ .simple = .struct_field_types });
2110520963
21106 const fields_len: u32 = @intCast(fields_val.typeOf(zcu).arrayLen(zcu));20964 const field_attrs_uncoerced = try sema.resolveInst(extra.field_attrs);
20965 const field_attrs_coerced = try sema.coerce(block, field_attrs_ty, field_attrs_uncoerced, field_attrs_src);
20966 const field_attrs_slice = try sema.resolveConstDefinedValue(block, field_attrs_src, field_attrs_coerced, .{ .simple = .struct_field_attrs });
20967 const field_attrs_arr = try sema.derefSliceAsArray(block, field_attrs_src, field_attrs_slice, .{ .simple = .struct_field_attrs });
20968
20969 // Before we begin, check for undefs...
20970 if (try sema.anyUndef(block, field_attrs_src, field_attrs_arr)) {
20971 return sema.failWithUseOfUndef(block, field_attrs_src, null);
20972 }
20973 if (try sema.anyUndef(block, field_types_src, field_types_arr)) {
20974 return sema.failWithUseOfUndef(block, field_types_src, null);
20975 }
20976 // We don't need to check `field_names_arr`, because `sliceToIpString` will check that for us.
20977 if (try sema.anyUndef(block, backing_ty_src, backing_int_ty_val)) {
20978 return sema.failWithUseOfUndef(block, backing_ty_src, null);
20979 }
2110720980
21108 // The validation work here is non-trivial, and it's possible the type already exists.20981 // The validation work here is non-trivial, and it's possible the type already exists.
21109 // So in this first pass, let's just construct a hash to optimize for this case. If the20982 // So in this first pass, let's just construct a hash to optimize for this case. If the
21110 // inputs turn out to be invalid, we can cancel the WIP type later.20983 // inputs turn out to be invalid, we can cancel the WIP type later.
2111120984
20985 var any_comptime_fields = false;
20986 var any_default_inits = false;
20987 var any_aligned_fields = false;
20988
21112 // For deduplication purposes, we must create a hash including all details of this type.20989 // For deduplication purposes, we must create a hash including all details of this type.
21113 // TODO: use a longer hash!20990 // TODO: use a longer hash!
21114 var hasher = std.hash.Wyhash.init(0);20991 var hasher = std.hash.Wyhash.init(0);
21115 std.hash.autoHash(&hasher, tag_ty.toIntern());20992 std.hash.autoHash(&hasher, layout);
21116 std.hash.autoHash(&hasher, is_exhaustive);20993 std.hash.autoHash(&hasher, backing_int_ty_val);
21117 std.hash.autoHash(&hasher, fields_len);20994 // The field *type* array has already been deduplicated for us thanks to the InternPool!
2111820995 std.hash.autoHash(&hasher, field_types_arr);
20996 // However, for field names and attributes, we need to actually iterate the individual fields,
20997 // because the presence of pointers (the `[]const u8` for the name and the `*const anyopaque`
20998 // for the default value) means that distinct interned values could ultimately result in the
20999 // same struct type.
21119 for (0..fields_len) |field_idx| {21000 for (0..fields_len) |field_idx| {
21120 const field_info = try fields_val.elemValue(pt, field_idx);21001 const field_name_val = try field_names_arr.elemValue(pt, field_idx);
21002 const field_attrs_val = try field_attrs_arr.elemValue(pt, field_idx);
21003
21004 const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, .{ .simple = .struct_field_names });
21005
21006 const field_attr_comptime = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex(
21007 std.builtin.Type.StructField.Attributes,
21008 "comptime",
21009 ).?);
21010 const field_attr_align = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex(
21011 std.builtin.Type.StructField.Attributes,
21012 "align",
21013 ).?);
21014 const field_attr_default_value_ptr = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex(
21015 std.builtin.Type.StructField.Attributes,
21016 "default_value_ptr",
21017 ).?);
2112121018
21122 const field_name_val = try field_info.fieldValue(pt, 0);21019 const field_default: InternPool.Index = d: {
21123 const field_value_val = try sema.resolveLazyValue(try field_info.fieldValue(pt, 1));21020 const ptr_val = field_attr_default_value_ptr.optionalValue(zcu) orelse break :d .none;
2112421021 const field_ty = (try field_types_arr.elemValue(pt, field_idx)).toType();
21125 const field_name = try sema.sliceToIpString(block, src, field_name_val, .{ .simple = .enum_field_name });21022 const ptr_ty = try pt.singleConstPtrType(field_ty);
21023 const deref_val = try sema.pointerDeref(block, field_attrs_src, ptr_val, ptr_ty) orelse return sema.failWithNeededComptime(
21024 block,
21025 field_attrs_src,
21026 .{ .simple = .struct_field_default_value },
21027 );
21028 // Resolve the value so that lazy values do not create distinct types.
21029 break :d (try sema.resolveLazyValue(deref_val)).toIntern();
21030 };
2112621031
21127 std.hash.autoHash(&hasher, .{21032 std.hash.autoHash(&hasher, .{
21128 field_name,21033 field_name,
21129 field_value_val.toIntern(),21034 field_attr_comptime,
21035 field_attr_align,
21036 field_default,
21130 });21037 });
21038
21039 if (field_attr_comptime.toBool()) any_comptime_fields = true;
21040 if (field_attr_align.optionalValue(zcu)) |_| any_aligned_fields = true;
21041 if (field_default != .none) any_default_inits = true;
21131 }21042 }
2113221043
21133 const tracked_inst = try block.trackZir(inst);21044 // Some basic validation to avoid a bogus `getStructType` call...
21045 const backing_int_ty: ?Type = if (backing_int_ty_val.optionalValue(zcu)) |backing| ty: {
21046 switch (layout) {
21047 .auto, .@"extern" => return sema.fail(block, backing_ty_src, "non-packed struct does not support backing integer type", .{}),
21048 .@"packed" => {},
21049 }
21050 break :ty backing.toType();
21051 } else null;
21052 if (any_aligned_fields and layout == .@"packed") {
21053 return sema.fail(block, field_attrs_src, "packed struct fields cannot be aligned", .{});
21054 }
21055 if (any_comptime_fields and layout != .auto) {
21056 return sema.fail(block, field_attrs_src, "{t} struct fields cannot be marked comptime", .{layout});
21057 }
2113421058
21135 const wip_ty = switch (try ip.getEnumType(gpa, pt.tid, .{21059 const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{
21136 .has_values = true,21060 .layout = layout,
21137 .tag_mode = if (is_exhaustive) .explicit else .nonexhaustive,21061 .fields_len = @intCast(fields_len),
21138 .fields_len = fields_len,21062 .known_non_opv = false,
21063 .requires_comptime = .unknown,
21064 .any_comptime_fields = any_comptime_fields,
21065 .any_default_inits = any_default_inits,
21066 .any_aligned_fields = any_aligned_fields,
21067 .inits_resolved = true,
21139 .key = .{ .reified = .{21068 .key = .{ .reified = .{
21140 .zir_index = tracked_inst,21069 .zir_index = tracked_inst,
21141 .type_hash = hasher.final(),21070 .type_hash = hasher.final(),
...@@ -21148,79 +21077,144 @@ fn reifyEnum(...@@ -21148,79 +21077,144 @@ fn reifyEnum(
21148 return Air.internedToRef(ty);21077 return Air.internedToRef(ty);
21149 },21078 },
21150 };21079 };
21151 var done = false;21080 errdefer wip_ty.cancel(ip, pt.tid);
21152 errdefer if (!done) wip_ty.cancel(ip, pt.tid);
21153
21154 if (tag_ty.zigTypeTag(zcu) != .int) {
21155 return sema.fail(block, src, "Type.Enum.tag_type must be an integer type", .{});
21156 }
2115721081
21158 const type_name = try sema.createTypeName(21082 const type_name = try sema.createTypeName(
21159 block,21083 block,
21160 name_strategy,21084 name_strategy,
21161 "enum",21085 "struct",
21162 inst,21086 inst,
21163 wip_ty.index,21087 wip_ty.index,
21164 );21088 );
21165 wip_ty.setName(ip, type_name.name, type_name.nav);21089 wip_ty.setName(ip, type_name.name, type_name.nav);
2116621090
21167 const new_namespace_index = try pt.createNamespace(.{21091 const wip_struct_type = ip.loadStructType(wip_ty.index);
21168 .parent = block.namespace.toOptional(),
21169 .owner_type = wip_ty.index,
21170 .file_scope = block.getFileScopeIndex(zcu),
21171 .generation = zcu.generation,
21172 });
21173
21174 try sema.declareDependency(.{ .interned = wip_ty.index });
21175 try sema.addTypeReferenceEntry(src, wip_ty.index);
21176 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
21177 wip_ty.prepare(ip, new_namespace_index);
21178 wip_ty.setTagTy(ip, tag_ty.toIntern());
21179 done = true;
2118021092
21181 for (0..fields_len) |field_idx| {21093 for (0..fields_len) |field_idx| {
21182 const field_info = try fields_val.elemValue(pt, field_idx);21094 const field_name_val = try field_names_arr.elemValue(pt, field_idx);
21095 const field_attrs_val = try field_attrs_arr.elemValue(pt, field_idx);
2118321096
21184 const field_name_val = try field_info.fieldValue(pt, 0);21097 const field_ty = (try field_types_arr.elemValue(pt, field_idx)).toType();
21185 const field_value_val = try sema.resolveLazyValue(try field_info.fieldValue(pt, 1));
2118621098
21187 // Don't pass a reason; first loop acts as an assertion that this is valid.21099 // Don't pass a reason; first loop acts as a check that this is valid.
21188 const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined);21100 const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined);
21101 if (wip_struct_type.addFieldName(ip, field_name)) |prev_index| {
21102 _ = prev_index; // TODO: better source location
21103 return sema.fail(block, field_names_src, "duplicate struct field name {f}", .{field_name.fmt(ip)});
21104 }
21105
21106 const field_attr_comptime = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex(
21107 std.builtin.Type.StructField.Attributes,
21108 "comptime",
21109 ).?);
21110 const field_attr_align = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex(
21111 std.builtin.Type.StructField.Attributes,
21112 "align",
21113 ).?);
21114 const field_attr_default_value_ptr = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex(
21115 std.builtin.Type.StructField.Attributes,
21116 "default_value_ptr",
21117 ).?);
21118
21119 if (field_attr_align.optionalValue(zcu)) |field_align_val| {
21120 assert(layout != .@"packed");
21121 const bytes = try field_align_val.toUnsignedIntSema(pt);
21122 const a = try sema.validateAlign(block, field_attrs_src, bytes);
21123 wip_struct_type.field_aligns.get(ip)[field_idx] = a;
21124 } else if (any_aligned_fields) {
21125 assert(layout != .@"packed");
21126 wip_struct_type.field_aligns.get(ip)[field_idx] = .none;
21127 }
2118921128
21190 if (!try sema.intFitsInType(field_value_val, tag_ty, null)) {21129 const field_default: InternPool.Index = d: {
21191 // TODO: better source location21130 const ptr_val = field_attr_default_value_ptr.optionalValue(zcu) orelse break :d .none;
21192 return sema.fail(block, src, "field '{f}' with enumeration value '{f}' is too large for backing int type '{f}'", .{21131 assert(any_default_inits);
21193 field_name.fmt(ip),21132 const ptr_ty = try pt.singleConstPtrType(field_ty);
21194 field_value_val.fmtValueSema(pt, sema),21133 // The first loop checked that this is comptime-dereferencable.
21195 tag_ty.fmt(pt),21134 const deref_val = (try sema.pointerDeref(block, field_attrs_src, ptr_val, ptr_ty)).?;
21196 });21135 // ...but we've not checked this yet!
21136 if (deref_val.canMutateComptimeVarState(zcu)) {
21137 return sema.failWithContainsReferenceToComptimeVar(block, field_attrs_src, field_name, "field default value", deref_val);
21138 }
21139 break :d (try sema.resolveLazyValue(deref_val)).toIntern();
21140 };
21141
21142 if (field_attr_comptime.toBool()) {
21143 assert(layout == .auto);
21144 if (field_default == .none) {
21145 return sema.fail(block, field_attrs_src, "comptime field without default initialization value", .{});
21146 }
21147 wip_struct_type.setFieldComptime(ip, field_idx);
21197 }21148 }
2119821149
21199 const coerced_field_val = try pt.getCoerced(field_value_val, tag_ty);21150 wip_struct_type.field_types.get(ip)[field_idx] = field_ty.toIntern();
21200 if (wip_ty.nextField(ip, field_name, coerced_field_val.toIntern())) |conflict| {21151 if (field_default != .none) {
21201 return sema.failWithOwnedErrorMsg(block, switch (conflict.kind) {21152 wip_struct_type.field_inits.get(ip)[field_idx] = field_default;
21202 .name => msg: {21153 }
21203 const msg = try sema.errMsg(src, "duplicate enum field '{f}'", .{field_name.fmt(ip)});21154
21155 switch (field_ty.zigTypeTag(zcu)) {
21156 .@"opaque" => return sema.failWithOwnedErrorMsg(block, msg: {
21157 const msg = try sema.errMsg(field_types_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
21158 errdefer msg.destroy(gpa);
21159 try sema.addDeclaredHereNote(msg, field_ty);
21160 break :msg msg;
21161 }),
21162 .noreturn => return sema.failWithOwnedErrorMsg(block, msg: {
21163 const msg = try sema.errMsg(field_types_src, "struct fields cannot be 'noreturn'", .{});
21164 errdefer msg.destroy(gpa);
21165 try sema.addDeclaredHereNote(msg, field_ty);
21166 break :msg msg;
21167 }),
21168 else => {},
21169 }
21170
21171 switch (layout) {
21172 .auto => {},
21173 .@"extern" => if (!try sema.validateExternType(field_ty, .struct_field)) {
21174 return sema.failWithOwnedErrorMsg(block, msg: {
21175 const msg = try sema.errMsg(field_types_src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
21204 errdefer msg.destroy(gpa);21176 errdefer msg.destroy(gpa);
21205 _ = conflict.prev_field_idx; // TODO: this note is incorrect21177 try sema.explainWhyTypeIsNotExtern(msg, field_types_src, field_ty, .struct_field);
21206 try sema.errNote(src, msg, "other field here", .{});21178 try sema.addDeclaredHereNote(msg, field_ty);
21207 break :msg msg;21179 break :msg msg;
21208 },21180 });
21209 .value => msg: {21181 },
21210 const msg = try sema.errMsg(src, "enum tag value {f} already taken", .{field_value_val.fmtValueSema(pt, sema)});21182 .@"packed" => if (!try sema.validatePackedType(field_ty)) {
21183 return sema.failWithOwnedErrorMsg(block, msg: {
21184 const msg = try sema.errMsg(field_types_src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
21211 errdefer msg.destroy(gpa);21185 errdefer msg.destroy(gpa);
21212 _ = conflict.prev_field_idx; // TODO: this note is incorrect21186 try sema.explainWhyTypeIsNotPacked(msg, field_types_src, field_ty);
21213 try sema.errNote(src, msg, "other enum tag value here", .{});21187 try sema.addDeclaredHereNote(msg, field_ty);
21214 break :msg msg;21188 break :msg msg;
21215 },21189 });
21216 });21190 },
21217 }21191 }
21218 }21192 }
2121921193
21220 if (!is_exhaustive and fields_len > 1 and std.math.log2_int(u64, fields_len) == tag_ty.bitSize(zcu)) {21194 if (layout == .@"packed") {
21221 return sema.fail(block, src, "non-exhaustive enum specified every value", .{});21195 var fields_bit_sum: u64 = 0;
21196 for (0..wip_struct_type.field_types.len) |field_idx| {
21197 const field_ty: Type = .fromInterned(wip_struct_type.field_types.get(ip)[field_idx]);
21198 try field_ty.resolveLayout(pt);
21199 fields_bit_sum += field_ty.bitSize(zcu);
21200 }
21201 if (backing_int_ty) |ty| {
21202 try sema.checkBackingIntType(block, src, ty, fields_bit_sum);
21203 wip_struct_type.setBackingIntType(ip, ty.toIntern());
21204 } else {
21205 const ty = try pt.intType(.unsigned, @intCast(fields_bit_sum));
21206 wip_struct_type.setBackingIntType(ip, ty.toIntern());
21207 }
21222 }21208 }
2122321209
21210 const new_namespace_index = try pt.createNamespace(.{
21211 .parent = block.namespace.toOptional(),
21212 .owner_type = wip_ty.index,
21213 .file_scope = block.getFileScopeIndex(zcu),
21214 .generation = zcu.generation,
21215 });
21216
21217 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
21224 codegen_type: {21218 codegen_type: {
21225 if (zcu.comp.config.use_llvm) break :codegen_type;21219 if (zcu.comp.config.use_llvm) break :codegen_type;
21226 if (block.ownerModule().strip) break :codegen_type;21220 if (block.ownerModule().strip) break :codegen_type;
...@@ -21228,75 +21222,177 @@ fn reifyEnum(...@@ -21228,75 +21222,177 @@ fn reifyEnum(
21228 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);21222 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
21229 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });21223 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
21230 }21224 }
21231 return Air.internedToRef(wip_ty.index);21225 try sema.declareDependency(.{ .interned = wip_ty.index });
21226 try sema.addTypeReferenceEntry(src, wip_ty.index);
21227 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
21228 return .fromIntern(wip_ty.finish(ip, new_namespace_index));
21232}21229}
2123321230
21234fn reifyUnion(21231fn zirReifyUnion(
21235 sema: *Sema,21232 sema: *Sema,
21236 block: *Block,21233 block: *Block,
21234 extended: Zir.Inst.Extended.InstData,
21237 inst: Zir.Inst.Index,21235 inst: Zir.Inst.Index,
21238 src: LazySrcLoc,
21239 layout: std.builtin.Type.ContainerLayout,
21240 opt_tag_type_val: Value,
21241 fields_val: Value,
21242 name_strategy: Zir.Inst.NameStrategy,
21243) CompileError!Air.Inst.Ref {21236) CompileError!Air.Inst.Ref {
21244 const pt = sema.pt;21237 const pt = sema.pt;
21245 const zcu = pt.zcu;21238 const zcu = pt.zcu;
21246 const gpa = sema.gpa;21239 const gpa = sema.gpa;
21247 const ip = &zcu.intern_pool;21240 const ip = &zcu.intern_pool;
2124821241
21249 // This logic must stay in sync with the structure of `std.builtin.Type.Union` - search for `fieldValue`.21242 const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small);
21243 const extra = sema.code.extraData(Zir.Inst.ReifyUnion, extended.operand).data;
21244 const tracked_inst = try block.trackZir(inst);
21245 const src: LazySrcLoc = .{
21246 .base_node_inst = tracked_inst,
21247 .offset = .nodeOffset(.zero),
21248 };
21249
21250 const layout_src: LazySrcLoc = .{
21251 .base_node_inst = tracked_inst,
21252 .offset = .{ .node_offset_builtin_call_arg = .{
21253 .builtin_call_node = .zero,
21254 .arg_index = 0,
21255 } },
21256 };
21257 const arg_ty_src: LazySrcLoc = .{
21258 .base_node_inst = tracked_inst,
21259 .offset = .{ .node_offset_builtin_call_arg = .{
21260 .builtin_call_node = .zero,
21261 .arg_index = 1,
21262 } },
21263 };
21264 const field_names_src: LazySrcLoc = .{
21265 .base_node_inst = tracked_inst,
21266 .offset = .{ .node_offset_builtin_call_arg = .{
21267 .builtin_call_node = .zero,
21268 .arg_index = 2,
21269 } },
21270 };
21271 const field_types_src: LazySrcLoc = .{
21272 .base_node_inst = tracked_inst,
21273 .offset = .{ .node_offset_builtin_call_arg = .{
21274 .builtin_call_node = .zero,
21275 .arg_index = 3,
21276 } },
21277 };
21278 const field_attrs_src: LazySrcLoc = .{
21279 .base_node_inst = tracked_inst,
21280 .offset = .{ .node_offset_builtin_call_arg = .{
21281 .builtin_call_node = .zero,
21282 .arg_index = 4,
21283 } },
21284 };
21285
21286 const container_layout_ty = try sema.getBuiltinType(layout_src, .@"Type.ContainerLayout");
21287 const single_field_attrs_ty = try sema.getBuiltinType(field_attrs_src, .@"Type.UnionField.Attributes");
21288
21289 const layout_uncoerced = try sema.resolveInst(extra.layout);
21290 const layout_coerced = try sema.coerce(block, container_layout_ty, layout_uncoerced, layout_src);
21291 const layout_val = try sema.resolveConstDefinedValue(block, layout_src, layout_coerced, .{ .simple = .union_layout });
21292 const layout = try sema.interpretBuiltinType(block, layout_src, layout_val, std.builtin.Type.ContainerLayout);
21293
21294 const arg_ty_uncoerced = try sema.resolveInst(extra.arg_ty);
21295 const arg_ty_coerced = try sema.coerce(block, .optional_type, arg_ty_uncoerced, arg_ty_src);
21296 const arg_ty_val = try sema.resolveConstDefinedValue(block, arg_ty_src, arg_ty_coerced, .{ .simple = .type });
21297
21298 const field_names_uncoerced = try sema.resolveInst(extra.field_names);
21299 const field_names_coerced = try sema.coerce(block, .slice_const_slice_const_u8, field_names_uncoerced, field_names_src);
21300 const field_names_slice = try sema.resolveConstDefinedValue(block, field_names_src, field_names_coerced, .{ .simple = .union_field_names });
21301 const field_names_arr = try sema.derefSliceAsArray(block, field_names_src, field_names_slice, .{ .simple = .union_field_names });
21302
21303 const fields_len = try sema.usizeCast(block, src, field_names_arr.typeOf(zcu).arrayLen(zcu));
21304
21305 const field_types_ty = try pt.singleConstPtrType(try pt.arrayType(.{
21306 .len = fields_len,
21307 .child = .type_type,
21308 }));
21309 const field_attrs_ty = try pt.singleConstPtrType(try pt.arrayType(.{
21310 .len = fields_len,
21311 .child = single_field_attrs_ty.toIntern(),
21312 }));
21313
21314 const field_types_uncoerced = try sema.resolveInst(extra.field_types);
21315 const field_types_coerced = try sema.coerce(block, field_types_ty, field_types_uncoerced, field_types_src);
21316 const field_types_slice = try sema.resolveConstDefinedValue(block, field_types_src, field_types_coerced, .{ .simple = .union_field_types });
21317 const field_types_arr = try sema.derefSliceAsArray(block, field_types_src, field_types_slice, .{ .simple = .union_field_types });
2125021318
21251 const fields_len: u32 = @intCast(fields_val.typeOf(zcu).arrayLen(zcu));21319 const field_attrs_uncoerced = try sema.resolveInst(extra.field_attrs);
21320 const field_attrs_coerced = try sema.coerce(block, field_attrs_ty, field_attrs_uncoerced, field_attrs_src);
21321 const field_attrs_slice = try sema.resolveConstDefinedValue(block, field_attrs_src, field_attrs_coerced, .{ .simple = .union_field_attrs });
21322 const field_attrs_arr = try sema.derefSliceAsArray(block, field_attrs_src, field_attrs_slice, .{ .simple = .union_field_attrs });
21323
21324 // Before we begin, check for undefs...
21325 if (try sema.anyUndef(block, field_attrs_src, field_attrs_arr)) {
21326 return sema.failWithUseOfUndef(block, field_attrs_src, null);
21327 }
21328 if (try sema.anyUndef(block, field_types_src, field_types_arr)) {
21329 return sema.failWithUseOfUndef(block, field_types_src, null);
21330 }
21331 // We don't need to check `field_names_arr`, because `sliceToIpString` will check that for us.
21332 if (try sema.anyUndef(block, arg_ty_src, arg_ty_val)) {
21333 return sema.failWithUseOfUndef(block, arg_ty_src, null);
21334 }
2125221335
21253 // The validation work here is non-trivial, and it's possible the type already exists.21336 // The validation work here is non-trivial, and it's possible the type already exists.
21254 // So in this first pass, let's just construct a hash to optimize for this case. If the21337 // So in this first pass, let's just construct a hash to optimize for this case. If the
21255 // inputs turn out to be invalid, we can cancel the WIP type later.21338 // inputs turn out to be invalid, we can cancel the WIP type later.
2125621339
21340 var any_aligned_fields = false;
21341
21257 // For deduplication purposes, we must create a hash including all details of this type.21342 // For deduplication purposes, we must create a hash including all details of this type.
21258 // TODO: use a longer hash!21343 // TODO: use a longer hash!
21259 var hasher = std.hash.Wyhash.init(0);21344 var hasher = std.hash.Wyhash.init(0);
21260 std.hash.autoHash(&hasher, layout);21345 std.hash.autoHash(&hasher, layout);
21261 std.hash.autoHash(&hasher, opt_tag_type_val.toIntern());21346 std.hash.autoHash(&hasher, arg_ty_val);
21262 std.hash.autoHash(&hasher, fields_len);21347 // `field_types_arr` and `field_attrs_arr` are already deduplicated by the InternPool!
2126321348 std.hash.autoHash(&hasher, field_types_arr);
21349 std.hash.autoHash(&hasher, field_attrs_arr);
21350 // However, for field names, we need to iterate the individual fields, because the pointers (the
21351 // names are slices) mean that distinct values could ultimately result in the same union type.
21264 for (0..fields_len) |field_idx| {21352 for (0..fields_len) |field_idx| {
21265 const field_info = try fields_val.elemValue(pt, field_idx);21353 const field_name_val = try field_names_arr.elemValue(pt, field_idx);
2126621354 const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, .{ .simple = .union_field_names });
21267 const field_name_val = try field_info.fieldValue(pt, 0);21355 std.hash.autoHash(&hasher, field_name);
21268 const field_type_val = try field_info.fieldValue(pt, 1);
21269 const field_align_val = try sema.resolveLazyValue(try field_info.fieldValue(pt, 2));
2127021356
21271 const field_name = try sema.sliceToIpString(block, src, field_name_val, .{ .simple = .union_field_name });21357 const field_attrs = try sema.interpretBuiltinType(
21272 std.hash.autoHash(&hasher, .{21358 block,
21273 field_name,21359 field_attrs_src,
21274 field_type_val.toIntern(),21360 try field_attrs_arr.elemValue(pt, field_idx),
21275 field_align_val.toIntern(),21361 std.builtin.Type.UnionField.Attributes,
21276 });21362 );
21363 if (field_attrs.@"align" != null) {
21364 any_aligned_fields = true;
21365 }
21277 }21366 }
2127821367
21279 const tracked_inst = try block.trackZir(inst);21368 // Some basic validation to avoid a bogus `getUnionType` call...
21369 const explicit_tag_ty: ?Type = if (arg_ty_val.optionalValue(zcu)) |arg_ty| ty: {
21370 switch (layout) {
21371 .@"extern", .@"packed" => return sema.fail(block, arg_ty_src, "{t} union does not support enum tag type", .{layout}),
21372 .auto => {},
21373 }
21374 break :ty arg_ty.toType();
21375 } else null;
21376 if (any_aligned_fields and layout == .@"packed") {
21377 return sema.fail(block, field_attrs_src, "packed union fields cannot be aligned", .{});
21378 }
2128021379
21281 const wip_ty = switch (try ip.getUnionType(gpa, pt.tid, .{21380 const wip_ty = switch (try ip.getUnionType(gpa, pt.tid, .{
21282 .flags = .{21381 .flags = .{
21283 .layout = layout,21382 .layout = layout,
21284 .status = .none,21383 .status = .none,
21285 .runtime_tag = if (opt_tag_type_val.optionalValue(zcu) != null)21384 .runtime_tag = rt: {
21286 .tagged21385 if (explicit_tag_ty != null) break :rt .tagged;
21287 else if (layout != .auto)21386 if (layout == .auto and block.wantSafeTypes()) break :rt .safety;
21288 .none21387 break :rt .none;
21289 else switch (block.wantSafeTypes()) {
21290 true => .safety,
21291 false => .none,
21292 },21388 },
21293 .any_aligned_fields = layout != .@"packed",21389 .any_aligned_fields = any_aligned_fields,
21294 .requires_comptime = .unknown,21390 .requires_comptime = .unknown,
21295 .assumed_runtime_bits = false,21391 .assumed_runtime_bits = false,
21296 .assumed_pointer_aligned = false,21392 .assumed_pointer_aligned = false,
21297 .alignment = .none,21393 .alignment = .none,
21298 },21394 },
21299 .fields_len = fields_len,21395 .fields_len = @intCast(fields_len),
21300 .enum_tag_ty = .none, // set later because not yet validated21396 .enum_tag_ty = .none, // set later because not yet validated
21301 .field_types = &.{}, // set later21397 .field_types = &.{}, // set later
21302 .field_aligns = &.{}, // set later21398 .field_aligns = &.{}, // set later
...@@ -21325,128 +21421,117 @@ fn reifyUnion(...@@ -21325,128 +21421,117 @@ fn reifyUnion(
2132521421
21326 const loaded_union = ip.loadUnionType(wip_ty.index);21422 const loaded_union = ip.loadUnionType(wip_ty.index);
2132721423
21328 const enum_tag_ty, const has_explicit_tag = if (opt_tag_type_val.optionalValue(zcu)) |tag_type_val| tag_ty: {21424 const enum_tag_ty, const has_explicit_tag = if (explicit_tag_ty) |enum_tag_ty| tag: {
21329 switch (ip.indexToKey(tag_type_val.toIntern())) {21425 if (enum_tag_ty.zigTypeTag(zcu) != .@"enum") {
21330 .enum_type => {},21426 return sema.fail(block, arg_ty_src, "tag type must be an enum type", .{});
21331 else => return sema.fail(block, src, "Type.Union.tag_type must be an enum type", .{}),
21332 }21427 }
21333 const enum_tag_ty = tag_type_val.toType();
2133421428
21335 // We simply track which fields of the tag type have been seen.
21336 const tag_ty_fields_len = enum_tag_ty.enumFieldCount(zcu);21429 const tag_ty_fields_len = enum_tag_ty.enumFieldCount(zcu);
21337 var seen_tags = try std.DynamicBitSetUnmanaged.initEmpty(sema.arena, tag_ty_fields_len);
2133821430
21339 for (0..fields_len) |field_idx| {21431 for (0..fields_len) |field_idx| {
21340 const field_info = try fields_val.elemValue(pt, field_idx);21432 const field_name_val = try field_names_arr.elemValue(pt, field_idx);
21433 // Don't pass a reason; first loop acts as a check that this is valid.
21434 const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined);
2134121435
21342 const field_name_val = try field_info.fieldValue(pt, 0);21436 if (field_idx >= tag_ty_fields_len) {
21343 const field_type_val = try field_info.fieldValue(pt, 1);21437 return sema.fail(block, field_names_src, "no field named '{f}' in enum '{f}'", .{
21344 const field_alignment_val = try field_info.fieldValue(pt, 2);
21345
21346 // Don't pass a reason; first loop acts as an assertion that this is valid.
21347 const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined);
21348
21349 const enum_index = enum_tag_ty.enumFieldIndex(field_name, zcu) orelse {
21350 // TODO: better source location
21351 return sema.fail(block, src, "no field named '{f}' in enum '{f}'", .{
21352 field_name.fmt(ip), enum_tag_ty.fmt(pt),21438 field_name.fmt(ip), enum_tag_ty.fmt(pt),
21353 });21439 });
21354 };
21355 if (seen_tags.isSet(enum_index)) {
21356 // TODO: better source location
21357 return sema.fail(block, src, "duplicate union field {f}", .{field_name.fmt(ip)});
21358 }21440 }
21359 seen_tags.set(enum_index);
2136021441
21361 loaded_union.field_types.get(ip)[field_idx] = field_type_val.toIntern();21442 const enum_field_name = enum_tag_ty.enumFieldName(field_idx, zcu);
21362 const byte_align = try field_alignment_val.toUnsignedIntSema(pt);21443 if (enum_field_name != field_name) {
21363 if (layout == .@"packed") {21444 return sema.fail(block, field_names_src, "union field name '{f}' does not match enum field name '{f}'", .{
21364 if (byte_align != 0) return sema.fail(block, src, "alignment of a packed union field must be set to 0", .{});21445 field_name.fmt(ip), enum_field_name.fmt(ip),
21365 } else {21446 });
21366 loaded_union.field_aligns.get(ip)[field_idx] = try sema.validateAlign(block, src, byte_align);
21367 }21447 }
21368 }21448 }
21369
21370 if (tag_ty_fields_len > fields_len) return sema.failWithOwnedErrorMsg(block, msg: {21449 if (tag_ty_fields_len > fields_len) return sema.failWithOwnedErrorMsg(block, msg: {
21371 const msg = try sema.errMsg(src, "enum fields missing in union", .{});21450 const msg = try sema.errMsg(field_names_src, "{d} enum fields missing in union", .{
21451 tag_ty_fields_len - fields_len,
21452 });
21372 errdefer msg.destroy(gpa);21453 errdefer msg.destroy(gpa);
21373 var it = seen_tags.iterator(.{ .kind = .unset });21454 for (fields_len..tag_ty_fields_len) |enum_field_idx| {
21374 while (it.next()) |enum_index| {21455 try sema.addFieldErrNote(enum_tag_ty, enum_field_idx, msg, "field '{f}' missing, declared here", .{
21375 const field_name = enum_tag_ty.enumFieldName(enum_index, zcu);21456 enum_tag_ty.enumFieldName(enum_field_idx, zcu).fmt(ip),
21376 try sema.addFieldErrNote(enum_tag_ty, enum_index, msg, "field '{f}' missing, declared here", .{
21377 field_name.fmt(ip),
21378 });21457 });
21379 }21458 }
21380 try sema.addDeclaredHereNote(msg, enum_tag_ty);21459 try sema.addDeclaredHereNote(msg, enum_tag_ty);
21381 break :msg msg;21460 break :msg msg;
21382 });21461 });
2138321462 break :tag .{ enum_tag_ty.toIntern(), true };
21384 break :tag_ty .{ enum_tag_ty.toIntern(), true };21463 } else tag: {
21385 } else tag_ty: {
21386 // We must track field names and set up the tag type ourselves.21464 // We must track field names and set up the tag type ourselves.
21387 var field_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void) = .empty;21465 var field_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void) = .empty;
21388 try field_names.ensureTotalCapacity(sema.arena, fields_len);21466 try field_names.ensureTotalCapacity(sema.arena, fields_len);
2138921467
21390 for (0..fields_len) |field_idx| {21468 for (0..fields_len) |field_idx| {
21391 const field_info = try fields_val.elemValue(pt, field_idx);21469 const field_name_val = try field_names_arr.elemValue(pt, field_idx);
2139221470 // Don't pass a reason; first loop acts as a check that this is valid.
21393 const field_name_val = try field_info.fieldValue(pt, 0);21471 const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined);
21394 const field_type_val = try field_info.fieldValue(pt, 1);
21395 const field_alignment_val = try field_info.fieldValue(pt, 2);
21396
21397 // Don't pass a reason; first loop acts as an assertion that this is valid.
21398 const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined);
21399 const gop = field_names.getOrPutAssumeCapacity(field_name);21472 const gop = field_names.getOrPutAssumeCapacity(field_name);
21400 if (gop.found_existing) {21473 if (gop.found_existing) {
21401 // TODO: better source location21474 // TODO: better source location
21402 return sema.fail(block, src, "duplicate union field {f}", .{field_name.fmt(ip)});21475 return sema.fail(block, field_names_src, "duplicate union field {f}", .{field_name.fmt(ip)});
21403 }
21404
21405 loaded_union.field_types.get(ip)[field_idx] = field_type_val.toIntern();
21406 const byte_align = try field_alignment_val.toUnsignedIntSema(pt);
21407 if (layout == .@"packed") {
21408 if (byte_align != 0) return sema.fail(block, src, "alignment of a packed union field must be set to 0", .{});
21409 } else {
21410 loaded_union.field_aligns.get(ip)[field_idx] = try sema.validateAlign(block, src, byte_align);
21411 }21476 }
21412 }21477 }
21413
21414 const enum_tag_ty = try sema.generateUnionTagTypeSimple(block, field_names.keys(), wip_ty.index, type_name.name);21478 const enum_tag_ty = try sema.generateUnionTagTypeSimple(block, field_names.keys(), wip_ty.index, type_name.name);
21415 break :tag_ty .{ enum_tag_ty, false };21479 break :tag .{ enum_tag_ty, false };
21416 };21480 };
21417 errdefer if (!has_explicit_tag) ip.remove(pt.tid, enum_tag_ty); // remove generated tag type on error21481 errdefer if (!has_explicit_tag) ip.remove(pt.tid, enum_tag_ty); // remove generated tag type on error
2141821482
21419 for (loaded_union.field_types.get(ip)) |field_ty_ip| {21483 for (0..fields_len) |field_idx| {
21420 const field_ty: Type = .fromInterned(field_ty_ip);21484 const field_ty = (try field_types_arr.elemValue(pt, field_idx)).toType();
21485 const field_attrs = try sema.interpretBuiltinType(
21486 block,
21487 field_attrs_src,
21488 try field_attrs_arr.elemValue(pt, field_idx),
21489 std.builtin.Type.UnionField.Attributes,
21490 );
21491
21421 if (field_ty.zigTypeTag(zcu) == .@"opaque") {21492 if (field_ty.zigTypeTag(zcu) == .@"opaque") {
21422 return sema.failWithOwnedErrorMsg(block, msg: {21493 return sema.failWithOwnedErrorMsg(block, msg: {
21423 const msg = try sema.errMsg(src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{});21494 const msg = try sema.errMsg(field_types_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{});
21424 errdefer msg.destroy(gpa);21495 errdefer msg.destroy(gpa);
21425
21426 try sema.addDeclaredHereNote(msg, field_ty);21496 try sema.addDeclaredHereNote(msg, field_ty);
21427 break :msg msg;21497 break :msg msg;
21428 });21498 });
21429 }21499 }
21430 if (layout == .@"extern" and !try sema.validateExternType(field_ty, .union_field)) {
21431 return sema.failWithOwnedErrorMsg(block, msg: {
21432 const msg = try sema.errMsg(src, "extern unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
21433 errdefer msg.destroy(gpa);
2143421500
21435 try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .union_field);21501 switch (layout) {
21502 .auto => {},
21503 .@"extern" => if (!try sema.validateExternType(field_ty, .union_field)) {
21504 return sema.failWithOwnedErrorMsg(block, msg: {
21505 const msg = try sema.errMsg(field_types_src, "extern unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
21506 errdefer msg.destroy(gpa);
21507
21508 try sema.explainWhyTypeIsNotExtern(msg, field_types_src, field_ty, .union_field);
2143621509
21437 try sema.addDeclaredHereNote(msg, field_ty);21510 try sema.addDeclaredHereNote(msg, field_ty);
21438 break :msg msg;21511 break :msg msg;
21439 });21512 });
21440 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {21513 },
21441 return sema.failWithOwnedErrorMsg(block, msg: {21514 .@"packed" => if (!try sema.validatePackedType(field_ty)) {
21442 const msg = try sema.errMsg(src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});21515 return sema.failWithOwnedErrorMsg(block, msg: {
21443 errdefer msg.destroy(gpa);21516 const msg = try sema.errMsg(field_types_src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
21517 errdefer msg.destroy(gpa);
2144421518
21445 try sema.explainWhyTypeIsNotPacked(msg, src, field_ty);21519 try sema.explainWhyTypeIsNotPacked(msg, field_types_src, field_ty);
2144621520
21447 try sema.addDeclaredHereNote(msg, field_ty);21521 try sema.addDeclaredHereNote(msg, field_ty);
21448 break :msg msg;21522 break :msg msg;
21449 });21523 });
21524 },
21525 }
21526
21527 loaded_union.field_types.get(ip)[field_idx] = field_ty.toIntern();
21528 if (field_attrs.@"align") |bytes| {
21529 assert(layout != .@"packed");
21530 const a = try sema.validateAlign(block, field_attrs_src, bytes);
21531 loaded_union.field_aligns.get(ip)[field_idx] = a;
21532 } else if (any_aligned_fields) {
21533 assert(layout != .@"packed");
21534 loaded_union.field_aligns.get(ip)[field_idx] = .none;
21450 }21535 }
21451 }21536 }
2145221537
...@@ -21471,116 +21556,94 @@ fn reifyUnion(...@@ -21471,116 +21556,94 @@ fn reifyUnion(
21471 try sema.declareDependency(.{ .interned = wip_ty.index });21556 try sema.declareDependency(.{ .interned = wip_ty.index });
21472 try sema.addTypeReferenceEntry(src, wip_ty.index);21557 try sema.addTypeReferenceEntry(src, wip_ty.index);
21473 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);21558 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
21474 return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));21559 return .fromIntern(wip_ty.finish(ip, new_namespace_index));
21475}21560}
2147621561
21477fn reifyTuple(21562fn zirReifyEnum(
21478 sema: *Sema,21563 sema: *Sema,
21479 block: *Block,21564 block: *Block,
21480 src: LazySrcLoc,21565 extended: Zir.Inst.Extended.InstData,
21481 fields_val: Value,21566 inst: Zir.Inst.Index,
21482) CompileError!Air.Inst.Ref {21567) CompileError!Air.Inst.Ref {
21483 const pt = sema.pt;21568 const pt = sema.pt;
21484 const zcu = pt.zcu;21569 const zcu = pt.zcu;
21485 const gpa = sema.gpa;21570 const gpa = sema.gpa;
21486 const ip = &zcu.intern_pool;21571 const ip = &zcu.intern_pool;
2148721572
21488 const fields_len: u32 = @intCast(fields_val.typeOf(zcu).arrayLen(zcu));21573 const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small);
2148921574 const extra = sema.code.extraData(Zir.Inst.ReifyEnum, extended.operand).data;
21490 const types = try sema.arena.alloc(InternPool.Index, fields_len);21575 const tracked_inst = try block.trackZir(inst);
21491 const inits = try sema.arena.alloc(InternPool.Index, fields_len);21576 const src: LazySrcLoc = .{
2149221577 .base_node_inst = tracked_inst,
21493 for (types, inits, 0..) |*field_ty, *field_init, field_idx| {21578 .offset = .nodeOffset(.zero),
21494 const field_info = try fields_val.elemValue(pt, field_idx);21579 };
21495
21496 const field_name_val = try field_info.fieldValue(pt, 0);
21497 const field_type_val = try field_info.fieldValue(pt, 1);
21498 const field_default_value_val = try field_info.fieldValue(pt, 2);
21499 const field_is_comptime_val = try field_info.fieldValue(pt, 3);
21500 const field_alignment_val = try sema.resolveLazyValue(try field_info.fieldValue(pt, 4));
21501
21502 const field_name = try sema.sliceToIpString(block, src, field_name_val, .{ .simple = .tuple_field_name });
21503 const field_type = field_type_val.toType();
21504 const field_default_value: InternPool.Index = if (field_default_value_val.optionalValue(zcu)) |ptr_val| d: {
21505 const ptr_ty = try pt.singleConstPtrType(field_type_val.toType());
21506 // We need to do this deref here, so we won't check for this error case later on.
21507 const val = try sema.pointerDeref(block, src, ptr_val, ptr_ty) orelse return sema.failWithNeededComptime(
21508 block,
21509 src,
21510 .{ .simple = .tuple_field_default_value },
21511 );
21512 if (val.canMutateComptimeVarState(zcu)) {
21513 return sema.failWithContainsReferenceToComptimeVar(block, src, field_name, "field default value", val);
21514 }
21515 // Resolve the value so that lazy values do not create distinct types.
21516 break :d (try sema.resolveLazyValue(val)).toIntern();
21517 } else .none;
2151821580
21519 const field_name_index = field_name.toUnsigned(ip) orelse return sema.fail(21581 const tag_ty_src: LazySrcLoc = .{
21520 block,21582 .base_node_inst = tracked_inst,
21521 src,21583 .offset = .{ .node_offset_builtin_call_arg = .{
21522 "tuple cannot have non-numeric field '{f}'",21584 .builtin_call_node = .zero,
21523 .{field_name.fmt(ip)},21585 .arg_index = 0,
21524 );21586 } },
21525 if (field_name_index != field_idx) {21587 };
21526 return sema.fail(21588 const mode_src: LazySrcLoc = .{
21527 block,21589 .base_node_inst = tracked_inst,
21528 src,21590 .offset = .{ .node_offset_builtin_call_arg = .{
21529 "tuple field name '{d}' does not match field index {d}",21591 .builtin_call_node = .zero,
21530 .{ field_name_index, field_idx },21592 .arg_index = 1,
21531 );21593 } },
21532 }21594 };
21595 const field_names_src: LazySrcLoc = .{
21596 .base_node_inst = tracked_inst,
21597 .offset = .{ .node_offset_builtin_call_arg = .{
21598 .builtin_call_node = .zero,
21599 .arg_index = 2,
21600 } },
21601 };
21602 const field_values_src: LazySrcLoc = .{
21603 .base_node_inst = tracked_inst,
21604 .offset = .{ .node_offset_builtin_call_arg = .{
21605 .builtin_call_node = .zero,
21606 .arg_index = 3,
21607 } },
21608 };
2153321609
21534 try sema.validateTupleFieldType(block, field_type, src);21610 const enum_mode_ty = try sema.getBuiltinType(mode_src, .@"Type.Enum.Mode");
2153521611
21536 {21612 const tag_ty = try sema.resolveType(block, tag_ty_src, extra.tag_ty);
21537 const alignment_ok = ok: {21613 if (tag_ty.zigTypeTag(zcu) != .int) {
21538 if (field_alignment_val.toIntern() == .zero) break :ok true;21614 return sema.fail(block, tag_ty_src, "tag type must be an integer type", .{});
21539 const given_align = try field_alignment_val.getUnsignedIntSema(pt) orelse break :ok false;21615 }
21540 const abi_align = (try field_type.abiAlignmentSema(pt)).toByteUnits() orelse 0;
21541 break :ok abi_align == given_align;
21542 };
21543 if (!alignment_ok) {
21544 return sema.fail(block, src, "tuple fields cannot specify alignment", .{});
21545 }
21546 }
2154721616
21548 if (field_is_comptime_val.toBool() and field_default_value == .none) {21617 const mode_uncoerced = try sema.resolveInst(extra.mode);
21549 return sema.fail(block, src, "comptime field without default initialization value", .{});21618 const mode_coerced = try sema.coerce(block, enum_mode_ty, mode_uncoerced, mode_src);
21550 }21619 const mode_val = try sema.resolveConstDefinedValue(block, mode_src, mode_coerced, .{ .simple = .type });
21620 const nonexhaustive = switch (try sema.interpretBuiltinType(block, mode_src, mode_val, std.builtin.Type.Enum.Mode)) {
21621 .exhaustive => false,
21622 .nonexhaustive => true,
21623 };
2155121624
21552 if (!field_is_comptime_val.toBool() and field_default_value != .none) {21625 const field_names_uncoerced = try sema.resolveInst(extra.field_names);
21553 return sema.fail(block, src, "non-comptime tuple fields cannot specify default initialization value", .{});21626 const field_names_coerced = try sema.coerce(block, .slice_const_slice_const_u8, field_names_uncoerced, field_names_src);
21554 }21627 const field_names_slice = try sema.resolveConstDefinedValue(block, field_names_src, field_names_coerced, .{ .simple = .enum_field_names });
21628 const field_names_arr = try sema.derefSliceAsArray(block, field_names_src, field_names_slice, .{ .simple = .enum_field_names });
2155521629
21556 field_ty.* = field_type.toIntern();21630 const fields_len = try sema.usizeCast(block, src, field_names_arr.typeOf(zcu).arrayLen(zcu));
21557 field_init.* = field_default_value;
21558 }
2155921631
21560 return Air.internedToRef(try zcu.intern_pool.getTupleType(gpa, pt.tid, .{21632 const field_values_ty = try pt.singleConstPtrType(try pt.arrayType(.{
21561 .types = types,21633 .len = fields_len,
21562 .values = inits,21634 .child = tag_ty.toIntern(),
21563 }));21635 }));
21564}
21565
21566fn reifyStruct(
21567 sema: *Sema,
21568 block: *Block,
21569 inst: Zir.Inst.Index,
21570 src: LazySrcLoc,
21571 layout: std.builtin.Type.ContainerLayout,
21572 opt_backing_int_val: Value,
21573 fields_val: Value,
21574 name_strategy: Zir.Inst.NameStrategy,
21575) CompileError!Air.Inst.Ref {
21576 const pt = sema.pt;
21577 const zcu = pt.zcu;
21578 const gpa = sema.gpa;
21579 const ip = &zcu.intern_pool;
2158021636
21581 // This logic must stay in sync with the structure of `std.builtin.Type.Struct` - search for `fieldValue`.21637 const field_values_uncoerced = try sema.resolveInst(extra.field_values);
21638 const field_values_coerced = try sema.coerce(block, field_values_ty, field_values_uncoerced, field_values_src);
21639 const field_values_slice = try sema.resolveConstDefinedValue(block, field_values_src, field_values_coerced, .{ .simple = .enum_field_values });
21640 const field_values_arr = try sema.derefSliceAsArray(block, field_values_src, field_values_slice, .{ .simple = .enum_field_values });
2158221641
21583 const fields_len: u32 = @intCast(fields_val.typeOf(zcu).arrayLen(zcu));21642 // Before we begin, check for undefs...
21643 if (try sema.anyUndef(block, field_values_src, field_values_arr)) {
21644 return sema.failWithUseOfUndef(block, field_values_src, null);
21645 }
21646 // We don't need to check `field_names_arr`, because `sliceToIpString` will check that for us.
2158421647
21585 // The validation work here is non-trivial, and it's possible the type already exists.21648 // The validation work here is non-trivial, and it's possible the type already exists.
21586 // So in this first pass, let's just construct a hash to optimize for this case. If the21649 // So in this first pass, let's just construct a hash to optimize for this case. If the
...@@ -21589,62 +21652,23 @@ fn reifyStruct(...@@ -21589,62 +21652,23 @@ fn reifyStruct(
21589 // For deduplication purposes, we must create a hash including all details of this type.21652 // For deduplication purposes, we must create a hash including all details of this type.
21590 // TODO: use a longer hash!21653 // TODO: use a longer hash!
21591 var hasher = std.hash.Wyhash.init(0);21654 var hasher = std.hash.Wyhash.init(0);
21592 std.hash.autoHash(&hasher, layout);21655 std.hash.autoHash(&hasher, tag_ty.toIntern());
21593 std.hash.autoHash(&hasher, opt_backing_int_val.toIntern());21656 std.hash.autoHash(&hasher, nonexhaustive);
21594 std.hash.autoHash(&hasher, fields_len);21657 std.hash.autoHash(&hasher, fields_len);
2159521658 // `field_values_arr` is already deduplicated by the InternPool!
21596 var any_comptime_fields = false;21659 std.hash.autoHash(&hasher, field_values_arr);
21597 var any_default_inits = false;21660 // However, for field names, we need to iterate the individual fields, because the pointers (the
2159821661 // names are slices) mean that distinct values could ultimately result in the same enum type.
21599 for (0..fields_len) |field_idx| {21662 for (0..fields_len) |field_idx| {
21600 const field_info = try fields_val.elemValue(pt, field_idx);21663 const field_name_val = try field_names_arr.elemValue(pt, field_idx);
2160121664 const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, .{ .simple = .enum_field_names });
21602 const field_name_val = try field_info.fieldValue(pt, 0);21665 std.hash.autoHash(&hasher, field_name);
21603 const field_type_val = try field_info.fieldValue(pt, 1);
21604 const field_default_value_val = try field_info.fieldValue(pt, 2);
21605 const field_is_comptime_val = try field_info.fieldValue(pt, 3);
21606 const field_alignment_val = try sema.resolveLazyValue(try field_info.fieldValue(pt, 4));
21607
21608 const field_name = try sema.sliceToIpString(block, src, field_name_val, .{ .simple = .struct_field_name });
21609 const field_is_comptime = field_is_comptime_val.toBool();
21610 const field_default_value: InternPool.Index = if (field_default_value_val.optionalValue(zcu)) |ptr_val| d: {
21611 const ptr_ty = try pt.singleConstPtrType(field_type_val.toType());
21612 // We need to do this deref here, so we won't check for this error case later on.
21613 const val = try sema.pointerDeref(block, src, ptr_val, ptr_ty) orelse return sema.failWithNeededComptime(
21614 block,
21615 src,
21616 .{ .simple = .struct_field_default_value },
21617 );
21618 if (val.canMutateComptimeVarState(zcu)) {
21619 return sema.failWithContainsReferenceToComptimeVar(block, src, field_name, "field default value", val);
21620 }
21621 // Resolve the value so that lazy values do not create distinct types.
21622 break :d (try sema.resolveLazyValue(val)).toIntern();
21623 } else .none;
21624
21625 std.hash.autoHash(&hasher, .{
21626 field_name,
21627 field_type_val.toIntern(),
21628 field_default_value,
21629 field_is_comptime,
21630 field_alignment_val.toIntern(),
21631 });
21632
21633 if (field_is_comptime) any_comptime_fields = true;
21634 if (field_default_value != .none) any_default_inits = true;
21635 }21666 }
2163621667
21637 const tracked_inst = try block.trackZir(inst);21668 const wip_ty = switch (try ip.getEnumType(gpa, pt.tid, .{
2163821669 .has_values = true,
21639 const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{21670 .tag_mode = if (nonexhaustive) .nonexhaustive else .explicit,
21640 .layout = layout,21671 .fields_len = @intCast(fields_len),
21641 .fields_len = fields_len,
21642 .known_non_opv = false,
21643 .requires_comptime = .unknown,
21644 .any_comptime_fields = any_comptime_fields,
21645 .any_default_inits = any_default_inits,
21646 .any_aligned_fields = layout != .@"packed",
21647 .inits_resolved = true,
21648 .key = .{ .reified = .{21672 .key = .{ .reified = .{
21649 .zir_index = tracked_inst,21673 .zir_index = tracked_inst,
21650 .type_hash = hasher.final(),21674 .type_hash = hasher.final(),
...@@ -21654,152 +21678,66 @@ fn reifyStruct(...@@ -21654,152 +21678,66 @@ fn reifyStruct(
21654 .existing => |ty| {21678 .existing => |ty| {
21655 try sema.declareDependency(.{ .interned = ty });21679 try sema.declareDependency(.{ .interned = ty });
21656 try sema.addTypeReferenceEntry(src, ty);21680 try sema.addTypeReferenceEntry(src, ty);
21657 return Air.internedToRef(ty);21681 return .fromIntern(ty);
21658 },21682 },
21659 };21683 };
21660 errdefer wip_ty.cancel(ip, pt.tid);21684 var done = false;
21685 errdefer if (!done) wip_ty.cancel(ip, pt.tid);
2166121686
21662 const type_name = try sema.createTypeName(21687 const type_name = try sema.createTypeName(
21663 block,21688 block,
21664 name_strategy,21689 name_strategy,
21665 "struct",21690 "enum",
21666 inst,21691 inst,
21667 wip_ty.index,21692 wip_ty.index,
21668 );21693 );
21669 wip_ty.setName(ip, type_name.name, type_name.nav);21694 wip_ty.setName(ip, type_name.name, type_name.nav);
2167021695
21671 const struct_type = ip.loadStructType(wip_ty.index);21696 const new_namespace_index = try pt.createNamespace(.{
2167221697 .parent = block.namespace.toOptional(),
21673 for (0..fields_len) |field_idx| {21698 .owner_type = wip_ty.index,
21674 const field_info = try fields_val.elemValue(pt, field_idx);21699 .file_scope = block.getFileScopeIndex(zcu),
2167521700 .generation = zcu.generation,
21676 const field_name_val = try field_info.fieldValue(pt, 0);21701 });
21677 const field_type_val = try field_info.fieldValue(pt, 1);
21678 const field_default_value_val = try field_info.fieldValue(pt, 2);
21679 const field_is_comptime_val = try field_info.fieldValue(pt, 3);
21680 const field_alignment_val = try field_info.fieldValue(pt, 4);
21681
21682 const field_ty = field_type_val.toType();
21683 // Don't pass a reason; first loop acts as an assertion that this is valid.
21684 const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined);
21685 if (struct_type.addFieldName(ip, field_name)) |prev_index| {
21686 _ = prev_index; // TODO: better source location
21687 return sema.fail(block, src, "duplicate struct field name {f}", .{field_name.fmt(ip)});
21688 }
21689
21690 if (!try sema.intFitsInType(field_alignment_val, align_ty, null)) {
21691 return sema.fail(block, src, "alignment must fit in '{f}'", .{align_ty.fmt(pt)});
21692 }
21693 const byte_align = try field_alignment_val.toUnsignedIntSema(pt);
21694 if (layout == .@"packed") {
21695 if (byte_align != 0) return sema.fail(block, src, "alignment of a packed struct field must be set to 0", .{});
21696 } else {
21697 struct_type.field_aligns.get(ip)[field_idx] = try sema.validateAlign(block, src, byte_align);
21698 }
21699
21700 const field_is_comptime = field_is_comptime_val.toBool();
21701 if (field_is_comptime) {
21702 assert(any_comptime_fields);
21703 switch (layout) {
21704 .@"extern" => return sema.fail(block, src, "extern struct fields cannot be marked comptime", .{}),
21705 .@"packed" => return sema.fail(block, src, "packed struct fields cannot be marked comptime", .{}),
21706 .auto => struct_type.setFieldComptime(ip, field_idx),
21707 }
21708 }
21709
21710 const field_default: InternPool.Index = d: {
21711 if (!any_default_inits) break :d .none;
21712 const ptr_val = field_default_value_val.optionalValue(zcu) orelse break :d .none;
21713 const ptr_ty = try pt.singleConstPtrType(field_ty);
21714 // Asserted comptime-dereferencable above.
21715 const val = (try sema.pointerDeref(block, src, ptr_val, ptr_ty)).?;
21716 // We already resolved this for deduplication, so we may as well do it now.
21717 break :d (try sema.resolveLazyValue(val)).toIntern();
21718 };
21719
21720 if (field_is_comptime and field_default == .none) {
21721 return sema.fail(block, src, "comptime field without default initialization value", .{});
21722 }
21723
21724 struct_type.field_types.get(ip)[field_idx] = field_type_val.toIntern();
21725 if (field_default != .none) {
21726 struct_type.field_inits.get(ip)[field_idx] = field_default;
21727 }
21728
21729 if (field_ty.zigTypeTag(zcu) == .@"opaque") {
21730 return sema.failWithOwnedErrorMsg(block, msg: {
21731 const msg = try sema.errMsg(src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
21732 errdefer msg.destroy(gpa);
21733
21734 try sema.addDeclaredHereNote(msg, field_ty);
21735 break :msg msg;
21736 });
21737 }
21738 if (field_ty.zigTypeTag(zcu) == .noreturn) {
21739 return sema.failWithOwnedErrorMsg(block, msg: {
21740 const msg = try sema.errMsg(src, "struct fields cannot be 'noreturn'", .{});
21741 errdefer msg.destroy(gpa);
21742
21743 try sema.addDeclaredHereNote(msg, field_ty);
21744 break :msg msg;
21745 });
21746 }
21747 if (layout == .@"extern" and !try sema.validateExternType(field_ty, .struct_field)) {
21748 return sema.failWithOwnedErrorMsg(block, msg: {
21749 const msg = try sema.errMsg(src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
21750 errdefer msg.destroy(gpa);
2175121702
21752 try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .struct_field);21703 try sema.declareDependency(.{ .interned = wip_ty.index });
21704 try sema.addTypeReferenceEntry(src, wip_ty.index);
21705 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
21706 wip_ty.prepare(ip, new_namespace_index);
21707 wip_ty.setTagTy(ip, tag_ty.toIntern());
21708 done = true;
2175321709
21754 try sema.addDeclaredHereNote(msg, field_ty);21710 for (0..fields_len) |field_idx| {
21755 break :msg msg;21711 const field_name_val = try field_names_arr.elemValue(pt, field_idx);
21756 });21712 // Don't pass a reason; first loop acts as a check that this is valid.
21757 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {21713 const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined);
21758 return sema.failWithOwnedErrorMsg(block, msg: {
21759 const msg = try sema.errMsg(src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
21760 errdefer msg.destroy(gpa);
2176121714
21762 try sema.explainWhyTypeIsNotPacked(msg, src, field_ty);21715 const field_val = try field_values_arr.elemValue(pt, field_idx);
2176321716
21764 try sema.addDeclaredHereNote(msg, field_ty);21717 if (wip_ty.nextField(ip, field_name, field_val.toIntern())) |conflict| {
21765 break :msg msg;21718 return sema.failWithOwnedErrorMsg(block, switch (conflict.kind) {
21719 .name => msg: {
21720 const msg = try sema.errMsg(field_names_src, "duplicate enum field '{f}'", .{field_name.fmt(ip)});
21721 errdefer msg.destroy(gpa);
21722 _ = conflict.prev_field_idx; // TODO: this note is incorrect
21723 try sema.errNote(field_names_src, msg, "other field here", .{});
21724 break :msg msg;
21725 },
21726 .value => msg: {
21727 const msg = try sema.errMsg(field_values_src, "enum tag value {f} already taken", .{field_val.fmtValueSema(pt, sema)});
21728 errdefer msg.destroy(gpa);
21729 _ = conflict.prev_field_idx; // TODO: this note is incorrect
21730 try sema.errNote(field_values_src, msg, "other enum tag value here", .{});
21731 break :msg msg;
21732 },
21766 });21733 });
21767 }21734 }
21768 }21735 }
2176921736
21770 if (layout == .@"packed") {21737 if (nonexhaustive and fields_len > 1 and std.math.log2_int(u64, fields_len) == tag_ty.bitSize(zcu)) {
21771 var fields_bit_sum: u64 = 0;21738 return sema.fail(block, src, "non-exhaustive enum specified every value", .{});
21772 for (0..struct_type.field_types.len) |field_idx| {
21773 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_idx]);
21774 field_ty.resolveLayout(pt) catch |err| switch (err) {
21775 error.AnalysisFail => {
21776 const msg = sema.err orelse return err;
21777 try sema.errNote(src, msg, "while checking a field of this struct", .{});
21778 return err;
21779 },
21780 else => return err,
21781 };
21782 fields_bit_sum += field_ty.bitSize(zcu);
21783 }
21784
21785 if (opt_backing_int_val.optionalValue(zcu)) |backing_int_val| {
21786 const backing_int_ty = backing_int_val.toType();
21787 try sema.checkBackingIntType(block, src, backing_int_ty, fields_bit_sum);
21788 struct_type.setBackingIntType(ip, backing_int_ty.toIntern());
21789 } else {
21790 const backing_int_ty = try pt.intType(.unsigned, @intCast(fields_bit_sum));
21791 struct_type.setBackingIntType(ip, backing_int_ty.toIntern());
21792 }
21793 }21739 }
2179421740
21795 const new_namespace_index = try pt.createNamespace(.{
21796 .parent = block.namespace.toOptional(),
21797 .owner_type = wip_ty.index,
21798 .file_scope = block.getFileScopeIndex(zcu),
21799 .generation = zcu.generation,
21800 });
21801
21802 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
21803 codegen_type: {21741 codegen_type: {
21804 if (zcu.comp.config.use_llvm) break :codegen_type;21742 if (zcu.comp.config.use_llvm) break :codegen_type;
21805 if (block.ownerModule().strip) break :codegen_type;21743 if (block.ownerModule().strip) break :codegen_type;
...@@ -21807,10 +21745,7 @@ fn reifyStruct(...@@ -21807,10 +21745,7 @@ fn reifyStruct(
21807 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);21745 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
21808 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });21746 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
21809 }21747 }
21810 try sema.declareDependency(.{ .interned = wip_ty.index });21748 return Air.internedToRef(wip_ty.index);
21811 try sema.addTypeReferenceEntry(src, wip_ty.index);
21812 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
21813 return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
21814}21749}
2181521750
21816fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref {21751fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref {
...@@ -23969,7 +23904,7 @@ fn analyzeShuffle(...@@ -23969,7 +23904,7 @@ fn analyzeShuffle(
23969 const b_src = block.builtinCallArgSrc(src_node, 2);23904 const b_src = block.builtinCallArgSrc(src_node, 2);
23970 const mask_src = block.builtinCallArgSrc(src_node, 3);23905 const mask_src = block.builtinCallArgSrc(src_node, 3);
2397123906
23972 // If the type of `a` is `@Type(.undefined)`, i.e. the argument is untyped,23907 // If the type of `a` is `@TypeOf(undefined)`, i.e. the argument is untyped,
23973 // this is 0, because it is an error to index into this vector.23908 // this is 0, because it is an error to index into this vector.
23974 const a_len: u32 = switch (sema.typeOf(a_uncoerced).zigTypeTag(zcu)) {23909 const a_len: u32 = switch (sema.typeOf(a_uncoerced).zigTypeTag(zcu)) {
23975 .array, .vector => @intCast(sema.typeOf(a_uncoerced).arrayLen(zcu)),23910 .array, .vector => @intCast(sema.typeOf(a_uncoerced).arrayLen(zcu)),
...@@ -23981,7 +23916,7 @@ fn analyzeShuffle(...@@ -23981,7 +23916,7 @@ fn analyzeShuffle(
23981 const a_ty = try pt.vectorType(.{ .len = a_len, .child = elem_ty.toIntern() });23916 const a_ty = try pt.vectorType(.{ .len = a_len, .child = elem_ty.toIntern() });
23982 const a_coerced = try sema.coerce(block, a_ty, a_uncoerced, a_src);23917 const a_coerced = try sema.coerce(block, a_ty, a_uncoerced, a_src);
2398323918
23984 // 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.23919 // 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.
23985 const b_len: u32 = switch (sema.typeOf(b_uncoerced).zigTypeTag(zcu)) {23920 const b_len: u32 = switch (sema.typeOf(b_uncoerced).zigTypeTag(zcu)) {
23986 .array, .vector => @intCast(sema.typeOf(b_uncoerced).arrayLen(zcu)),23921 .array, .vector => @intCast(sema.typeOf(b_uncoerced).arrayLen(zcu)),
23987 .undefined => 0,23922 .undefined => 0,
...@@ -25541,7 +25476,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -25541,7 +25476,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
25541 extra_index += body.len;25476 extra_index += body.len;
25542 if (extra.data.bits.ret_ty_is_generic) break :blk .generic_poison;25477 if (extra.data.bits.ret_ty_is_generic) break :blk .generic_poison;
2554325478
25544 const val = try sema.resolveGenericBody(block, ret_src, body, inst, .type, .{ .simple = .function_ret_ty });25479 const val = try sema.resolveGenericBody(block, ret_src, body, inst, .type, .{ .simple = .fn_ret_ty });
25545 const ty = val.toType();25480 const ty = val.toType();
25546 break :blk ty;25481 break :blk ty;
25547 } else if (extra.data.bits.has_ret_ty_ref) blk: {25482 } else if (extra.data.bits.has_ret_ty_ref) blk: {
...@@ -25968,21 +25903,26 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD...@@ -25968,21 +25903,26 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
25968 const src = block.nodeOffset(src_node);25903 const src = block.nodeOffset(src_node);
25969 const value: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);25904 const value: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);
2597025905
25971 const ty = switch (value) {25906 const builtin_type: Zcu.BuiltinDecl = switch (value) {
25972 // zig fmt: off25907 // zig fmt: off
25973 .atomic_order => try sema.getBuiltinType(src, .AtomicOrder),25908 .atomic_order => .AtomicOrder,
25974 .atomic_rmw_op => try sema.getBuiltinType(src, .AtomicRmwOp),25909 .atomic_rmw_op => .AtomicRmwOp,
25975 .calling_convention => try sema.getBuiltinType(src, .CallingConvention),25910 .calling_convention => .CallingConvention,
25976 .address_space => try sema.getBuiltinType(src, .AddressSpace),25911 .address_space => .AddressSpace,
25977 .float_mode => try sema.getBuiltinType(src, .FloatMode),25912 .float_mode => .FloatMode,
25978 .reduce_op => try sema.getBuiltinType(src, .ReduceOp),25913 .signedness => .Signedness,
25979 .call_modifier => try sema.getBuiltinType(src, .CallModifier),25914 .reduce_op => .ReduceOp,
25980 .prefetch_options => try sema.getBuiltinType(src, .PrefetchOptions),25915 .call_modifier => .CallModifier,
25981 .export_options => try sema.getBuiltinType(src, .ExportOptions),25916 .prefetch_options => .PrefetchOptions,
25982 .extern_options => try sema.getBuiltinType(src, .ExternOptions),25917 .export_options => .ExportOptions,
25983 .type_info => try sema.getBuiltinType(src, .Type),25918 .extern_options => .ExternOptions,
25984 .branch_hint => try sema.getBuiltinType(src, .BranchHint),25919 .branch_hint => .BranchHint,
25985 .clobbers => try sema.getBuiltinType(src, .@"assembly.Clobbers"),25920 .clobbers => .@"assembly.Clobbers",
25921 .pointer_size => .@"Type.Pointer.Size",
25922 .pointer_attributes => .@"Type.Pointer.Attributes",
25923 .fn_attributes, => .@"Type.Fn.Attributes",
25924 .container_layout => .@"Type.ContainerLayout",
25925 .enum_mode => .@"Type.Enum.Mode",
25986 // zig fmt: on25926 // zig fmt: on
2598725927
25988 // Values are handled here.25928 // Values are handled here.
...@@ -26009,7 +25949,7 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD...@@ -26009,7 +25949,7 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
26009 return sema.coerce(block, callconv_ty, Air.internedToRef(inline_tag_val.toIntern()), src);25949 return sema.coerce(block, callconv_ty, Air.internedToRef(inline_tag_val.toIntern()), src);
26010 },25950 },
26011 };25951 };
26012 return Air.internedToRef(ty.toIntern());25952 return .fromType(try sema.getBuiltinType(src, builtin_type));
26013}25953}
2601425954
26015fn zirInplaceArithResultTy(sema: *Sema, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {25955fn zirInplaceArithResultTy(sema: *Sema, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
...@@ -35259,7 +35199,7 @@ fn structFields(...@@ -35259,7 +35199,7 @@ fn structFields(
35259 .base_node_inst = struct_type.zir_index,35199 .base_node_inst = struct_type.zir_index,
35260 .offset = .nodeOffset(.zero),35200 .offset = .nodeOffset(.zero),
35261 },35201 },
35262 .r = .{ .simple = .struct_fields },35202 .r = .{ .simple = .type },
35263 } },35203 } },
35264 .src_base_inst = struct_type.zir_index,35204 .src_base_inst = struct_type.zir_index,
35265 .type_name_ctx = struct_type.name,35205 .type_name_ctx = struct_type.name,
...@@ -35614,7 +35554,7 @@ fn unionFields(...@@ -35614,7 +35554,7 @@ fn unionFields(
35614 .inlining = null,35554 .inlining = null,
35615 .comptime_reason = .{ .reason = .{35555 .comptime_reason = .{ .reason = .{
35616 .src = src,35556 .src = src,
35617 .r = .{ .simple = .union_fields },35557 .r = .{ .simple = .type },
35618 } },35558 } },
35619 .src_base_inst = union_type.zir_index,35559 .src_base_inst = union_type.zir_index,
35620 .type_name_ctx = union_type.name,35560 .type_name_ctx = union_type.name,
...@@ -36077,8 +36017,13 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -36077,8 +36017,13 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
36077 .manyptr_u8_type,36017 .manyptr_u8_type,
36078 .manyptr_const_u8_type,36018 .manyptr_const_u8_type,
36079 .manyptr_const_u8_sentinel_0_type,36019 .manyptr_const_u8_sentinel_0_type,
36020 .manyptr_const_slice_const_u8_type,
36080 .slice_const_u8_type,36021 .slice_const_u8_type,
36081 .slice_const_u8_sentinel_0_type,36022 .slice_const_u8_sentinel_0_type,
36023 .slice_const_slice_const_u8_type,
36024 .optional_type_type,
36025 .manyptr_const_type_type,
36026 .slice_const_type_type,
36082 .vector_8_i8_type,36027 .vector_8_i8_type,
36083 .vector_16_i8_type,36028 .vector_16_i8_type,
36084 .vector_32_i8_type,36029 .vector_32_i8_type,
...@@ -37230,7 +37175,7 @@ fn sliceToIpString(...@@ -37230,7 +37175,7 @@ fn sliceToIpString(
3723037175
37231/// Given a slice value, attempts to dereference it into a comptime-known array.37176/// Given a slice value, attempts to dereference it into a comptime-known array.
37232/// Emits a compile error if the contents of the slice are not comptime-known.37177/// Emits a compile error if the contents of the slice are not comptime-known.
37233/// Asserts that `slice_val` is a slice.37178/// Asserts that `slice_val` is a slice or a pointer to an array.
37234fn derefSliceAsArray(37179fn derefSliceAsArray(
37235 sema: *Sema,37180 sema: *Sema,
37236 block: *Block,37181 block: *Block,
...@@ -37247,7 +37192,7 @@ fn derefSliceAsArray(...@@ -37247,7 +37192,7 @@ fn derefSliceAsArray(
3724737192
37248/// Given a slice value, attempts to dereference it into a comptime-known array.37193/// Given a slice value, attempts to dereference it into a comptime-known array.
37249/// Returns `null` if the contents of the slice are not comptime-known.37194/// Returns `null` if the contents of the slice are not comptime-known.
37250/// Asserts that `slice_val` is a slice.37195/// Asserts that `slice_val` is a slice or a pointer to an array.
37251fn maybeDerefSliceAsArray(37196fn maybeDerefSliceAsArray(
37252 sema: *Sema,37197 sema: *Sema,
37253 block: *Block,37198 block: *Block,
...@@ -37257,7 +37202,13 @@ fn maybeDerefSliceAsArray(...@@ -37257,7 +37202,13 @@ fn maybeDerefSliceAsArray(
37257 const pt = sema.pt;37202 const pt = sema.pt;
37258 const zcu = pt.zcu;37203 const zcu = pt.zcu;
37259 const ip = &zcu.intern_pool;37204 const ip = &zcu.intern_pool;
37260 assert(slice_val.typeOf(zcu).isSlice(zcu));37205 const slice_ty = slice_val.typeOf(zcu);
37206 assert(slice_ty.zigTypeTag(zcu) == .pointer);
37207 switch (slice_ty.ptrInfo(zcu).flags.size) {
37208 .slice => {},
37209 .one => return sema.pointerDeref(block, src, slice_val, slice_ty),
37210 .many, .c => unreachable,
37211 }
37261 const slice = switch (ip.indexToKey(slice_val.toIntern())) {37212 const slice = switch (ip.indexToKey(slice_val.toIntern())) {
37262 .undef => return sema.failWithUseOfUndef(block, src, null),37213 .undef => return sema.failWithUseOfUndef(block, src, null),
37263 .slice => |slice| slice,37214 .slice => |slice| slice,
...@@ -37393,7 +37344,7 @@ pub fn resolveDeclaredEnum(...@@ -37393,7 +37344,7 @@ pub fn resolveDeclaredEnum(
37393 .inlining = null,37344 .inlining = null,
37394 .comptime_reason = .{ .reason = .{37345 .comptime_reason = .{ .reason = .{
37395 .src = src,37346 .src = src,
37396 .r = .{ .simple = .enum_fields },37347 .r = .{ .simple = .enum_field_values },
37397 } },37348 } },
37398 .src_base_inst = tracked_inst,37349 .src_base_inst = tracked_inst,
37399 .type_name_ctx = type_name,37350 .type_name_ctx = type_name,
src/Type.zig+8-2
...@@ -317,7 +317,7 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari...@@ -317,7 +317,7 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari
317 .undefined,317 .undefined,
318 => try writer.print("@TypeOf({s})", .{@tagName(s)}),318 => try writer.print("@TypeOf({s})", .{@tagName(s)}),
319319
320 .enum_literal => try writer.writeAll("@Type(.enum_literal)"),320 .enum_literal => try writer.writeAll("@EnumLiteral()"),
321321
322 .generic_poison => unreachable,322 .generic_poison => unreachable,
323 },323 },
...@@ -3509,7 +3509,9 @@ pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 {...@@ -3509,7 +3509,9 @@ pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 {
3509 .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_line,3509 .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_line,
3510 .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_line,3510 .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_line,
3511 .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_line,3511 .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_line,
3512 .reify => zir.extraData(Zir.Inst.Reify, inst.data.extended.operand).data.src_line,3512 .reify_enum => zir.extraData(Zir.Inst.ReifyEnum, inst.data.extended.operand).data.src_line,
3513 .reify_struct => zir.extraData(Zir.Inst.ReifyStruct, inst.data.extended.operand).data.src_line,
3514 .reify_union => zir.extraData(Zir.Inst.ReifyUnion, inst.data.extended.operand).data.src_line,
3513 else => unreachable,3515 else => unreachable,
3514 },3516 },
3515 else => unreachable,3517 else => unreachable,
...@@ -4280,6 +4282,10 @@ pub const manyptr_const_u8: Type = .{ .ip_index = .manyptr_const_u8_type };...@@ -4280,6 +4282,10 @@ pub const manyptr_const_u8: Type = .{ .ip_index = .manyptr_const_u8_type };
4280pub const manyptr_const_u8_sentinel_0: Type = .{ .ip_index = .manyptr_const_u8_sentinel_0_type };4282pub const manyptr_const_u8_sentinel_0: Type = .{ .ip_index = .manyptr_const_u8_sentinel_0_type };
4281pub const slice_const_u8: Type = .{ .ip_index = .slice_const_u8_type };4283pub const slice_const_u8: Type = .{ .ip_index = .slice_const_u8_type };
4282pub const slice_const_u8_sentinel_0: Type = .{ .ip_index = .slice_const_u8_sentinel_0_type };4284pub const slice_const_u8_sentinel_0: Type = .{ .ip_index = .slice_const_u8_sentinel_0_type };
4285pub const slice_const_slice_const_u8: Type = .{ .ip_index = .slice_const_slice_const_u8_type };
4286pub const slice_const_type: Type = .{ .ip_index = .slice_const_type_type };
4287pub const optional_type: Type = .{ .ip_index = .optional_type_type };
4288pub const optional_noreturn: Type = .{ .ip_index = .optional_noreturn_type };
42834289
4284pub const vector_8_i8: Type = .{ .ip_index = .vector_8_i8_type };4290pub const vector_8_i8: Type = .{ .ip_index = .vector_8_i8_type };
4285pub const vector_16_i8: Type = .{ .ip_index = .vector_16_i8_type };4291pub const vector_16_i8: Type = .{ .ip_index = .vector_16_i8_type };
src/Value.zig+23
...@@ -2824,6 +2824,29 @@ pub fn resolveLazy(...@@ -2824,6 +2824,29 @@ pub fn resolveLazy(
2824 .val = resolved_val,2824 .val = resolved_val,
2825 }));2825 }));
2826 },2826 },
2827 .error_union => |eu| switch (eu.val) {
2828 .err_name => return val,
2829 .payload => |payload| {
2830 const resolved_payload = try Value.fromInterned(payload).resolveLazy(arena, pt);
2831 if (resolved_payload.toIntern() == payload) return val;
2832 return .fromInterned(try pt.intern(.{ .error_union = .{
2833 .ty = eu.ty,
2834 .val = .{ .payload = resolved_payload.toIntern() },
2835 } }));
2836 },
2837 },
2838 .opt => |opt| switch (opt.val) {
2839 .none => return val,
2840 else => |payload| {
2841 const resolved_payload = try Value.fromInterned(payload).resolveLazy(arena, pt);
2842 if (resolved_payload.toIntern() == payload) return val;
2843 return .fromInterned(try pt.intern(.{ .opt = .{
2844 .ty = opt.ty,
2845 .val = resolved_payload.toIntern(),
2846 } }));
2847 },
2848 },
2849
2827 else => return val,2850 else => return val,
2828 }2851 }
2829}2852}
src/Zcu.zig+19-5
...@@ -416,10 +416,13 @@ pub const BuiltinDecl = enum {...@@ -416,10 +416,13 @@ pub const BuiltinDecl = enum {
416 Type,416 Type,
417 @"Type.Fn",417 @"Type.Fn",
418 @"Type.Fn.Param",418 @"Type.Fn.Param",
419 @"Type.Fn.Param.Attributes",
420 @"Type.Fn.Attributes",
419 @"Type.Int",421 @"Type.Int",
420 @"Type.Float",422 @"Type.Float",
421 @"Type.Pointer",423 @"Type.Pointer",
422 @"Type.Pointer.Size",424 @"Type.Pointer.Size",
425 @"Type.Pointer.Attributes",
423 @"Type.Array",426 @"Type.Array",
424 @"Type.Vector",427 @"Type.Vector",
425 @"Type.Optional",428 @"Type.Optional",
...@@ -427,10 +430,13 @@ pub const BuiltinDecl = enum {...@@ -427,10 +430,13 @@ pub const BuiltinDecl = enum {
427 @"Type.ErrorUnion",430 @"Type.ErrorUnion",
428 @"Type.EnumField",431 @"Type.EnumField",
429 @"Type.Enum",432 @"Type.Enum",
433 @"Type.Enum.Mode",
430 @"Type.Union",434 @"Type.Union",
431 @"Type.UnionField",435 @"Type.UnionField",
436 @"Type.UnionField.Attributes",
432 @"Type.Struct",437 @"Type.Struct",
433 @"Type.StructField",438 @"Type.StructField",
439 @"Type.StructField.Attributes",
434 @"Type.ContainerLayout",440 @"Type.ContainerLayout",
435 @"Type.Opaque",441 @"Type.Opaque",
436 @"Type.Declaration",442 @"Type.Declaration",
...@@ -495,10 +501,13 @@ pub const BuiltinDecl = enum {...@@ -495,10 +501,13 @@ pub const BuiltinDecl = enum {
495 .Type,501 .Type,
496 .@"Type.Fn",502 .@"Type.Fn",
497 .@"Type.Fn.Param",503 .@"Type.Fn.Param",
504 .@"Type.Fn.Param.Attributes",
505 .@"Type.Fn.Attributes",
498 .@"Type.Int",506 .@"Type.Int",
499 .@"Type.Float",507 .@"Type.Float",
500 .@"Type.Pointer",508 .@"Type.Pointer",
501 .@"Type.Pointer.Size",509 .@"Type.Pointer.Size",
510 .@"Type.Pointer.Attributes",
502 .@"Type.Array",511 .@"Type.Array",
503 .@"Type.Vector",512 .@"Type.Vector",
504 .@"Type.Optional",513 .@"Type.Optional",
...@@ -506,10 +515,13 @@ pub const BuiltinDecl = enum {...@@ -506,10 +515,13 @@ pub const BuiltinDecl = enum {
506 .@"Type.ErrorUnion",515 .@"Type.ErrorUnion",
507 .@"Type.EnumField",516 .@"Type.EnumField",
508 .@"Type.Enum",517 .@"Type.Enum",
518 .@"Type.Enum.Mode",
509 .@"Type.Union",519 .@"Type.Union",
510 .@"Type.UnionField",520 .@"Type.UnionField",
521 .@"Type.UnionField.Attributes",
511 .@"Type.Struct",522 .@"Type.Struct",
512 .@"Type.StructField",523 .@"Type.StructField",
524 .@"Type.StructField.Attributes",
513 .@"Type.ContainerLayout",525 .@"Type.ContainerLayout",
514 .@"Type.Opaque",526 .@"Type.Opaque",
515 .@"Type.Declaration",527 .@"Type.Declaration",
...@@ -1745,28 +1757,28 @@ pub const SrcLoc = struct {...@@ -1745,28 +1757,28 @@ pub const SrcLoc = struct {
1745 const node = node_off.toAbsolute(src_loc.base_node);1757 const node = node_off.toAbsolute(src_loc.base_node);
1746 var buf: [1]Ast.Node.Index = undefined;1758 var buf: [1]Ast.Node.Index = undefined;
1747 const full = tree.fullFnProto(&buf, node).?;1759 const full = tree.fullFnProto(&buf, node).?;
1748 return tree.nodeToSpan(full.ast.align_expr.unwrap().?);1760 return tree.nodeToSpan(full.ast.align_expr.unwrap() orelse node);
1749 },1761 },
1750 .node_offset_fn_type_addrspace => |node_off| {1762 .node_offset_fn_type_addrspace => |node_off| {
1751 const tree = try src_loc.file_scope.getTree(zcu);1763 const tree = try src_loc.file_scope.getTree(zcu);
1752 const node = node_off.toAbsolute(src_loc.base_node);1764 const node = node_off.toAbsolute(src_loc.base_node);
1753 var buf: [1]Ast.Node.Index = undefined;1765 var buf: [1]Ast.Node.Index = undefined;
1754 const full = tree.fullFnProto(&buf, node).?;1766 const full = tree.fullFnProto(&buf, node).?;
1755 return tree.nodeToSpan(full.ast.addrspace_expr.unwrap().?);1767 return tree.nodeToSpan(full.ast.addrspace_expr.unwrap() orelse node);
1756 },1768 },
1757 .node_offset_fn_type_section => |node_off| {1769 .node_offset_fn_type_section => |node_off| {
1758 const tree = try src_loc.file_scope.getTree(zcu);1770 const tree = try src_loc.file_scope.getTree(zcu);
1759 const node = node_off.toAbsolute(src_loc.base_node);1771 const node = node_off.toAbsolute(src_loc.base_node);
1760 var buf: [1]Ast.Node.Index = undefined;1772 var buf: [1]Ast.Node.Index = undefined;
1761 const full = tree.fullFnProto(&buf, node).?;1773 const full = tree.fullFnProto(&buf, node).?;
1762 return tree.nodeToSpan(full.ast.section_expr.unwrap().?);1774 return tree.nodeToSpan(full.ast.section_expr.unwrap() orelse node);
1763 },1775 },
1764 .node_offset_fn_type_cc => |node_off| {1776 .node_offset_fn_type_cc => |node_off| {
1765 const tree = try src_loc.file_scope.getTree(zcu);1777 const tree = try src_loc.file_scope.getTree(zcu);
1766 const node = node_off.toAbsolute(src_loc.base_node);1778 const node = node_off.toAbsolute(src_loc.base_node);
1767 var buf: [1]Ast.Node.Index = undefined;1779 var buf: [1]Ast.Node.Index = undefined;
1768 const full = tree.fullFnProto(&buf, node).?;1780 const full = tree.fullFnProto(&buf, node).?;
1769 return tree.nodeToSpan(full.ast.callconv_expr.unwrap().?);1781 return tree.nodeToSpan(full.ast.callconv_expr.unwrap() orelse node);
1770 },1782 },
17711783
1772 .node_offset_fn_type_ret_ty => |node_off| {1784 .node_offset_fn_type_ret_ty => |node_off| {
...@@ -2684,7 +2696,9 @@ pub const LazySrcLoc = struct {...@@ -2684,7 +2696,9 @@ pub const LazySrcLoc = struct {
2684 .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_node,2696 .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_node,
2685 .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_node,2697 .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_node,
2686 .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_node,2698 .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_node,
2687 .reify => zir.extraData(Zir.Inst.Reify, inst.data.extended.operand).data.node,2699 .reify_enum => zir.extraData(Zir.Inst.ReifyEnum, inst.data.extended.operand).data.node,
2700 .reify_struct => zir.extraData(Zir.Inst.ReifyStruct, inst.data.extended.operand).data.node,
2701 .reify_union => zir.extraData(Zir.Inst.ReifyUnion, inst.data.extended.operand).data.node,
2688 else => unreachable,2702 else => unreachable,
2689 },2703 },
2690 else => unreachable,2704 else => unreachable,
src/codegen/aarch64/Assemble.zig+11-21
...@@ -120,23 +120,13 @@ const matchers = matchers: {...@@ -120,23 +120,13 @@ const matchers = matchers: {
120 );120 );
121 var symbols: Symbols: {121 var symbols: Symbols: {
122 const symbols = @typeInfo(@TypeOf(instruction.symbols)).@"struct".fields;122 const symbols = @typeInfo(@TypeOf(instruction.symbols)).@"struct".fields;
123 var symbol_fields: [symbols.len]std.builtin.Type.StructField = undefined;123 var field_names: [symbols.len][]const u8 = undefined;
124 for (&symbol_fields, symbols) |*symbol_field, symbol| {124 var field_types: [symbols.len]type = undefined;
125 const Storage = zonCast(SymbolSpec, @field(instruction.symbols, symbol.name), .{}).Storage();125 for (symbols, &field_names, &field_types) |symbol, *field_name, *FieldType| {
126 symbol_field.* = .{126 field_name.* = symbol.name;
127 .name = symbol.name,127 FieldType.* = zonCast(SymbolSpec, @field(instruction.symbols, symbol.name), .{}).Storage();
128 .type = Storage,
129 .default_value_ptr = null,
130 .is_comptime = false,
131 .alignment = @alignOf(Storage),
132 };
133 }128 }
134 break :Symbols @Type(.{ .@"struct" = .{129 break :Symbols @Struct(.auto, null, &field_names, &field_types, &@splat(.{}));
135 .layout = .auto,
136 .fields = &symbol_fields,
137 .decls = &.{},
138 .is_tuple = false,
139 } });
140 } = undefined;130 } = undefined;
141 const Symbol = std.meta.FieldEnum(@TypeOf(instruction.symbols));131 const Symbol = std.meta.FieldEnum(@TypeOf(instruction.symbols));
142 comptime var unused_symbols: std.enums.EnumSet(Symbol) = .initFull();132 comptime var unused_symbols: std.enums.EnumSet(Symbol) = .initFull();
...@@ -334,7 +324,7 @@ const SymbolSpec = union(enum) {...@@ -334,7 +324,7 @@ const SymbolSpec = union(enum) {
334 .reg => aarch64.encoding.Register,324 .reg => aarch64.encoding.Register,
335 .arrangement => aarch64.encoding.Register.Arrangement,325 .arrangement => aarch64.encoding.Register.Arrangement,
336 .systemreg => aarch64.encoding.Register.System,326 .systemreg => aarch64.encoding.Register.System,
337 .imm => |imm_spec| @Type(.{ .int = imm_spec.type }),327 .imm => |imm_spec| @Int(imm_spec.type.signedness, imm_spec.type.bits),
338 .fimm => f16,328 .fimm => f16,
339 .extend => Instruction.DataProcessingRegister.AddSubtractExtendedRegister.Option,329 .extend => Instruction.DataProcessingRegister.AddSubtractExtendedRegister.Option,
340 .shift => Instruction.DataProcessingRegister.Shift.Op,330 .shift => Instruction.DataProcessingRegister.Shift.Op,
...@@ -413,13 +403,13 @@ const SymbolSpec = union(enum) {...@@ -413,13 +403,13 @@ const SymbolSpec = union(enum) {
413 return systemreg;403 return systemreg;
414 },404 },
415 .imm => |imm_spec| {405 .imm => |imm_spec| {
416 const imm = std.fmt.parseInt(@Type(.{ .int = .{406 const imm = std.fmt.parseInt(@Int(
417 .signedness = imm_spec.type.signedness,407 imm_spec.type.signedness,
418 .bits = switch (imm_spec.adjust) {408 switch (imm_spec.adjust) {
419 .none, .neg_wrap => imm_spec.type.bits,409 .none, .neg_wrap => imm_spec.type.bits,
420 .dec => imm_spec.type.bits + 1,410 .dec => imm_spec.type.bits + 1,
421 },411 },
422 } }), token, 0) catch {412 ), token, 0) catch {
423 log.debug("invalid immediate: \"{f}\"", .{std.zig.fmtString(token)});413 log.debug("invalid immediate: \"{f}\"", .{std.zig.fmtString(token)});
424 return null;414 return null;
425 };415 };
src/codegen/aarch64/Select.zig+22-14
...@@ -8928,12 +8928,16 @@ pub const Value = struct {...@@ -8928,12 +8928,16 @@ pub const Value = struct {
8928 constant: Constant,8928 constant: Constant,
89298929
8930 pub const Tag = @typeInfo(Parent).@"union".tag_type.?;8930 pub const Tag = @typeInfo(Parent).@"union".tag_type.?;
8931 pub const Payload = @Type(.{ .@"union" = .{8931 pub const Payload = Payload: {
8932 .layout = .auto,8932 const fields = @typeInfo(Parent).@"union".fields;
8933 .tag_type = null,8933 var types: [fields.len]type = undefined;
8934 .fields = @typeInfo(Parent).@"union".fields,8934 var names: [fields.len][]const u8 = undefined;
8935 .decls = &.{},8935 for (fields, &types, &names) |f, *ty, *name| {
8936 } });8936 ty.* = f.type;
8937 name.* = f.name;
8938 }
8939 break :Payload @Union(.auto, null, &names, &types, &@splat(.{}));
8940 };
8937 };8941 };
89388942
8939 pub const Location = union(enum(u1)) {8943 pub const Location = union(enum(u1)) {
...@@ -8949,12 +8953,16 @@ pub const Value = struct {...@@ -8949,12 +8953,16 @@ pub const Value = struct {
8949 },8953 },
89508954
8951 pub const Tag = @typeInfo(Location).@"union".tag_type.?;8955 pub const Tag = @typeInfo(Location).@"union".tag_type.?;
8952 pub const Payload = @Type(.{ .@"union" = .{8956 pub const Payload = Payload: {
8953 .layout = .auto,8957 const fields = @typeInfo(Location).@"union".fields;
8954 .tag_type = null,8958 var types: [fields.len]type = undefined;
8955 .fields = @typeInfo(Location).@"union".fields,8959 var names: [fields.len][]const u8 = undefined;
8956 .decls = &.{},8960 for (fields, &types, &names) |f, *ty, *name| {
8957 } });8961 ty.* = f.type;
8962 name.* = f.name;
8963 }
8964 break :Payload @Union(.auto, null, &names, &types, &@splat(.{}));
8965 };
8958 };8966 };
89598967
8960 pub const Indirect = packed struct(u32) {8968 pub const Indirect = packed struct(u32) {
...@@ -11210,7 +11218,7 @@ pub const Value = struct {...@@ -11210,7 +11218,7 @@ pub const Value = struct {
11210 .storage = .{ .u64 = switch (size) {11218 .storage = .{ .u64 = switch (size) {
11211 else => unreachable,11219 else => unreachable,
11212 inline 1...8 => |ct_size| std.mem.readInt(11220 inline 1...8 => |ct_size| std.mem.readInt(
11213 @Type(.{ .int = .{ .signedness = .unsigned, .bits = 8 * ct_size } }),11221 @Int(.unsigned, 8 * ct_size),
11214 buffer[@intCast(offset)..][0..ct_size],11222 buffer[@intCast(offset)..][0..ct_size],
11215 isel.target.cpu.arch.endian(),11223 isel.target.cpu.arch.endian(),
11216 ),11224 ),
...@@ -11438,7 +11446,7 @@ fn writeKeyToMemory(isel: *Select, constant_key: InternPool.Key, buffer: []u8) e...@@ -11438,7 +11446,7 @@ fn writeKeyToMemory(isel: *Select, constant_key: InternPool.Key, buffer: []u8) e
11438 switch (buffer.len) {11446 switch (buffer.len) {
11439 else => unreachable,11447 else => unreachable,
11440 inline 1...4 => |size| std.mem.writeInt(11448 inline 1...4 => |size| std.mem.writeInt(
11441 @Type(.{ .int = .{ .signedness = .unsigned, .bits = 8 * size } }),11449 @Int(.unsigned, 8 * size),
11442 buffer[0..size],11450 buffer[0..size],
11443 @intCast(error_int),11451 @intCast(error_int),
11444 isel.target.cpu.arch.endian(),11452 isel.target.cpu.arch.endian(),
src/codegen/c/Type.zig+70
...@@ -1416,6 +1416,9 @@ pub const Pool = struct {...@@ -1416,6 +1416,9 @@ pub const Pool = struct {
1416 .null_type,1416 .null_type,
1417 .undefined_type,1417 .undefined_type,
1418 .enum_literal_type,1418 .enum_literal_type,
1419 .optional_type_type,
1420 .manyptr_const_type_type,
1421 .slice_const_type_type,
1419 => return .void,1422 => return .void,
1420 .u1_type, .u8_type => return .u8,1423 .u1_type, .u8_type => return .u8,
1421 .i8_type => return .i8,1424 .i8_type => return .i8,
...@@ -1525,6 +1528,73 @@ pub const Pool = struct {...@@ -1525,6 +1528,73 @@ pub const Pool = struct {
1525 return pool.fromFields(allocator, .@"struct", &fields, kind);1528 return pool.fromFields(allocator, .@"struct", &fields, kind);
1526 },1529 },
15271530
1531 .manyptr_const_slice_const_u8_type => {
1532 const target = &mod.resolved_target.result;
1533 var fields: [2]Info.Field = .{
1534 .{
1535 .name = .{ .index = .ptr },
1536 .ctype = try pool.getPointer(allocator, .{
1537 .elem_ctype = .u8,
1538 .@"const" = true,
1539 .nonstring = true,
1540 }),
1541 .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target)),
1542 },
1543 .{
1544 .name = .{ .index = .len },
1545 .ctype = .usize,
1546 .alignas = AlignAs.fromAbiAlignment(
1547 .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())),
1548 ),
1549 },
1550 };
1551 const slice_const_u8 = try pool.fromFields(allocator, .@"struct", &fields, kind);
1552 return pool.getPointer(allocator, .{
1553 .elem_ctype = slice_const_u8,
1554 .@"const" = true,
1555 });
1556 },
1557 .slice_const_slice_const_u8_type => {
1558 const target = &mod.resolved_target.result;
1559 var fields: [2]Info.Field = .{
1560 .{
1561 .name = .{ .index = .ptr },
1562 .ctype = try pool.getPointer(allocator, .{
1563 .elem_ctype = .u8,
1564 .@"const" = true,
1565 .nonstring = true,
1566 }),
1567 .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target)),
1568 },
1569 .{
1570 .name = .{ .index = .len },
1571 .ctype = .usize,
1572 .alignas = AlignAs.fromAbiAlignment(
1573 .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())),
1574 ),
1575 },
1576 };
1577 const slice_const_u8 = try pool.fromFields(allocator, .@"struct", &fields, .forward);
1578 fields = .{
1579 .{
1580 .name = .{ .index = .ptr },
1581 .ctype = try pool.getPointer(allocator, .{
1582 .elem_ctype = slice_const_u8,
1583 .@"const" = true,
1584 }),
1585 .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target)),
1586 },
1587 .{
1588 .name = .{ .index = .len },
1589 .ctype = .usize,
1590 .alignas = AlignAs.fromAbiAlignment(
1591 .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())),
1592 ),
1593 },
1594 };
1595 return pool.fromFields(allocator, .@"struct", &fields, kind);
1596 },
1597
1528 .vector_8_i8_type => {1598 .vector_8_i8_type => {
1529 const vector_ctype = try pool.getVector(allocator, .{1599 const vector_ctype = try pool.getVector(allocator, .{
1530 .elem_ctype = .i8,1600 .elem_ctype = .i8,
src/codegen/x86_64/CodeGen.zig+5-7
...@@ -189867,9 +189867,7 @@ const Select = struct {...@@ -189867,9 +189867,7 @@ const Select = struct {
189867 }189867 }
189868189868
189869 fn adjustedImm(op: Select.Operand, comptime SignedImm: type, s: *const Select) SignedImm {189869 fn adjustedImm(op: Select.Operand, comptime SignedImm: type, s: *const Select) SignedImm {
189870 const UnsignedImm = @Type(.{189870 const UnsignedImm = @Int(.unsigned, @typeInfo(SignedImm).int.bits);
189871 .int = .{ .signedness = .unsigned, .bits = @typeInfo(SignedImm).int.bits },
189872 });
189873 const lhs: SignedImm = lhs: switch (op.flags.adjust.lhs) {189871 const lhs: SignedImm = lhs: switch (op.flags.adjust.lhs) {
189874 .none => 0,189872 .none => 0,
189875 .ptr_size => @divExact(s.cg.target.ptrBitWidth(), 8),189873 .ptr_size => @divExact(s.cg.target.ptrBitWidth(), 8),
...@@ -189934,10 +189932,10 @@ const Select = struct {...@@ -189934,10 +189932,10 @@ const Select = struct {
189934 const RefImm = switch (size) {189932 const RefImm = switch (size) {
189935 else => comptime unreachable,189933 else => comptime unreachable,
189936 .none => Imm,189934 .none => Imm,
189937 .byte, .word, .dword, .qword => @Type(comptime .{ .int = .{189935 .byte, .word, .dword, .qword => @Int(
189938 .signedness = @typeInfo(Imm).int.signedness,189936 @typeInfo(Imm).int.signedness,
189939 .bits = size.bitSize(undefined),189937 size.bitSize(undefined),
189940 } }),189938 ),
189941 };189939 };
189942 break :lhs @bitCast(@as(Imm, @intCast(@as(RefImm, switch (adjust) {189940 break :lhs @bitCast(@as(Imm, @intCast(@as(RefImm, switch (adjust) {
189943 else => comptime unreachable,189941 else => comptime unreachable,
src/codegen/x86_64/Emit.zig+1-1
...@@ -708,7 +708,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -708,7 +708,7 @@ pub fn emitMir(emit: *Emit) Error!void {
708 switch (reloc.source_length) {708 switch (reloc.source_length) {
709 else => unreachable,709 else => unreachable,
710 inline 1, 4 => |source_length| std.mem.writeInt(710 inline 1, 4 => |source_length| std.mem.writeInt(
711 @Type(.{ .int = .{ .signedness = .signed, .bits = @as(u16, 8) * source_length } }),711 @Int(.signed, @as(u16, 8) * source_length),
712 inst_bytes[reloc.source_offset..][0..source_length],712 inst_bytes[reloc.source_offset..][0..source_length],
713 @intCast(disp),713 @intCast(disp),
714 .little,714 .little,
src/link.zig+1-4
...@@ -51,10 +51,7 @@ pub const Diags = struct {...@@ -51,10 +51,7 @@ pub const Diags = struct {
5151
52 const Int = blk: {52 const Int = blk: {
53 const bits = @typeInfo(@This()).@"struct".fields.len;53 const bits = @typeInfo(@This()).@"struct".fields.len;
54 break :blk @Type(.{ .int = .{54 break :blk @Int(.unsigned, bits);
55 .signedness = .unsigned,
56 .bits = bits,
57 } });
58 };55 };
5956
60 pub fn anySet(ef: Flags) bool {57 pub fn anySet(ef: Flags) bool {
src/link/Dwarf.zig+19-14
...@@ -4490,7 +4490,12 @@ fn updateContainerTypeWriterError(...@@ -4490,7 +4490,12 @@ fn updateContainerTypeWriterError(
4490 .enum_decl => @as(Zir.Inst.EnumDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,4490 .enum_decl => @as(Zir.Inst.EnumDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,
4491 .union_decl => @as(Zir.Inst.UnionDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,4491 .union_decl => @as(Zir.Inst.UnionDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,
4492 .opaque_decl => @as(Zir.Inst.OpaqueDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,4492 .opaque_decl => @as(Zir.Inst.OpaqueDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,
4493 .reify => @as(Zir.Inst.NameStrategy, @enumFromInt(decl_inst.data.extended.small)),4493
4494 .reify_enum,
4495 .reify_struct,
4496 .reify_union,
4497 => @enumFromInt(decl_inst.data.extended.small),
4498
4494 else => unreachable,4499 else => unreachable,
4495 },4500 },
4496 else => unreachable,4501 else => unreachable,
...@@ -5125,25 +5130,23 @@ pub fn resolveRelocs(dwarf: *Dwarf) RelocError!void {...@@ -5125,25 +5130,23 @@ pub fn resolveRelocs(dwarf: *Dwarf) RelocError!void {
51255130
5126fn DeclValEnum(comptime T: type) type {5131fn DeclValEnum(comptime T: type) type {
5127 const decls = @typeInfo(T).@"struct".decls;5132 const decls = @typeInfo(T).@"struct".decls;
5128 @setEvalBranchQuota(7 * decls.len);5133 @setEvalBranchQuota(10 * decls.len);
5129 var fields: [decls.len]std.builtin.Type.EnumField = undefined;5134 var field_names: [decls.len][]const u8 = undefined;
5130 var fields_len = 0;5135 var fields_len = 0;
5131 var min_value: ?comptime_int = null;5136 var min_value: ?comptime_int = null;
5132 var max_value: ?comptime_int = null;5137 var max_value: ?comptime_int = null;
5133 for (decls) |decl| {5138 for (decls) |decl| {
5134 if (std.mem.startsWith(u8, decl.name, "HP_") or std.mem.endsWith(u8, decl.name, "_user")) continue;5139 if (std.mem.startsWith(u8, decl.name, "HP_") or std.mem.endsWith(u8, decl.name, "_user")) continue;
5135 const value = @field(T, decl.name);5140 const value = @field(T, decl.name);
5136 fields[fields_len] = .{ .name = decl.name, .value = value };5141 field_names[fields_len] = decl.name;
5137 fields_len += 1;5142 fields_len += 1;
5138 if (min_value == null or min_value.? > value) min_value = value;5143 if (min_value == null or min_value.? > value) min_value = value;
5139 if (max_value == null or max_value.? < value) max_value = value;5144 if (max_value == null or max_value.? < value) max_value = value;
5140 }5145 }
5141 return @Type(.{ .@"enum" = .{5146 const TagInt = std.math.IntFittingRange(min_value orelse 0, max_value orelse 0);
5142 .tag_type = std.math.IntFittingRange(min_value orelse 0, max_value orelse 0),5147 var field_vals: [fields_len]TagInt = undefined;
5143 .fields = fields[0..fields_len],5148 for (field_names[0..fields_len], &field_vals) |name, *val| val.* = @field(T, name);
5144 .decls = &.{},5149 return @Enum(TagInt, .exhaustive, field_names[0..fields_len], &field_vals);
5145 .is_exhaustive = true,
5146 } });
5147}5150}
51485151
5149const AbbrevCode = enum {5152const AbbrevCode = enum {
...@@ -6377,10 +6380,12 @@ fn freeCommonEntry(...@@ -6377,10 +6380,12 @@ fn freeCommonEntry(
63776380
6378fn writeInt(dwarf: *Dwarf, buf: []u8, int: u64) void {6381fn writeInt(dwarf: *Dwarf, buf: []u8, int: u64) void {
6379 switch (buf.len) {6382 switch (buf.len) {
6380 inline 0...8 => |len| std.mem.writeInt(@Type(.{ .int = .{6383 inline 0...8 => |len| std.mem.writeInt(
6381 .signedness = .unsigned,6384 @Int(.unsigned, len * 8),
6382 .bits = len * 8,6385 buf[0..len],
6383 } }), buf[0..len], @intCast(int), dwarf.endian),6386 @intCast(int),
6387 dwarf.endian,
6388 ),
6384 else => unreachable,6389 else => unreachable,
6385 }6390 }
6386}6391}
src/link/MappedFile.zig+6-14
...@@ -108,10 +108,7 @@ pub const Node = extern struct {...@@ -108,10 +108,7 @@ pub const Node = extern struct {
108 has_content: bool,108 has_content: bool,
109 /// Whether a moved event on this node bubbles down to children.109 /// Whether a moved event on this node bubbles down to children.
110 bubbles_moved: bool,110 bubbles_moved: bool,
111 unused: @Type(.{ .int = .{111 unused: @Int(.unsigned, 32 - @bitSizeOf(std.mem.Alignment) - 6) = 0,
112 .signedness = .unsigned,
113 .bits = 32 - @bitSizeOf(std.mem.Alignment) - 6,
114 } }) = 0,
115 };112 };
116113
117 pub const Location = union(enum(u1)) {114 pub const Location = union(enum(u1)) {
...@@ -122,19 +119,14 @@ pub const Node = extern struct {...@@ -122,19 +119,14 @@ pub const Node = extern struct {
122 },119 },
123 large: extern struct {120 large: extern struct {
124 index: usize,121 index: usize,
125 unused: @Type(.{ .int = .{122 unused: @Int(.unsigned, 64 - @bitSizeOf(usize)) = 0,
126 .signedness = .unsigned,
127 .bits = 64 - @bitSizeOf(usize),
128 } }) = 0,
129 },123 },
130124
131 pub const Tag = @typeInfo(Location).@"union".tag_type.?;125 pub const Tag = @typeInfo(Location).@"union".tag_type.?;
132 pub const Payload = @Type(.{ .@"union" = .{126 pub const Payload = extern union {
133 .layout = .@"extern",127 small: @FieldType(Location, "small"),
134 .tag_type = null,128 large: @FieldType(Location, "large"),
135 .fields = @typeInfo(Location).@"union".fields,129 };
136 .decls = &.{},
137 } });
138130
139 pub fn resolve(loc: Location, mf: *const MappedFile) [2]u64 {131 pub fn resolve(loc: Location, mf: *const MappedFile) [2]u64 {
140 return switch (loc) {132 return switch (loc) {
src/main.zig+1-1
...@@ -136,7 +136,7 @@ var log_scopes: std.ArrayList([]const u8) = .empty;...@@ -136,7 +136,7 @@ var log_scopes: std.ArrayList([]const u8) = .empty;
136136
137pub fn log(137pub fn log(
138 comptime level: std.log.Level,138 comptime level: std.log.Level,
139 comptime scope: @Type(.enum_literal),139 comptime scope: @EnumLiteral(),
140 comptime format: []const u8,140 comptime format: []const u8,
141 args: anytype,141 args: anytype,
142) void {142) void {
src/print_zir.zig+93-11
...@@ -399,6 +399,7 @@ const Writer = struct {...@@ -399,6 +399,7 @@ const Writer = struct {
399 .splat,399 .splat,
400 .reduce,400 .reduce,
401 .bitcast,401 .bitcast,
402 .reify_int,
402 .vector_type,403 .vector_type,
403 .max,404 .max,
404 .min,405 .min,
...@@ -568,6 +569,8 @@ const Writer = struct {...@@ -568,6 +569,8 @@ const Writer = struct {
568 .work_group_id,569 .work_group_id,
569 .branch_hint,570 .branch_hint,
570 .float_op_result_ty,571 .float_op_result_ty,
572 .reify_tuple,
573 .reify_pointer_sentinel_ty,
571 => {574 => {
572 const inst_data = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;575 const inst_data = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;
573 try self.writeInstRef(stream, inst_data.operand);576 try self.writeInstRef(stream, inst_data.operand);
...@@ -575,23 +578,13 @@ const Writer = struct {...@@ -575,23 +578,13 @@ const Writer = struct {
575 try self.writeSrcNode(stream, inst_data.node);578 try self.writeSrcNode(stream, inst_data.node);
576 },579 },
577580
578 .reify => {
579 const inst_data = self.code.extraData(Zir.Inst.Reify, extended.operand).data;
580 try stream.print("line({d}), ", .{inst_data.src_line});
581 try self.writeInstRef(stream, inst_data.operand);
582 try stream.writeAll(")) ");
583 const prev_parent_decl_node = self.parent_decl_node;
584 self.parent_decl_node = inst_data.node;
585 defer self.parent_decl_node = prev_parent_decl_node;
586 try self.writeSrcNode(stream, .zero);
587 },
588
589 .builtin_extern,581 .builtin_extern,
590 .c_define,582 .c_define,
591 .error_cast,583 .error_cast,
592 .wasm_memory_grow,584 .wasm_memory_grow,
593 .prefetch,585 .prefetch,
594 .c_va_arg,586 .c_va_arg,
587 .reify_enum_value_slice_ty,
595 => {588 => {
596 const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;589 const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
597 try self.writeInstRef(stream, inst_data.lhs);590 try self.writeInstRef(stream, inst_data.lhs);
...@@ -601,6 +594,95 @@ const Writer = struct {...@@ -601,6 +594,95 @@ const Writer = struct {
601 try self.writeSrcNode(stream, inst_data.node);594 try self.writeSrcNode(stream, inst_data.node);
602 },595 },
603596
597 .reify_slice_arg_ty => {
598 const reify_slice_arg_info: Zir.Inst.ReifySliceArgInfo = @enumFromInt(extended.operand);
599 const extra = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;
600 try stream.print("{t}, ", .{reify_slice_arg_info});
601 try self.writeInstRef(stream, extra.operand);
602 try stream.writeAll(")) ");
603 try self.writeSrcNode(stream, extra.node);
604 },
605
606 .reify_pointer => {
607 const extra = self.code.extraData(Zir.Inst.ReifyPointer, extended.operand).data;
608 try self.writeInstRef(stream, extra.size);
609 try stream.writeAll(", ");
610 try self.writeInstRef(stream, extra.attrs);
611 try stream.writeAll(", ");
612 try self.writeInstRef(stream, extra.elem_ty);
613 try stream.writeAll(", ");
614 try self.writeInstRef(stream, extra.sentinel);
615 try stream.writeAll(")) ");
616 try self.writeSrcNode(stream, extra.node);
617 },
618 .reify_fn => {
619 const extra = self.code.extraData(Zir.Inst.ReifyFn, extended.operand).data;
620 try self.writeInstRef(stream, extra.param_types);
621 try stream.writeAll(", ");
622 try self.writeInstRef(stream, extra.param_attrs);
623 try stream.writeAll(", ");
624 try self.writeInstRef(stream, extra.ret_ty);
625 try stream.writeAll(", ");
626 try self.writeInstRef(stream, extra.fn_attrs);
627 try stream.writeAll(")) ");
628 try self.writeSrcNode(stream, extra.node);
629 },
630 .reify_struct => {
631 const extra = self.code.extraData(Zir.Inst.ReifyStruct, extended.operand).data;
632 const name_strat: Zir.Inst.NameStrategy = @enumFromInt(extended.small);
633 try stream.print("line({d}), {t}, ", .{ extra.src_line, name_strat });
634 try self.writeInstRef(stream, extra.layout);
635 try stream.writeAll(", ");
636 try self.writeInstRef(stream, extra.backing_ty);
637 try stream.writeAll(", ");
638 try self.writeInstRef(stream, extra.field_names);
639 try stream.writeAll(", ");
640 try self.writeInstRef(stream, extra.field_types);
641 try stream.writeAll(", ");
642 try self.writeInstRef(stream, extra.field_attrs);
643 try stream.writeAll(")) ");
644 const prev_parent_decl_node = self.parent_decl_node;
645 self.parent_decl_node = extra.node;
646 defer self.parent_decl_node = prev_parent_decl_node;
647 try self.writeSrcNode(stream, .zero);
648 },
649 .reify_union => {
650 const extra = self.code.extraData(Zir.Inst.ReifyUnion, extended.operand).data;
651 const name_strat: Zir.Inst.NameStrategy = @enumFromInt(extended.small);
652 try stream.print("line({d}), {t}, ", .{ extra.src_line, name_strat });
653 try self.writeInstRef(stream, extra.layout);
654 try stream.writeAll(", ");
655 try self.writeInstRef(stream, extra.arg_ty);
656 try stream.writeAll(", ");
657 try self.writeInstRef(stream, extra.field_names);
658 try stream.writeAll(", ");
659 try self.writeInstRef(stream, extra.field_types);
660 try stream.writeAll(", ");
661 try self.writeInstRef(stream, extra.field_attrs);
662 try stream.writeAll(")) ");
663 const prev_parent_decl_node = self.parent_decl_node;
664 self.parent_decl_node = extra.node;
665 defer self.parent_decl_node = prev_parent_decl_node;
666 try self.writeSrcNode(stream, .zero);
667 },
668 .reify_enum => {
669 const extra = self.code.extraData(Zir.Inst.ReifyEnum, extended.operand).data;
670 const name_strat: Zir.Inst.NameStrategy = @enumFromInt(extended.small);
671 try stream.print("line({d}), {t}, ", .{ extra.src_line, name_strat });
672 try self.writeInstRef(stream, extra.tag_ty);
673 try stream.writeAll(", ");
674 try self.writeInstRef(stream, extra.mode);
675 try stream.writeAll(", ");
676 try self.writeInstRef(stream, extra.field_names);
677 try stream.writeAll(", ");
678 try self.writeInstRef(stream, extra.field_values);
679 try stream.writeAll(")) ");
680 const prev_parent_decl_node = self.parent_decl_node;
681 self.parent_decl_node = extra.node;
682 defer self.parent_decl_node = prev_parent_decl_node;
683 try self.writeSrcNode(stream, .zero);
684 },
685
604 .cmpxchg => try self.writeCmpxchg(stream, extended),686 .cmpxchg => try self.writeCmpxchg(stream, extended),
605 .ptr_cast_full => try self.writePtrCastFull(stream, extended),687 .ptr_cast_full => try self.writePtrCastFull(stream, extended),
606 .ptr_cast_no_dest => try self.writePtrCastNoDest(stream, extended),688 .ptr_cast_no_dest => try self.writePtrCastNoDest(stream, extended),
stage1/zig1.wasm
Binary files a/stage1/zig1.wasm and b/stage1/zig1.wasm differ
test/behavior/basic.zig+2-5
...@@ -1264,12 +1264,9 @@ test "reference to inferred local variable works as expected" {...@@ -1264,12 +1264,9 @@ test "reference to inferred local variable works as expected" {
1264 try expect(crasher_local.lets_crash != a.lets_crash);1264 try expect(crasher_local.lets_crash != a.lets_crash);
1265}1265}
12661266
1267test "@Type returned from block" {1267test "@Int returned from block" {
1268 const T = comptime b: {1268 const T = comptime b: {
1269 break :b @Type(.{ .int = .{1269 break :b @Int(.unsigned, 8);
1270 .signedness = .unsigned,
1271 .bits = 8,
1272 } });
1273 };1270 };
1274 try std.testing.expect(T == u8);1271 try std.testing.expect(T == u8);
1275}1272}
test/behavior/bit_shifting.zig+1-10
...@@ -119,21 +119,12 @@ test "Saturating Shift Left where lhs is of a computed type" {...@@ -119,21 +119,12 @@ test "Saturating Shift Left where lhs is of a computed type" {
119 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;119 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
120120
121 const S = struct {121 const S = struct {
122 fn getIntShiftType(comptime T: type) type {
123 var unsigned_shift_type = @typeInfo(std.math.Log2Int(T)).int;
124 unsigned_shift_type.signedness = .signed;
125
126 return @Type(.{
127 .int = unsigned_shift_type,
128 });
129 }
130
131 pub fn FixedPoint(comptime ValueType: type) type {122 pub fn FixedPoint(comptime ValueType: type) type {
132 return struct {123 return struct {
133 value: ValueType,124 value: ValueType,
134 exponent: ShiftType,125 exponent: ShiftType,
135126
136 const ShiftType: type = getIntShiftType(ValueType);127 const ShiftType = @Int(.signed, @typeInfo(std.math.Log2Int(ValueType)).int.bits);
137128
138 pub fn shiftExponent(self: @This(), shift: ShiftType) @This() {129 pub fn shiftExponent(self: @This(), shift: ShiftType) @This() {
139 const shiftAbs = @abs(shift);130 const shiftAbs = @abs(shift);
test/behavior/call.zig+1-1
...@@ -355,7 +355,7 @@ test "inline call doesn't re-evaluate non generic struct" {...@@ -355,7 +355,7 @@ test "inline call doesn't re-evaluate non generic struct" {
355 try comptime @call(.always_inline, S.foo, ArgTuple{.{ .a = 123, .b = 45 }});355 try comptime @call(.always_inline, S.foo, ArgTuple{.{ .a = 123, .b = 45 }});
356}356}
357357
358test "Enum constructed by @Type passed as generic argument" {358test "Enum constructed by @Enum passed as generic argument" {
359 const S = struct {359 const S = struct {
360 const E = std.meta.FieldEnum(struct {360 const E = std.meta.FieldEnum(struct {
361 prev_pos: bool,361 prev_pos: bool,
test/behavior/cast.zig+8-3
...@@ -2446,9 +2446,14 @@ test "peer type resolution: pointer attributes are combined correctly" {...@@ -2446,9 +2446,14 @@ test "peer type resolution: pointer attributes are combined correctly" {
2446 };2446 };
24472447
2448 const NonAllowZero = comptime blk: {2448 const NonAllowZero = comptime blk: {
2449 var ti = @typeInfo(@TypeOf(r1, r2, r3, r4));2449 const ptr = @typeInfo(@TypeOf(r1, r2, r3, r4)).pointer;
2450 ti.pointer.is_allowzero = false;2450 break :blk @Pointer(ptr.size, .{
2451 break :blk @Type(ti);2451 .@"const" = ptr.is_const,
2452 .@"volatile" = ptr.is_volatile,
2453 .@"allowzero" = false,
2454 .@"align" = ptr.alignment,
2455 .@"addrspace" = ptr.address_space,
2456 }, ptr.child, ptr.sentinel());
2452 };2457 };
2453 try expectEqualSlices(u8, std.mem.span(@volatileCast(@as(NonAllowZero, @ptrCast(r1)))), "foo");2458 try expectEqualSlices(u8, std.mem.span(@volatileCast(@as(NonAllowZero, @ptrCast(r1)))), "foo");
2454 try expectEqualSlices(u8, std.mem.span(@volatileCast(@as(NonAllowZero, @ptrCast(r2)))), "bar");2459 try expectEqualSlices(u8, std.mem.span(@volatileCast(@as(NonAllowZero, @ptrCast(r2)))), "bar");
test/behavior/enum.zig+1-4
...@@ -1283,10 +1283,7 @@ test "Non-exhaustive enum backed by comptime_int" {...@@ -1283,10 +1283,7 @@ test "Non-exhaustive enum backed by comptime_int" {
1283test "matching captures causes enum equivalence" {1283test "matching captures causes enum equivalence" {
1284 const S = struct {1284 const S = struct {
1285 fn Nonexhaustive(comptime I: type) type {1285 fn Nonexhaustive(comptime I: type) type {
1286 const UTag = @Type(.{ .int = .{1286 const UTag = @Int(.unsigned, @typeInfo(I).int.bits);
1287 .signedness = .unsigned,
1288 .bits = @typeInfo(I).int.bits,
1289 } });
1290 return enum(UTag) { _ };1287 return enum(UTag) { _ };
1291 }1288 }
1292 };1289 };
test/behavior/fn.zig+2-2
...@@ -556,10 +556,10 @@ test "lazy values passed to anytype parameter" {...@@ -556,10 +556,10 @@ test "lazy values passed to anytype parameter" {
556556
557test "pass and return comptime-only types" {557test "pass and return comptime-only types" {
558 const S = struct {558 const S = struct {
559 fn returnNull(comptime x: @Type(.null)) @Type(.null) {559 fn returnNull(comptime x: @TypeOf(null)) @TypeOf(null) {
560 return x;560 return x;
561 }561 }
562 fn returnUndefined(comptime x: @Type(.undefined)) @Type(.undefined) {562 fn returnUndefined(comptime x: @TypeOf(undefined)) @TypeOf(undefined) {
563 return x;563 return x;
564 }564 }
565 };565 };
test/behavior/generics.zig+1-9
...@@ -263,15 +263,7 @@ test "generic function instantiation turns into comptime call" {...@@ -263,15 +263,7 @@ test "generic function instantiation turns into comptime call" {
263263
264 pub fn FieldEnum(comptime T: type) type {264 pub fn FieldEnum(comptime T: type) type {
265 _ = T;265 _ = T;
266 var enumFields: [1]std.builtin.Type.EnumField = .{.{ .name = "A", .value = 0 }};266 return @Enum(u0, .exhaustive, &.{"A"}, &.{0});
267 return @Type(.{
268 .@"enum" = .{
269 .tag_type = u0,
270 .fields = &enumFields,
271 .decls = &.{},
272 .is_exhaustive = true,
273 },
274 });
275 }267 }
276 };268 };
277 try S.doTheTest();269 try S.doTheTest();
test/behavior/sizeof_and_typeof.zig+6-6
...@@ -338,14 +338,14 @@ test "peer type resolution with @TypeOf doesn't trigger dependency loop check" {...@@ -338,14 +338,14 @@ test "peer type resolution with @TypeOf doesn't trigger dependency loop check" {
338338
339test "@sizeOf reified union zero-size payload fields" {339test "@sizeOf reified union zero-size payload fields" {
340 comptime {340 comptime {
341 try std.testing.expect(0 == @sizeOf(@Type(@typeInfo(union {}))));341 try std.testing.expect(0 == @sizeOf(@Union(.auto, null, &.{}, &.{}, &.{})));
342 try std.testing.expect(0 == @sizeOf(@Type(@typeInfo(union { a: void }))));342 try std.testing.expect(0 == @sizeOf(@Union(.auto, null, &.{"a"}, &.{void}, &.{.{}})));
343 if (builtin.mode == .Debug or builtin.mode == .ReleaseSafe) {343 if (builtin.mode == .Debug or builtin.mode == .ReleaseSafe) {
344 try std.testing.expect(1 == @sizeOf(@Type(@typeInfo(union { a: void, b: void }))));344 try std.testing.expect(1 == @sizeOf(@Union(.auto, null, &.{ "a", "b" }, &.{ void, void }, &.{ .{}, .{} })));
345 try std.testing.expect(1 == @sizeOf(@Type(@typeInfo(union { a: void, b: void, c: void }))));345 try std.testing.expect(1 == @sizeOf(@Union(.auto, null, &.{ "a", "b", "c" }, &.{ void, void, void }, &.{ .{}, .{}, .{} })));
346 } else {346 } else {
347 try std.testing.expect(0 == @sizeOf(@Type(@typeInfo(union { a: void, b: void }))));347 try std.testing.expect(0 == @sizeOf(@Union(.auto, null, &.{ "a", "b" }, &.{ void, void }, &.{ .{}, .{} })));
348 try std.testing.expect(0 == @sizeOf(@Type(@typeInfo(union { a: void, b: void, c: void }))));348 try std.testing.expect(0 == @sizeOf(@Union(.auto, null, &.{ "a", "b", "c" }, &.{ void, void, void }, &.{ .{}, .{}, .{} })));
349 }349 }
350 }350 }
351}351}
test/behavior/struct.zig+1-4
...@@ -2034,10 +2034,7 @@ test "matching captures causes struct equivalence" {...@@ -2034,10 +2034,7 @@ test "matching captures causes struct equivalence" {
2034 fn UnsignedWrapper(comptime I: type) type {2034 fn UnsignedWrapper(comptime I: type) type {
2035 const bits = @typeInfo(I).int.bits;2035 const bits = @typeInfo(I).int.bits;
2036 return struct {2036 return struct {
2037 x: @Type(.{ .int = .{2037 x: @Int(.unsigned, bits),
2038 .signedness = .unsigned,
2039 .bits = bits,
2040 } }),
2041 };2038 };
2042 }2039 }
2043 };2040 };
test/behavior/switch.zig+4-2
...@@ -843,7 +843,8 @@ test "switch capture peer type resolution for in-memory coercible payloads" {...@@ -843,7 +843,8 @@ test "switch capture peer type resolution for in-memory coercible payloads" {
843 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;843 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
844844
845 const T1 = c_int;845 const T1 = c_int;
846 const T2 = @Type(@typeInfo(T1));846 const t1_info = @typeInfo(T1).int;
847 const T2 = @Int(t1_info.signedness, t1_info.bits);
847848
848 comptime assert(T1 != T2);849 comptime assert(T1 != T2);
849850
...@@ -865,7 +866,8 @@ test "switch pointer capture peer type resolution" {...@@ -865,7 +866,8 @@ test "switch pointer capture peer type resolution" {
865 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;866 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
866867
867 const T1 = c_int;868 const T1 = c_int;
868 const T2 = @Type(@typeInfo(T1));869 const t1_info = @typeInfo(T1).int;
870 const T2 = @Int(t1_info.signedness, t1_info.bits);
869871
870 comptime assert(T1 != T2);872 comptime assert(T1 != T2);
871873
test/behavior/switch_loop.zig+1-4
...@@ -230,10 +230,7 @@ test "switch loop on larger than pointer integer" {...@@ -230,10 +230,7 @@ test "switch loop on larger than pointer integer" {
230 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;230 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
231 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;231 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
232232
233 var entry: @Type(.{ .int = .{233 var entry: @Int(.unsigned, @bitSizeOf(usize) + 1) = undefined;
234 .signedness = .unsigned,
235 .bits = @bitSizeOf(usize) + 1,
236 } }) = undefined;
237 entry = 0;234 entry = 0;
238 loop: switch (entry) {235 loop: switch (entry) {
239 0 => {236 0 => {
test/behavior/tuple.zig+4-55
...@@ -130,29 +130,7 @@ test "array-like initializer for tuple types" {...@@ -130,29 +130,7 @@ test "array-like initializer for tuple types" {
130 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO130 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
131 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;131 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
132132
133 const T = @Type(.{133 const T = @Tuple(&.{ i32, u8 });
134 .@"struct" = .{
135 .is_tuple = true,
136 .layout = .auto,
137 .decls = &.{},
138 .fields = &.{
139 .{
140 .name = "0",
141 .type = i32,
142 .default_value_ptr = null,
143 .is_comptime = false,
144 .alignment = @alignOf(i32),
145 },
146 .{
147 .name = "1",
148 .type = u8,
149 .default_value_ptr = null,
150 .is_comptime = false,
151 .alignment = @alignOf(u8),
152 },
153 },
154 },
155 });
156 const S = struct {134 const S = struct {
157 fn doTheTest() !void {135 fn doTheTest() !void {
158 var obj: T = .{ -1234, 128 };136 var obj: T = .{ -1234, 128 };
...@@ -320,20 +298,7 @@ test "zero sized struct in tuple handled correctly" {...@@ -320,20 +298,7 @@ test "zero sized struct in tuple handled correctly" {
320 const Self = @This();298 const Self = @This();
321 const Inner = struct {};299 const Inner = struct {};
322300
323 data: @Type(.{301 data: @Tuple(&.{Inner}),
324 .@"struct" = .{
325 .is_tuple = true,
326 .layout = .auto,
327 .decls = &.{},
328 .fields = &.{.{
329 .name = "0",
330 .type = Inner,
331 .default_value_ptr = null,
332 .is_comptime = false,
333 .alignment = @alignOf(Inner),
334 }},
335 },
336 }),
337302
338 pub fn do(this: Self) usize {303 pub fn do(this: Self) usize {
339 return @sizeOf(@TypeOf(this));304 return @sizeOf(@TypeOf(this));
...@@ -470,12 +435,7 @@ test "coerce anon tuple to tuple" {...@@ -470,12 +435,7 @@ test "coerce anon tuple to tuple" {
470}435}
471436
472test "empty tuple type" {437test "empty tuple type" {
473 const S = @Type(.{ .@"struct" = .{438 const S = @Tuple(&.{});
474 .layout = .auto,
475 .fields = &.{},
476 .decls = &.{},
477 .is_tuple = true,
478 } });
479439
480 const s: S = .{};440 const s: S = .{};
481 try expect(s.len == 0);441 try expect(s.len == 0);
...@@ -616,18 +576,7 @@ test "OPV tuple fields aren't comptime" {...@@ -616,18 +576,7 @@ test "OPV tuple fields aren't comptime" {
616 const t_info = @typeInfo(T);576 const t_info = @typeInfo(T);
617 try expect(!t_info.@"struct".fields[0].is_comptime);577 try expect(!t_info.@"struct".fields[0].is_comptime);
618578
619 const T2 = @Type(.{ .@"struct" = .{579 const T2 = @Tuple(&.{void});
620 .layout = .auto,
621 .fields = &.{.{
622 .name = "0",
623 .type = void,
624 .default_value_ptr = null,
625 .is_comptime = false,
626 .alignment = @alignOf(void),
627 }},
628 .decls = &.{},
629 .is_tuple = true,
630 } });
631 const t2_info = @typeInfo(T2);580 const t2_info = @typeInfo(T2);
632 try expect(!t2_info.@"struct".fields[0].is_comptime);581 try expect(!t2_info.@"struct".fields[0].is_comptime);
633}582}
test/behavior/type.zig+93-477
...@@ -4,63 +4,17 @@ const Type = std.builtin.Type;...@@ -4,63 +4,17 @@ const Type = std.builtin.Type;
4const testing = std.testing;4const testing = std.testing;
5const assert = std.debug.assert;5const assert = std.debug.assert;
66
7fn testTypes(comptime types: []const type) !void {
8 inline for (types) |testType| {
9 try testing.expect(testType == @Type(@typeInfo(testType)));
10 }
11}
12
13test "Type.MetaType" {
14 try testing.expect(type == @Type(.{ .type = {} }));
15 try testTypes(&[_]type{type});
16}
17
18test "Type.Void" {
19 try testing.expect(void == @Type(.{ .void = {} }));
20 try testTypes(&[_]type{void});
21}
22
23test "Type.Bool" {
24 try testing.expect(bool == @Type(.{ .bool = {} }));
25 try testTypes(&[_]type{bool});
26}
27
28test "Type.NoReturn" {
29 try testing.expect(noreturn == @Type(.{ .noreturn = {} }));
30 try testTypes(&[_]type{noreturn});
31}
32
33test "Type.Int" {7test "Type.Int" {
34 try testing.expect(u1 == @Type(.{ .int = .{ .signedness = .unsigned, .bits = 1 } }));8 try testing.expect(u1 == @Int(.unsigned, 1));
35 try testing.expect(i1 == @Type(.{ .int = .{ .signedness = .signed, .bits = 1 } }));9 try testing.expect(i1 == @Int(.signed, 1));
36 try testing.expect(u8 == @Type(.{ .int = .{ .signedness = .unsigned, .bits = 8 } }));10 try testing.expect(u8 == @Int(.unsigned, 8));
37 try testing.expect(i8 == @Type(.{ .int = .{ .signedness = .signed, .bits = 8 } }));11 try testing.expect(i8 == @Int(.signed, 8));
38 try testing.expect(u64 == @Type(.{ .int = .{ .signedness = .unsigned, .bits = 64 } }));12 try testing.expect(u64 == @Int(.unsigned, 64));
39 try testing.expect(i64 == @Type(.{ .int = .{ .signedness = .signed, .bits = 64 } }));13 try testing.expect(i64 == @Int(.signed, 64));
40 try testTypes(&[_]type{ u8, u32, i64 });
41}
42
43test "Type.ComptimeFloat" {
44 try testTypes(&[_]type{comptime_float});
45}
46test "Type.ComptimeInt" {
47 try testTypes(&[_]type{comptime_int});
48}
49test "Type.Undefined" {
50 try testTypes(&[_]type{@TypeOf(undefined)});
51}
52test "Type.Null" {
53 try testTypes(&[_]type{@TypeOf(null)});
54}
55
56test "Type.EnumLiteral" {
57 try testTypes(&[_]type{
58 @TypeOf(.Dummy),
59 });
60}14}
6115
62test "Type.Pointer" {16test "Type.Pointer" {
63 try testTypes(&[_]type{17 inline for (&[_]type{
64 // One Value Pointer Types18 // One Value Pointer Types
65 *u8, *const u8,19 *u8, *const u8,
66 *volatile u8, *const volatile u8,20 *volatile u8, *const volatile u8,
...@@ -101,62 +55,30 @@ test "Type.Pointer" {...@@ -101,62 +55,30 @@ test "Type.Pointer" {
101 [*c]align(4) volatile u8, [*c]align(4) const volatile u8,55 [*c]align(4) volatile u8, [*c]align(4) const volatile u8,
102 [*c]align(8) u8, [*c]align(8) const u8,56 [*c]align(8) u8, [*c]align(8) const u8,
103 [*c]align(8) volatile u8, [*c]align(8) const volatile u8,57 [*c]align(8) volatile u8, [*c]align(8) const volatile u8,
104 });58 }) |testType| {
59 const ptr = @typeInfo(testType).pointer;
60 try testing.expect(testType == @Pointer(ptr.size, .{
61 .@"const" = ptr.is_const,
62 .@"volatile" = ptr.is_volatile,
63 .@"allowzero" = ptr.is_allowzero,
64 .@"align" = ptr.alignment,
65 .@"addrspace" = ptr.address_space,
66 }, ptr.child, ptr.sentinel()));
67 }
105}68}
10669
107test "Type.Float" {70test "@Pointer create slice without sentinel" {
108 try testing.expect(f16 == @Type(.{ .float = .{ .bits = 16 } }));71 const Slice = @Pointer(.slice, .{ .@"const" = true, .@"align" = 8 }, ?*i32, null);
109 try testing.expect(f32 == @Type(.{ .float = .{ .bits = 32 } }));72 try testing.expect(Slice == []align(8) const ?*i32);
110 try testing.expect(f64 == @Type(.{ .float = .{ .bits = 64 } }));
111 try testing.expect(f80 == @Type(.{ .float = .{ .bits = 80 } }));
112 try testing.expect(f128 == @Type(.{ .float = .{ .bits = 128 } }));
113 try testTypes(&[_]type{ f16, f32, f64, f80, f128 });
114}73}
11574
116test "Type.Array" {75test "@Pointer create slice with null sentinel" {
117 try testing.expect([123]u8 == @Type(.{76 const Slice = @Pointer(.slice, .{ .@"const" = true, .@"align" = 8 }, ?*i32, @as(?*i32, null));
118 .array = .{77 try testing.expect(Slice == [:null]align(8) const ?*i32);
119 .len = 123,
120 .child = u8,
121 .sentinel_ptr = null,
122 },
123 }));
124 try testing.expect([2]u32 == @Type(.{
125 .array = .{
126 .len = 2,
127 .child = u32,
128 .sentinel_ptr = null,
129 },
130 }));
131 try testing.expect([2:0]u32 == @Type(.{
132 .array = .{
133 .len = 2,
134 .child = u32,
135 .sentinel_ptr = &@as(u32, 0),
136 },
137 }));
138 try testTypes(&[_]type{ [1]u8, [30]usize, [7]bool });
139}78}
14079
141test "@Type create slice with null sentinel" {80test "@Pointer on @typeInfo round-trips sentinels" {
142 const Slice = @Type(.{81 inline for (&[_]type{
143 .pointer = .{
144 .size = .slice,
145 .is_const = true,
146 .is_volatile = false,
147 .is_allowzero = false,
148 .alignment = 8,
149 .address_space = .generic,
150 .child = *i32,
151 .sentinel_ptr = null,
152 },
153 });
154 try testing.expect(Slice == []align(8) const *i32);
155}
156
157test "@Type picks up the sentinel value from Type" {
158 try testTypes(&[_]type{
159 [11:0]u8, [4:10]u8,
160 [*:0]u8, [*:0]const u8,82 [*:0]u8, [*:0]const u8,
161 [*:0]volatile u8, [*:0]const volatile u8,83 [*:0]volatile u8, [*:0]const volatile u8,
162 [*:0]align(4) u8, [*:0]align(4) const u8,84 [*:0]align(4) u8, [*:0]align(4) const u8,
...@@ -179,24 +101,16 @@ test "@Type picks up the sentinel value from Type" {...@@ -179,24 +101,16 @@ test "@Type picks up the sentinel value from Type" {
179 [:0]allowzero align(4) u8, [:0]allowzero align(4) const u8,101 [:0]allowzero align(4) u8, [:0]allowzero align(4) const u8,
180 [:0]allowzero align(4) volatile u8, [:0]allowzero align(4) const volatile u8,102 [:0]allowzero align(4) volatile u8, [:0]allowzero align(4) const volatile u8,
181 [:4]allowzero align(4) volatile u8, [:4]allowzero align(4) const volatile u8,103 [:4]allowzero align(4) volatile u8, [:4]allowzero align(4) const volatile u8,
182 });104 }) |TestType| {
183}105 const ptr = @typeInfo(TestType).pointer;
184106 try testing.expect(TestType == @Pointer(ptr.size, .{
185test "Type.Optional" {107 .@"const" = ptr.is_const,
186 try testTypes(&[_]type{108 .@"volatile" = ptr.is_volatile,
187 ?u8,109 .@"allowzero" = ptr.is_allowzero,
188 ?*u8,110 .@"align" = ptr.alignment,
189 ?[]u8,111 .@"addrspace" = ptr.address_space,
190 ?[*]u8,112 }, ptr.child, ptr.sentinel()));
191 ?[*c]u8,113 }
192 });
193}
194
195test "Type.ErrorUnion" {
196 try testTypes(&[_]type{
197 error{}!void,
198 error{Error}!void,
199 });
200}114}
201115
202test "Type.Opaque" {116test "Type.Opaque" {
...@@ -205,11 +119,7 @@ test "Type.Opaque" {...@@ -205,11 +119,7 @@ test "Type.Opaque" {
205 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO119 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
206 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;120 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
207121
208 const Opaque = @Type(.{122 const Opaque = opaque {};
209 .@"opaque" = .{
210 .decls = &.{},
211 },
212 });
213 try testing.expect(Opaque != opaque {});123 try testing.expect(Opaque != opaque {});
214 try testing.expectEqualSlices(124 try testing.expectEqualSlices(
215 Type.Declaration,125 Type.Declaration,
...@@ -218,52 +128,17 @@ test "Type.Opaque" {...@@ -218,52 +128,17 @@ test "Type.Opaque" {
218 );128 );
219}129}
220130
221test "Type.Vector" {
222 try testTypes(&[_]type{
223 @Vector(0, u8),
224 @Vector(4, u8),
225 @Vector(8, *u8),
226 @Vector(0, u8),
227 @Vector(4, u8),
228 @Vector(8, *u8),
229 });
230}
231
232test "Type.AnyFrame" {
233 if (true) {
234 // https://github.com/ziglang/zig/issues/6025
235 return error.SkipZigTest;
236 }
237
238 try testTypes(&[_]type{
239 anyframe,
240 anyframe->u8,
241 anyframe->anyframe->u8,
242 });
243}
244
245fn add(a: i32, b: i32) i32 {131fn add(a: i32, b: i32) i32 {
246 return a + b;132 return a + b;
247}133}
248134
249test "Type.ErrorSet" {
250 try testing.expect(@Type(.{ .error_set = null }) == anyerror);
251
252 // error sets don't compare equal so just check if they compile
253 inline for (.{ error{}, error{A}, error{ A, B, C } }) |T| {
254 const info = @typeInfo(T);
255 const T2 = @Type(info);
256 try testing.expect(T == T2);
257 }
258}
259
260test "Type.Struct" {135test "Type.Struct" {
261 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;136 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
262 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO137 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
263 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO138 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
264 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;139 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
265140
266 const A = @Type(@typeInfo(struct { x: u8, y: u32 }));141 const A = @Struct(.auto, null, &.{ "x", "y" }, &.{ u8, u32 }, &@splat(.{}));
267 const infoA = @typeInfo(A).@"struct";142 const infoA = @typeInfo(A).@"struct";
268 try testing.expectEqual(Type.ContainerLayout.auto, infoA.layout);143 try testing.expectEqual(Type.ContainerLayout.auto, infoA.layout);
269 try testing.expectEqualSlices(u8, "x", infoA.fields[0].name);144 try testing.expectEqualSlices(u8, "x", infoA.fields[0].name);
...@@ -281,7 +156,13 @@ test "Type.Struct" {...@@ -281,7 +156,13 @@ test "Type.Struct" {
281 a.y += 1;156 a.y += 1;
282 try testing.expectEqual(@as(u32, 2), a.y);157 try testing.expectEqual(@as(u32, 2), a.y);
283158
284 const B = @Type(@typeInfo(extern struct { x: u8, y: u32 = 5 }));159 const B = @Struct(
160 .@"extern",
161 null,
162 &.{ "x", "y" },
163 &.{ u8, u32 },
164 &.{ .{}, .{ .default_value_ptr = &@as(u32, 5) } },
165 );
285 const infoB = @typeInfo(B).@"struct";166 const infoB = @typeInfo(B).@"struct";
286 try testing.expectEqual(Type.ContainerLayout.@"extern", infoB.layout);167 try testing.expectEqual(Type.ContainerLayout.@"extern", infoB.layout);
287 try testing.expectEqualSlices(u8, "x", infoB.fields[0].name);168 try testing.expectEqualSlices(u8, "x", infoB.fields[0].name);
...@@ -293,7 +174,16 @@ test "Type.Struct" {...@@ -293,7 +174,16 @@ test "Type.Struct" {
293 try testing.expectEqual(@as(usize, 0), infoB.decls.len);174 try testing.expectEqual(@as(usize, 0), infoB.decls.len);
294 try testing.expectEqual(@as(bool, false), infoB.is_tuple);175 try testing.expectEqual(@as(bool, false), infoB.is_tuple);
295176
296 const C = @Type(@typeInfo(packed struct { x: u8 = 3, y: u32 = 5 }));177 const C = @Struct(
178 .@"packed",
179 null,
180 &.{ "x", "y" },
181 &.{ u8, u32 },
182 &.{
183 .{ .default_value_ptr = &@as(u8, 3) },
184 .{ .default_value_ptr = &@as(u32, 5) },
185 },
186 );
297 const infoC = @typeInfo(C).@"struct";187 const infoC = @typeInfo(C).@"struct";
298 try testing.expectEqual(Type.ContainerLayout.@"packed", infoC.layout);188 try testing.expectEqual(Type.ContainerLayout.@"packed", infoC.layout);
299 try testing.expectEqualSlices(u8, "x", infoC.fields[0].name);189 try testing.expectEqualSlices(u8, "x", infoC.fields[0].name);
...@@ -305,76 +195,23 @@ test "Type.Struct" {...@@ -305,76 +195,23 @@ test "Type.Struct" {
305 try testing.expectEqual(@as(usize, 0), infoC.decls.len);195 try testing.expectEqual(@as(usize, 0), infoC.decls.len);
306 try testing.expectEqual(@as(bool, false), infoC.is_tuple);196 try testing.expectEqual(@as(bool, false), infoC.is_tuple);
307197
308 // anon structs
309 const D = @Type(@typeInfo(@TypeOf(.{ .x = 3, .y = 5 })));
310 const infoD = @typeInfo(D).@"struct";
311 try testing.expectEqual(Type.ContainerLayout.auto, infoD.layout);
312 try testing.expectEqualSlices(u8, "x", infoD.fields[0].name);
313 try testing.expectEqual(comptime_int, infoD.fields[0].type);
314 try testing.expectEqual(@as(comptime_int, 3), infoD.fields[0].defaultValue().?);
315 try testing.expectEqualSlices(u8, "y", infoD.fields[1].name);
316 try testing.expectEqual(comptime_int, infoD.fields[1].type);
317 try testing.expectEqual(@as(comptime_int, 5), infoD.fields[1].defaultValue().?);
318 try testing.expectEqual(@as(usize, 0), infoD.decls.len);
319 try testing.expectEqual(@as(bool, false), infoD.is_tuple);
320
321 // tuples
322 const E = @Type(@typeInfo(@TypeOf(.{ 1, 2 })));
323 const infoE = @typeInfo(E).@"struct";
324 try testing.expectEqual(Type.ContainerLayout.auto, infoE.layout);
325 try testing.expectEqualSlices(u8, "0", infoE.fields[0].name);
326 try testing.expectEqual(comptime_int, infoE.fields[0].type);
327 try testing.expectEqual(@as(comptime_int, 1), infoE.fields[0].defaultValue().?);
328 try testing.expectEqualSlices(u8, "1", infoE.fields[1].name);
329 try testing.expectEqual(comptime_int, infoE.fields[1].type);
330 try testing.expectEqual(@as(comptime_int, 2), infoE.fields[1].defaultValue().?);
331 try testing.expectEqual(@as(usize, 0), infoE.decls.len);
332 try testing.expectEqual(@as(bool, true), infoE.is_tuple);
333
334 // empty struct198 // empty struct
335 const F = @Type(@typeInfo(struct {}));199 const F = @Struct(.auto, null, &.{}, &.{}, &.{});
336 const infoF = @typeInfo(F).@"struct";200 const infoF = @typeInfo(F).@"struct";
337 try testing.expectEqual(Type.ContainerLayout.auto, infoF.layout);201 try testing.expectEqual(Type.ContainerLayout.auto, infoF.layout);
338 try testing.expect(infoF.fields.len == 0);202 try testing.expect(infoF.fields.len == 0);
339 try testing.expectEqual(@as(bool, false), infoF.is_tuple);203 try testing.expectEqual(@as(bool, false), infoF.is_tuple);
340
341 // empty tuple
342 const G = @Type(@typeInfo(@TypeOf(.{})));
343 const infoG = @typeInfo(G).@"struct";
344 try testing.expectEqual(Type.ContainerLayout.auto, infoG.layout);
345 try testing.expect(infoG.fields.len == 0);
346 try testing.expectEqual(@as(bool, true), infoG.is_tuple);
347}204}
348205
349test "Type.Enum" {206test "Type.Enum" {
350 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO207 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
351 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;208 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
352209
353 const Foo = @Type(.{210 const Foo = @Enum(u8, .exhaustive, &.{ "a", "b" }, &.{ 1, 5 });
354 .@"enum" = .{
355 .tag_type = u8,
356 .fields = &.{
357 .{ .name = "a", .value = 1 },
358 .{ .name = "b", .value = 5 },
359 },
360 .decls = &.{},
361 .is_exhaustive = true,
362 },
363 });
364 try testing.expectEqual(true, @typeInfo(Foo).@"enum".is_exhaustive);211 try testing.expectEqual(true, @typeInfo(Foo).@"enum".is_exhaustive);
365 try testing.expectEqual(@as(u8, 1), @intFromEnum(Foo.a));212 try testing.expectEqual(@as(u8, 1), @intFromEnum(Foo.a));
366 try testing.expectEqual(@as(u8, 5), @intFromEnum(Foo.b));213 try testing.expectEqual(@as(u8, 5), @intFromEnum(Foo.b));
367 const Bar = @Type(.{214 const Bar = @Enum(u32, .nonexhaustive, &.{ "a", "b" }, &.{ 1, 5 });
368 .@"enum" = .{
369 .tag_type = u32,
370 .fields = &.{
371 .{ .name = "a", .value = 1 },
372 .{ .name = "b", .value = 5 },
373 },
374 .decls = &.{},
375 .is_exhaustive = false,
376 },
377 });
378 try testing.expectEqual(false, @typeInfo(Bar).@"enum".is_exhaustive);215 try testing.expectEqual(false, @typeInfo(Bar).@"enum".is_exhaustive);
379 try testing.expectEqual(@as(u32, 1), @intFromEnum(Bar.a));216 try testing.expectEqual(@as(u32, 1), @intFromEnum(Bar.a));
380 try testing.expectEqual(@as(u32, 5), @intFromEnum(Bar.b));217 try testing.expectEqual(@as(u32, 5), @intFromEnum(Bar.b));
...@@ -382,12 +219,7 @@ test "Type.Enum" {...@@ -382,12 +219,7 @@ test "Type.Enum" {
382219
383 { // from https://github.com/ziglang/zig/issues/19985220 { // from https://github.com/ziglang/zig/issues/19985
384 { // enum with single field can be initialized.221 { // enum with single field can be initialized.
385 const E = @Type(.{ .@"enum" = .{222 const E = @Enum(u0, .exhaustive, &.{"foo"}, &.{0});
386 .tag_type = u0,
387 .is_exhaustive = true,
388 .fields = &.{.{ .name = "foo", .value = 0 }},
389 .decls = &.{},
390 } });
391 const s: struct { E } = .{.foo};223 const s: struct { E } = .{.foo};
392 try testing.expectEqual(.foo, s[0]);224 try testing.expectEqual(.foo, s[0]);
393 }225 }
...@@ -411,60 +243,20 @@ test "Type.Union" {...@@ -411,60 +243,20 @@ test "Type.Union" {
411 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO243 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
412 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;244 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
413245
414 const Untagged = @Type(.{246 const Untagged = @Union(.@"extern", null, &.{ "int", "float" }, &.{ i32, f32 }, &.{ .{}, .{} });
415 .@"union" = .{
416 .layout = .@"extern",
417 .tag_type = null,
418 .fields = &.{
419 .{ .name = "int", .type = i32, .alignment = @alignOf(f32) },
420 .{ .name = "float", .type = f32, .alignment = @alignOf(f32) },
421 },
422 .decls = &.{},
423 },
424 });
425 var untagged = Untagged{ .int = 1 };247 var untagged = Untagged{ .int = 1 };
426 untagged.float = 2.0;248 untagged.float = 2.0;
427 untagged.int = 3;249 untagged.int = 3;
428 try testing.expectEqual(@as(i32, 3), untagged.int);250 try testing.expectEqual(@as(i32, 3), untagged.int);
429251
430 const PackedUntagged = @Type(.{252 const PackedUntagged = @Union(.@"packed", null, &.{ "signed", "unsigned" }, &.{ i32, u32 }, &.{ .{}, .{} });
431 .@"union" = .{
432 .layout = .@"packed",
433 .tag_type = null,
434 .fields = &.{
435 .{ .name = "signed", .type = i32, .alignment = 0 },
436 .{ .name = "unsigned", .type = u32, .alignment = 0 },
437 },
438 .decls = &.{},
439 },
440 });
441 var packed_untagged: PackedUntagged = .{ .signed = -1 };253 var packed_untagged: PackedUntagged = .{ .signed = -1 };
442 _ = &packed_untagged;254 _ = &packed_untagged;
443 try testing.expectEqual(@as(i32, -1), packed_untagged.signed);255 try testing.expectEqual(@as(i32, -1), packed_untagged.signed);
444 try testing.expectEqual(~@as(u32, 0), packed_untagged.unsigned);256 try testing.expectEqual(~@as(u32, 0), packed_untagged.unsigned);
445257
446 const Tag = @Type(.{258 const Tag = @Enum(u1, .exhaustive, &.{ "signed", "unsigned" }, &.{ 0, 1 });
447 .@"enum" = .{259 const Tagged = @Union(.auto, Tag, &.{ "signed", "unsigned" }, &.{ i32, u32 }, &.{ .{}, .{} });
448 .tag_type = u1,
449 .fields = &.{
450 .{ .name = "signed", .value = 0 },
451 .{ .name = "unsigned", .value = 1 },
452 },
453 .decls = &.{},
454 .is_exhaustive = true,
455 },
456 });
457 const Tagged = @Type(.{
458 .@"union" = .{
459 .layout = .auto,
460 .tag_type = Tag,
461 .fields = &.{
462 .{ .name = "signed", .type = i32, .alignment = @alignOf(i32) },
463 .{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) },
464 },
465 .decls = &.{},
466 },
467 });
468 var tagged = Tagged{ .signed = -1 };260 var tagged = Tagged{ .signed = -1 };
469 try testing.expectEqual(Tag.signed, @as(Tag, tagged));261 try testing.expectEqual(Tag.signed, @as(Tag, tagged));
470 tagged = .{ .unsigned = 1 };262 tagged = .{ .unsigned = 1 };
...@@ -472,74 +264,26 @@ test "Type.Union" {...@@ -472,74 +264,26 @@ test "Type.Union" {
472}264}
473265
474test "Type.Union from Type.Enum" {266test "Type.Union from Type.Enum" {
475 const Tag = @Type(.{267 const Tag = @Enum(u0, .exhaustive, &.{"working_as_expected"}, &.{0});
476 .@"enum" = .{268 const T = @Union(.auto, Tag, &.{"working_as_expected"}, &.{u32}, &.{.{}});
477 .tag_type = u0,
478 .fields = &.{
479 .{ .name = "working_as_expected", .value = 0 },
480 },
481 .decls = &.{},
482 .is_exhaustive = true,
483 },
484 });
485 const T = @Type(.{
486 .@"union" = .{
487 .layout = .auto,
488 .tag_type = Tag,
489 .fields = &.{
490 .{ .name = "working_as_expected", .type = u32, .alignment = @alignOf(u32) },
491 },
492 .decls = &.{},
493 },
494 });
495 _ = @typeInfo(T).@"union";269 _ = @typeInfo(T).@"union";
496}270}
497271
498test "Type.Union from regular enum" {272test "Type.Union from regular enum" {
499 const E = enum { working_as_expected };273 const E = enum { working_as_expected };
500 const T = @Type(.{274 const T = @Union(.auto, E, &.{"working_as_expected"}, &.{u32}, &.{.{}});
501 .@"union" = .{
502 .layout = .auto,
503 .tag_type = E,
504 .fields = &.{
505 .{ .name = "working_as_expected", .type = u32, .alignment = @alignOf(u32) },
506 },
507 .decls = &.{},
508 },
509 });
510 _ = @typeInfo(T).@"union";275 _ = @typeInfo(T).@"union";
511}276}
512277
513test "Type.Union from empty regular enum" {278test "Type.Union from empty regular enum" {
514 const E = enum {};279 const E = enum {};
515 const U = @Type(.{280 const U = @Union(.auto, E, &.{}, &.{}, &.{});
516 .@"union" = .{
517 .layout = .auto,
518 .tag_type = E,
519 .fields = &.{},
520 .decls = &.{},
521 },
522 });
523 try testing.expectEqual(@sizeOf(U), 0);281 try testing.expectEqual(@sizeOf(U), 0);
524}282}
525283
526test "Type.Union from empty Type.Enum" {284test "Type.Union from empty Type.Enum" {
527 const E = @Type(.{285 const E = @Enum(u0, .exhaustive, &.{}, &.{});
528 .@"enum" = .{286 const U = @Union(.auto, E, &.{}, &.{}, &.{});
529 .tag_type = u0,
530 .fields = &.{},
531 .decls = &.{},
532 .is_exhaustive = true,
533 },
534 });
535 const U = @Type(.{
536 .@"union" = .{
537 .layout = .auto,
538 .tag_type = E,
539 .fields = &.{},
540 .decls = &.{},
541 },
542 });
543 try testing.expectEqual(@sizeOf(U), 0);287 try testing.expectEqual(@sizeOf(U), 0);
544}288}
545289
...@@ -548,47 +292,22 @@ test "Type.Fn" {...@@ -548,47 +292,22 @@ test "Type.Fn" {
548292
549 const some_opaque = opaque {};293 const some_opaque = opaque {};
550 const some_ptr = *some_opaque;294 const some_ptr = *some_opaque;
551 const T = fn (c_int, some_ptr) callconv(.c) void;
552
553 {
554 const fn_info = std.builtin.Type{ .@"fn" = .{
555 .calling_convention = .c,
556 .is_generic = false,
557 .is_var_args = false,
558 .return_type = void,
559 .params = &.{
560 .{ .is_generic = false, .is_noalias = false, .type = c_int },
561 .{ .is_generic = false, .is_noalias = false, .type = some_ptr },
562 },
563 } };
564
565 const fn_type = @Type(fn_info);
566 try std.testing.expectEqual(T, fn_type);
567 }
568295
569 {296 const A = @Fn(&.{ c_int, some_ptr }, &@splat(.{}), void, .{ .@"callconv" = .c });
570 const fn_info = @typeInfo(T);297 comptime assert(A == fn (c_int, some_ptr) callconv(.c) void);
571 const fn_type = @Type(fn_info);298
572 try std.testing.expectEqual(T, fn_type);299 const B = @Fn(&.{ c_int, some_ptr, u32 }, &.{ .{}, .{ .@"noalias" = true }, .{} }, u64, .{});
573 }300 comptime assert(B == fn (c_int, noalias some_ptr, u32) u64);
301
302 const C = @Fn(&.{?[*]u8}, &.{.{}}, *const anyopaque, .{ .@"callconv" = .c, .varargs = true });
303 comptime assert(C == fn (?[*]u8, ...) callconv(.c) *const anyopaque);
574}304}
575305
576test "reified struct field name from optional payload" {306test "reified struct field name from optional payload" {
577 comptime {307 comptime {
578 const m_name: ?[1:0]u8 = "a".*;308 const m_name: ?[1:0]u8 = "a".*;
579 if (m_name) |*name| {309 if (m_name) |*name| {
580 const T = @Type(.{ .@"struct" = .{310 const T = @Struct(.auto, null, &.{name}, &.{u8}, &.{.{}});
581 .layout = .auto,
582 .fields = &.{.{
583 .name = name,
584 .type = u8,
585 .default_value_ptr = null,
586 .is_comptime = false,
587 .alignment = 1,
588 }},
589 .decls = &.{},
590 .is_tuple = false,
591 } });
592 const t: T = .{ .a = 123 };311 const t: T = .{ .a = 123 };
593 try std.testing.expect(t.a == 123);312 try std.testing.expect(t.a == 123);
594 }313 }
...@@ -598,20 +317,7 @@ test "reified struct field name from optional payload" {...@@ -598,20 +317,7 @@ test "reified struct field name from optional payload" {
598test "reified union uses @alignOf" {317test "reified union uses @alignOf" {
599 const S = struct {318 const S = struct {
600 fn CreateUnion(comptime T: type) type {319 fn CreateUnion(comptime T: type) type {
601 return @Type(.{320 return @Union(.auto, null, &.{"field"}, &.{T}, &.{.{}});
602 .@"union" = .{
603 .layout = .auto,
604 .tag_type = null,
605 .fields = &[_]std.builtin.Type.UnionField{
606 .{
607 .name = "field",
608 .type = T,
609 .alignment = @alignOf(T),
610 },
611 },
612 .decls = &.{},
613 },
614 });
615 }321 }
616 };322 };
617 _ = S.CreateUnion(struct {});323 _ = S.CreateUnion(struct {});
...@@ -620,22 +326,13 @@ test "reified union uses @alignOf" {...@@ -620,22 +326,13 @@ test "reified union uses @alignOf" {
620test "reified struct uses @alignOf" {326test "reified struct uses @alignOf" {
621 const S = struct {327 const S = struct {
622 fn NamespacedGlobals(comptime modules: anytype) type {328 fn NamespacedGlobals(comptime modules: anytype) type {
623 return @Type(.{329 return @Struct(
624 .@"struct" = .{330 .auto,
625 .layout = .auto,331 null,
626 .is_tuple = false,332 &.{"globals"},
627 .fields = &.{333 &.{modules.mach.globals},
628 .{334 &.{.{ .@"align" = @alignOf(modules.mach.globals) }},
629 .name = "globals",335 );
630 .type = modules.mach.globals,
631 .default_value_ptr = null,
632 .is_comptime = false,
633 .alignment = @alignOf(modules.mach.globals),
634 },
635 },
636 .decls = &.{},
637 },
638 });
639 }336 }
640 };337 };
641 _ = S.NamespacedGlobals(.{338 _ = S.NamespacedGlobals(.{
...@@ -645,56 +342,10 @@ test "reified struct uses @alignOf" {...@@ -645,56 +342,10 @@ test "reified struct uses @alignOf" {
645 });342 });
646}343}
647344
648test "reified error set initialized with field pointer" {
649 const S = struct {
650 const info = .{
651 .args = [_]Type.Error{
652 .{ .name = "bar" },
653 },
654 };
655 const Foo = @Type(.{
656 .error_set = &info.args,
657 });
658 };
659 try testing.expect(S.Foo == error{bar});
660}
661test "reified function type params initialized with field pointer" {
662 const S = struct {
663 const fn_info = .{
664 .params = [_]Type.Fn.Param{
665 .{ .is_generic = false, .is_noalias = false, .type = u8 },
666 },
667 };
668 const Bar = @Type(.{
669 .@"fn" = .{
670 .calling_convention = .auto,
671 .is_generic = false,
672 .is_var_args = false,
673 .return_type = void,
674 .params = &fn_info.params,
675 },
676 });
677 };
678 try testing.expect(@typeInfo(S.Bar) == .@"fn");
679}
680
681test "empty struct assigned to reified struct field" {345test "empty struct assigned to reified struct field" {
682 const S = struct {346 const S = struct {
683 fn NamespacedComponents(comptime modules: anytype) type {347 fn NamespacedComponents(comptime modules: anytype) type {
684 return @Type(.{348 return @Struct(.auto, null, &.{"components"}, &.{@TypeOf(modules.components)}, &.{.{}});
685 .@"struct" = .{
686 .layout = .auto,
687 .is_tuple = false,
688 .fields = &.{.{
689 .name = "components",
690 .type = @TypeOf(modules.components),
691 .default_value_ptr = null,
692 .is_comptime = false,
693 .alignment = @alignOf(@TypeOf(modules.components)),
694 }},
695 .decls = &.{},
696 },
697 });
698 }349 }
699350
700 fn namespacedComponents(comptime modules: anytype) NamespacedComponents(modules) {351 fn namespacedComponents(comptime modules: anytype) NamespacedComponents(modules) {
...@@ -710,16 +361,6 @@ test "empty struct assigned to reified struct field" {...@@ -710,16 +361,6 @@ test "empty struct assigned to reified struct field" {
710 });361 });
711}362}
712363
713test "@Type should resolve its children types" {
714 const sparse = enum(u2) { a, b, c };
715 const dense = enum(u2) { a, b, c, d };
716
717 comptime var sparse_info = @typeInfo(anyerror!sparse);
718 sparse_info.error_union.payload = dense;
719 const B = @Type(sparse_info);
720 try testing.expectEqual(anyerror!dense, B);
721}
722
723test "struct field names sliced at comptime from larger string" {364test "struct field names sliced at comptime from larger string" {
724 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO365 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
725366
...@@ -729,28 +370,14 @@ test "struct field names sliced at comptime from larger string" {...@@ -729,28 +370,14 @@ test "struct field names sliced at comptime from larger string" {
729 \\f3370 \\f3
730 ;371 ;
731 comptime {372 comptime {
732 var fields: []const Type.StructField = &[0]Type.StructField{};373 var field_names: []const []const u8 = &.{};
733374
734 var it = std.mem.tokenizeScalar(u8, text, '\n');375 var it = std.mem.tokenizeScalar(u8, text, '\n');
735 while (it.next()) |name| {376 while (it.next()) |name| {
736 fields = fields ++ &[_]Type.StructField{.{377 field_names = field_names ++ @as([]const []const u8, &.{name});
737 .alignment = @alignOf(usize),
738 .name = name ++ "",
739 .type = usize,
740 .default_value_ptr = null,
741 .is_comptime = false,
742 }};
743 }378 }
744379
745 const T = @Type(.{380 const T = @Struct(.auto, null, field_names, &@splat(usize), &@splat(.{}));
746 .@"struct" = .{
747 .layout = .auto,
748 .is_tuple = false,
749 .fields = fields,
750 .decls = &.{},
751 },
752 });
753
754 const gen_fields = @typeInfo(T).@"struct".fields;381 const gen_fields = @typeInfo(T).@"struct".fields;
755 try testing.expectEqual(3, gen_fields.len);382 try testing.expectEqual(3, gen_fields.len);
756 try testing.expectEqualStrings("f1", gen_fields[0].name);383 try testing.expectEqualStrings("f1", gen_fields[0].name);
...@@ -762,10 +389,7 @@ test "struct field names sliced at comptime from larger string" {...@@ -762,10 +389,7 @@ test "struct field names sliced at comptime from larger string" {
762test "matching captures causes opaque equivalence" {389test "matching captures causes opaque equivalence" {
763 const S = struct {390 const S = struct {
764 fn UnsignedId(comptime I: type) type {391 fn UnsignedId(comptime I: type) type {
765 const U = @Type(.{ .int = .{392 const U = @Int(.unsigned, @typeInfo(I).int.bits);
766 .signedness = .unsigned,
767 .bits = @typeInfo(I).int.bits,
768 } });
769 return opaque {393 return opaque {
770 fn id(x: U) U {394 fn id(x: U) U {
771 return x;395 return x;
...@@ -785,17 +409,9 @@ test "matching captures causes opaque equivalence" {...@@ -785,17 +409,9 @@ test "matching captures causes opaque equivalence" {
785}409}
786410
787test "reify enum where fields refers to part of array" {411test "reify enum where fields refers to part of array" {
788 const fields: [3]std.builtin.Type.EnumField = .{412 const field_names: [3][]const u8 = .{ "foo", "bar", undefined };
789 .{ .name = "foo", .value = 0 },413 const field_values: [3]u8 = .{ undefined, 0, 1 };
790 .{ .name = "bar", .value = 1 },414 const E = @Enum(u8, .exhaustive, field_names[0..2], field_values[1..3]);
791 undefined,
792 };
793 const E = @Type(.{ .@"enum" = .{
794 .tag_type = u8,
795 .fields = fields[0..2],
796 .decls = &.{},
797 .is_exhaustive = true,
798 } });
799 var a: E = undefined;415 var a: E = undefined;
800 var b: E = undefined;416 var b: E = undefined;
801 a = .foo;417 a = .foo;
test/behavior/union.zig+2-8
...@@ -2198,14 +2198,8 @@ test "matching captures causes union equivalence" {...@@ -2198,14 +2198,8 @@ test "matching captures causes union equivalence" {
2198 fn SignedUnsigned(comptime I: type) type {2198 fn SignedUnsigned(comptime I: type) type {
2199 const bits = @typeInfo(I).int.bits;2199 const bits = @typeInfo(I).int.bits;
2200 return union {2200 return union {
2201 u: @Type(.{ .int = .{2201 u: @Int(.unsigned, bits),
2202 .signedness = .unsigned,2202 i: @Int(.signed, bits),
2203 .bits = bits,
2204 } }),
2205 i: @Type(.{ .int = .{
2206 .signedness = .signed,
2207 .bits = bits,
2208 } }),
2209 };2203 };
2210 }2204 }
2211 };2205 };
test/behavior/x86_64/math.zig+5-14
...@@ -36,34 +36,28 @@ pub fn ChangeScalar(comptime Type: type, comptime NewScalar: type) type {...@@ -36,34 +36,28 @@ pub fn ChangeScalar(comptime Type: type, comptime NewScalar: type) type {
36}36}
37pub fn AsSignedness(comptime Type: type, comptime signedness: std.builtin.Signedness) type {37pub fn AsSignedness(comptime Type: type, comptime signedness: std.builtin.Signedness) type {
38 return switch (@typeInfo(Scalar(Type))) {38 return switch (@typeInfo(Scalar(Type))) {
39 .int => |int| ChangeScalar(Type, @Type(.{ .int = .{39 .int => |int| ChangeScalar(Type, @Int(signedness, int.bits)),
40 .signedness = signedness,
41 .bits = int.bits,
42 } })),
43 .float => Type,40 .float => Type,
44 else => @compileError(@typeName(Type)),41 else => @compileError(@typeName(Type)),
45 };42 };
46}43}
47pub fn AddOneBit(comptime Type: type) type {44pub fn AddOneBit(comptime Type: type) type {
48 return ChangeScalar(Type, switch (@typeInfo(Scalar(Type))) {45 return ChangeScalar(Type, switch (@typeInfo(Scalar(Type))) {
49 .int => |int| @Type(.{ .int = .{ .signedness = int.signedness, .bits = 1 + int.bits } }),46 .int => |int| @Int(int.signedness, 1 + int.bits),
50 .float => Scalar(Type),47 .float => Scalar(Type),
51 else => @compileError(@typeName(Type)),48 else => @compileError(@typeName(Type)),
52 });49 });
53}50}
54pub fn DoubleBits(comptime Type: type) type {51pub fn DoubleBits(comptime Type: type) type {
55 return ChangeScalar(Type, switch (@typeInfo(Scalar(Type))) {52 return ChangeScalar(Type, switch (@typeInfo(Scalar(Type))) {
56 .int => |int| @Type(.{ .int = .{ .signedness = int.signedness, .bits = int.bits * 2 } }),53 .int => |int| @Int(int.signedness, int.bits * 2),
57 .float => Scalar(Type),54 .float => Scalar(Type),
58 else => @compileError(@typeName(Type)),55 else => @compileError(@typeName(Type)),
59 });56 });
60}57}
61pub fn RoundBitsUp(comptime Type: type, comptime multiple: u16) type {58pub fn RoundBitsUp(comptime Type: type, comptime multiple: u16) type {
62 return ChangeScalar(Type, switch (@typeInfo(Scalar(Type))) {59 return ChangeScalar(Type, switch (@typeInfo(Scalar(Type))) {
63 .int => |int| @Type(.{ .int = .{60 .int => |int| @Int(int.signedness, std.mem.alignForward(u16, int.bits, multiple)),
64 .signedness = int.signedness,
65 .bits = std.mem.alignForward(u16, int.bits, multiple),
66 } }),
67 .float => Scalar(Type),61 .float => Scalar(Type),
68 else => @compileError(@typeName(Type)),62 else => @compileError(@typeName(Type)),
69 });63 });
...@@ -83,10 +77,7 @@ pub fn splat(comptime Type: type, scalar: Scalar(Type)) Type {...@@ -83,10 +77,7 @@ pub fn splat(comptime Type: type, scalar: Scalar(Type)) Type {
83pub fn sign(rhs: anytype) ChangeScalar(@TypeOf(rhs), bool) {77pub fn sign(rhs: anytype) ChangeScalar(@TypeOf(rhs), bool) {
84 const Int = ChangeScalar(@TypeOf(rhs), switch (@typeInfo(Scalar(@TypeOf(rhs)))) {78 const Int = ChangeScalar(@TypeOf(rhs), switch (@typeInfo(Scalar(@TypeOf(rhs)))) {
85 .int, .comptime_int => Scalar(@TypeOf(rhs)),79 .int, .comptime_int => Scalar(@TypeOf(rhs)),
86 .float => |float| @Type(.{ .int = .{80 .float => |float| @Int(.signed, float.bits),
87 .signedness = .signed,
88 .bits = float.bits,
89 } }),
90 else => @compileError(@typeName(@TypeOf(rhs))),81 else => @compileError(@typeName(@TypeOf(rhs))),
91 });82 });
92 return @as(Int, @bitCast(rhs)) < splat(Int, 0);83 return @as(Int, @bitCast(rhs)) < splat(Int, 0);
test/cases/compile_errors/@import_zon_bad_type.zig+1-1
...@@ -116,7 +116,7 @@ export fn testMutablePointer() void {...@@ -116,7 +116,7 @@ export fn testMutablePointer() void {
116// tmp.zig:85:26: note: ZON does not allow nested optionals116// tmp.zig:85:26: note: ZON does not allow nested optionals
117// tmp.zig:90:29: error: type '*i32' is not available in ZON117// tmp.zig:90:29: error: type '*i32' is not available in ZON
118// tmp.zig:90:29: note: ZON does not allow mutable pointers118// tmp.zig:90:29: note: ZON does not allow mutable pointers
119// neg_inf.zon:1:1: error: expected type '@Type(.enum_literal)'119// neg_inf.zon:1:1: error: expected type '@EnumLiteral()'
120// tmp.zig:37:38: note: imported here120// tmp.zig:37:38: note: imported here
121// neg_inf.zon:1:1: error: expected type '?u8'121// neg_inf.zon:1:1: error: expected type '?u8'
122// tmp.zig:57:28: note: imported here122// tmp.zig:57:28: note: imported here
test/cases/compile_errors/@import_zon_opt_in_err.zig+1-1
...@@ -70,7 +70,7 @@ export fn testVector() void {...@@ -70,7 +70,7 @@ export fn testVector() void {
70// tmp.zig:22:29: note: imported here70// tmp.zig:22:29: note: imported here
71// vec2.zon:1:2: error: expected type '?tmp.Enum'71// vec2.zon:1:2: error: expected type '?tmp.Enum'
72// tmp.zig:28:30: note: imported here72// tmp.zig:28:30: note: imported here
73// vec2.zon:1:2: error: expected type '?@Type(.enum_literal)'73// vec2.zon:1:2: error: expected type '?@EnumLiteral()'
74// tmp.zig:33:39: note: imported here74// tmp.zig:33:39: note: imported here
75// vec2.zon:1:2: error: expected type '?[1]u8'75// vec2.zon:1:2: error: expected type '?[1]u8'
76// tmp.zig:38:31: note: imported here76// tmp.zig:38:31: note: imported here
test/cases/compile_errors/align_zero.zig+4-24
...@@ -38,31 +38,11 @@ export fn i() void {...@@ -38,31 +38,11 @@ export fn i() void {
38}38}
3939
40export fn j() void {40export fn j() void {
41 _ = @Type(.{ .@"struct" = .{41 _ = @Struct(.auto, null, &.{"test"}, &.{u32}, &.{.{ .@"align" = 0 }});
42 .layout = .auto,
43 .fields = &.{.{
44 .name = "test",
45 .type = u32,
46 .default_value_ptr = null,
47 .is_comptime = false,
48 .alignment = 0,
49 }},
50 .decls = &.{},
51 .is_tuple = false,
52 } });
53}42}
5443
55export fn k() void {44export fn k() void {
56 _ = @Type(.{ .pointer = .{45 _ = @Pointer(.one, .{ .@"align" = 0 }, u32, null);
57 .size = .one,
58 .is_const = false,
59 .is_volatile = false,
60 .alignment = 0,
61 .address_space = .generic,
62 .child = u32,
63 .is_allowzero = false,
64 .sentinel_ptr = null,
65 } });
66}46}
6747
68// error48// error
...@@ -76,5 +56,5 @@ export fn k() void {...@@ -76,5 +56,5 @@ export fn k() void {
76// :29:17: error: alignment must be >= 156// :29:17: error: alignment must be >= 1
77// :33:35: error: alignment must be >= 157// :33:35: error: alignment must be >= 1
78// :37:34: error: alignment must be >= 158// :37:34: error: alignment must be >= 1
79// :41:9: error: alignment must be >= 159// :41:51: error: alignment must be >= 1
80// :56:9: error: alignment must be >= 160// :45:25: error: alignment must be >= 1
test/cases/compile_errors/attempt_to_cast_enum_literal_to_error.zig+1-1
...@@ -6,4 +6,4 @@ export fn entry() void {...@@ -6,4 +6,4 @@ export fn entry() void {
66
7// error7// error
8//8//
9// :3:10: error: expected type 'error{Hi}', found '@Type(.enum_literal)'9// :3:10: error: expected type 'error{Hi}', found '@EnumLiteral()'
test/cases/compile_errors/attempt_to_create_17_bit_float_type.zig deleted-8
...@@ -1,8 +0,0 @@
1const builtin = @import("std").builtin;
2comptime {
3 _ = @Type(.{ .float = .{ .bits = 17 } });
4}
5
6// error
7//
8// :3:9: error: 17-bit float unsupported
test/cases/compile_errors/enum_with_declarations_unavailable_for_reify_type.zig deleted-10
...@@ -1,10 +0,0 @@
1export fn entry() void {
2 _ = @Type(@typeInfo(enum {
3 foo,
4 pub const bar = 1;
5 }));
6}
7
8// error
9//
10// :2:9: error: reified enums must have no decls
test/cases/compile_errors/error_set_decl_literal.zig+1-1
...@@ -6,4 +6,4 @@ export fn entry() void {...@@ -6,4 +6,4 @@ export fn entry() void {
66
7// error7// error
8//8//
9// :3:19: error: expected type 'error{Foo}', found '@Type(.enum_literal)'9// :3:19: error: expected type 'error{Foo}', found '@EnumLiteral()'
test/cases/compile_errors/invalid_pointer_to_opaque.zig+5-32
...@@ -9,40 +9,13 @@ export fn c() void {...@@ -9,40 +9,13 @@ export fn c() void {
9}9}
1010
11export fn d() void {11export fn d() void {
12 _ = @Type(.{ .pointer = .{12 _ = @Pointer(.slice, .{}, anyopaque, null);
13 .size = .slice,
14 .is_const = false,
15 .is_volatile = false,
16 .alignment = 1,
17 .address_space = .generic,
18 .child = anyopaque,
19 .is_allowzero = false,
20 .sentinel_ptr = null,
21 } });
22}13}
23export fn e() void {14export fn e() void {
24 _ = @Type(.{ .pointer = .{15 _ = @Pointer(.many, .{}, anyopaque, null);
25 .size = .many,
26 .is_const = false,
27 .is_volatile = false,
28 .alignment = 1,
29 .address_space = .generic,
30 .child = anyopaque,
31 .is_allowzero = false,
32 .sentinel_ptr = null,
33 } });
34}16}
35export fn f() void {17export fn f() void {
36 _ = @Type(.{ .pointer = .{18 _ = @Pointer(.c, .{}, anyopaque, null);
37 .size = .c,
38 .is_const = false,
39 .is_volatile = false,
40 .alignment = 1,
41 .address_space = .generic,
42 .child = anyopaque,
43 .is_allowzero = false,
44 .sentinel_ptr = null,
45 } });
46}19}
4720
48// error21// error
...@@ -51,5 +24,5 @@ export fn f() void {...@@ -51,5 +24,5 @@ export fn f() void {
51// :5:12: error: indexable pointer to opaque type 'anyopaque' not allowed24// :5:12: error: indexable pointer to opaque type 'anyopaque' not allowed
52// :8:13: error: indexable pointer to opaque type 'anyopaque' not allowed25// :8:13: error: indexable pointer to opaque type 'anyopaque' not allowed
53// :12:9: error: indexable pointer to opaque type 'anyopaque' not allowed26// :12:9: error: indexable pointer to opaque type 'anyopaque' not allowed
54// :24:9: error: indexable pointer to opaque type 'anyopaque' not allowed27// :15:9: error: indexable pointer to opaque type 'anyopaque' not allowed
55// :36:9: error: indexable pointer to opaque type 'anyopaque' not allowed28// :18:9: error: indexable pointer to opaque type 'anyopaque' not allowed
test/cases/compile_errors/invalid_pointer_with_reify_type.zig+2-11
...@@ -1,16 +1,7 @@...@@ -1,16 +1,7 @@
1export fn entry() void {1export fn entry() void {
2 _ = @Type(.{ .pointer = .{2 _ = @Pointer(.one, .{}, u8, 0);
3 .size = .one,
4 .is_const = false,
5 .is_volatile = false,
6 .alignment = 1,
7 .address_space = .generic,
8 .child = u8,
9 .is_allowzero = false,
10 .sentinel_ptr = &@as(u8, 0),
11 } });
12}3}
134
14// error5// error
15//6//
16// :2:9: error: sentinels are only allowed on slices and unknown-length pointers7// :2:33: error: sentinels are only allowed on slices and unknown-length pointers
test/cases/compile_errors/minmax_nonnumeric_operand.zig+1-1
...@@ -36,4 +36,4 @@ const Union = union { foo: void };...@@ -36,4 +36,4 @@ const Union = union { foo: void };
36// :13:29: error: expected number, found 'tmp.Union'36// :13:29: error: expected number, found 'tmp.Union'
37// :19:15: note: union declared here37// :19:15: note: union declared here
38// :14:61: error: expected number, found 'fn () u8'38// :14:61: error: expected number, found 'fn () u8'
39// :15:25: error: expected number, found '@Type(.enum_literal)'39// :15:25: error: expected number, found '@EnumLiteral()'
test/cases/compile_errors/nested_vectors.zig+2-2
...@@ -1,10 +1,10 @@...@@ -1,10 +1,10 @@
1export fn entry() void {1export fn entry() void {
2 const V1 = @Vector(4, u8);2 const V1 = @Vector(4, u8);
3 const V2 = @Type(.{ .vector = .{ .len = 4, .child = V1 } });3 const V2 = @Vector(4, V1);
4 const v: V2 = undefined;4 const v: V2 = undefined;
5 _ = v;5 _ = v;
6}6}
77
8// error8// error
9//9//
10// :3:16: error: expected integer, float, bool, or pointer for the vector element type; found '@Vector(4, u8)'10// :3:27: error: expected integer, float, bool, or pointer for the vector element type; found '@Vector(4, u8)'
test/cases/compile_errors/non_constant_expression_in_array_size.zig+1-1
...@@ -14,4 +14,4 @@ export fn entry() usize {...@@ -14,4 +14,4 @@ export fn entry() usize {
14//14//
15// :6:12: error: unable to resolve comptime value15// :6:12: error: unable to resolve comptime value
16// :2:12: note: called at comptime from here16// :2:12: note: called at comptime from here
17// :1:13: note: struct fields must be comptime-known17// :1:13: note: types must be comptime-known
test/cases/compile_errors/non_scalar_sentinel.zig+4-27
...@@ -12,31 +12,10 @@ comptime {...@@ -12,31 +12,10 @@ comptime {
12}12}
1313
14comptime {14comptime {
15 _ = @Type(.{ .array = .{ .child = S, .len = 0, .sentinel_ptr = &sentinel } });15 _ = @Pointer(.slice, .{}, S, sentinel);
16}16}
17comptime {17comptime {
18 _ = @Type(.{ .pointer = .{18 _ = @Pointer(.many, .{}, S, sentinel);
19 .size = .slice,
20 .is_const = false,
21 .is_volatile = false,
22 .alignment = @alignOf(S),
23 .address_space = .generic,
24 .child = S,
25 .is_allowzero = false,
26 .sentinel_ptr = &sentinel,
27 } });
28}
29comptime {
30 _ = @Type(.{ .pointer = .{
31 .size = .many,
32 .is_const = false,
33 .is_volatile = false,
34 .alignment = @alignOf(S),
35 .address_space = .generic,
36 .child = S,
37 .is_allowzero = false,
38 .sentinel_ptr = &sentinel,
39 } });
40}19}
4120
42// error21// error
...@@ -47,9 +26,7 @@ comptime {...@@ -47,9 +26,7 @@ comptime {
47// :1:11: note: struct declared here26// :1:11: note: struct declared here
48// :11:12: error: non-scalar sentinel type 'tmp.S'27// :11:12: error: non-scalar sentinel type 'tmp.S'
49// :1:11: note: struct declared here28// :1:11: note: struct declared here
50// :15:9: error: non-scalar sentinel type 'tmp.S'29// :15:34: error: non-scalar sentinel type 'tmp.S'
51// :1:11: note: struct declared here
52// :18:9: error: non-scalar sentinel type 'tmp.S'
53// :1:11: note: struct declared here30// :1:11: note: struct declared here
54// :30:9: error: non-scalar sentinel type 'tmp.S'31// :18:33: error: non-scalar sentinel type 'tmp.S'
55// :1:11: note: struct declared here32// :1:11: note: struct declared here
test/cases/compile_errors/reified_enum_field_value_overflow.zig+2-11
...@@ -1,17 +1,8 @@...@@ -1,17 +1,8 @@
1comptime {1comptime {
2 const E = @Type(.{ .@"enum" = .{2 const E = @Enum(u1, .exhaustive, &.{ "f0", "f1", "f2" }, &.{ 0, 1, 2 });
3 .tag_type = u1,
4 .fields = &.{
5 .{ .name = "f0", .value = 0 },
6 .{ .name = "f1", .value = 1 },
7 .{ .name = "f2", .value = 2 },
8 },
9 .decls = &.{},
10 .is_exhaustive = true,
11 } });
12 _ = E;3 _ = E;
13}4}
145
15// error6// error
16//7//
17// :2:15: error: field 'f2' with enumeration value '2' is too large for backing int type 'u1'8// :2:72: error: type 'u1' cannot represent integer value '2'
test/cases/compile_errors/reify_enum_with_duplicate_field.zig+3-13
...@@ -1,18 +1,8 @@...@@ -1,18 +1,8 @@
1export fn entry() void {1export fn entry() void {
2 _ = @Type(.{2 _ = @Enum(u32, .nonexhaustive, &.{ "A", "A" }, &.{ 0, 1 });
3 .@"enum" = .{
4 .tag_type = u32,
5 .fields = &.{
6 .{ .name = "A", .value = 0 },
7 .{ .name = "A", .value = 1 },
8 },
9 .decls = &.{},
10 .is_exhaustive = false,
11 },
12 });
13}3}
144
15// error5// error
16//6//
17// :2:9: error: duplicate enum field 'A'7// :2:36: error: duplicate enum field 'A'
18// :2:9: note: other field here8// :2:36: note: other field here
test/cases/compile_errors/reify_enum_with_duplicate_tag_value.zig+3-13
...@@ -1,18 +1,8 @@...@@ -1,18 +1,8 @@
1export fn entry() void {1export fn entry() void {
2 _ = @Type(.{2 _ = @Enum(u32, .nonexhaustive, &.{ "A", "B" }, &.{ 10, 10 });
3 .@"enum" = .{
4 .tag_type = u32,
5 .fields = &.{
6 .{ .name = "A", .value = 10 },
7 .{ .name = "B", .value = 10 },
8 },
9 .decls = &.{},
10 .is_exhaustive = false,
11 },
12 });
13}3}
144
15// error5// error
16//6//
17// :2:9: error: enum tag value 10 already taken7// :2:52: error: enum tag value 10 already taken
18// :2:9: note: other enum tag value here8// :2:52: note: other enum tag value here
test/cases/compile_errors/reify_struct.zig+6-69
...@@ -1,79 +1,16 @@...@@ -1,79 +1,16 @@
1comptime {1comptime {
2 @Type(.{ .@"struct" = .{2 @Struct(.auto, null, &.{"foo"}, &.{u32}, &.{.{ .@"comptime" = true }});
3 .layout = .auto,
4 .fields = &.{.{
5 .name = "foo",
6 .type = u32,
7 .default_value_ptr = null,
8 .is_comptime = false,
9 .alignment = 4,
10 }},
11 .decls = &.{},
12 .is_tuple = true,
13 } });
14}3}
15comptime {4comptime {
16 @Type(.{ .@"struct" = .{5 @Struct(.@"extern", null, &.{"foo"}, &.{u32}, &.{.{ .@"comptime" = true, .default_value_ptr = &@as(u32, 10) }});
17 .layout = .auto,
18 .fields = &.{.{
19 .name = "3",
20 .type = u32,
21 .default_value_ptr = null,
22 .is_comptime = false,
23 .alignment = 4,
24 }},
25 .decls = &.{},
26 .is_tuple = true,
27 } });
28}6}
29comptime {7comptime {
30 @Type(.{ .@"struct" = .{8 @Struct(.@"packed", null, &.{"foo"}, &.{u32}, &.{.{ .@"align" = 4 }});
31 .layout = .auto,
32 .fields = &.{.{
33 .name = "0",
34 .type = u32,
35 .default_value_ptr = null,
36 .is_comptime = true,
37 .alignment = 4,
38 }},
39 .decls = &.{},
40 .is_tuple = true,
41 } });
42}
43comptime {
44 @Type(.{ .@"struct" = .{
45 .layout = .@"extern",
46 .fields = &.{.{
47 .name = "0",
48 .type = u32,
49 .default_value_ptr = null,
50 .is_comptime = true,
51 .alignment = 4,
52 }},
53 .decls = &.{},
54 .is_tuple = false,
55 } });
56}
57comptime {
58 @Type(.{ .@"struct" = .{
59 .layout = .@"packed",
60 .fields = &.{.{
61 .name = "0",
62 .type = u32,
63 .default_value_ptr = null,
64 .is_comptime = true,
65 .alignment = 4,
66 }},
67 .decls = &.{},
68 .is_tuple = false,
69 } });
70}9}
7110
72// error11// error
73//12//
74// :2:5: error: tuple cannot have non-numeric field 'foo'13// :2:46: error: comptime field without default initialization value
75// :16:5: error: tuple field name '3' does not match field index 014// :5:51: error: extern struct fields cannot be marked comptime
76// :30:5: error: comptime field without default initialization value15// :8:51: error: packed struct fields cannot be aligned
77// :44:5: error: extern struct fields cannot be marked comptime
78// :58:5: error: alignment of a packed struct field must be set to 0
7916
test/cases/compile_errors/reify_type.Fn_with_is_generic_true.zig deleted-16
...@@ -1,16 +0,0 @@
1const Foo = @Type(.{
2 .@"fn" = .{
3 .calling_convention = .auto,
4 .is_generic = true,
5 .is_var_args = false,
6 .return_type = u0,
7 .params = &.{},
8 },
9});
10comptime {
11 _ = Foo;
12}
13
14// error
15//
16// :1:13: error: Type.Fn.is_generic must be false for @Type
test/cases/compile_errors/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig+3-12
...@@ -1,18 +1,9 @@...@@ -1,18 +1,9 @@
1const Foo = @Type(.{
2 .@"fn" = .{
3 .calling_convention = .auto,
4 .is_generic = false,
5 .is_var_args = true,
6 .return_type = u0,
7 .params = &.{},
8 },
9});
10comptime {1comptime {
11 _ = Foo;2 _ = @Fn(&.{u32}, &.{.{}}, u8, .{ .varargs = true });
12}3}
134
14// error5// error
15// target=x86_64-linux6// target=x86_64-linux
16//7//
17// :1:13: error: variadic function does not support 'auto' calling convention8// :2:36: error: variadic function does not support 'auto' calling convention
18// :1:13: note: supported calling conventions: 'x86_64_sysv', 'x86_64_x32', 'x86_64_win'9// :2:36: note: supported calling conventions: 'x86_64_sysv', 'x86_64_x32', 'x86_64_win'
test/cases/compile_errors/reify_type.Fn_with_return_type_null.zig deleted-16
...@@ -1,16 +0,0 @@
1const Foo = @Type(.{
2 .@"fn" = .{
3 .calling_convention = .auto,
4 .is_generic = false,
5 .is_var_args = false,
6 .return_type = null,
7 .params = &.{},
8 },
9});
10comptime {
11 _ = Foo;
12}
13
14// error
15//
16// :1:13: error: Type.Fn.return_type must be non-null for @Type
test/cases/compile_errors/reify_type_for_exhaustive_enum_with_non-integer_tag_type.zig+2-9
...@@ -1,15 +1,8 @@...@@ -1,15 +1,8 @@
1const Tag = @Type(.{1const Tag = @Enum(bool, .nonexhaustive, &.{}, &.{});
2 .@"enum" = .{
3 .tag_type = bool,
4 .fields = &.{},
5 .decls = &.{},
6 .is_exhaustive = false,
7 },
8});
9export fn entry() void {2export fn entry() void {
10 _ = @as(Tag, @enumFromInt(0));3 _ = @as(Tag, @enumFromInt(0));
11}4}
125
13// error6// error
14//7//
15// :1:13: error: Type.Enum.tag_type must be an integer type8// :1:19: error: tag type must be an integer type
test/cases/compile_errors/reify_type_for_exhaustive_enum_with_undefined_tag_type.zig+2-9
...@@ -1,15 +1,8 @@...@@ -1,15 +1,8 @@
1const Tag = @Type(.{1const Tag = @Enum(undefined, .exhaustive, &.{}, &.{});
2 .@"enum" = .{
3 .tag_type = undefined,
4 .fields = &.{},
5 .decls = &.{},
6 .is_exhaustive = false,
7 },
8});
9export fn entry() void {2export fn entry() void {
10 _ = @as(Tag, @enumFromInt(0));3 _ = @as(Tag, @enumFromInt(0));
11}4}
125
13// error6// error
14//7//
15// :1:20: error: use of undefined value here causes illegal behavior8// :1:19: error: use of undefined value here causes illegal behavior
test/cases/compile_errors/reify_type_for_tagged_extern_union.zig+3-24
...@@ -1,26 +1,5 @@...@@ -1,26 +1,5 @@
1const Tag = @Type(.{1const Tag = @Enum(u2, .exhaustive, &.{ "signed", "unsigned" }, &.{ 0, 1 });
2 .@"enum" = .{2const Extern = @Union(.@"extern", Tag, &.{ "signed", "unsigned" }, &.{ i32, u32 }, &@splat(.{}));
3 .tag_type = u2,
4 .fields = &.{
5 .{ .name = "signed", .value = 0 },
6 .{ .name = "unsigned", .value = 1 },
7 },
8 .decls = &.{},
9 .is_exhaustive = true,
10 },
11});
12
13const Extern = @Type(.{
14 .@"union" = .{
15 .layout = .@"extern",
16 .tag_type = Tag,
17 .fields = &.{
18 .{ .name = "signed", .type = i32, .alignment = @alignOf(i32) },
19 .{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) },
20 },
21 .decls = &.{},
22 },
23});
243
25export fn entry() void {4export fn entry() void {
26 const tagged: Extern = .{ .signed = -1 };5 const tagged: Extern = .{ .signed = -1 };
...@@ -29,4 +8,4 @@ export fn entry() void {...@@ -29,4 +8,4 @@ export fn entry() void {
298
30// error9// error
31//10//
32// :13:16: error: extern union does not support enum tag type11// :2:35: error: extern union does not support enum tag type
test/cases/compile_errors/reify_type_for_tagged_packed_union.zig+3-24
...@@ -1,26 +1,5 @@...@@ -1,26 +1,5 @@
1const Tag = @Type(.{1const Tag = @Enum(u2, .exhaustive, &.{ "signed", "unsigned" }, &.{ 0, 1 });
2 .@"enum" = .{2const Packed = @Union(.@"packed", Tag, &.{ "signed", "unsigned" }, &.{ i32, u32 }, &@splat(.{}));
3 .tag_type = u2,
4 .fields = &.{
5 .{ .name = "signed", .value = 0 },
6 .{ .name = "unsigned", .value = 1 },
7 },
8 .decls = &.{},
9 .is_exhaustive = true,
10 },
11});
12
13const Packed = @Type(.{
14 .@"union" = .{
15 .layout = .@"packed",
16 .tag_type = Tag,
17 .fields = &.{
18 .{ .name = "signed", .type = i32, .alignment = @alignOf(i32) },
19 .{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) },
20 },
21 .decls = &.{},
22 },
23});
243
25export fn entry() void {4export fn entry() void {
26 const tagged: Packed = .{ .signed = -1 };5 const tagged: Packed = .{ .signed = -1 };
...@@ -29,4 +8,4 @@ export fn entry() void {...@@ -29,4 +8,4 @@ export fn entry() void {
298
30// error9// error
31//10//
32// :13:16: error: packed union does not support enum tag type11// :2:35: error: packed union does not support enum tag type
test/cases/compile_errors/reify_type_for_tagged_union_with_extra_enum_field.zig+3-24
...@@ -1,26 +1,5 @@...@@ -1,26 +1,5 @@
1const Tag = @Type(.{1const Tag = @Enum(u2, .exhaustive, &.{ "signed", "unsigned", "arst" }, &.{ 0, 1, 2 });
2 .@"enum" = .{2const Tagged = @Union(.auto, Tag, &.{ "signed", "unsigned" }, &.{ i32, u32 }, &@splat(.{}));
3 .tag_type = u2,
4 .fields = &.{
5 .{ .name = "signed", .value = 0 },
6 .{ .name = "unsigned", .value = 1 },
7 .{ .name = "arst", .value = 2 },
8 },
9 .decls = &.{},
10 .is_exhaustive = true,
11 },
12});
13const Tagged = @Type(.{
14 .@"union" = .{
15 .layout = .auto,
16 .tag_type = Tag,
17 .fields = &.{
18 .{ .name = "signed", .type = i32, .alignment = @alignOf(i32) },
19 .{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) },
20 },
21 .decls = &.{},
22 },
23});
24export fn entry() void {3export fn entry() void {
25 var tagged = Tagged{ .signed = -1 };4 var tagged = Tagged{ .signed = -1 };
26 tagged = .{ .unsigned = 1 };5 tagged = .{ .unsigned = 1 };
...@@ -28,6 +7,6 @@ export fn entry() void {...@@ -28,6 +7,6 @@ export fn entry() void {
287
29// error8// error
30//9//
31// :13:16: error: enum fields missing in union10// :2:35: error: 1 enum fields missing in union
32// :1:13: note: field 'arst' missing, declared here11// :1:13: note: field 'arst' missing, declared here
33// :1:13: note: enum declared here12// :1:13: note: enum declared here
test/cases/compile_errors/reify_type_for_tagged_union_with_extra_union_field.zig+3-24
...@@ -1,26 +1,5 @@...@@ -1,26 +1,5 @@
1const Tag = @Type(.{1const Tag = @Enum(u1, .exhaustive, &.{ "signed", "unsigned" }, &.{ 0, 1 });
2 .@"enum" = .{2const Tagged = @Union(.auto, Tag, &.{ "signed", "unsigned", "arst" }, &.{ i32, u32, f32 }, &@splat(.{}));
3 .tag_type = u1,
4 .fields = &.{
5 .{ .name = "signed", .value = 0 },
6 .{ .name = "unsigned", .value = 1 },
7 },
8 .decls = &.{},
9 .is_exhaustive = true,
10 },
11});
12const Tagged = @Type(.{
13 .@"union" = .{
14 .layout = .auto,
15 .tag_type = Tag,
16 .fields = &.{
17 .{ .name = "signed", .type = i32, .alignment = @alignOf(i32) },
18 .{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) },
19 .{ .name = "arst", .type = f32, .alignment = @alignOf(f32) },
20 },
21 .decls = &.{},
22 },
23});
24export fn entry() void {3export fn entry() void {
25 var tagged = Tagged{ .signed = -1 };4 var tagged = Tagged{ .signed = -1 };
26 tagged = .{ .unsigned = 1 };5 tagged = .{ .unsigned = 1 };
...@@ -28,5 +7,5 @@ export fn entry() void {...@@ -28,5 +7,5 @@ export fn entry() void {
287
29// error8// error
30//9//
31// :12:16: error: no field named 'arst' in enum 'tmp.Tag'10// :2:35: error: no field named 'arst' in enum 'tmp.Tag'
32// :1:13: note: enum declared here11// :1:13: note: enum declared here
test/cases/compile_errors/reify_type_for_tagged_union_with_no_enum_fields.zig+3-20
...@@ -1,22 +1,5 @@...@@ -1,22 +1,5 @@
1const Tag = @Type(.{1const Tag = @Enum(u0, .exhaustive, &.{}, &.{});
2 .@"enum" = .{2const Tagged = @Union(.auto, Tag, &.{ "signed", "unsigned" }, &.{ i32, u32 }, &@splat(.{}));
3 .tag_type = u0,
4 .fields = &.{},
5 .decls = &.{},
6 .is_exhaustive = true,
7 },
8});
9const Tagged = @Type(.{
10 .@"union" = .{
11 .layout = .auto,
12 .tag_type = Tag,
13 .fields = &.{
14 .{ .name = "signed", .type = i32, .alignment = @alignOf(i32) },
15 .{ .name = "unsigned", .type = u32, .alignment = @alignOf(u32) },
16 },
17 .decls = &.{},
18 },
19});
20export fn entry() void {3export fn entry() void {
21 const tagged: Tagged = undefined;4 const tagged: Tagged = undefined;
22 _ = tagged;5 _ = tagged;
...@@ -24,5 +7,5 @@ export fn entry() void {...@@ -24,5 +7,5 @@ export fn entry() void {
247
25// error8// error
26//9//
27// :9:16: error: no field named 'signed' in enum 'tmp.Tag'10// :2:35: error: no field named 'signed' in enum 'tmp.Tag'
28// :1:13: note: enum declared here11// :1:13: note: enum declared here
test/cases/compile_errors/reify_type_for_tagged_union_with_no_union_fields.zig+3-20
...@@ -1,22 +1,5 @@...@@ -1,22 +1,5 @@
1const Tag = @Type(.{1const Tag = @Enum(u1, .exhaustive, &.{ "signed", "unsigned" }, &.{ 0, 1 });
2 .@"enum" = .{2const Tagged = @Union(.auto, Tag, &.{}, &.{}, &.{});
3 .tag_type = u1,
4 .fields = &.{
5 .{ .name = "signed", .value = 0 },
6 .{ .name = "unsigned", .value = 1 },
7 },
8 .decls = &.{},
9 .is_exhaustive = true,
10 },
11});
12const Tagged = @Type(.{
13 .@"union" = .{
14 .layout = .auto,
15 .tag_type = Tag,
16 .fields = &.{},
17 .decls = &.{},
18 },
19});
20export fn entry() void {3export fn entry() void {
21 const tagged: Tagged = undefined;4 const tagged: Tagged = undefined;
22 _ = tagged;5 _ = tagged;
...@@ -24,7 +7,7 @@ export fn entry() void {...@@ -24,7 +7,7 @@ export fn entry() void {
247
25// error8// error
26//9//
27// :12:16: error: enum fields missing in union10// :2:35: error: 2 enum fields missing in union
28// :1:13: note: field 'signed' missing, declared here11// :1:13: note: field 'signed' missing, declared here
29// :1:13: note: field 'unsigned' missing, declared here12// :1:13: note: field 'unsigned' missing, declared here
30// :1:13: note: enum declared here13// :1:13: note: enum declared here
test/cases/compile_errors/reify_type_for_union_with_opaque_field.zig+3-12
...@@ -1,18 +1,9 @@...@@ -1,18 +1,9 @@
1const Untagged = @Type(.{1const Untagged = @Union(.auto, null, &.{"foo"}, &.{opaque {}}, &.{.{}});
2 .@"union" = .{
3 .layout = .auto,
4 .tag_type = null,
5 .fields = &.{
6 .{ .name = "foo", .type = opaque {}, .alignment = 1 },
7 },
8 .decls = &.{},
9 },
10});
11export fn entry() usize {2export fn entry() usize {
12 return @sizeOf(Untagged);3 return @sizeOf(Untagged);
13}4}
145
15// error6// error
16//7//
17// :1:18: error: opaque types have unknown size and therefore cannot be directly embedded in unions8// :1:49: error: opaque types have unknown size and therefore cannot be directly embedded in unions
18// :6:39: note: opaque declared here9// :1:52: note: opaque declared here
test/cases/compile_errors/reify_type_union_payload_is_undefined.zig deleted-10
...@@ -1,10 +0,0 @@
1const Foo = @Type(.{
2 .@"struct" = undefined,
3});
4comptime {
5 _ = Foo;
6}
7
8// error
9//
10// :1:20: error: use of undefined value here causes illegal behavior
test/cases/compile_errors/reify_type_with_Type.Int.zig deleted-13
...@@ -1,13 +0,0 @@
1const builtin = @import("std").builtin;
2export fn entry() void {
3 _ = @Type(builtin.Type.Int{
4 .signedness = .signed,
5 .bits = 8,
6 });
7}
8
9// error
10//
11// :3:31: error: expected type 'builtin.Type', found 'builtin.Type.Int'
12// :?:?: note: struct declared here
13// :?:?: note: union declared here
test/cases/compile_errors/reify_type_with_invalid_field_alignment.zig+6-39
...@@ -1,48 +1,15 @@...@@ -1,48 +1,15 @@
1comptime {1comptime {
2 _ = @Type(.{2 _ = @Union(.auto, null, &.{"foo"}, &.{usize}, &.{.{ .@"align" = 3 }});
3 .@"union" = .{
4 .layout = .auto,
5 .tag_type = null,
6 .fields = &.{
7 .{ .name = "foo", .type = usize, .alignment = 3 },
8 },
9 .decls = &.{},
10 },
11 });
12}3}
13comptime {4comptime {
14 _ = @Type(.{5 _ = @Struct(.auto, null, &.{"a"}, &.{u32}, &.{.{ .@"comptime" = true, .@"align" = 5 }});
15 .@"struct" = .{
16 .layout = .auto,
17 .fields = &.{.{
18 .name = "0",
19 .type = u32,
20 .default_value_ptr = null,
21 .is_comptime = true,
22 .alignment = 5,
23 }},
24 .decls = &.{},
25 .is_tuple = false,
26 },
27 });
28}6}
29comptime {7comptime {
30 _ = @Type(.{8 _ = @Pointer(.many, .{ .@"align" = 7 }, u8, null);
31 .pointer = .{
32 .size = .many,
33 .is_const = true,
34 .is_volatile = false,
35 .alignment = 7,
36 .address_space = .generic,
37 .child = u8,
38 .is_allowzero = false,
39 .sentinel_ptr = null,
40 },
41 });
42}9}
4310
44// error11// error
45//12//
46// :2:9: error: alignment value '3' is not a power of two13// :2:51: error: alignment value '3' is not a power of two
47// :14:9: error: alignment value '5' is not a power of two14// :5:48: error: alignment value '5' is not a power of two
48// :30:9: error: alignment value '7' is not a power of two15// :8:26: error: alignment value '7' is not a power of two
test/cases/compile_errors/reify_type_with_undefined.zig+4-24
...@@ -1,31 +1,11 @@...@@ -1,31 +1,11 @@
1comptime {1comptime {
2 _ = @Type(.{ .array = .{ .len = 0, .child = u8, .sentinel_ptr = undefined } });2 _ = @Struct(.auto, null, &.{}, &.{}, undefined);
3}3}
4comptime {4comptime {
5 _ = @Type(.{5 _ = @Struct(.auto, null, &.{"foo"}, &.{undefined}, &.{.{}});
6 .@"struct" = .{
7 .fields = undefined,
8 .decls = undefined,
9 .is_tuple = false,
10 .layout = .auto,
11 },
12 });
13}
14comptime {
15 const std = @import("std");
16 const fields: [1]std.builtin.Type.StructField = undefined;
17 _ = @Type(.{
18 .@"struct" = .{
19 .layout = .auto,
20 .fields = &fields,
21 .decls = &.{},
22 .is_tuple = false,
23 },
24 });
25}6}
267
27// error8// error
28//9//
29// :2:16: error: use of undefined value here causes illegal behavior10// :2:42: error: use of undefined value here causes illegal behavior
30// :5:16: error: use of undefined value here causes illegal behavior11// :5:41: error: use of undefined value here causes illegal behavior
31// :17:16: error: use of undefined value here causes illegal behavior
test/cases/compile_errors/runtime_condition_comptime_type_in_destructure.zig+1-1
...@@ -7,4 +7,4 @@ export fn foobar() void {...@@ -7,4 +7,4 @@ export fn foobar() void {
77
8// error8// error
9//9//
10// :4:5: error: value with comptime-only type '@Type(.enum_literal)' depends on runtime control flow10// :4:5: error: value with comptime-only type '@EnumLiteral()' depends on runtime control flow
test/cases/compile_errors/struct_with_declarations_unavailable_for_reify_type.zig deleted-9
...@@ -1,9 +0,0 @@
1export fn entry() void {
2 _ = @Type(@typeInfo(struct {
3 pub const foo = 1;
4 }));
5}
6
7// error
8//
9// :2:9: error: reified structs must have no decls
test/cases/compile_errors/tagName_on_undef_enum_literal.zig+1-1
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1comptime {1comptime {
2 const undef: @Type(.enum_literal) = undefined;2 const undef: @EnumLiteral() = undefined;
3 _ = @tagName(undef);3 _ = @tagName(undef);
4}4}
55
test/cases/compile_errors/unable_to_evaluate_comptime_expr.zig+1-1
...@@ -42,4 +42,4 @@ pub export fn entry3() void {...@@ -42,4 +42,4 @@ pub export fn entry3() void {
42// :13:13: note: initializer of container-level variable must be comptime-known42// :13:13: note: initializer of container-level variable must be comptime-known
43// :22:9: error: unable to evaluate comptime expression43// :22:9: error: unable to evaluate comptime expression
44// :22:21: note: operation is runtime due to this operand44// :22:21: note: operation is runtime due to this operand
45// :21:13: note: enum fields must be comptime-known45// :21:13: note: enum field values must be comptime-known
test/cases/compile_errors/wrong_type_for_reify_type.zig+21-4
...@@ -1,8 +1,25 @@...@@ -1,8 +1,25 @@
1export fn entry() void {1export fn entryI() void {
2 _ = @Type(0);2 _ = @Int(0, 0);
3}
4
5export fn entryE() void {
6 _ = @Enum(0, 0, 0, 0);
7}
8
9export fn entryS() void {
10 _ = @Struct(0, 0, &.{}, &.{}, &.{});
11}
12
13export fn entryU() void {
14 _ = @Union(0, 0, &.{}, &.{}, &.{});
3}15}
416
5// error17// error
6//18//
7// :2:15: error: expected type 'builtin.Type', found 'comptime_int'19// :2:14: error: expected type 'builtin.Signedness', found 'comptime_int'
8// :?:?: note: union declared here20// :?:?: note: enum declared here
21// :6:15: error: expected type 'type', found 'comptime_int'
22// :10:17: error: expected type 'builtin.Type.ContainerLayout', found 'comptime_int'
23// :?:?: enum declared here
24// :14:16: error: expected type 'builtin.Type.ContainerLayout', found 'comptime_int'
25// :?:?: enum declared here
test/cases/default_value_references_comptime_var.zig+13-35
...@@ -2,49 +2,27 @@ export fn foo() void {...@@ -2,49 +2,27 @@ export fn foo() void {
2 comptime var a: u8 = 0;2 comptime var a: u8 = 0;
3 _ = struct { comptime *u8 = &a };3 _ = struct { comptime *u8 = &a };
4}4}
5export fn bar() void {
6 comptime var a: u8 = 0;
7 _ = @Type(.{ .@"struct" = .{
8 .layout = .auto,
9 .fields = &.{.{
10 .name = "0",
11 .type = *u8,
12 .default_value_ptr = @ptrCast(&&a),
13 .is_comptime = true,
14 .alignment = @alignOf(*u8),
15 }},
16 .decls = &.{},
17 .is_tuple = true,
18 } });
19}
205
21export fn baz() void {6export fn bar() void {
22 comptime var a: u8 = 0;7 comptime var a: u8 = 0;
23 _ = struct { foo: *u8 = &a };8 _ = struct { foo: *u8 = &a };
24}9}
25export fn qux() void {10export fn baz() void {
26 comptime var a: u8 = 0;11 comptime var a: u8 = 0;
27 _ = @Type(.{ .@"struct" = .{12 _ = @Struct(
28 .layout = .auto,13 .auto,
29 .fields = &.{.{14 null,
30 .name = "foo",15 &.{"foo"},
31 .type = *u8,16 &.{*u8},
32 .default_value_ptr = @ptrCast(&&a),17 &.{.{ .default_value_ptr = @ptrCast(&&a) }},
33 .is_comptime = false,18 );
34 .alignment = @alignOf(*u8),
35 }},
36 .decls = &.{},
37 .is_tuple = false,
38 } });
39}19}
4020
41// error21// error
42//22//
43// :3:33: error: field default value contains reference to comptime var23// :3:33: error: field default value contains reference to comptime var
44// :2:14: note: '0' points to comptime var declared here24// :2:14: note: '0' points to comptime var declared here
45// :7:9: error: field default value contains reference to comptime var25// :8:9: error: captured value contains reference to comptime var
46// :6:14: note: '0' points to comptime var declared here26// :7:14: note: 'a' points to comptime var declared here
47// :23:9: error: captured value contains reference to comptime var27// :17:9: error: field default value contains reference to comptime var
48// :22:14: note: 'a' points to comptime var declared here28// :11:14: note: 'foo' points to comptime var declared here
49// :27:9: error: field default value contains reference to comptime var
50// :26:14: note: 'foo' points to comptime var declared here
test/cases/sentinel_references_comptime_var.zig+5-24
...@@ -2,14 +2,6 @@ export fn foo() void {...@@ -2,14 +2,6 @@ export fn foo() void {
2 comptime var a: u8 = 0;2 comptime var a: u8 = 0;
3 _ = [0:&a]*u8;3 _ = [0:&a]*u8;
4}4}
5export fn bar() void {
6 comptime var a: u8 = 0;
7 _ = @Type(.{ .array = .{
8 .child = *u8,
9 .len = 0,
10 .sentinel_ptr = @ptrCast(&&a),
11 } });
12}
135
14export fn baz() void {6export fn baz() void {
15 comptime var a: u8 = 0;7 comptime var a: u8 = 0;
...@@ -17,25 +9,14 @@ export fn baz() void {...@@ -17,25 +9,14 @@ export fn baz() void {
17}9}
18export fn qux() void {10export fn qux() void {
19 comptime var a: u8 = 0;11 comptime var a: u8 = 0;
20 _ = @Type(.{ .pointer = .{12 _ = @Pointer(.many, .{}, *u8, &a);
21 .size = .many,
22 .is_const = false,
23 .is_volatile = false,
24 .alignment = @alignOf(u8),
25 .address_space = .generic,
26 .child = *u8,
27 .is_allowzero = false,
28 .sentinel_ptr = @ptrCast(&&a),
29 } });
30}13}
3114
32// error15// error
33//16//
34// :3:12: error: sentinel contains reference to comptime var17// :3:12: error: sentinel contains reference to comptime var
35// :2:14: note: 'sentinel' points to comptime var declared here18// :2:14: note: 'sentinel' points to comptime var declared here
36// :7:9: error: sentinel contains reference to comptime var19// :8:11: error: sentinel contains reference to comptime var
37// :6:14: note: 'sentinel_ptr' points to comptime var declared here20// :7:14: note: 'sentinel' points to comptime var declared here
38// :16:11: error: sentinel contains reference to comptime var21// :12:35: error: sentinel contains reference to comptime var
39// :15:14: note: 'sentinel' points to comptime var declared here22// :11:14: note: 'sentinel' points to comptime var declared here
40// :20:9: error: sentinel contains reference to comptime var
41// :19:14: note: 'sentinel_ptr' points to comptime var declared here
test/standalone/simple/issue_7030.zig+1-1
...@@ -6,7 +6,7 @@ pub const std_options: std.Options = .{...@@ -6,7 +6,7 @@ pub const std_options: std.Options = .{
66
7pub fn log(7pub fn log(
8 comptime message_level: std.log.Level,8 comptime message_level: std.log.Level,
9 comptime scope: @Type(.enum_literal),9 comptime scope: @EnumLiteral(),
10 comptime format: []const u8,10 comptime format: []const u8,
11 args: anytype,11 args: anytype,
12) void {12) void {
test/standalone/simple/std_enums_big_enums.zig+14-15
...@@ -3,20 +3,18 @@ const std = @import("std");...@@ -3,20 +3,18 @@ const std = @import("std");
3// big enums should not hit the eval branch quota3// big enums should not hit the eval branch quota
4pub fn main() void {4pub fn main() void {
5 const big = struct {5 const big = struct {
6 const Big = @Type(.{ .@"enum" = .{6 const Big = Big: {
7 .tag_type = u16,7 @setEvalBranchQuota(500000);
8 .fields = make_fields: {8 var names: [1001][]const u8 = undefined;
9 @setEvalBranchQuota(500000);9 var values: [1001]u16 = undefined;
10 var fields: [1001]std.builtin.Type.EnumField = undefined;10 for (values[0..1000], names[0..1000], 0..1000) |*val, *name, i| {
11 for (&fields, 0..) |*field, i| {11 name.* = std.fmt.comptimePrint("field_{d}", .{i});
12 field.* = .{ .name = std.fmt.comptimePrint("field_{d}", .{i}), .value = i };12 val.* = i;
13 }13 }
14 fields[1000] = .{ .name = "field_9999", .value = 9999 };14 names[1000] = "field_9999";
15 break :make_fields &fields;15 values[1000] = 9999;
16 },16 break :Big @Enum(u16, .exhaustive, &names, &values);
17 .decls = &.{},17 };
18 .is_exhaustive = true,
19 } });
20 };18 };
2119
22 var set = std.enums.EnumSet(big.Big).init(.{});20 var set = std.enums.EnumSet(big.Big).init(.{});
...@@ -29,10 +27,11 @@ pub fn main() void {...@@ -29,10 +27,11 @@ pub fn main() void {
29 var multiset = std.enums.EnumMultiset(big.Big).init(.{});27 var multiset = std.enums.EnumMultiset(big.Big).init(.{});
30 _ = &multiset;28 _ = &multiset;
3129
30 @setEvalBranchQuota(4000);
31
32 var bounded_multiset = std.enums.BoundedEnumMultiset(big.Big, u8).init(.{});32 var bounded_multiset = std.enums.BoundedEnumMultiset(big.Big, u8).init(.{});
33 _ = &bounded_multiset;33 _ = &bounded_multiset;
3434
35 @setEvalBranchQuota(3000);
36 var array = std.enums.EnumArray(big.Big, u8).init(undefined);35 var array = std.enums.EnumArray(big.Big, u8).init(undefined);
37 array = std.enums.EnumArray(big.Big, u8).initDefault(123, .{});36 array = std.enums.EnumArray(big.Big, u8).initDefault(123, .{});
38}37}
tools/lldb_pretty_printers.py+1-1
...@@ -559,7 +559,7 @@ type_tag_handlers = {...@@ -559,7 +559,7 @@ type_tag_handlers = {
559 'extern_options': lambda payload: 'std.builtin.ExternOptions',559 'extern_options': lambda payload: 'std.builtin.ExternOptions',
560 'type_info': lambda payload: 'std.builtin.Type',560 'type_info': lambda payload: 'std.builtin.Type',
561561
562 'enum_literal': lambda payload: '@TypeOf(.enum_literal)',562 'enum_literal': lambda payload: '@EnumLiteral()',
563 'null': lambda payload: '@TypeOf(null)',563 'null': lambda payload: '@TypeOf(null)',
564 'undefined': lambda payload: '@TypeOf(undefined)',564 'undefined': lambda payload: '@TypeOf(undefined)',
565 'empty_struct_literal': lambda payload: '@TypeOf(.{})',565 'empty_struct_literal': lambda payload: '@TypeOf(.{})',