| author | |
| committer | |
| log | 6d543bcf94b2deefa918cb29de93fc32a10d4abf |
| tree | d6d90938858a7479b682a3b97c98cb3ab67cd4df |
| parent | 0a9f666ea62829607d782dc0cac5d10099def180 |
| parent | dec1163fbb892f276179ae74b51007c656157d99 |
| signature |
replace @Type with individual type-creating builtins122 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 an | 638 | {#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#} |
| 5757 | 5757 | ||
| 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 information | 5761 | {#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 = .{ |
| 11 | 11 | ||
| 12 | fn myLogFn( | 12 | fn 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); |
| 42 | 42 | ||
| 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 |
| 49 | 49 | ||
| 50 | fn logFn( | 50 | fn 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); |
| 717 | 717 | ||
| 718 | pub const Arguments = blk: { | 718 | pub 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 | } |
| 728 | 726 | 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 | }; |
| 738 | 728 | ||
| 739 | pub fn ArgumentsForTag(comptime tag: Tag) type { | 729 | pub 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) { |
| 179 | 179 | ||
| 180 | pub const CodePage = blk: { | 180 | pub 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 | }; |
| 189 | 190 | ||
| 190 | pub fn isSupported(code_page: CodePage) bool { | 191 | pub 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 { |
| 862 | pub const ErrorDetailsWithoutCodePage = blk: { | 862 | pub 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 | }; |
| 880 | 883 | ||
| 881 | fn cellCount(code_page: SupportedCodePage, source: []const u8, start_index: usize, end_index: usize) usize { | 884 | fn 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 { |
| 298 | 298 | ||
| 299 | pub fn log( | 299 | pub 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 |
| 290 | pub inline fn fneg(a: anytype) @TypeOf(a) { | 290 | pub 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 | } |
| 74 | 74 | ||
| 75 | // sign implicit fraction round sticky | 75 | // 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 | ); |
| 80 | 80 | ||
| 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 |
| 66 | 66 | ||
| 67 | // sign implicit fraction | 67 | // 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 | } }); | ||
| 73 | 70 | ||
| 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 | else | 161 | else |
| 162 | @Type(.{ .int = .{ .signedness = .unsigned, .bits = len * 8 } }); | 162 | @Int(.unsigned, len * 8); |
| 163 | 163 | ||
| 164 | const loop_count = @divExact(len, @sizeOf(T)); | 164 | const loop_count = @divExact(len, @sizeOf(T)); |
| 165 | 165 |
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 |
| 41 | 41 | ||
| 42 | fn logFn( | 42 | fn 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{ |
| 15 | 15 | ||
| 16 | fn logOverride( | 16 | fn 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( |
| 416 | fn userInputOptionsFromArgs(arena: Allocator, args: anytype) UserInputOptionsMap { | 416 | fn 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 field | 528 | /// 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. |
| 530 | pub fn PollFiles(comptime StreamEnum: type) type { | 530 | pub 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 | } |
| 549 | 533 | ||
| 550 | test { | 534 | test { |
| ... | @@ -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. |
| 1626 | pub fn SelectUnion(S: type) type { | 1610 | pub 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 | } |
| 1645 | 1621 | ||
| 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. |
| 1274 | pub fn takeLeb128(r: *Reader, comptime Result: type) TakeLeb128Error!Result { | 1274 | pub 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 | } |
| 1281 | 1281 | ||
| 1282 | fn takeMultipleOf7Leb128(r: *Reader, comptime Result: type) TakeLeb128Error!Result { | 1282 | fn 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. |
| 1913 | pub fn writeLeb128(w: *Writer, value: anytype) Error!void { | 1913 | pub 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 | } |
| 1920 | 1920 | ||
| 1921 | fn writeMultipleOf7Leb128(w: *Writer, value: anytype) Error!void { | 1921 | fn 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 and | 548 | /// 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. |
| 550 | pub const Type = union(enum) { | 550 | pub 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, |
| 575 | 575 | ||
| 576 | /// This data structure is used by the Zig language code generation and | 576 | /// 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 | }; |
| 623 | 633 | ||
| 624 | /// This data structure is used by the Zig language code generation and | 634 | /// 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 | }; |
| 672 | 690 | ||
| 673 | /// This data structure is used by the Zig language code generation and | 691 | /// 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 | }; |
| 722 | 744 | ||
| 723 | /// This data structure is used by the Zig language code generation and | 745 | /// 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 | }; |
| 730 | 758 | ||
| 731 | /// This data structure is used by the Zig language code generation and | 759 | /// 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 | }; |
| 758 | 799 |
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. |
| 34 | pub fn EnumFieldStruct(comptime E: type, comptime Data: type, comptime field_default: ?Data) type { | 34 | pub 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 | } |
| 53 | 39 | ||
| 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" { |
| 1532 | test "EnumIndexer large dense unsorted" { | 1518 | test "EnumIndexer large dense unsorted" { |
| 1533 | @setEvalBranchQuota(500_000); // many `comptimePrint`s | 1519 | @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". |
| 280 | pub fn alt( | 280 | pub 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 { |
| 61 | 61 | ||
| 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)); |
| 65 | 65 | ||
| 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 = .{ |
| 1516 | const builtin = @import("builtin"); | 1516 | const builtin = @import("builtin"); |
| 1517 | 1517 | ||
| 1518 | fn check(comptime T: type, value: T, comptime expected: []const u8) !void { | 1518 | fn 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)); |
| 1520 | 1520 | ||
| 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 heuristic | 48 | // 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 | }; |
| 58 | 58 | ||
| 59 | pub const ScopeLevel = struct { | 59 | pub const ScopeLevel = struct { |
| 60 | scope: @Type(.enum_literal), | 60 | scope: @EnumLiteral(), |
| 61 | level: Level, | 61 | level: Level, |
| 62 | }; | 62 | }; |
| 63 | 63 | ||
| 64 | fn log( | 64 | fn 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 | } |
| 74 | 74 | ||
| 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. |
| 76 | pub fn logEnabled(comptime level: Level, comptime scope: @Type(.enum_literal)) bool { | 76 | pub 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. |
| 88 | pub fn defaultLog( | 88 | pub 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( |
| 115 | 115 | ||
| 116 | /// Returns a scoped logging namespace that logs all messages using the scope | 116 | /// Returns a scoped logging namespace that logs all messages using the scope |
| 117 | /// provided here. | 117 | /// provided here. |
| 118 | pub fn scoped(comptime scope: @Type(.enum_literal)) type { | 118 | pub fn scoped(comptime scope: @EnumLiteral()) type { |
| 119 | return struct { | 119 | return struct { |
| 120 | /// Log an error message. This log level is intended to be used | 120 | /// Log an error message. This log level is intended to be used |
| 121 | /// when something has gone wrong. This might be recoverable or might | 121 | /// 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 overflow | 452 | // 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 overflow | 455 | 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 { |
| 799 | pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) type { | 794 | pub 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 | } |
| 811 | 806 | ||
| 812 | test IntFittingRange { | 807 | test IntFittingRange { |
| ... | @@ -1107,9 +1102,14 @@ test cast { | ... | @@ -1107,9 +1102,14 @@ test cast { |
| 1107 | pub const AlignCastError = error{UnalignedMemory}; | 1102 | pub const AlignCastError = error{UnalignedMemory}; |
| 1108 | 1103 | ||
| 1109 | fn AlignCastResult(comptime alignment: Alignment, comptime Ptr: type) type { | 1104 | fn 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 | } |
| 1114 | 1114 | ||
| 1115 | /// Align cast a pointer but return an error if it's the wrong alignment | 1115 | /// 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; |
| 2788 | 2788 | ||
| 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))); |
| 2792 | 2792 | ||
| 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 | } |
| 2797 | 2797 |
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, |
| 16 | 16 | ||
| 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, |
| 58 | 46 | ||
| 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 | } }); | ||
| 67 | 49 | ||
| 68 | /// This currently truncates denormal values, which needs to be fixed before this can be used to | 50 | /// 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 { |
| 122 | 104 | ||
| 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. |
| 124 | inline fn reconstructFloat(comptime T: type, comptime exponent: comptime_int, comptime mantissa: comptime_int) T { | 106 | inline 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 { |
| 209 | pub inline fn floatEpsAt(comptime T: type, x: T) T { | 191 | pub 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)); |
| 69 | 69 | ||
| 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; |
| 6 | pub fn signbit(x: anytype) bool { | 6 | pub 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 do | 10 | .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`. |
| 81 | pub fn Sqrt(comptime T: type) type { | 81 | pub 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 guaranteed | 920 | .@"const" = ptr_info.is_const, |
| 920 | // to find the value searched for, which is only the case if it matches | 921 | .@"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 | } |
| 3953 | fn ReverseIterator(comptime T: type) type { | 3927 | fn 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 | } |
| 4359 | 4315 | ||
| 4360 | fn AsBytesReturnType(comptime P: type) type { | 4316 | fn 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`. |
| 4938 | fn AlignedSlice(comptime AttributeSource: type, comptime new_alignment: usize) type { | 4894 | fn 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 | } |
| 4953 | 4904 | ||
| 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 { |
| 487 | 463 | ||
| 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`. |
| 489 | pub fn FieldEnum(comptime T: type) type { | 465 | pub 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 | } | ||
| 502 | 467 | ||
| 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 consecutive | 471 | 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 order | 472 | 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 | } |
| 513 | 479 | ||
| 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 | } |
| 531 | 483 | ||
| 532 | fn expectEqualEnum(expected: anytype, actual: @TypeOf(expected)) !void { | 484 | fn expectEqualEnum(expected: anytype, actual: @TypeOf(expected)) !void { |
| ... | @@ -583,20 +535,11 @@ test FieldEnum { | ... | @@ -583,20 +535,11 @@ test FieldEnum { |
| 583 | } | 535 | } |
| 584 | 536 | ||
| 585 | pub fn DeclEnum(comptime T: type) type { | 537 | pub 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 | } |
| 601 | 544 | ||
| 602 | test DeclEnum { | 545 | test 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 | } |
| 870 | 813 | ||
| 814 | /// Deprecated: use @Int | ||
| 871 | pub fn Int(comptime signedness: std.builtin.Signedness, comptime bit_count: u16) type { | 815 | pub 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 | } |
| 879 | 818 | ||
| 880 | pub fn Float(comptime bit_count: u8) type { | 819 | pub 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 | |||
| 886 | test Float { | 829 | test 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 | } |
| 892 | 836 | ||
| ... | @@ -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 | } |
| 914 | 858 | ||
| 915 | return CreateUniqueTuple(argument_field_list.len, argument_field_list); | 859 | return Tuple(&argument_field_list); |
| 916 | } | 860 | } |
| 917 | 861 | ||
| 918 | /// For a given anonymous list of types, returns a new tuple type | 862 | /// 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 }` | ||
| 925 | pub fn Tuple(comptime types: []const type) type { | 865 | pub fn Tuple(comptime types: []const type) type { |
| 926 | return CreateUniqueTuple(types.len, types[0..types.len].*); | 866 | return @Tuple(types); |
| 927 | } | ||
| 928 | |||
| 929 | fn 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 | } |
| 952 | 868 | ||
| 953 | const TupleTester = struct { | 869 | const 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 { |
| 20 | 20 | ||
| 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 | }; |
| 42 | 34 | ||
| 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 | } |
| 610 | 615 | ||
| 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 the | 630 | /// 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 | } |
| 1044 | 1033 | ||
| 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 { |
| 124 | 124 | ||
| 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 { |
| 773 | pub const SimpleComptimeReason = enum(u32) { | 773 | pub 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, | ||
| 823 | 835 | ||
| 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, |
| 832 | 840 | ||
| 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: off | 866 | // 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", |
| 889 | 896 | ||
| 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", | ||
| 902 | 922 | ||
| 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", |
| 910 | 926 | ||
| 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 | }, |
| 838 | 838 | ||
| 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` error | 1205 | 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; |
| 1407 | 1413 | ||
| 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); |
| 1410 | 1416 | ||
| 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).?; |
| 2630 | 2636 | ||
| 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 | }, |
| 2635 | 2641 | ||
| ... | @@ -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 | }, |
| 9445 | 9453 | ||
| 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 | } |
| 9767 | fn 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 | } | ||
| 9802 | 9906 | ||
| 9803 | fn hasDeclOrField( | 9907 | fn 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=>strong | 2083 | /// `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 | }; |
| 3171 | 3216 | ||
| 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 | }; |
| 3181 | 3243 | ||
| 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, and | 3262 | /// 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 | }; |
| 3189 | 3294 | ||
| 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 | // Values | 3617 | // 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 | }, |
| 4464 | 4581 | ||
| 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), | ||
| 4467 | 4588 | ||
| 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 types | 5373 | => {}, // tracked in order, as the owner instructions of explicit container types |
| 5251 | else => unreachable, // assertion failure; not trackable | 5374 | 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 | } |
| 82 | 82 | ||
| 83 | /// Constructs a [*c] pointer with the const and volatile annotations | 83 | /// 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. |
| 85 | pub fn FlexibleArrayType(comptime SelfType: type, comptime ElementType: type) type { | 85 | pub 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 | } |
| 102 | 94 | ||
| 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; |
| 221 | 213 | ||
| 222 | const Int = @Type(.{ .int = .{ .bits = dest.bits, .signedness = source.signedness } }); | 214 | const Int = @Int(source.signedness, dest.bits); |
| 223 | 215 | ||
| 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"; |
| 8643 | 8622 | ||
| 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 | } |
| 1207 | 1186 | ||
| 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 some | 2001 | /// 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, |
| 4643 | 4621 | ||
| 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 | } }, |
| 5203 | 5188 | ||
| 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 | } |
| 10226 | 10250 | ||
| 10227 | pub const OpaqueTypeInit = struct { | 10251 | pub 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 | }; |
| 10239 | 10255 | ||
| 10240 | pub fn getOpaqueType( | 10256 | pub 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 }; |
| 10258 | 10268 | ||
| ... | @@ -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); |
| 10263 | 10273 | ||
| 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, |
| 12361 | 12371 | ||
| 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, |
| 12410 | 12420 | ||
| 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: on | 1437 | // zig fmt: on |
| 1428 | 1438 | ||
| 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; |
| 3518 | 3528 | ||
| 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); |
| 7387 | 7395 | ||
| 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 | } }; |
| 7392 | 7400 | ||
| ... | @@ -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; |
| 7471 | 7479 | ||
| 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 | } }; |
| 7476 | 7484 | ||
| ... | @@ -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; |
| 8929 | 8937 | ||
| 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 | } |
| 9173 | 9181 | ||
| 9182 | fn 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 | |||
| 9247 | fn 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 | |||
| 9174 | fn callConvIsCallable(cc: std.builtin.CallingConvention.Tag) bool { | 9357 | fn 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 | } |
| 9416 | 9501 | ||
| 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 | } |
| 9455 | 9505 | ||
| 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 | |||
| 9472 | fn 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 | } | ||
| 9518 | 9519 | ||
| 9519 | // If the return type is comptime-only but not dependent on parameters then | 9520 | // 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; |
| 9525 | 9526 | 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); |
| 9533 | 9534 | ||
| 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 | } |
| 9558 | 9559 | ||
| 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 | } | ||
| 9570 | 9561 | ||
| 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 | } |
| 9595 | 9583 | ||
| 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 | } |
| 9619 | 9608 | ||
| 9620 | return Air.internedToRef(if (opt_func_index != .none) opt_func_index else func_ty); | 9609 | return .fromIntern(func_ty); |
| 9621 | } | 9610 | } |
| 9622 | 9611 | ||
| 9623 | fn zirParam( | 9612 | fn 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 | } |
| 20555 | 20544 | ||
| 20556 | fn zirReify( | 20545 | fn 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 | |||
| 20555 | fn 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 0 | 20575 | // 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 | }; | ||
| 20707 | 20577 | ||
| 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); | ||
| 20721 | 20582 | ||
| 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); | ||
| 20723 | 20589 | ||
| 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 | } | ||
| 20730 | 20595 | ||
| 20731 | const ty = try pt.ptrTypeSema(.{ | 20596 | fn 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 | ).?); | ||
| 20786 | 20603 | ||
| 20787 | const child_ty = child_val.toType(); | 20604 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; |
| 20788 | 20605 | ||
| 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 | ).?); | ||
| 20802 | 20608 | ||
| 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(); | ||
| 20805 | 20610 | ||
| 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); | ||
| 20809 | 20617 | ||
| 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) orelse | 20622 | } |
| 20815 | return .anyerror_type; | 20623 | |
| 20624 | fn 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 | } | ||
| 20816 | 20641 | ||
| 20817 | const names_val = try sema.derefSliceAsArray(block, src, payload_val, .{ .simple = .error_set_contents }); | 20642 | fn 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; | ||
| 20818 | 20649 | ||
| 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 | } | ||
| 20839 | 20652 | ||
| 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 | ).?); | ||
| 20923 | 20658 | ||
| 20924 | // Decls | 20659 | 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 | } | ||
| 20928 | 20667 | ||
| 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); | ||
| 20941 | 20670 | ||
| 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); | ||
| 20950 | 20676 | ||
| 20951 | const new_namespace_index = try pt.createNamespace(.{ | 20677 | fn 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; | ||
| 20957 | 20686 | ||
| 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; | ||
| 20980 | 20710 | ||
| 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); | ||
| 20985 | 20712 | ||
| 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 | } | ||
| 20987 | 20729 | ||
| 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 | } | ||
| 20995 | 20739 | ||
| 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 | } | ||
| 20997 | 20756 | ||
| 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); | ||
| 21041 | 20773 | ||
| 21042 | var noalias_bits: u32 = 0; | 20774 | fn 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 | |
| 21058 | 20790 | 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); |
| 21062 | 20794 | 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) orelse | 20795 | 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 | |
| 21066 | 20798 | 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) orelse | 20803 | })); |
| 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 | } | ||
| 21075 | 20845 | ||
| 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 | } |
| 21088 | 20875 | ||
| 21089 | fn reifyEnum( | 20876 | fn 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; |
| 21103 | 20886 | ||
| 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 }); | ||
| 21105 | 20963 | ||
| 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 | } | ||
| 21107 | 20980 | ||
| 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 the | 20982 | // 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. |
| 21111 | 20984 | ||
| 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! |
| 21118 | 20995 | 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 | ).?); | ||
| 21121 | 21018 | ||
| 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; |
| 21124 | 21021 | 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 | }; | ||
| 21126 | 21031 | ||
| 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 | } |
| 21132 | 21043 | ||
| 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 | } | ||
| 21134 | 21058 | ||
| 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 | } | ||
| 21157 | 21081 | ||
| 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); |
| 21166 | 21090 | ||
| 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; | ||
| 21180 | 21092 | ||
| 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); | ||
| 21183 | 21096 | ||
| 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)); | ||
| 21186 | 21098 | ||
| 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 | } | ||
| 21189 | 21128 | ||
| 21190 | if (!try sema.intFitsInType(field_value_val, tag_ty, null)) { | 21129 | const field_default: InternPool.Index = d: { |
| 21191 | // TODO: better source location | 21130 | 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 | } |
| 21198 | 21149 | ||
| 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 incorrect | 21177 | 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 incorrect | 21186 | 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 | } |
| 21219 | 21193 | ||
| 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 | } |
| 21223 | 21209 | ||
| 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 | } |
| 21233 | 21230 | ||
| 21234 | fn reifyUnion( | 21231 | fn 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; |
| 21248 | 21241 | ||
| 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 }); | ||
| 21250 | 21318 | ||
| 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 | } | ||
| 21252 | 21335 | ||
| 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 the | 21337 | // 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. |
| 21256 | 21339 | ||
| 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! |
| 21263 | 21348 | 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); |
| 21266 | 21354 | 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)); | ||
| 21270 | 21356 | ||
| 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 | } |
| 21278 | 21367 | ||
| 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 | } | ||
| 21280 | 21379 | ||
| 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 | .tagged | 21385 | if (explicit_tag_ty != null) break :rt .tagged; |
| 21287 | else if (layout != .auto) | 21386 | if (layout == .auto and block.wantSafeTypes()) break :rt .safety; |
| 21288 | .none | 21387 | 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 validated | 21396 | .enum_tag_ty = .none, // set later because not yet validated |
| 21301 | .field_types = &.{}, // set later | 21397 | .field_types = &.{}, // set later |
| 21302 | .field_aligns = &.{}, // set later | 21398 | .field_aligns = &.{}, // set later |
| ... | @@ -21325,128 +21421,117 @@ fn reifyUnion( | ... | @@ -21325,128 +21421,117 @@ fn reifyUnion( |
| 21325 | 21421 | ||
| 21326 | const loaded_union = ip.loadUnionType(wip_ty.index); | 21422 | const loaded_union = ip.loadUnionType(wip_ty.index); |
| 21327 | 21423 | ||
| 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(); | ||
| 21334 | 21428 | ||
| 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); | ||
| 21338 | 21430 | ||
| 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); | ||
| 21341 | 21435 | ||
| 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); | ||
| 21360 | 21441 | ||
| 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 | }); |
| 21383 | 21462 | 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); |
| 21389 | 21467 | ||
| 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); |
| 21392 | 21470 | // 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 location | 21474 | // 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 error | 21481 | errdefer if (!has_explicit_tag) ip.remove(pt.tid, enum_tag_ty); // remove generated tag type on error |
| 21418 | 21482 | ||
| 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); | ||
| 21434 | 21500 | ||
| 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); | ||
| 21436 | 21509 | ||
| 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); | ||
| 21444 | 21518 | ||
| 21445 | try sema.explainWhyTypeIsNotPacked(msg, src, field_ty); | 21519 | try sema.explainWhyTypeIsNotPacked(msg, field_types_src, field_ty); |
| 21446 | 21520 | ||
| 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 | } |
| 21452 | 21537 | ||
| ... | @@ -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 | } |
| 21476 | 21561 | ||
| 21477 | fn reifyTuple( | 21562 | fn 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; |
| 21487 | 21572 | ||
| 21488 | const fields_len: u32 = @intCast(fields_val.typeOf(zcu).arrayLen(zcu)); | 21573 | const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small); |
| 21489 | 21574 | 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 = .{ |
| 21492 | 21577 | .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; | ||
| 21518 | 21580 | ||
| 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 | }; | ||
| 21533 | 21609 | ||
| 21534 | try sema.validateTupleFieldType(block, field_type, src); | 21610 | const enum_mode_ty = try sema.getBuiltinType(mode_src, .@"Type.Enum.Mode"); |
| 21535 | 21611 | ||
| 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 | } | ||
| 21547 | 21616 | ||
| 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 | }; | ||
| 21551 | 21624 | ||
| 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 }); | ||
| 21555 | 21629 | ||
| 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 | } | ||
| 21559 | 21631 | ||
| 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 | |||
| 21566 | fn 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; | ||
| 21580 | 21636 | ||
| 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 }); | ||
| 21582 | 21641 | ||
| 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. | ||
| 21584 | 21647 | ||
| 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 the | 21649 | // 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); |
| 21595 | 21658 | // `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 |
| 21598 | 21661 | // 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); |
| 21601 | 21664 | 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 | } |
| 21636 | 21667 | ||
| 21637 | const tracked_inst = try block.trackZir(inst); | 21668 | const wip_ty = switch (try ip.getEnumType(gpa, pt.tid, .{ |
| 21638 | 21669 | .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); | ||
| 21661 | 21686 | ||
| 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); |
| 21670 | 21695 | ||
| 21671 | const struct_type = ip.loadStructType(wip_ty.index); | 21696 | const new_namespace_index = try pt.createNamespace(.{ |
| 21672 | 21697 | .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), |
| 21675 | 21700 | .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); | ||
| 21751 | 21702 | ||
| 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; | ||
| 21753 | 21709 | ||
| 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); | ||
| 21761 | 21714 | ||
| 21762 | try sema.explainWhyTypeIsNotPacked(msg, src, field_ty); | 21715 | const field_val = try field_values_arr.elemValue(pt, field_idx); |
| 21763 | 21716 | ||
| 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 | } |
| 21769 | 21736 | ||
| 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 | } |
| 21794 | 21740 | ||
| 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 | } |
| 21815 | 21750 | ||
| 21816 | fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref { | 21751 | fn 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); |
| 23971 | 23906 | ||
| 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); |
| 23983 | 23918 | ||
| 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; |
| 25543 | 25478 | ||
| 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); |
| 25970 | 25905 | ||
| 25971 | const ty = switch (value) { | 25906 | const builtin_type: Zcu.BuiltinDecl = switch (value) { |
| 25972 | // zig fmt: off | 25907 | // 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: on | 25926 | // zig fmt: on |
| 25987 | 25927 | ||
| 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 | } |
| 26014 | 25954 | ||
| 26015 | fn zirInplaceArithResultTy(sema: *Sema, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { | 25955 | fn 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( |
| 37230 | 37175 | ||
| 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. |
| 37234 | fn derefSliceAsArray( | 37179 | fn 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( |
| 37247 | 37192 | ||
| 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. |
| 37251 | fn maybeDerefSliceAsArray( | 37196 | fn 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)}), |
| 319 | 319 | ||
| 320 | .enum_literal => try writer.writeAll("@Type(.enum_literal)"), | 320 | .enum_literal => try writer.writeAll("@EnumLiteral()"), |
| 321 | 321 | ||
| 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 }; |
| 4280 | pub const manyptr_const_u8_sentinel_0: Type = .{ .ip_index = .manyptr_const_u8_sentinel_0_type }; | 4282 | pub const manyptr_const_u8_sentinel_0: Type = .{ .ip_index = .manyptr_const_u8_sentinel_0_type }; |
| 4281 | pub const slice_const_u8: Type = .{ .ip_index = .slice_const_u8_type }; | 4283 | pub const slice_const_u8: Type = .{ .ip_index = .slice_const_u8_type }; |
| 4282 | pub const slice_const_u8_sentinel_0: Type = .{ .ip_index = .slice_const_u8_sentinel_0_type }; | 4284 | pub const slice_const_u8_sentinel_0: Type = .{ .ip_index = .slice_const_u8_sentinel_0_type }; |
| 4285 | pub const slice_const_slice_const_u8: Type = .{ .ip_index = .slice_const_slice_const_u8_type }; | ||
| 4286 | pub const slice_const_type: Type = .{ .ip_index = .slice_const_type_type }; | ||
| 4287 | pub const optional_type: Type = .{ .ip_index = .optional_type_type }; | ||
| 4288 | pub const optional_noreturn: Type = .{ .ip_index = .optional_noreturn_type }; | ||
| 4283 | 4289 | ||
| 4284 | pub const vector_8_i8: Type = .{ .ip_index = .vector_8_i8_type }; | 4290 | pub const vector_8_i8: Type = .{ .ip_index = .vector_8_i8_type }; |
| 4285 | pub const vector_16_i8: Type = .{ .ip_index = .vector_16_i8_type }; | 4291 | pub 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 | }, |
| 1771 | 1783 | ||
| 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, |
| 8929 | 8929 | ||
| 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 | }; |
| 8938 | 8942 | ||
| 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 | }, |
| 8950 | 8954 | ||
| 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 | }; |
| 8959 | 8967 | ||
| 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 | }, |
| 1527 | 1530 | ||
| 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 | } |
| 189868 | 189868 | ||
| 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 { |
| 51 | 51 | ||
| 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 | }; |
| 59 | 56 | ||
| 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 { |
| 5125 | 5130 | ||
| 5126 | fn DeclValEnum(comptime T: type) type { | 5131 | fn 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 | } |
| 5148 | 5151 | ||
| 5149 | const AbbrevCode = enum { | 5152 | const AbbrevCode = enum { |
| ... | @@ -6377,10 +6380,12 @@ fn freeCommonEntry( | ... | @@ -6377,10 +6380,12 @@ fn freeCommonEntry( |
| 6377 | 6380 | ||
| 6378 | fn writeInt(dwarf: *Dwarf, buf: []u8, int: u64) void { | 6381 | fn 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 | }; |
| 116 | 113 | ||
| 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 | }, |
| 130 | 124 | ||
| 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 | } }); | ||
| 138 | 130 | ||
| 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; |
| 136 | 136 | ||
| 137 | pub fn log( | 137 | pub 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 | }, |
| 577 | 580 | ||
| 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 | }, |
| 603 | 596 | ||
| 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 | } |
| 1266 | 1266 | ||
| 1267 | test "@Type returned from block" { | 1267 | test "@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; |
| 120 | 120 | ||
| 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, |
| 135 | 126 | ||
| 136 | const ShiftType: type = getIntShiftType(ValueType); | 127 | const ShiftType = @Int(.signed, @typeInfo(std.math.Log2Int(ValueType)).int.bits); |
| 137 | 128 | ||
| 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 | } |
| 357 | 357 | ||
| 358 | test "Enum constructed by @Type passed as generic argument" { | 358 | test "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 | }; |
| 2447 | 2447 | ||
| 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" { |
| 1283 | test "matching captures causes enum equivalence" { | 1283 | test "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" { |
| 556 | 556 | ||
| 557 | test "pass and return comptime-only types" { | 557 | test "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" { |
| 263 | 263 | ||
| 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" { |
| 338 | 338 | ||
| 339 | test "@sizeOf reified union zero-size payload fields" { | 339 | test "@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; |
| 844 | 844 | ||
| 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); | ||
| 847 | 848 | ||
| 848 | comptime assert(T1 != T2); | 849 | comptime assert(T1 != T2); |
| 849 | 850 | ||
| ... | @@ -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; |
| 866 | 867 | ||
| 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); | ||
| 869 | 871 | ||
| 870 | comptime assert(T1 != T2); | 872 | comptime assert(T1 != T2); |
| 871 | 873 |
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; |
| 232 | 232 | ||
| 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; // TODO | 130 | 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; |
| 132 | 132 | ||
| 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 {}; |
| 322 | 300 | ||
| 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 | }), | ||
| 337 | 302 | ||
| 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 | } |
| 471 | 436 | ||
| 472 | test "empty tuple type" { | 437 | test "empty tuple type" { |
| 473 | const S = @Type(.{ .@"struct" = .{ | 438 | const S = @Tuple(&.{}); |
| 474 | .layout = .auto, | ||
| 475 | .fields = &.{}, | ||
| 476 | .decls = &.{}, | ||
| 477 | .is_tuple = true, | ||
| 478 | } }); | ||
| 479 | 439 | ||
| 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); |
| 618 | 578 | ||
| 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; |
| 4 | const testing = std.testing; | 4 | const testing = std.testing; |
| 5 | const assert = std.debug.assert; | 5 | const assert = std.debug.assert; |
| 6 | 6 | ||
| 7 | fn testTypes(comptime types: []const type) !void { | ||
| 8 | inline for (types) |testType| { | ||
| 9 | try testing.expect(testType == @Type(@typeInfo(testType))); | ||
| 10 | } | ||
| 11 | } | ||
| 12 | |||
| 13 | test "Type.MetaType" { | ||
| 14 | try testing.expect(type == @Type(.{ .type = {} })); | ||
| 15 | try testTypes(&[_]type{type}); | ||
| 16 | } | ||
| 17 | |||
| 18 | test "Type.Void" { | ||
| 19 | try testing.expect(void == @Type(.{ .void = {} })); | ||
| 20 | try testTypes(&[_]type{void}); | ||
| 21 | } | ||
| 22 | |||
| 23 | test "Type.Bool" { | ||
| 24 | try testing.expect(bool == @Type(.{ .bool = {} })); | ||
| 25 | try testTypes(&[_]type{bool}); | ||
| 26 | } | ||
| 27 | |||
| 28 | test "Type.NoReturn" { | ||
| 29 | try testing.expect(noreturn == @Type(.{ .noreturn = {} })); | ||
| 30 | try testTypes(&[_]type{noreturn}); | ||
| 31 | } | ||
| 32 | |||
| 33 | test "Type.Int" { | 7 | test "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 | |||
| 43 | test "Type.ComptimeFloat" { | ||
| 44 | try testTypes(&[_]type{comptime_float}); | ||
| 45 | } | ||
| 46 | test "Type.ComptimeInt" { | ||
| 47 | try testTypes(&[_]type{comptime_int}); | ||
| 48 | } | ||
| 49 | test "Type.Undefined" { | ||
| 50 | try testTypes(&[_]type{@TypeOf(undefined)}); | ||
| 51 | } | ||
| 52 | test "Type.Null" { | ||
| 53 | try testTypes(&[_]type{@TypeOf(null)}); | ||
| 54 | } | ||
| 55 | |||
| 56 | test "Type.EnumLiteral" { | ||
| 57 | try testTypes(&[_]type{ | ||
| 58 | @TypeOf(.Dummy), | ||
| 59 | }); | ||
| 60 | } | 14 | } |
| 61 | 15 | ||
| 62 | test "Type.Pointer" { | 16 | test "Type.Pointer" { |
| 63 | try testTypes(&[_]type{ | 17 | inline for (&[_]type{ |
| 64 | // One Value Pointer Types | 18 | // 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 | } |
| 106 | 69 | ||
| 107 | test "Type.Float" { | 70 | test "@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 | } |
| 115 | 74 | ||
| 116 | test "Type.Array" { | 75 | test "@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 | } |
| 140 | 79 | ||
| 141 | test "@Type create slice with null sentinel" { | 80 | test "@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 | |||
| 157 | test "@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; |
| 184 | 106 | try testing.expect(TestType == @Pointer(ptr.size, .{ | |
| 185 | test "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 | |||
| 195 | test "Type.ErrorUnion" { | ||
| 196 | try testTypes(&[_]type{ | ||
| 197 | error{}!void, | ||
| 198 | error{Error}!void, | ||
| 199 | }); | ||
| 200 | } | 114 | } |
| 201 | 115 | ||
| 202 | test "Type.Opaque" { | 116 | test "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; // TODO | 119 | 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; |
| 207 | 121 | ||
| 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 | } |
| 220 | 130 | ||
| 221 | test "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 | |||
| 232 | test "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 | |||
| 245 | fn add(a: i32, b: i32) i32 { | 131 | fn add(a: i32, b: i32) i32 { |
| 246 | return a + b; | 132 | return a + b; |
| 247 | } | 133 | } |
| 248 | 134 | ||
| 249 | test "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 | |||
| 260 | test "Type.Struct" { | 135 | test "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; // TODO | 137 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 263 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 138 | 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; |
| 265 | 140 | ||
| 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); |
| 283 | 158 | ||
| 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); |
| 295 | 176 | ||
| 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); |
| 307 | 197 | ||
| 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 struct | 198 | // 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 | } |
| 348 | 205 | ||
| 349 | test "Type.Enum" { | 206 | test "Type.Enum" { |
| 350 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 207 | 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; |
| 352 | 209 | ||
| 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" { |
| 382 | 219 | ||
| 383 | { // from https://github.com/ziglang/zig/issues/19985 | 220 | { // 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; // TODO | 243 | 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; |
| 413 | 245 | ||
| 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); |
| 429 | 251 | ||
| 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); |
| 445 | 257 | ||
| 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 | } |
| 473 | 265 | ||
| 474 | test "Type.Union from Type.Enum" { | 266 | test "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 | } |
| 497 | 271 | ||
| 498 | test "Type.Union from regular enum" { | 272 | test "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 | } |
| 512 | 277 | ||
| 513 | test "Type.Union from empty regular enum" { | 278 | test "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 | } |
| 525 | 283 | ||
| 526 | test "Type.Union from empty Type.Enum" { | 284 | test "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 | } |
| 545 | 289 | ||
| ... | @@ -548,47 +292,22 @@ test "Type.Fn" { | ... | @@ -548,47 +292,22 @@ test "Type.Fn" { |
| 548 | 292 | ||
| 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 | } | ||
| 568 | 295 | ||
| 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 | } |
| 575 | 305 | ||
| 576 | test "reified struct field name from optional payload" { | 306 | test "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" { |
| 598 | test "reified union uses @alignOf" { | 317 | test "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" { |
| 620 | test "reified struct uses @alignOf" { | 326 | test "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 | } |
| 647 | 344 | ||
| 648 | test "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 | } | ||
| 661 | test "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 | |||
| 681 | test "empty struct assigned to reified struct field" { | 345 | test "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 | } |
| 699 | 350 | ||
| 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 | } |
| 712 | 363 | ||
| 713 | test "@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 | |||
| 723 | test "struct field names sliced at comptime from larger string" { | 364 | test "struct field names sliced at comptime from larger string" { |
| 724 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 365 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 725 | 366 | ||
| ... | @@ -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 | \\f3 | 370 | \\f3 |
| 730 | ; | 371 | ; |
| 731 | comptime { | 372 | comptime { |
| 732 | var fields: []const Type.StructField = &[0]Type.StructField{}; | 373 | var field_names: []const []const u8 = &.{}; |
| 733 | 374 | ||
| 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 | } |
| 744 | 379 | ||
| 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" { |
| 762 | test "matching captures causes opaque equivalence" { | 389 | test "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 | } |
| 786 | 410 | ||
| 787 | test "reify enum where fields refers to part of array" { | 411 | test "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 | } |
| 37 | pub fn AsSignedness(comptime Type: type, comptime signedness: std.builtin.Signedness) type { | 37 | pub 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 | } |
| 47 | pub fn AddOneBit(comptime Type: type) type { | 44 | pub 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 | } |
| 54 | pub fn DoubleBits(comptime Type: type) type { | 51 | pub 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 | } |
| 61 | pub fn RoundBitsUp(comptime Type: type, comptime multiple: u16) type { | 58 | pub 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 { |
| 83 | pub fn sign(rhs: anytype) ChangeScalar(@TypeOf(rhs), bool) { | 77 | pub 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 optionals | 116 | // tmp.zig:85:26: note: ZON does not allow nested optionals |
| 117 | // tmp.zig:90:29: error: type '*i32' is not available in ZON | 117 | // tmp.zig:90:29: error: type '*i32' is not available in ZON |
| 118 | // tmp.zig:90:29: note: ZON does not allow mutable pointers | 118 | // 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 here | 120 | // 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 here | 122 | // 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 here | 70 | // 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 here | 72 | // 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 here | 74 | // 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 here | 76 | // 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 | } |
| 39 | 39 | ||
| 40 | export fn j() void { | 40 | export 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 | } |
| 54 | 43 | ||
| 55 | export fn k() void { | 44 | export 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 | } |
| 67 | 47 | ||
| 68 | // error | 48 | // error |
| ... | @@ -76,5 +56,5 @@ export fn k() void { | ... | @@ -76,5 +56,5 @@ export fn k() void { |
| 76 | // :29:17: error: alignment must be >= 1 | 56 | // :29:17: error: alignment must be >= 1 |
| 77 | // :33:35: error: alignment must be >= 1 | 57 | // :33:35: error: alignment must be >= 1 |
| 78 | // :37:34: error: alignment must be >= 1 | 58 | // :37:34: error: alignment must be >= 1 |
| 79 | // :41:9: error: alignment must be >= 1 | 59 | // :41:51: error: alignment must be >= 1 |
| 80 | // :56:9: error: alignment must be >= 1 | 60 | // :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 { |
| 6 | 6 | ||
| 7 | // error | 7 | // 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 @@ | ||
| 1 | const builtin = @import("std").builtin; | ||
| 2 | comptime { | ||
| 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 @@ | ||
| 1 | export 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 { |
| 6 | 6 | ||
| 7 | // error | 7 | // 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 | } |
| 10 | 10 | ||
| 11 | export fn d() void { | 11 | export 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 | } |
| 23 | export fn e() void { | 14 | export 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 | } |
| 35 | export fn f() void { | 17 | export 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 | } |
| 47 | 20 | ||
| 48 | // error | 21 | // 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 allowed | 24 | // :5:12: error: indexable pointer to opaque type 'anyopaque' not allowed |
| 52 | // :8:13: error: indexable pointer to opaque type 'anyopaque' not allowed | 25 | // :8:13: error: indexable pointer to opaque type 'anyopaque' not allowed |
| 53 | // :12:9: error: indexable pointer to opaque type 'anyopaque' not allowed | 26 | // :12:9: error: indexable pointer to opaque type 'anyopaque' not allowed |
| 54 | // :24:9: error: indexable pointer to opaque type 'anyopaque' not allowed | 27 | // :15:9: error: indexable pointer to opaque type 'anyopaque' not allowed |
| 55 | // :36:9: error: indexable pointer to opaque type 'anyopaque' not allowed | 28 | // :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 @@ |
| 1 | export fn entry() void { | 1 | export 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 | } |
| 13 | 4 | ||
| 14 | // error | 5 | // error |
| 15 | // | 6 | // |
| 16 | // :2:9: error: sentinels are only allowed on slices and unknown-length pointers | 7 | // :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 here | 37 | // :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 @@ |
| 1 | export fn entry() void { | 1 | export 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 | } |
| 7 | 7 | ||
| 8 | // error | 8 | // 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 value | 15 | // :6:12: error: unable to resolve comptime value |
| 16 | // :2:12: note: called at comptime from here | 16 | // :2:12: note: called at comptime from here |
| 17 | // :1:13: note: struct fields must be comptime-known | 17 | // :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 | } |
| 13 | 13 | ||
| 14 | comptime { | 14 | comptime { |
| 15 | _ = @Type(.{ .array = .{ .child = S, .len = 0, .sentinel_ptr = &sentinel } }); | 15 | _ = @Pointer(.slice, .{}, S, sentinel); |
| 16 | } | 16 | } |
| 17 | comptime { | 17 | comptime { |
| 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 | } | ||
| 29 | comptime { | ||
| 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 | } |
| 41 | 20 | ||
| 42 | // error | 21 | // error |
| ... | @@ -47,9 +26,7 @@ comptime { | ... | @@ -47,9 +26,7 @@ comptime { |
| 47 | // :1:11: note: struct declared here | 26 | // :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 here | 28 | // :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 here | 30 | // :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 here | 32 | // :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 @@ |
| 1 | comptime { | 1 | comptime { |
| 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 | } |
| 14 | 5 | ||
| 15 | // error | 6 | // 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 @@ |
| 1 | export fn entry() void { | 1 | export 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 | } |
| 14 | 4 | ||
| 15 | // error | 5 | // 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 here | 8 | // :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 @@ |
| 1 | export fn entry() void { | 1 | export 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 | } |
| 14 | 4 | ||
| 15 | // error | 5 | // error |
| 16 | // | 6 | // |
| 17 | // :2:9: error: enum tag value 10 already taken | 7 | // :2:52: error: enum tag value 10 already taken |
| 18 | // :2:9: note: other enum tag value here | 8 | // :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 @@ |
| 1 | comptime { | 1 | comptime { |
| 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 | } |
| 15 | comptime { | 4 | comptime { |
| 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 | } |
| 29 | comptime { | 7 | comptime { |
| 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 | } | ||
| 43 | comptime { | ||
| 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 | } | ||
| 57 | comptime { | ||
| 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 | } |
| 71 | 10 | ||
| 72 | // error | 11 | // 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 0 | 14 | // :5:51: error: extern struct fields cannot be marked comptime |
| 76 | // :30:5: error: comptime field without default initialization value | 15 | // :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 | ||
| 79 | 16 |
test/cases/compile_errors/reify_type.Fn_with_is_generic_true.zig deleted-16| ... | @@ -1,16 +0,0 @@ | ||
| 1 | const 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 | }); | ||
| 10 | comptime { | ||
| 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 @@ |
| 1 | const 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 | }); | ||
| 10 | comptime { | 1 | comptime { |
| 11 | _ = Foo; | 2 | _ = @Fn(&.{u32}, &.{.{}}, u8, .{ .varargs = true }); |
| 12 | } | 3 | } |
| 13 | 4 | ||
| 14 | // error | 5 | // error |
| 15 | // target=x86_64-linux | 6 | // target=x86_64-linux |
| 16 | // | 7 | // |
| 17 | // :1:13: error: variadic function does not support 'auto' calling convention | 8 | // :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 @@ | ||
| 1 | const 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 | }); | ||
| 10 | comptime { | ||
| 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 @@ |
| 1 | const Tag = @Type(.{ | 1 | const Tag = @Enum(bool, .nonexhaustive, &.{}, &.{}); |
| 2 | .@"enum" = .{ | ||
| 3 | .tag_type = bool, | ||
| 4 | .fields = &.{}, | ||
| 5 | .decls = &.{}, | ||
| 6 | .is_exhaustive = false, | ||
| 7 | }, | ||
| 8 | }); | ||
| 9 | export fn entry() void { | 2 | export fn entry() void { |
| 10 | _ = @as(Tag, @enumFromInt(0)); | 3 | _ = @as(Tag, @enumFromInt(0)); |
| 11 | } | 4 | } |
| 12 | 5 | ||
| 13 | // error | 6 | // error |
| 14 | // | 7 | // |
| 15 | // :1:13: error: Type.Enum.tag_type must be an integer type | 8 | // :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 @@ |
| 1 | const Tag = @Type(.{ | 1 | const Tag = @Enum(undefined, .exhaustive, &.{}, &.{}); |
| 2 | .@"enum" = .{ | ||
| 3 | .tag_type = undefined, | ||
| 4 | .fields = &.{}, | ||
| 5 | .decls = &.{}, | ||
| 6 | .is_exhaustive = false, | ||
| 7 | }, | ||
| 8 | }); | ||
| 9 | export fn entry() void { | 2 | export fn entry() void { |
| 10 | _ = @as(Tag, @enumFromInt(0)); | 3 | _ = @as(Tag, @enumFromInt(0)); |
| 11 | } | 4 | } |
| 12 | 5 | ||
| 13 | // error | 6 | // error |
| 14 | // | 7 | // |
| 15 | // :1:20: error: use of undefined value here causes illegal behavior | 8 | // :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 @@ |
| 1 | const Tag = @Type(.{ | 1 | const Tag = @Enum(u2, .exhaustive, &.{ "signed", "unsigned" }, &.{ 0, 1 }); |
| 2 | .@"enum" = .{ | 2 | const 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 | |||
| 13 | const 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 | }); | ||
| 24 | 3 | ||
| 25 | export fn entry() void { | 4 | export 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 { |
| 29 | 8 | ||
| 30 | // error | 9 | // error |
| 31 | // | 10 | // |
| 32 | // :13:16: error: extern union does not support enum tag type | 11 | // :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 @@ |
| 1 | const Tag = @Type(.{ | 1 | const Tag = @Enum(u2, .exhaustive, &.{ "signed", "unsigned" }, &.{ 0, 1 }); |
| 2 | .@"enum" = .{ | 2 | const 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 | |||
| 13 | const 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 | }); | ||
| 24 | 3 | ||
| 25 | export fn entry() void { | 4 | export 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 { |
| 29 | 8 | ||
| 30 | // error | 9 | // error |
| 31 | // | 10 | // |
| 32 | // :13:16: error: packed union does not support enum tag type | 11 | // :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 @@ |
| 1 | const Tag = @Type(.{ | 1 | const Tag = @Enum(u2, .exhaustive, &.{ "signed", "unsigned", "arst" }, &.{ 0, 1, 2 }); |
| 2 | .@"enum" = .{ | 2 | const 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 | }); | ||
| 13 | const 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 | }); | ||
| 24 | export fn entry() void { | 3 | export 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 { |
| 28 | 7 | ||
| 29 | // error | 8 | // error |
| 30 | // | 9 | // |
| 31 | // :13:16: error: enum fields missing in union | 10 | // :2:35: error: 1 enum fields missing in union |
| 32 | // :1:13: note: field 'arst' missing, declared here | 11 | // :1:13: note: field 'arst' missing, declared here |
| 33 | // :1:13: note: enum declared here | 12 | // :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 @@ |
| 1 | const Tag = @Type(.{ | 1 | const Tag = @Enum(u1, .exhaustive, &.{ "signed", "unsigned" }, &.{ 0, 1 }); |
| 2 | .@"enum" = .{ | 2 | const 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 | }); | ||
| 12 | const 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 | }); | ||
| 24 | export fn entry() void { | 3 | export 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 { |
| 28 | 7 | ||
| 29 | // error | 8 | // 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 here | 11 | // :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 @@ |
| 1 | const Tag = @Type(.{ | 1 | const Tag = @Enum(u0, .exhaustive, &.{}, &.{}); |
| 2 | .@"enum" = .{ | 2 | const Tagged = @Union(.auto, Tag, &.{ "signed", "unsigned" }, &.{ i32, u32 }, &@splat(.{})); |
| 3 | .tag_type = u0, | ||
| 4 | .fields = &.{}, | ||
| 5 | .decls = &.{}, | ||
| 6 | .is_exhaustive = true, | ||
| 7 | }, | ||
| 8 | }); | ||
| 9 | const 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 | }); | ||
| 20 | export fn entry() void { | 3 | export 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 { |
| 24 | 7 | ||
| 25 | // error | 8 | // 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 here | 11 | // :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 @@ |
| 1 | const Tag = @Type(.{ | 1 | const Tag = @Enum(u1, .exhaustive, &.{ "signed", "unsigned" }, &.{ 0, 1 }); |
| 2 | .@"enum" = .{ | 2 | const 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 | }); | ||
| 12 | const Tagged = @Type(.{ | ||
| 13 | .@"union" = .{ | ||
| 14 | .layout = .auto, | ||
| 15 | .tag_type = Tag, | ||
| 16 | .fields = &.{}, | ||
| 17 | .decls = &.{}, | ||
| 18 | }, | ||
| 19 | }); | ||
| 20 | export fn entry() void { | 3 | export 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 { |
| 24 | 7 | ||
| 25 | // error | 8 | // error |
| 26 | // | 9 | // |
| 27 | // :12:16: error: enum fields missing in union | 10 | // :2:35: error: 2 enum fields missing in union |
| 28 | // :1:13: note: field 'signed' missing, declared here | 11 | // :1:13: note: field 'signed' missing, declared here |
| 29 | // :1:13: note: field 'unsigned' missing, declared here | 12 | // :1:13: note: field 'unsigned' missing, declared here |
| 30 | // :1:13: note: enum declared here | 13 | // :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 @@ |
| 1 | const Untagged = @Type(.{ | 1 | const 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 | }); | ||
| 11 | export fn entry() usize { | 2 | export fn entry() usize { |
| 12 | return @sizeOf(Untagged); | 3 | return @sizeOf(Untagged); |
| 13 | } | 4 | } |
| 14 | 5 | ||
| 15 | // error | 6 | // error |
| 16 | // | 7 | // |
| 17 | // :1:18: error: opaque types have unknown size and therefore cannot be directly embedded in unions | 8 | // :1:49: error: opaque types have unknown size and therefore cannot be directly embedded in unions |
| 18 | // :6:39: note: opaque declared here | 9 | // :1:52: note: opaque declared here |
test/cases/compile_errors/reify_type_union_payload_is_undefined.zig deleted-10| ... | @@ -1,10 +0,0 @@ | ||
| 1 | const Foo = @Type(.{ | ||
| 2 | .@"struct" = undefined, | ||
| 3 | }); | ||
| 4 | comptime { | ||
| 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 @@ | ||
| 1 | const builtin = @import("std").builtin; | ||
| 2 | export 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 @@ |
| 1 | comptime { | 1 | comptime { |
| 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 | } |
| 13 | comptime { | 4 | comptime { |
| 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 | } |
| 29 | comptime { | 7 | comptime { |
| 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 | } |
| 43 | 10 | ||
| 44 | // error | 11 | // error |
| 45 | // | 12 | // |
| 46 | // :2:9: error: alignment value '3' is not a power of two | 13 | // :2:51: error: alignment value '3' is not a power of two |
| 47 | // :14:9: error: alignment value '5' is not a power of two | 14 | // :5:48: error: alignment value '5' is not a power of two |
| 48 | // :30:9: error: alignment value '7' is not a power of two | 15 | // :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 @@ |
| 1 | comptime { | 1 | comptime { |
| 2 | _ = @Type(.{ .array = .{ .len = 0, .child = u8, .sentinel_ptr = undefined } }); | 2 | _ = @Struct(.auto, null, &.{}, &.{}, undefined); |
| 3 | } | 3 | } |
| 4 | comptime { | 4 | comptime { |
| 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 | } | ||
| 14 | comptime { | ||
| 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 | } |
| 26 | 7 | ||
| 27 | // error | 8 | // error |
| 28 | // | 9 | // |
| 29 | // :2:16: error: use of undefined value here causes illegal behavior | 10 | // :2:42: error: use of undefined value here causes illegal behavior |
| 30 | // :5:16: error: use of undefined value here causes illegal behavior | 11 | // :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 { |
| 7 | 7 | ||
| 8 | // error | 8 | // error |
| 9 | // | 9 | // |
| 10 | // :4:5: error: value with comptime-only type '@Type(.enum_literal)' depends on runtime control flow | 10 | // :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 @@ | ||
| 1 | export 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 @@ |
| 1 | comptime { | 1 | comptime { |
| 2 | const undef: @Type(.enum_literal) = undefined; | 2 | const undef: @EnumLiteral() = undefined; |
| 3 | _ = @tagName(undef); | 3 | _ = @tagName(undef); |
| 4 | } | 4 | } |
| 5 | 5 |
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-known | 42 | // :13:13: note: initializer of container-level variable must be comptime-known |
| 43 | // :22:9: error: unable to evaluate comptime expression | 43 | // :22:9: error: unable to evaluate comptime expression |
| 44 | // :22:21: note: operation is runtime due to this operand | 44 | // :22:21: note: operation is runtime due to this operand |
| 45 | // :21:13: note: enum fields must be comptime-known | 45 | // :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 @@ |
| 1 | export fn entry() void { | 1 | export fn entryI() void { |
| 2 | _ = @Type(0); | 2 | _ = @Int(0, 0); |
| 3 | } | ||
| 4 | |||
| 5 | export fn entryE() void { | ||
| 6 | _ = @Enum(0, 0, 0, 0); | ||
| 7 | } | ||
| 8 | |||
| 9 | export fn entryS() void { | ||
| 10 | _ = @Struct(0, 0, &.{}, &.{}, &.{}); | ||
| 11 | } | ||
| 12 | |||
| 13 | export fn entryU() void { | ||
| 14 | _ = @Union(0, 0, &.{}, &.{}, &.{}); | ||
| 3 | } | 15 | } |
| 4 | 16 | ||
| 5 | // error | 17 | // 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 here | 20 | // :?:?: 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 | } |
| 5 | export 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 | } | ||
| 20 | 5 | ||
| 21 | export fn baz() void { | 6 | export 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 | } |
| 25 | export fn qux() void { | 10 | export 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 | } |
| 40 | 20 | ||
| 41 | // error | 21 | // error |
| 42 | // | 22 | // |
| 43 | // :3:33: error: field default value contains reference to comptime var | 23 | // :3:33: error: field default value contains reference to comptime var |
| 44 | // :2:14: note: '0' points to comptime var declared here | 24 | // :2:14: note: '0' points to comptime var declared here |
| 45 | // :7:9: error: field default value contains reference to comptime var | 25 | // :8:9: error: captured value contains reference to comptime var |
| 46 | // :6:14: note: '0' points to comptime var declared here | 26 | // :7:14: note: 'a' points to comptime var declared here |
| 47 | // :23:9: error: captured value contains reference to comptime var | 27 | // :17:9: error: field default value contains reference to comptime var |
| 48 | // :22:14: note: 'a' points to comptime var declared here | 28 | // :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 | } |
| 5 | export 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 | } | ||
| 13 | 5 | ||
| 14 | export fn baz() void { | 6 | export 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 | } |
| 18 | export fn qux() void { | 10 | export 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 | } |
| 31 | 14 | ||
| 32 | // error | 15 | // error |
| 33 | // | 16 | // |
| 34 | // :3:12: error: sentinel contains reference to comptime var | 17 | // :3:12: error: sentinel contains reference to comptime var |
| 35 | // :2:14: note: 'sentinel' points to comptime var declared here | 18 | // :2:14: note: 'sentinel' points to comptime var declared here |
| 36 | // :7:9: error: sentinel contains reference to comptime var | 19 | // :8:11: error: sentinel contains reference to comptime var |
| 37 | // :6:14: note: 'sentinel_ptr' points to comptime var declared here | 20 | // :7:14: note: 'sentinel' points to comptime var declared here |
| 38 | // :16:11: error: sentinel contains reference to comptime var | 21 | // :12:35: error: sentinel contains reference to comptime var |
| 39 | // :15:14: note: 'sentinel' points to comptime var declared here | 22 | // :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 = .{ |
| 6 | 6 | ||
| 7 | pub fn log( | 7 | pub 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 quota | 3 | // big enums should not hit the eval branch quota |
| 4 | pub fn main() void { | 4 | pub 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 | }; |
| 21 | 19 | ||
| 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; |
| 31 | 29 | ||
| 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; |
| 34 | 34 | ||
| 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', |
| 561 | 561 | ||
| 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(.{})', |