diff options
Diffstat (limited to 'src/type.zig')
| -rw-r--r-- | src/type.zig | 1789 |
1 files changed, 267 insertions, 1522 deletions
diff --git a/src/type.zig b/src/type.zig index f5ce296e4d..c338072c15 100644 --- a/src/type.zig +++ b/src/type.zig @@ -93,9 +93,15 @@ pub const Type = extern union { .anyerror_void_error_union, .error_union => return .ErrorUnion, - .empty_struct => return .Struct, - .empty_struct_literal => return .Struct, - .@"struct" => return .Struct, + .empty_struct, + .empty_struct_literal, + .@"struct", + => return .Struct, + + .enum_full, + .enum_nonexhaustive, + .enum_simple, + => return .Enum, .var_args_param => unreachable, // can be any type } @@ -614,6 +620,8 @@ pub const Type = extern union { .error_set_single => return self.copyPayloadShallow(allocator, Payload.Name), .empty_struct => return self.copyPayloadShallow(allocator, Payload.ContainerScope), .@"struct" => return self.copyPayloadShallow(allocator, Payload.Struct), + .enum_simple => return self.copyPayloadShallow(allocator, Payload.EnumSimple), + .enum_full, .enum_nonexhaustive => return self.copyPayloadShallow(allocator, Payload.EnumFull), .@"opaque" => return self.copyPayloadShallow(allocator, Payload.Opaque), } } @@ -629,8 +637,8 @@ pub const Type = extern union { self: Type, comptime fmt: []const u8, options: std.fmt.FormatOptions, - out_stream: anytype, - ) @TypeOf(out_stream).Error!void { + writer: anytype, + ) @TypeOf(writer).Error!void { comptime assert(fmt.len == 0); var ty = self; while (true) { @@ -670,132 +678,149 @@ pub const Type = extern union { .comptime_float, .noreturn, .var_args_param, - => return out_stream.writeAll(@tagName(t)), - - .enum_literal => return out_stream.writeAll("@Type(.EnumLiteral)"), - .@"null" => return out_stream.writeAll("@Type(.Null)"), - .@"undefined" => return out_stream.writeAll("@Type(.Undefined)"), - - .empty_struct, .empty_struct_literal => return out_stream.writeAll("struct {}"), - .@"struct" => return out_stream.writeAll("(struct)"), - .anyerror_void_error_union => return out_stream.writeAll("anyerror!void"), - .const_slice_u8 => return out_stream.writeAll("[]const u8"), - .fn_noreturn_no_args => return out_stream.writeAll("fn() noreturn"), - .fn_void_no_args => return out_stream.writeAll("fn() void"), - .fn_naked_noreturn_no_args => return out_stream.writeAll("fn() callconv(.Naked) noreturn"), - .fn_ccc_void_no_args => return out_stream.writeAll("fn() callconv(.C) void"), - .single_const_pointer_to_comptime_int => return out_stream.writeAll("*const comptime_int"), + => return writer.writeAll(@tagName(t)), + + .enum_literal => return writer.writeAll("@Type(.EnumLiteral)"), + .@"null" => return writer.writeAll("@Type(.Null)"), + .@"undefined" => return writer.writeAll("@Type(.Undefined)"), + + .empty_struct, .empty_struct_literal => return writer.writeAll("struct {}"), + + .@"struct" => { + const struct_obj = self.castTag(.@"struct").?.data; + return struct_obj.owner_decl.renderFullyQualifiedName(writer); + }, + .enum_full, .enum_nonexhaustive => { + const enum_full = self.castTag(.enum_full).?.data; + return enum_full.owner_decl.renderFullyQualifiedName(writer); + }, + .enum_simple => { + const enum_simple = self.castTag(.enum_simple).?.data; + return enum_simple.owner_decl.renderFullyQualifiedName(writer); + }, + .@"opaque" => { + // TODO use declaration name + return writer.writeAll("opaque {}"); + }, + + .anyerror_void_error_union => return writer.writeAll("anyerror!void"), + .const_slice_u8 => return writer.writeAll("[]const u8"), + .fn_noreturn_no_args => return writer.writeAll("fn() noreturn"), + .fn_void_no_args => return writer.writeAll("fn() void"), + .fn_naked_noreturn_no_args => return writer.writeAll("fn() callconv(.Naked) noreturn"), + .fn_ccc_void_no_args => return writer.writeAll("fn() callconv(.C) void"), + .single_const_pointer_to_comptime_int => return writer.writeAll("*const comptime_int"), .function => { const payload = ty.castTag(.function).?.data; - try out_stream.writeAll("fn("); + try writer.writeAll("fn("); for (payload.param_types) |param_type, i| { - if (i != 0) try out_stream.writeAll(", "); - try param_type.format("", .{}, out_stream); + if (i != 0) try writer.writeAll(", "); + try param_type.format("", .{}, writer); } if (payload.is_var_args) { if (payload.param_types.len != 0) { - try out_stream.writeAll(", "); + try writer.writeAll(", "); } - try out_stream.writeAll("..."); + try writer.writeAll("..."); } - try out_stream.writeAll(") callconv(."); - try out_stream.writeAll(@tagName(payload.cc)); - try out_stream.writeAll(")"); + try writer.writeAll(") callconv(."); + try writer.writeAll(@tagName(payload.cc)); + try writer.writeAll(")"); ty = payload.return_type; continue; }, .array_u8 => { const len = ty.castTag(.array_u8).?.data; - return out_stream.print("[{d}]u8", .{len}); + return writer.print("[{d}]u8", .{len}); }, .array_u8_sentinel_0 => { const len = ty.castTag(.array_u8_sentinel_0).?.data; - return out_stream.print("[{d}:0]u8", .{len}); + return writer.print("[{d}:0]u8", .{len}); }, .array => { const payload = ty.castTag(.array).?.data; - try out_stream.print("[{d}]", .{payload.len}); + try writer.print("[{d}]", .{payload.len}); ty = payload.elem_type; continue; }, .array_sentinel => { const payload = ty.castTag(.array_sentinel).?.data; - try out_stream.print("[{d}:{}]", .{ payload.len, payload.sentinel }); + try writer.print("[{d}:{}]", .{ payload.len, payload.sentinel }); ty = payload.elem_type; continue; }, .single_const_pointer => { const pointee_type = ty.castTag(.single_const_pointer).?.data; - try out_stream.writeAll("*const "); + try writer.writeAll("*const "); ty = pointee_type; continue; }, .single_mut_pointer => { const pointee_type = ty.castTag(.single_mut_pointer).?.data; - try out_stream.writeAll("*"); + try writer.writeAll("*"); ty = pointee_type; continue; }, .many_const_pointer => { const pointee_type = ty.castTag(.many_const_pointer).?.data; - try out_stream.writeAll("[*]const "); + try writer.writeAll("[*]const "); ty = pointee_type; continue; }, .many_mut_pointer => { const pointee_type = ty.castTag(.many_mut_pointer).?.data; - try out_stream.writeAll("[*]"); + try writer.writeAll("[*]"); ty = pointee_type; continue; }, .c_const_pointer => { const pointee_type = ty.castTag(.c_const_pointer).?.data; - try out_stream.writeAll("[*c]const "); + try writer.writeAll("[*c]const "); ty = pointee_type; continue; }, .c_mut_pointer => { const pointee_type = ty.castTag(.c_mut_pointer).?.data; - try out_stream.writeAll("[*c]"); + try writer.writeAll("[*c]"); ty = pointee_type; continue; }, .const_slice => { const pointee_type = ty.castTag(.const_slice).?.data; - try out_stream.writeAll("[]const "); + try writer.writeAll("[]const "); ty = pointee_type; continue; }, .mut_slice => { const pointee_type = ty.castTag(.mut_slice).?.data; - try out_stream.writeAll("[]"); + try writer.writeAll("[]"); ty = pointee_type; continue; }, .int_signed => { const bits = ty.castTag(.int_signed).?.data; - return out_stream.print("i{d}", .{bits}); + return writer.print("i{d}", .{bits}); }, .int_unsigned => { const bits = ty.castTag(.int_unsigned).?.data; - return out_stream.print("u{d}", .{bits}); + return writer.print("u{d}", .{bits}); }, .optional => { const child_type = ty.castTag(.optional).?.data; - try out_stream.writeByte('?'); + try writer.writeByte('?'); ty = child_type; continue; }, .optional_single_const_pointer => { const pointee_type = ty.castTag(.optional_single_const_pointer).?.data; - try out_stream.writeAll("?*const "); + try writer.writeAll("?*const "); ty = pointee_type; continue; }, .optional_single_mut_pointer => { const pointee_type = ty.castTag(.optional_single_mut_pointer).?.data; - try out_stream.writeAll("?*"); + try writer.writeAll("?*"); ty = pointee_type; continue; }, @@ -804,48 +829,46 @@ pub const Type = extern union { const payload = ty.castTag(.pointer).?.data; if (payload.sentinel) |some| switch (payload.size) { .One, .C => unreachable, - .Many => try out_stream.print("[*:{}]", .{some}), - .Slice => try out_stream.print("[:{}]", .{some}), + .Many => try writer.print("[*:{}]", .{some}), + .Slice => try writer.print("[:{}]", .{some}), } else switch (payload.size) { - .One => try out_stream.writeAll("*"), - .Many => try out_stream.writeAll("[*]"), - .C => try out_stream.writeAll("[*c]"), - .Slice => try out_stream.writeAll("[]"), + .One => try writer.writeAll("*"), + .Many => try writer.writeAll("[*]"), + .C => try writer.writeAll("[*c]"), + .Slice => try writer.writeAll("[]"), } if (payload.@"align" != 0) { - try out_stream.print("align({d}", .{payload.@"align"}); + try writer.print("align({d}", .{payload.@"align"}); if (payload.bit_offset != 0) { - try out_stream.print(":{d}:{d}", .{ payload.bit_offset, payload.host_size }); + try writer.print(":{d}:{d}", .{ payload.bit_offset, payload.host_size }); } - try out_stream.writeAll(") "); + try writer.writeAll(") "); } - if (!payload.mutable) try out_stream.writeAll("const "); - if (payload.@"volatile") try out_stream.writeAll("volatile "); - if (payload.@"allowzero") try out_stream.writeAll("allowzero "); + if (!payload.mutable) try writer.writeAll("const "); + if (payload.@"volatile") try writer.writeAll("volatile "); + if (payload.@"allowzero") try writer.writeAll("allowzero "); ty = payload.pointee_type; continue; }, .error_union => { const payload = ty.castTag(.error_union).?.data; - try payload.error_set.format("", .{}, out_stream); - try out_stream.writeAll("!"); + try payload.error_set.format("", .{}, writer); + try writer.writeAll("!"); ty = payload.payload; continue; }, .error_set => { const error_set = ty.castTag(.error_set).?.data; - return out_stream.writeAll(std.mem.spanZ(error_set.owner_decl.name)); + return writer.writeAll(std.mem.spanZ(error_set.owner_decl.name)); }, .error_set_single => { const name = ty.castTag(.error_set_single).?.data; - return out_stream.print("error{{{s}}}", .{name}); + return writer.print("error{{{s}}}", .{name}); }, - .inferred_alloc_const => return out_stream.writeAll("(inferred_alloc_const)"), - .inferred_alloc_mut => return out_stream.writeAll("(inferred_alloc_mut)"), - // TODO use declaration name - .@"opaque" => return out_stream.writeAll("opaque {}"), + .inferred_alloc_const => return writer.writeAll("(inferred_alloc_const)"), + .inferred_alloc_mut => return writer.writeAll("(inferred_alloc_mut)"), } unreachable; } @@ -954,6 +977,19 @@ pub const Type = extern union { return false; } }, + .enum_full => { + const enum_full = self.castTag(.enum_full).?.data; + return enum_full.fields.count() >= 2; + }, + .enum_simple => { + const enum_simple = self.castTag(.enum_simple).?.data; + return enum_simple.fields.count() >= 2; + }, + .enum_nonexhaustive => { + var buffer: Payload.Bits = undefined; + const int_tag_ty = self.intTagType(&buffer); + return int_tag_ty.hasCodeGenBits(); + }, // TODO lazy types .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0, @@ -1112,13 +1148,37 @@ pub const Type = extern union { } else if (!payload.payload.hasCodeGenBits()) { return payload.error_set.abiAlignment(target); } - @panic("TODO abiAlignment error union"); + return std.math.max( + payload.payload.abiAlignment(target), + payload.error_set.abiAlignment(target), + ); }, .@"struct" => { - @panic("TODO abiAlignment struct"); + // TODO take into account field alignment + // also make this possible to fail, and lazy + // I think we need to move all the functions from type.zig which can + // fail into Sema. + // Probably will need to introduce multi-stage struct resolution just + // like we have in stage1. + const struct_obj = self.castTag(.@"struct").?.data; + var biggest: u32 = 0; + for (struct_obj.fields.entries.items) |entry| { + const field_ty = entry.value.ty; + if (!field_ty.hasCodeGenBits()) continue; + const field_align = field_ty.abiAlignment(target); + if (field_align > biggest) { + return field_align; + } + } + assert(biggest != 0); + return biggest; + }, + .enum_full, .enum_nonexhaustive, .enum_simple => { + var buffer: Payload.Bits = undefined; + const int_tag_ty = self.intTagType(&buffer); + return int_tag_ty.abiAlignment(target); }, - .c_void, .void, .type, @@ -1166,6 +1226,11 @@ pub const Type = extern union { .@"struct" => { @panic("TODO abiSize struct"); }, + .enum_simple, .enum_full, .enum_nonexhaustive => { + var buffer: Payload.Bits = undefined; + const int_tag_ty = self.intTagType(&buffer); + return int_tag_ty.abiSize(target); + }, .u8, .i8, @@ -1276,76 +1341,25 @@ pub const Type = extern union { }; } + /// Asserts the type is an enum. + pub fn intTagType(self: Type, buffer: *Payload.Bits) Type { + switch (self.tag()) { + .enum_full, .enum_nonexhaustive => return self.castTag(.enum_full).?.data.tag_ty, + .enum_simple => { + const enum_simple = self.castTag(.enum_simple).?.data; + const bits = std.math.log2_int_ceil(usize, enum_simple.fields.count()); + buffer.* = .{ + .base = .{ .tag = .int_unsigned }, + .data = bits, + }; + return Type.initPayload(&buffer.base); + }, + else => unreachable, + } + } + pub fn isSinglePointer(self: Type) bool { return switch (self.tag()) { - .u8, - .i8, - .u16, - .i16, - .u32, - .i32, - .u64, - .i64, - .u128, - .i128, - .usize, - .isize, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - .c_longdouble, - .f16, - .f32, - .f64, - .f128, - .c_void, - .bool, - .void, - .type, - .anyerror, - .comptime_int, - .comptime_float, - .noreturn, - .@"null", - .@"undefined", - .array, - .array_sentinel, - .array_u8, - .array_u8_sentinel_0, - .const_slice_u8, - .fn_noreturn_no_args, - .fn_void_no_args, - .fn_naked_noreturn_no_args, - .fn_ccc_void_no_args, - .function, - .int_unsigned, - .int_signed, - .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .enum_literal, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - .error_union, - .anyerror_void_error_union, - .error_set, - .error_set_single, - .@"struct", - .empty_struct, - .empty_struct_literal, - .@"opaque", - .var_args_param, - => false, - .single_const_pointer, .single_mut_pointer, .single_const_pointer_to_comptime_int, @@ -1354,73 +1368,14 @@ pub const Type = extern union { => true, .pointer => self.castTag(.pointer).?.data.size == .One, + + else => false, }; } /// Asserts the `Type` is a pointer. pub fn ptrSize(self: Type) std.builtin.TypeInfo.Pointer.Size { return switch (self.tag()) { - .u8, - .i8, - .u16, - .i16, - .u32, - .i32, - .u64, - .i64, - .u128, - .i128, - .usize, - .isize, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - .c_longdouble, - .f16, - .f32, - .f64, - .f128, - .c_void, - .bool, - .void, - .type, - .anyerror, - .comptime_int, - .comptime_float, - .noreturn, - .@"null", - .@"undefined", - .array, - .array_sentinel, - .array_u8, - .array_u8_sentinel_0, - .fn_noreturn_no_args, - .fn_void_no_args, - .fn_naked_noreturn_no_args, - .fn_ccc_void_no_args, - .function, - .int_unsigned, - .int_signed, - .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .enum_literal, - .error_union, - .anyerror_void_error_union, - .error_set, - .error_set_single, - .empty_struct, - .empty_struct_literal, - .@"opaque", - .@"struct", - .var_args_param, - => unreachable, - .const_slice, .mut_slice, .const_slice_u8, @@ -1442,159 +1397,26 @@ pub const Type = extern union { => .One, .pointer => self.castTag(.pointer).?.data.size, + + else => unreachable, }; } pub fn isSlice(self: Type) bool { return switch (self.tag()) { - .u8, - .i8, - .u16, - .i16, - .u32, - .i32, - .u64, - .i64, - .u128, - .i128, - .usize, - .isize, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - .c_longdouble, - .f16, - .f32, - .f64, - .f128, - .c_void, - .bool, - .void, - .type, - .anyerror, - .comptime_int, - .comptime_float, - .noreturn, - .@"null", - .@"undefined", - .array, - .array_sentinel, - .array_u8, - .array_u8_sentinel_0, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .single_const_pointer_to_comptime_int, - .fn_noreturn_no_args, - .fn_void_no_args, - .fn_naked_noreturn_no_args, - .fn_ccc_void_no_args, - .function, - .int_unsigned, - .int_signed, - .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .enum_literal, - .error_union, - .anyerror_void_error_union, - .error_set, - .error_set_single, - .empty_struct, - .empty_struct_literal, - .inferred_alloc_const, - .inferred_alloc_mut, - .@"struct", - .@"opaque", - .var_args_param, - => false, - .const_slice, .mut_slice, .const_slice_u8, => true, .pointer => self.castTag(.pointer).?.data.size == .Slice, + + else => false, }; } pub fn isConstPtr(self: Type) bool { return switch (self.tag()) { - .u8, - .i8, - .u16, - .i16, - .u32, - .i32, - .u64, - .i64, - .u128, - .i128, - .usize, - .isize, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - .c_longdouble, - .f16, - .f32, - .f64, - .f128, - .c_void, - .bool, - .void, - .type, - .anyerror, - .comptime_int, - .comptime_float, - .noreturn, - .@"null", - .@"undefined", - .array, - .array_sentinel, - .array_u8, - .array_u8_sentinel_0, - .fn_noreturn_no_args, - .fn_void_no_args, - .fn_naked_noreturn_no_args, - .fn_ccc_void_no_args, - .function, - .int_unsigned, - .int_signed, - .single_mut_pointer, - .many_mut_pointer, - .c_mut_pointer, - .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .enum_literal, - .mut_slice, - .error_union, - .anyerror_void_error_union, - .error_set, - .error_set_single, - .empty_struct, - .empty_struct_literal, - .inferred_alloc_const, - .inferred_alloc_mut, - .@"struct", - .@"opaque", - .var_args_param, - => false, - .single_const_pointer, .many_const_pointer, .c_const_pointer, @@ -1604,170 +1426,40 @@ pub const Type = extern union { => true, .pointer => !self.castTag(.pointer).?.data.mutable, + + else => false, }; } pub fn isVolatilePtr(self: Type) bool { return switch (self.tag()) { - .u8, - .i8, - .u16, - .i16, - .u32, - .i32, - .u64, - .i64, - .u128, - .i128, - .usize, - .isize, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - .c_longdouble, - .f16, - .f32, - .f64, - .f128, - .c_void, - .bool, - .void, - .type, - .anyerror, - .comptime_int, - .comptime_float, - .noreturn, - .@"null", - .@"undefined", - .array, - .array_sentinel, - .array_u8, - .array_u8_sentinel_0, - .fn_noreturn_no_args, - .fn_void_no_args, - .fn_naked_noreturn_no_args, - .fn_ccc_void_no_args, - .function, - .int_unsigned, - .int_signed, - .single_mut_pointer, - .single_const_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .enum_literal, - .error_union, - .anyerror_void_error_union, - .error_set, - .error_set_single, - .empty_struct, - .empty_struct_literal, - .inferred_alloc_const, - .inferred_alloc_mut, - .@"struct", - .@"opaque", - .var_args_param, - => false, - .pointer => { const payload = self.castTag(.pointer).?.data; return payload.@"volatile"; }, + else => false, }; } pub fn isAllowzeroPtr(self: Type) bool { return switch (self.tag()) { - .u8, - .i8, - .u16, - .i16, - .u32, - .i32, - .u64, - .i64, - .u128, - .i128, - .usize, - .isize, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - .c_longdouble, - .f16, - .f32, - .f64, - .f128, - .c_void, - .bool, - .void, - .type, - .anyerror, - .comptime_int, - .comptime_float, - .noreturn, - .@"null", - .@"undefined", - .array, - .array_sentinel, - .array_u8, - .array_u8_sentinel_0, - .fn_noreturn_no_args, - .fn_void_no_args, - .fn_naked_noreturn_no_args, - .fn_ccc_void_no_args, - .function, - .int_unsigned, - .int_signed, - .single_mut_pointer, - .single_const_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .enum_literal, - .error_union, - .anyerror_void_error_union, - .error_set, - .error_set_single, - .empty_struct, - .empty_struct_literal, - .inferred_alloc_const, - .inferred_alloc_mut, - .@"struct", - .@"opaque", - .var_args_param, - => false, - .pointer => { const payload = self.castTag(.pointer).?.data; return payload.@"allowzero"; }, + else => false, + }; + } + + pub fn isCPtr(self: Type) bool { + return switch (self.tag()) { + .c_const_pointer, + .c_mut_pointer, + => return true, + + .pointer => self.castTag(.pointer).?.data.size == .C, + + else => return false, }; } @@ -1833,64 +1525,6 @@ pub const Type = extern union { /// Asserts the type is a pointer or array type. pub fn elemType(self: Type) Type { return switch (self.tag()) { - .u8 => unreachable, - .i8 => unreachable, - .u16 => unreachable, - .i16 => unreachable, - .u32 => unreachable, - .i32 => unreachable, - .u64 => unreachable, - .i64 => unreachable, - .u128 => unreachable, - .i128 => unreachable, - .usize => unreachable, - .isize => unreachable, - .c_short => unreachable, - .c_ushort => unreachable, - .c_int => unreachable, - .c_uint => unreachable, - .c_long => unreachable, - .c_ulong => unreachable, - .c_longlong => unreachable, - .c_ulonglong => unreachable, - .c_longdouble => unreachable, - .f16 => unreachable, - .f32 => unreachable, - .f64 => unreachable, - .f128 => unreachable, - .c_void => unreachable, - .bool => unreachable, - .void => unreachable, - .type => unreachable, - .anyerror => unreachable, - .comptime_int => unreachable, - .comptime_float => unreachable, - .noreturn => unreachable, - .@"null" => unreachable, - .@"undefined" => unreachable, - .fn_noreturn_no_args => unreachable, - .fn_void_no_args => unreachable, - .fn_naked_noreturn_no_args => unreachable, - .fn_ccc_void_no_args => unreachable, - .function => unreachable, - .int_unsigned => unreachable, - .int_signed => unreachable, - .optional => unreachable, - .optional_single_const_pointer => unreachable, - .optional_single_mut_pointer => unreachable, - .enum_literal => unreachable, - .error_union => unreachable, - .anyerror_void_error_union => unreachable, - .error_set => unreachable, - .error_set_single => unreachable, - .@"struct" => unreachable, - .empty_struct => unreachable, - .empty_struct_literal => unreachable, - .inferred_alloc_const => unreachable, - .inferred_alloc_mut => unreachable, - .@"opaque" => unreachable, - .var_args_param => unreachable, - .array => self.castTag(.array).?.data.elem_type, .array_sentinel => self.castTag(.array_sentinel).?.data.elem_type, .single_const_pointer, @@ -1902,9 +1536,12 @@ pub const Type = extern union { .const_slice, .mut_slice, => self.castPointer().?.data, + .array_u8, .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8), .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int), .pointer => self.castTag(.pointer).?.data.pointee_type, + + else => unreachable, }; } @@ -1972,148 +1609,18 @@ pub const Type = extern union { /// Asserts the type is an array or vector. pub fn arrayLen(self: Type) u64 { return switch (self.tag()) { - .u8, - .i8, - .u16, - .i16, - .u32, - .i32, - .u64, - .i64, - .u128, - .i128, - .usize, - .isize, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - .c_longdouble, - .f16, - .f32, - .f64, - .f128, - .c_void, - .bool, - .void, - .type, - .anyerror, - .comptime_int, - .comptime_float, - .noreturn, - .@"null", - .@"undefined", - .fn_noreturn_no_args, - .fn_void_no_args, - .fn_naked_noreturn_no_args, - .fn_ccc_void_no_args, - .function, - .pointer, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .int_unsigned, - .int_signed, - .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .enum_literal, - .error_union, - .anyerror_void_error_union, - .error_set, - .error_set_single, - .@"struct", - .empty_struct, - .empty_struct_literal, - .inferred_alloc_const, - .inferred_alloc_mut, - .@"opaque", - .var_args_param, - => unreachable, - .array => self.castTag(.array).?.data.len, .array_sentinel => self.castTag(.array_sentinel).?.data.len, .array_u8 => self.castTag(.array_u8).?.data, .array_u8_sentinel_0 => self.castTag(.array_u8_sentinel_0).?.data, + + else => unreachable, }; } /// Asserts the type is an array, pointer or vector. pub fn sentinel(self: Type) ?Value { return switch (self.tag()) { - .u8, - .i8, - .u16, - .i16, - .u32, - .i32, - .u64, - .i64, - .u128, - .i128, - .usize, - .isize, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - .c_longdouble, - .f16, - .f32, - .f64, - .f128, - .c_void, - .bool, - .void, - .type, - .anyerror, - .comptime_int, - .comptime_float, - .noreturn, - .@"null", - .@"undefined", - .fn_noreturn_no_args, - .fn_void_no_args, - .fn_naked_noreturn_no_args, - .fn_ccc_void_no_args, - .function, - .const_slice, - .mut_slice, - .const_slice_u8, - .int_unsigned, - .int_signed, - .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .enum_literal, - .error_union, - .anyerror_void_error_union, - .error_set, - .error_set_single, - .@"struct", - .empty_struct, - .empty_struct_literal, - .inferred_alloc_const, - .inferred_alloc_mut, - .@"opaque", - .var_args_param, - => unreachable, - .single_const_pointer, .single_mut_pointer, .many_const_pointer, @@ -2128,6 +1635,8 @@ pub const Type = extern union { .pointer => return self.castTag(.pointer).?.data.sentinel, .array_sentinel => return self.castTag(.array_sentinel).?.data.sentinel, .array_u8_sentinel_0 => return Value.initTag(.zero), + + else => unreachable, }; } @@ -2139,68 +1648,6 @@ pub const Type = extern union { /// Returns true if and only if the type is a fixed-width, signed integer. pub fn isSignedInt(self: Type) bool { return switch (self.tag()) { - .f16, - .f32, - .f64, - .f128, - .c_longdouble, - .c_void, - .bool, - .void, - .type, - .anyerror, - .comptime_int, - .comptime_float, - .noreturn, - .@"null", - .@"undefined", - .fn_noreturn_no_args, - .fn_void_no_args, - .fn_naked_noreturn_no_args, - .fn_ccc_void_no_args, - .function, - .array, - .array_sentinel, - .array_u8, - .array_u8_sentinel_0, - .pointer, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .int_unsigned, - .u8, - .usize, - .c_ushort, - .c_uint, - .c_ulong, - .c_ulonglong, - .u16, - .u32, - .u64, - .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .enum_literal, - .error_union, - .anyerror_void_error_union, - .error_set, - .error_set_single, - .@"struct", - .empty_struct, - .empty_struct_literal, - .inferred_alloc_const, - .inferred_alloc_mut, - .@"opaque", - .var_args_param, - => false, - .int_signed, .i8, .isize, @@ -2211,79 +1658,16 @@ pub const Type = extern union { .i16, .i32, .i64, - .u128, .i128, => true, + + else => false, }; } /// Returns true if and only if the type is a fixed-width, unsigned integer. pub fn isUnsignedInt(self: Type) bool { return switch (self.tag()) { - .f16, - .f32, - .f64, - .f128, - .c_longdouble, - .c_void, - .bool, - .void, - .type, - .anyerror, - .comptime_int, - .comptime_float, - .noreturn, - .@"null", - .@"undefined", - .fn_noreturn_no_args, - .fn_void_no_args, - .fn_naked_noreturn_no_args, - .fn_ccc_void_no_args, - .function, - .array, - .array_sentinel, - .array_u8, - .array_u8_sentinel_0, - .pointer, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .int_signed, - .i8, - .isize, - .c_short, - .c_int, - .c_long, - .c_longlong, - .i16, - .i32, - .i64, - .u128, - .i128, - .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .enum_literal, - .error_union, - .anyerror_void_error_union, - .error_set, - .error_set_single, - .@"struct", - .empty_struct, - .empty_struct_literal, - .inferred_alloc_const, - .inferred_alloc_mut, - .@"opaque", - .var_args_param, - => false, - .int_unsigned, .u8, .usize, @@ -2294,65 +1678,16 @@ pub const Type = extern union { .u16, .u32, .u64, + .u128, => true, + + else => false, }; } /// Asserts the type is an integer. pub fn intInfo(self: Type, target: Target) struct { signedness: std.builtin.Signedness, bits: u16 } { return switch (self.tag()) { - .f16, - .f32, - .f64, - .f128, - .c_longdouble, - .c_void, - .bool, - .void, - .type, - .anyerror, - .comptime_int, - .comptime_float, - .noreturn, - .@"null", - .@"undefined", - .fn_noreturn_no_args, - .fn_void_no_args, - .fn_naked_noreturn_no_args, - .fn_ccc_void_no_args, - .function, - .array, - .array_sentinel, - .array_u8, - .array_u8_sentinel_0, - .pointer, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .enum_literal, - .error_union, - .anyerror_void_error_union, - .error_set, - .error_set_single, - .@"struct", - .empty_struct, - .empty_struct_literal, - .inferred_alloc_const, - .inferred_alloc_mut, - .@"opaque", - .var_args_param, - => unreachable, - .int_unsigned => .{ .signedness = .unsigned, .bits = self.castTag(.int_unsigned).?.data, @@ -2381,75 +1716,13 @@ pub const Type = extern union { .c_ulong => .{ .signedness = .unsigned, .bits = CType.ulong.sizeInBits(target) }, .c_longlong => .{ .signedness = .signed, .bits = CType.longlong.sizeInBits(target) }, .c_ulonglong => .{ .signedness = .unsigned, .bits = CType.ulonglong.sizeInBits(target) }, + + else => unreachable, }; } pub fn isNamedInt(self: Type) bool { return switch (self.tag()) { - .f16, - .f32, - .f64, - .f128, - .c_longdouble, - .c_void, - .bool, - .void, - .type, - .anyerror, - .comptime_int, - .comptime_float, - .noreturn, - .@"null", - .@"undefined", - .fn_noreturn_no_args, - .fn_void_no_args, - .fn_naked_noreturn_no_args, - .fn_ccc_void_no_args, - .function, - .array, - .array_sentinel, - .array_u8, - .array_u8_sentinel_0, - .pointer, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .int_unsigned, - .int_signed, - .u8, - .i8, - .u16, - .i16, - .u32, - .i32, - .u64, - .i64, - .u128, - .i128, - .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .enum_literal, - .error_union, - .anyerror_void_error_union, - .error_set, - .error_set_single, - .@"struct", - .empty_struct, - .empty_struct_literal, - .inferred_alloc_const, - .inferred_alloc_mut, - .@"opaque", - .var_args_param, - => false, - .usize, .isize, .c_short, @@ -2461,6 +1734,8 @@ pub const Type = extern union { .c_longlong, .c_ulonglong, => true, + + else => false, }; } @@ -2499,74 +1774,7 @@ pub const Type = extern union { .fn_ccc_void_no_args => 0, .function => self.castTag(.function).?.data.param_types.len, - .f16, - .f32, - .f64, - .f128, - .c_longdouble, - .c_void, - .bool, - .void, - .type, - .anyerror, - .comptime_int, - .comptime_float, - .noreturn, - .@"null", - .@"undefined", - .array, - .array_sentinel, - .array_u8, - .array_u8_sentinel_0, - .pointer, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .u8, - .i8, - .u16, - .i16, - .u32, - .i32, - .u64, - .i64, - .u128, - .i128, - .usize, - .isize, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - .int_unsigned, - .int_signed, - .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .enum_literal, - .error_union, - .anyerror_void_error_union, - .error_set, - .error_set_single, - .@"struct", - .empty_struct, - .empty_struct_literal, - .inferred_alloc_const, - .inferred_alloc_mut, - .@"opaque", - .var_args_param, - => unreachable, + else => unreachable, }; } @@ -2583,74 +1791,7 @@ pub const Type = extern union { std.mem.copy(Type, types, payload.param_types); }, - .f16, - .f32, - .f64, - .f128, - .c_longdouble, - .c_void, - .bool, - .void, - .type, - .anyerror, - .comptime_int, - .comptime_float, - .noreturn, - .@"null", - .@"undefined", - .array, - .array_sentinel, - .array_u8, - .array_u8_sentinel_0, - .pointer, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .u8, - .i8, - .u16, - .i16, - .u32, - .i32, - .u64, - .i64, - .u128, - .i128, - .usize, - .isize, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - .int_unsigned, - .int_signed, - .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .enum_literal, - .error_union, - .anyerror_void_error_union, - .error_set, - .error_set_single, - .@"struct", - .empty_struct, - .empty_struct_literal, - .inferred_alloc_const, - .inferred_alloc_mut, - .@"opaque", - .var_args_param, - => unreachable, + else => unreachable, } } @@ -2662,78 +1803,7 @@ pub const Type = extern union { return payload.param_types[index]; }, - .fn_noreturn_no_args, - .fn_void_no_args, - .fn_naked_noreturn_no_args, - .fn_ccc_void_no_args, - .f16, - .f32, - .f64, - .f128, - .c_longdouble, - .c_void, - .bool, - .void, - .type, - .anyerror, - .comptime_int, - .comptime_float, - .noreturn, - .@"null", - .@"undefined", - .array, - .array_sentinel, - .array_u8, - .array_u8_sentinel_0, - .pointer, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .u8, - .i8, - .u16, - .i16, - .u32, - .i32, - .u64, - .i64, - .u128, - .i128, - .usize, - .isize, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - .int_unsigned, - .int_signed, - .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .enum_literal, - .error_union, - .anyerror_void_error_union, - .error_set, - .error_set_single, - .@"struct", - .empty_struct, - .empty_struct_literal, - .inferred_alloc_const, - .inferred_alloc_mut, - .@"opaque", - .var_args_param, - => unreachable, + else => unreachable, } } @@ -2749,74 +1819,7 @@ pub const Type = extern union { .function => self.castTag(.function).?.data.return_type, - .f16, - .f32, - .f64, - .f128, - .c_longdouble, - .c_void, - .bool, - .void, - .type, - .anyerror, - .comptime_int, - .comptime_float, - .noreturn, - .@"null", - .@"undefined", - .array, - .array_sentinel, - .array_u8, - .array_u8_sentinel_0, - .pointer, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .u8, - .i8, - .u16, - .i16, - .u32, - .i32, - .u64, - .i64, - .u128, - .i128, - .usize, - .isize, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - .int_unsigned, - .int_signed, - .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .enum_literal, - .error_union, - .anyerror_void_error_union, - .error_set, - .error_set_single, - .@"struct", - .empty_struct, - .empty_struct_literal, - .inferred_alloc_const, - .inferred_alloc_mut, - .@"opaque", - .var_args_param, - => unreachable, + else => unreachable, }; } @@ -2829,74 +1832,7 @@ pub const Type = extern union { .fn_ccc_void_no_args => .C, .function => self.castTag(.function).?.data.cc, - .f16, - .f32, - .f64, - .f128, - .c_longdouble, - .c_void, - .bool, - .void, - .type, - .anyerror, - .comptime_int, - .comptime_float, - .noreturn, - .@"null", - .@"undefined", - .array, - .array_sentinel, - .array_u8, - .array_u8_sentinel_0, - .pointer, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .u8, - .i8, - .u16, - .i16, - .u32, - .i32, - .u64, - .i64, - .u128, - .i128, - .usize, - .isize, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - .int_unsigned, - .int_signed, - .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .enum_literal, - .error_union, - .anyerror_void_error_union, - .error_set, - .error_set_single, - .@"struct", - .empty_struct, - .empty_struct_literal, - .inferred_alloc_const, - .inferred_alloc_mut, - .@"opaque", - .var_args_param, - => unreachable, + else => unreachable, }; } @@ -2909,74 +1845,7 @@ pub const Type = extern union { .fn_ccc_void_no_args => false, .function => self.castTag(.function).?.data.is_var_args, - .f16, - .f32, - .f64, - .f128, - .c_longdouble, - .c_void, - .bool, - .void, - .type, - .anyerror, - .comptime_int, - .comptime_float, - .noreturn, - .@"null", - .@"undefined", - .array, - .array_sentinel, - .array_u8, - .array_u8_sentinel_0, - .pointer, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .u8, - .i8, - .u16, - .i16, - .u32, - .i32, - .u64, - .i64, - .u128, - .i128, - .usize, - .isize, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - .int_unsigned, - .int_signed, - .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .enum_literal, - .error_union, - .anyerror_void_error_union, - .error_set, - .error_set_single, - .@"struct", - .empty_struct, - .empty_struct_literal, - .inferred_alloc_const, - .inferred_alloc_mut, - .@"opaque", - .var_args_param, - => unreachable, + else => unreachable, }; } @@ -3013,50 +1882,7 @@ pub const Type = extern union { .int_signed, => true, - .c_void, - .bool, - .void, - .type, - .anyerror, - .noreturn, - .@"null", - .@"undefined", - .fn_noreturn_no_args, - .fn_void_no_args, - .fn_naked_noreturn_no_args, - .fn_ccc_void_no_args, - .function, - .array, - .array_sentinel, - .array_u8, - .array_u8_sentinel_0, - .pointer, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .c_const_pointer, - .c_mut_pointer, - .const_slice, - .mut_slice, - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .enum_literal, - .error_union, - .anyerror_void_error_union, - .error_set, - .error_set_single, - .@"struct", - .empty_struct, - .empty_struct_literal, - .inferred_alloc_const, - .inferred_alloc_mut, - .@"opaque", - .var_args_param, - => false, + else => false, }; } @@ -3127,6 +1953,23 @@ pub const Type = extern union { } return Value.initTag(.empty_struct_value); }, + .enum_full => { + const enum_full = self.castTag(.enum_full).?.data; + if (enum_full.fields.count() == 1) { + return enum_full.values.entries.items[0].key; + } else { + return null; + } + }, + .enum_simple => { + const enum_simple = self.castTag(.enum_simple).?.data; + if (enum_simple.fields.count() == 1) { + return Value.initTag(.zero); + } else { + return null; + } + }, + .enum_nonexhaustive => return self.castTag(.enum_full).?.data.tag_ty.onePossibleValue(), .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value), .void => return Value.initTag(.void_value), @@ -3166,87 +2009,6 @@ pub const Type = extern union { }; } - pub fn isCPtr(self: Type) bool { - return switch (self.tag()) { - .f16, - .f32, - .f64, - .f128, - .c_longdouble, - .comptime_int, - .comptime_float, - .u8, - .i8, - .u16, - .i16, - .u32, - .i32, - .u64, - .i64, - .u128, - .i128, - .usize, - .isize, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - .bool, - .type, - .anyerror, - .fn_noreturn_no_args, - .fn_void_no_args, - .fn_naked_noreturn_no_args, - .fn_ccc_void_no_args, - .function, - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .c_void, - .void, - .noreturn, - .@"null", - .@"undefined", - .int_unsigned, - .int_signed, - .array, - .array_sentinel, - .array_u8, - .array_u8_sentinel_0, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .const_slice, - .mut_slice, - .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .enum_literal, - .error_union, - .anyerror_void_error_union, - .error_set, - .error_set_single, - .@"struct", - .empty_struct, - .empty_struct_literal, - .inferred_alloc_const, - .inferred_alloc_mut, - .@"opaque", - .var_args_param, - => return false, - - .c_const_pointer, - .c_mut_pointer, - => return true, - - .pointer => self.castTag(.pointer).?.data.size == .C, - }; - } - pub fn isIndexable(self: Type) bool { const zig_tag = self.zigTypeTag(); // TODO tuples are indexable @@ -3257,80 +2019,12 @@ pub const Type = extern union { /// Asserts that the type is a container. (note: ErrorSet is not a container). pub fn getContainerScope(self: Type) *Module.Scope.Container { return switch (self.tag()) { - .f16, - .f32, - .f64, - .f128, - .c_longdouble, - .comptime_int, - .comptime_float, - .u8, - .i8, - .u16, - .i16, - .u32, - .i32, - .u64, - .i64, - .u128, - .i128, - .usize, - .isize, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - .bool, - .type, - .anyerror, - .fn_noreturn_no_args, - .fn_void_no_args, - .fn_naked_noreturn_no_args, - .fn_ccc_void_no_args, - .function, - .single_const_pointer_to_comptime_int, - .const_slice_u8, - .c_void, - .void, - .noreturn, - .@"null", - .@"undefined", - .int_unsigned, - .int_signed, - .array, - .array_sentinel, - .array_u8, - .array_u8_sentinel_0, - .single_const_pointer, - .single_mut_pointer, - .many_const_pointer, - .many_mut_pointer, - .const_slice, - .mut_slice, - .optional, - .optional_single_mut_pointer, - .optional_single_const_pointer, - .enum_literal, - .error_union, - .anyerror_void_error_union, - .error_set, - .error_set_single, - .c_const_pointer, - .c_mut_pointer, - .pointer, - .inferred_alloc_const, - .inferred_alloc_mut, - .var_args_param, - .empty_struct_literal, - => unreachable, - .@"struct" => &self.castTag(.@"struct").?.data.container, + .enum_full => &self.castTag(.enum_full).?.data.container, .empty_struct => self.castTag(.empty_struct).?.data, .@"opaque" => &self.castTag(.@"opaque").?.data, + + else => unreachable, }; } @@ -3390,7 +2084,43 @@ pub const Type = extern union { } pub fn isExhaustiveEnum(ty: Type) bool { - return false; // TODO + return switch (ty.tag()) { + .enum_full, .enum_simple => true, + else => false, + }; + } + + /// Asserts the type is an enum. + pub fn enumHasInt(ty: Type, int: Value, target: Target) bool { + const S = struct { + fn intInRange(int_val: Value, end: usize) bool { + if (int_val.compareWithZero(.lt)) return false; + var end_payload: Value.Payload.U64 = .{ + .base = .{ .tag = .int_u64 }, + .data = end, + }; + const end_val = Value.initPayload(&end_payload.base); + if (int_val.compare(.gte, end_val)) return false; + return true; + } + }; + switch (ty.tag()) { + .enum_nonexhaustive => return int.intFitsInType(ty, target), + .enum_full => { + const enum_full = ty.castTag(.enum_full).?.data; + if (enum_full.values.count() == 0) { + return S.intInRange(int, enum_full.fields.count()); + } else { + return enum_full.values.contains(int); + } + }, + .enum_simple => { + const enum_simple = ty.castTag(.enum_simple).?.data; + return S.intInRange(int, enum_simple.fields.count()); + }, + + else => unreachable, + } } /// This enum does not directly correspond to `std.builtin.TypeId` because @@ -3482,6 +2212,9 @@ pub const Type = extern union { empty_struct, @"opaque", @"struct", + enum_simple, + enum_full, + enum_nonexhaustive, pub const last_no_payload_tag = Tag.inferred_alloc_const; pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; @@ -3568,6 +2301,8 @@ pub const Type = extern union { .error_set_single => Payload.Name, .@"opaque" => Payload.Opaque, .@"struct" => Payload.Struct, + .enum_full, .enum_nonexhaustive => Payload.EnumFull, + .enum_simple => Payload.EnumSimple, .empty_struct => Payload.ContainerScope, }; } @@ -3705,6 +2440,16 @@ pub const Type = extern union { base: Payload = .{ .tag = .@"struct" }, data: *Module.Struct, }; + + pub const EnumFull = struct { + base: Payload, + data: *Module.EnumFull, + }; + + pub const EnumSimple = struct { + base: Payload = .{ .tag = .enum_simple }, + data: *Module.EnumSimple, + }; }; }; |
