diff --git a/src/InternPool.zig b/src/InternPool.zig index 0844e0f7a586..6680c9b298e7 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -308,6 +308,11 @@ pub const Key = union(enum) { /// A comptime function call with a memoized result. memoized_call: Key.MemoizedCall, + /// A type aliased to another declaration only meaningful for error messages + /// and transparent to any other uses. + /// `type_alias.ty` MUST NOT be another `.type_alias`. + type_alias: TypeAlias, + pub const TypeValue = extern struct { ty: Index, val: Index, @@ -1247,6 +1252,11 @@ pub const Key = union(enum) { result: Index, }; + pub const TypeAlias = extern struct { + ty: Index, + decl: DeclIndex, + }; + pub fn hash32(key: Key, ip: *const InternPool) u32 { return @truncate(key.hash64(ip)); } @@ -1273,6 +1283,7 @@ pub const Key = union(enum) { .empty_enum_value, .inferred_error_set_type, .un, + .type_alias, => |x| Hash.hash(seed, asBytes(&x)), .int_type => |x| Hash.hash(seed + @intFromEnum(x.signedness), asBytes(&x.bits)), @@ -1540,6 +1551,10 @@ pub const Key = union(enum) { const b_info = b.empty_enum_value; return a_info == b_info; }, + .type_alias => |a_info| { + const b_info = b.type_alias; + return a_info.decl == b_info.decl; + }, .variable => |a_info| { const b_info = b.variable; @@ -1796,6 +1811,7 @@ pub const Key = union(enum) { .enum_type, .anon_struct_type, .func_type, + .type_alias, => .type_type, inline .ptr, @@ -2304,6 +2320,8 @@ pub const Index = enum(u32) { @"trailing.arg_values.len": *@"data.args_len", trailing: struct { arg_values: []Index }, }, + + type_alias: struct { data: *Key.TypeAlias }, }) void { _ = self; const map_fields = @typeInfo(@typeInfo(@TypeOf(tag_to_encoding_map)).Pointer.child).Struct.fields; @@ -2850,6 +2868,10 @@ pub const Tag = enum(u8) { /// data is extra index to `MemoizedCall` memoized_call, + /// A type aliased to another declaration only meaningful for error messages + /// and transparent to any other uses. + type_alias, + const ErrorUnionType = Key.ErrorUnionType; const OpaqueType = Key.OpaqueType; const TypeValue = Key.TypeValue; @@ -2858,6 +2880,7 @@ pub const Tag = enum(u8) { const ExternFunc = Key.ExternFunc; const Union = Key.Union; const TypePointer = Key.PtrType; + const TypeAlias = Key.TypeAlias; fn Payload(comptime tag: Tag) type { return switch (tag) { @@ -2938,6 +2961,7 @@ pub const Tag = enum(u8) { .aggregate => Aggregate, .repeated => Repeated, .memoized_call => MemoizedCall, + .type_alias => TypeAlias, }; } @@ -3712,8 +3736,21 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { } pub fn indexToKey(ip: *const InternPool, index: Index) Key { + return ip.indexToKeyExtra(index, false); +} + +pub fn indexToKeyExtra(ip: *const InternPool, index: Index, allow_alias: bool) Key { assert(index != .none); - const item = ip.items.get(@intFromEnum(index)); + const item = item: { + const item = ip.items.get(@intFromEnum(index)); + if (!allow_alias and item.tag == .type_alias) { + // `.type_alias` is supposed to be transparent to most of the + // compiler so it is handled separately. + const type_alias = ip.extraData(Key.TypeAlias, item.data); + break :item ip.items.get(@intFromEnum(type_alias.ty)); + } + break :item item; + }; const data = item.data; return switch (item.tag) { .type_int_signed => .{ @@ -4232,6 +4269,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { .result = extra.data.result, } }; }, + + .type_alias => .{ .type_alias = ip.extraData(Key.TypeAlias, data) }, }; } @@ -4666,6 +4705,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { .data = @intFromEnum(ty), }); }, + .type_alias => |type_alias| { + ip.items.appendAssumeCapacity(.{ + .tag = .type_alias, + .data = try ip.addExtra(gpa, type_alias), + }); + }, .struct_type => unreachable, // use getStructType() instead .anon_struct_type => unreachable, // use getAnonStructType() instead @@ -6803,6 +6848,7 @@ pub fn sliceLen(ip: *const InternPool, i: Index) Index { pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index { const old_ty = ip.typeOf(val); if (old_ty == new_ty) return val; + if (old_ty == .type_type) return val; const tags = ip.items.items(.tag); @@ -7429,6 +7475,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { const info = ip.extraData(MemoizedCall, data); break :b @sizeOf(MemoizedCall) + (@sizeOf(Index) * info.args_len); }, + .type_alias => @sizeOf(Key.ErrorUnionType), }); } const SortContext = struct { @@ -7532,6 +7579,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { .func_coerced, .union_value, .memoized_call, + .type_alias, => try w.print("{d}", .{data}), .opt_null, @@ -7889,6 +7937,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { .type_tuple_anon, .type_union, .type_function, + .type_alias, => .type_type, .undef, @@ -8281,6 +8330,8 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois // memoization, not types .memoized_call, => unreachable, + + .type_alias => return .Type, }, .none => unreachable, // special tag }; diff --git a/src/Module.zig b/src/Module.zig index 8f6f0e34d1b1..5a5f137298dd 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -3750,6 +3750,29 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { } decl.ty = decl_tv.ty; + + // Check if the type of this decl should be set to a `type_alias`. + alias: { + if (!decl.ty.eql(Type.type, mod)) break :alias; + const ty = decl_tv.val.toType(); + if (ty.getOwnerDeclOrNull(mod)) |some| { + // Don't create an alias when creating a type. + // const foo = struct { ... }; + if (some == decl_index) break :alias; + } + const ty_index = if (ty.getTypeAlias(mod)) |some| blk: { + // Rename previous alias. + // const previous_alias = ; + // const new_alias = previous_alias; + break :blk some.ty; + } else ty.toIntern(); + + decl.ty = Type.fromInterned(try mod.intern(.{ .type_alias = .{ + .ty = ty_index, + .decl = decl_index, + } })); + } + decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod))); decl.alignment = blk: { const align_ref = decl.zirAlignRef(mod); diff --git a/src/Sema.zig b/src/Sema.zig index 7a73b52e83c8..e75a1fc0055b 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2459,6 +2459,11 @@ pub fn fail( args: anytype, ) CompileError { const err_msg = try sema.errMsg(block, src, format, args); + inline for (args) |arg| { + if (@TypeOf(arg) == Type.Formatter) { + try addDeclaredHereNote(sema, err_msg, arg.data.ty); + } + } return sema.failWithOwnedErrorMsg(block, err_msg); } @@ -5250,24 +5255,15 @@ fn failWithBadMemberAccess( .Enum => "enum", else => unreachable, }; - const msg = msg: { - const msg = blk: { - if (agg_ty.getOwnerDeclOrNull(mod)) |some| if (mod.declIsRoot(some)) { - break :blk try sema.errMsg(block, field_src, "root struct of file '{}' has no member named '{}'", .{ - agg_ty.fmt(mod), field_name.fmt(&mod.intern_pool), - }); - }; - - break :blk try sema.errMsg(block, field_src, "{s} '{}' has no member named '{}'", .{ - kw_name, agg_ty.fmt(mod), field_name.fmt(&mod.intern_pool), - }); - }; - - errdefer msg.destroy(sema.gpa); - try sema.addDeclaredHereNote(msg, agg_ty); - break :msg msg; + if (agg_ty.getOwnerDeclOrNull(mod)) |some| if (mod.declIsRoot(some)) { + return sema.fail(block, field_src, "root struct of file '{}' has no member named '{}'", .{ + agg_ty.fmt(mod), field_name.fmt(&mod.intern_pool), + }); }; - return sema.failWithOwnedErrorMsg(block, msg); + + return sema.fail(block, field_src, "{s} '{}' has no member named '{}'", .{ + kw_name, agg_ty.fmt(mod), field_name.fmt(&mod.intern_pool), + }); } fn failWithBadStructFieldAccess( @@ -8570,35 +8566,17 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError if (try sema.intFitsInType(int_val, int_tag_ty, null)) { return Air.internedToRef((try mod.getCoerced(int_val, dest_ty)).toIntern()); } - const msg = msg: { - const msg = try sema.errMsg( - block, - src, - "int value '{}' out of range of non-exhaustive enum '{}'", - .{ int_val.fmtValue(sema.typeOf(operand), mod), dest_ty.fmt(mod) }, - ); - errdefer msg.destroy(sema.gpa); - try sema.addDeclaredHereNote(msg, dest_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.fail(block, src, "int value '{}' out of range of non-exhaustive enum '{}'", .{ + int_val.fmtValue(sema.typeOf(operand), mod), dest_ty.fmt(mod), + }); } if (int_val.isUndef(mod)) { return sema.failWithUseOfUndef(block, operand_src); } if (!(try sema.enumHasInt(dest_ty, int_val))) { - const msg = msg: { - const msg = try sema.errMsg( - block, - src, - "enum '{}' has no tag with value '{}'", - .{ dest_ty.fmt(mod), int_val.fmtValue(sema.typeOf(operand), mod) }, - ); - errdefer msg.destroy(sema.gpa); - try sema.addDeclaredHereNote(msg, dest_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.fail(block, src, "enum '{}' has no tag with value '{}'", .{ + dest_ty.fmt(mod), int_val.fmtValue(sema.typeOf(operand), mod), + }); } return Air.internedToRef((try mod.getCoerced(int_val, dest_ty)).toIntern()); } @@ -9276,16 +9254,9 @@ fn funcCommon( } if (!param_ty.isValidParamType(mod)) { const opaque_str = if (param_ty.zigTypeTag(mod) == .Opaque) "opaque " else ""; - const msg = msg: { - const msg = try sema.errMsg(block, param_src, "parameter of {s}type '{}' not allowed", .{ - opaque_str, param_ty.fmt(mod), - }); - errdefer msg.destroy(sema.gpa); - - try sema.addDeclaredHereNote(msg, param_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.fail(block, param_src, "parameter of {s}type '{}' not allowed", .{ + opaque_str, param_ty.fmt(mod), + }); } if (!this_generic and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and !try sema.validateExternType(param_ty, .param_ty)) { const msg = msg: { @@ -9566,16 +9537,9 @@ fn finishFunc( if (!return_type.isValidReturnType(mod)) { const opaque_str = if (return_type.zigTypeTag(mod) == .Opaque) "opaque " else ""; - const msg = msg: { - const msg = try sema.errMsg(block, ret_ty_src, "{s}return type '{}' not allowed", .{ - opaque_str, return_type.fmt(mod), - }); - errdefer msg.destroy(gpa); - - try sema.addDeclaredHereNote(msg, return_type); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.fail(block, ret_ty_src, "{s}return type '{}' not allowed", .{ + opaque_str, return_type.fmt(mod), + }); } if (!ret_poison and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and !try sema.validateExternType(return_type, .ret_ty)) @@ -10720,15 +10684,9 @@ const SwitchProngAnalysis = struct { else => unreachable, }; const capture_src = raw_tag_capture_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, .none); - const msg = msg: { - const msg = try sema.errMsg(block, capture_src, "cannot capture tag of non-union type '{}'", .{ - operand_ty.fmt(mod), - }); - errdefer msg.destroy(sema.gpa); - try sema.addDeclaredHereNote(msg, operand_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.fail(block, capture_src, "cannot capture tag of non-union type '{}'", .{ + operand_ty.fmt(mod), + }); } assert(inline_case_capture != .none); return inline_case_capture; @@ -19608,13 +19566,7 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A const extra = sema.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data; const union_ty = try sema.resolveType(block, ty_src, extra.union_type); if (union_ty.zigTypeTag(sema.mod) != .Union) { - const msg = msg: { - const msg = try sema.errMsg(block, ty_src, "expected union type, found '{}'", .{union_ty.fmt(sema.mod)}); - errdefer msg.destroy(sema.gpa); - try sema.addDeclaredHereNote(msg, union_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.fail(block, ty_src, "expected union type, found '{}'", .{union_ty.fmt(sema.mod)}); } const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, .{ .needed_comptime_reason = "name of field being initialized must be comptime-known", @@ -20040,16 +19992,9 @@ fn structInitAnon( const init = try sema.resolveInst(item.data.init); field_ty.* = sema.typeOf(init).toIntern(); if (Type.fromInterned(field_ty.*).zigTypeTag(mod) == .Opaque) { - const msg = msg: { - const decl = mod.declPtr(block.src_decl); - const field_src = mod.initSrc(src.node_offset.x, decl, @intCast(i_usize)); - const msg = try sema.errMsg(block, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); - errdefer msg.destroy(sema.gpa); - - try sema.addDeclaredHereNote(msg, Type.fromInterned(field_ty.*)); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + const decl = mod.declPtr(block.src_decl); + const field_src = mod.initSrc(src.node_offset.x, decl, @intCast(i_usize)); + return sema.fail(block, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); } if (try sema.resolveValue(init)) |init_val| { field_val.* = try init_val.intern(Type.fromInterned(field_ty.*), mod); @@ -20332,14 +20277,7 @@ fn arrayInitAnon( const elem = try sema.resolveInst(operand); types[i] = sema.typeOf(elem).toIntern(); if (Type.fromInterned(types[i]).zigTypeTag(mod) == .Opaque) { - const msg = msg: { - const msg = try sema.errMsg(block, operand_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); - errdefer msg.destroy(gpa); - - try sema.addDeclaredHereNote(msg, Type.fromInterned(types[i])); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.fail(block, operand_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); } if (try sema.resolveValue(elem)) |val| { values[i] = val.toIntern(); @@ -20715,17 +20653,8 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air return sema.addStrLit(ip.stringToSlice(tag_name)); }, .Enum => operand_ty, - .Union => operand_ty.unionTagType(mod) orelse { - const msg = msg: { - const msg = try sema.errMsg(block, src, "union '{}' is untagged", .{ - operand_ty.fmt(sema.mod), - }); - errdefer msg.destroy(sema.gpa); - try sema.addDeclaredHereNote(msg, operand_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); - }, + .Union => operand_ty.unionTagType(mod) orelse + return sema.fail(block, src, "union '{}' is untagged", .{operand_ty.fmt(sema.mod)}), else => return sema.fail(block, operand_src, "expected enum or union; found '{}'", .{ operand_ty.fmt(mod), }), @@ -21338,16 +21267,9 @@ fn zirReify( if (enum_tag_ty != .none) { const tag_info = ip.indexToKey(enum_tag_ty).enum_type; const enum_index = tag_info.nameIndex(ip, field_name) orelse { - const msg = msg: { - const msg = try sema.errMsg(block, src, "no field named '{}' in enum '{}'", .{ - field_name.fmt(ip), - Type.fromInterned(enum_tag_ty).fmt(mod), - }); - errdefer msg.destroy(gpa); - try sema.addDeclaredHereNote(msg, Type.fromInterned(enum_tag_ty)); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.fail(block, src, "no field named '{}' in enum '{}'", .{ + field_name.fmt(ip), Type.fromInterned(enum_tag_ty).fmt(mod), + }); }; assert(explicit_tags_seen.len == tag_info.names.len); // No check for duplicate because the check already happened in order @@ -21379,14 +21301,7 @@ fn zirReify( }); if (field_ty.zigTypeTag(mod) == .Opaque) { - const msg = msg: { - const msg = try sema.errMsg(block, src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); - errdefer msg.destroy(gpa); - - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.fail(block, src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); } if (layout == .Extern and !try sema.validateExternType(field_ty, .union_field)) { const msg = msg: { @@ -21738,24 +21653,10 @@ fn reifyStruct( struct_type.setFieldComptime(ip, i); if (field_ty.zigTypeTag(mod) == .Opaque) { - const msg = msg: { - const msg = try sema.errMsg(block, src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); - errdefer msg.destroy(gpa); - - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.fail(block, src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); } if (field_ty.zigTypeTag(mod) == .NoReturn) { - const msg = msg: { - const msg = try sema.errMsg(block, src, "struct fields cannot be 'noreturn'", .{}); - errdefer msg.destroy(gpa); - - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.fail(block, src, "struct fields cannot be 'noreturn'", .{}); } if (layout == .Extern and !try sema.validateExternType(field_ty, .struct_field)) { const msg = msg: { @@ -22218,19 +22119,9 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData break :disjoint true; }; if (disjoint and dest_tag != .ErrorUnion) { - const msg = msg: { - const msg = try sema.errMsg( - block, - src, - "error sets '{}' and '{}' have no common errors", - .{ operand_ty.fmt(sema.mod), dest_ty.fmt(sema.mod) }, - ); - errdefer msg.destroy(sema.gpa); - try sema.addDeclaredHereNote(msg, operand_ty); - try sema.addDeclaredHereNote(msg, dest_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.fail(block, src, "error sets '{}' and '{}' have no common errors", .{ + operand_ty.fmt(sema.mod), dest_ty.fmt(sema.mod), + }); } if (maybe_operand_val) |val| { @@ -22244,18 +22135,9 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData error_name = operand_val.err.name; } if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), error_name)) { - const msg = msg: { - const msg = try sema.errMsg( - block, - src, - "'error.{}' not a member of error set '{}'", - .{ error_name.fmt(ip), dest_ty.fmt(sema.mod) }, - ); - errdefer msg.destroy(sema.gpa); - try sema.addDeclaredHereNote(msg, dest_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.fail(block, src, "'error.{}' not a member of error set '{}'", .{ + error_name.fmt(ip), dest_ty.fmt(sema.mod), + }); } } @@ -23015,15 +22897,7 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 try sema.resolveTypeLayout(ty); switch (ty.zigTypeTag(mod)) { .Struct => {}, - else => { - const msg = msg: { - const msg = try sema.errMsg(block, lhs_src, "expected struct type, found '{}'", .{ty.fmt(mod)}); - errdefer msg.destroy(sema.gpa); - try sema.addDeclaredHereNote(msg, ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); - }, + else => return sema.fail(block, lhs_src, "expected struct type, found '{}'", .{ty.fmt(mod)}), } const field_index = if (ty.isTuple(mod)) blk: { @@ -24465,23 +24339,9 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr } orelse return sema.fail(block, ptr_src, "pointer value not based on parent struct", .{}); if (field.index != field_index) { - const msg = msg: { - const msg = try sema.errMsg( - block, - src, - "field '{}' has index '{d}' but pointer value is index '{d}' of struct '{}'", - .{ - field_name.fmt(ip), - field_index, - field.index, - parent_ty.fmt(sema.mod), - }, - ); - errdefer msg.destroy(sema.gpa); - try sema.addDeclaredHereNote(msg, parent_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.fail(block, src, "field '{}' has index '{d}' but pointer value is index '{d}' of struct '{}'", .{ + field_name.fmt(ip), field_index, field.index, parent_ty.fmt(sema.mod), + }); } return Air.internedToRef(field.base); } @@ -26666,15 +26526,9 @@ fn fieldVal( switch (ip.indexToKey(child_type.toIntern())) { .error_set_type => |error_set_type| blk: { if (error_set_type.nameIndex(ip, field_name) != null) break :blk; - const msg = msg: { - const msg = try sema.errMsg(block, src, "no error named '{}' in '{}'", .{ - field_name.fmt(ip), child_type.fmt(mod), - }); - errdefer msg.destroy(sema.gpa); - try sema.addDeclaredHereNote(msg, child_type); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.fail(block, src, "no error named '{}' in '{}'", .{ + field_name.fmt(ip), child_type.fmt(mod), + }); }, .inferred_error_set_type => { return sema.fail(block, src, "TODO handle inferred error sets here", .{}); @@ -27601,18 +27455,11 @@ fn unionFieldPtr( const field_tag = try mod.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index); const tag_matches = un.tag == field_tag.toIntern(); if (!tag_matches) { - const msg = msg: { - const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), mod).?; - const active_field_name = Type.fromInterned(union_obj.enum_tag_ty).enumFieldName(active_index, mod); - const msg = try sema.errMsg(block, src, "access of union field '{}' while field '{}' is active", .{ - field_name.fmt(ip), - active_field_name.fmt(ip), - }); - errdefer msg.destroy(sema.gpa); - try sema.addDeclaredHereNote(msg, union_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), mod).?; + const active_field_name = Type.fromInterned(union_obj.enum_tag_ty).enumFieldName(active_index, mod); + return sema.fail(block, src, "access of union field '{}' while field '{}' is active", .{ + field_name.fmt(ip), active_field_name.fmt(ip), + }); } }, .Packed, .Extern => {}, @@ -27674,17 +27521,11 @@ fn unionFieldVal( if (tag_matches) { return Air.internedToRef(un.val); } else { - const msg = msg: { - const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), mod).?; - const active_field_name = Type.fromInterned(union_obj.enum_tag_ty).enumFieldName(active_index, mod); - const msg = try sema.errMsg(block, src, "access of union field '{}' while field '{}' is active", .{ - field_name.fmt(ip), active_field_name.fmt(ip), - }); - errdefer msg.destroy(sema.gpa); - try sema.addDeclaredHereNote(msg, union_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), mod).?; + const active_field_name = Type.fromInterned(union_obj.enum_tag_ty).enumFieldName(active_index, mod); + return sema.fail(block, src, "access of union field '{}' while field '{}' is active", .{ + field_name.fmt(ip), active_field_name.fmt(ip), + }); } }, .Packed, .Extern => |layout| { @@ -28812,18 +28653,9 @@ fn coerceExtra( const val = try sema.resolveConstDefinedValue(block, .unneeded, inst, undefined); const string = mod.intern_pool.indexToKey(val.toIntern()).enum_literal; const field_index = dest_ty.enumFieldIndex(string, mod) orelse { - const msg = msg: { - const msg = try sema.errMsg( - block, - inst_src, - "no field named '{}' in enum '{}'", - .{ string.fmt(&mod.intern_pool), dest_ty.fmt(mod) }, - ); - errdefer msg.destroy(sema.gpa); - try sema.addDeclaredHereNote(msg, dest_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.fail(block, inst_src, "no field named '{}' in enum '{}'", .{ + string.fmt(&mod.intern_pool), dest_ty.fmt(mod), + }); }; return Air.internedToRef((try mod.enumValueFieldIndex(dest_ty, @intCast(field_index))).toIntern()); }, @@ -28917,6 +28749,11 @@ fn coerceExtra( }; } }, + .Type => { + if (inst_ty.zigTypeTag(mod) == .Type) { + return inst; + } + }, else => {}, } @@ -31449,15 +31286,9 @@ fn coerceEnumToUnion( const enum_tag = try sema.coerce(block, tag_ty, inst, inst_src); if (try sema.resolveDefinedValue(block, inst_src, enum_tag)) |val| { const field_index = union_ty.unionTagFieldIndex(val, sema.mod) orelse { - const msg = msg: { - const msg = try sema.errMsg(block, inst_src, "union '{}' has no tag with value '{}'", .{ - union_ty.fmt(sema.mod), val.fmtValue(tag_ty, sema.mod), - }); - errdefer msg.destroy(sema.gpa); - try sema.addDeclaredHereNote(msg, union_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.fail(block, inst_src, "union '{}' has no tag with value '{}'", .{ + union_ty.fmt(sema.mod), val.fmtValue(tag_ty, sema.mod), + }); }; const union_obj = mod.typeToUnion(union_ty).?; @@ -31501,15 +31332,9 @@ fn coerceEnumToUnion( try sema.requireRuntimeBlock(block, inst_src, null); if (tag_ty.isNonexhaustiveEnum(mod)) { - const msg = msg: { - const msg = try sema.errMsg(block, inst_src, "runtime coercion to union '{}' from non-exhaustive enum", .{ - union_ty.fmt(sema.mod), - }); - errdefer msg.destroy(sema.gpa); - try sema.addDeclaredHereNote(msg, tag_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + return sema.fail(block, inst_src, "runtime coercion to union '{}' from non-exhaustive enum", .{ + union_ty.fmt(sema.mod), + }); } const union_obj = mod.typeToUnion(union_ty).?; @@ -36423,32 +36248,18 @@ fn semaStructFields( struct_type.field_types.get(ip)[field_i] = field_ty.toIntern(); if (field_ty.zigTypeTag(mod) == .Opaque) { - const msg = msg: { - const ty_src = mod.fieldSrcLoc(decl_index, .{ - .index = field_i, - .range = .type, - }).lazy; - const msg = try sema.errMsg(&block_scope, ty_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); - errdefer msg.destroy(sema.gpa); - - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); + const ty_src = mod.fieldSrcLoc(decl_index, .{ + .index = field_i, + .range = .type, + }).lazy; + return sema.fail(&block_scope, ty_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); } if (field_ty.zigTypeTag(mod) == .NoReturn) { - const msg = msg: { - const ty_src = mod.fieldSrcLoc(decl_index, .{ - .index = field_i, - .range = .type, - }).lazy; - const msg = try sema.errMsg(&block_scope, ty_src, "struct fields cannot be 'noreturn'", .{}); - errdefer msg.destroy(sema.gpa); - - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); + const ty_src = mod.fieldSrcLoc(decl_index, .{ + .index = field_i, + .range = .type, + }).lazy; + return sema.fail(&block_scope, ty_src, "struct fields cannot be 'noreturn'", .{}); } switch (struct_type.layout) { .Extern => if (!try sema.validateExternType(field_ty, .struct_field)) { @@ -36951,19 +36762,13 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un if (explicit_tags_seen.len > 0) { const tag_info = ip.indexToKey(union_type.tagTypePtr(ip).*).enum_type; const enum_index = tag_info.nameIndex(ip, field_name) orelse { - const msg = msg: { - const ty_src = mod.fieldSrcLoc(union_type.decl, .{ - .index = field_i, - .range = .type, - }).lazy; - const msg = try sema.errMsg(&block_scope, ty_src, "no field named '{}' in enum '{}'", .{ - field_name.fmt(ip), Type.fromInterned(union_type.tagTypePtr(ip).*).fmt(mod), - }); - errdefer msg.destroy(sema.gpa); - try sema.addDeclaredHereNote(msg, Type.fromInterned(union_type.tagTypePtr(ip).*)); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); + const ty_src = mod.fieldSrcLoc(union_type.decl, .{ + .index = field_i, + .range = .type, + }).lazy; + return sema.fail(&block_scope, ty_src, "no field named '{}' in enum '{}'", .{ + field_name.fmt(ip), Type.fromInterned(union_type.tagTypePtr(ip).*).fmt(mod), + }); }; // No check for duplicate because the check already happened in order // to create the enum type in the first place. @@ -36990,18 +36795,11 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un } if (field_ty.zigTypeTag(mod) == .Opaque) { - const msg = msg: { - const ty_src = mod.fieldSrcLoc(union_type.decl, .{ - .index = field_i, - .range = .type, - }).lazy; - const msg = try sema.errMsg(&block_scope, ty_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); - errdefer msg.destroy(sema.gpa); - - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); + const ty_src = mod.fieldSrcLoc(union_type.decl, .{ + .index = field_i, + .range = .type, + }).lazy; + return sema.fail(&block_scope, ty_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); } const layout = union_type.getLayout(ip); if (layout == .Extern and @@ -37441,6 +37239,13 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { // memoized value, not types .memoized_call, => unreachable, + + .type_alias => { + const data_index = ip.items.items(.data)[@intFromEnum(ty.toIntern())]; + const ty_index = ip.extra.items[data_index + std.meta.fieldIndex(InternPool.Key.TypeAlias, "ty").?]; + // Recurses once. + return sema.typeHasOnePossibleValue(Type.fromInterned(@enumFromInt(ty_index))); + }, .type_array_big, .type_array_small, diff --git a/src/TypedValue.zig b/src/TypedValue.zig index df4baf1008cf..e132c2e7bb46 100644 --- a/src/TypedValue.zig +++ b/src/TypedValue.zig @@ -446,6 +446,7 @@ pub fn print( return writer.writeAll(" }"); }, .memoized_call => unreachable, + .type_alias => unreachable, }, }; } diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index da33ae521d49..30a6343bfb5b 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -3253,6 +3253,7 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue { .func_type, .error_set_type, .inferred_error_set_type, + .type_alias, => unreachable, // types, not values .undef => unreachable, // handled above diff --git a/src/codegen.zig b/src/codegen.zig index 1ac8626a7959..0add8a95dd6e 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -212,6 +212,7 @@ pub fn generateSymbol( .func_type, .error_set_type, .inferred_error_set_type, + .type_alias, => unreachable, // types, not values .undef => unreachable, // handled above diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 7fd367bb4993..0d75e630c007 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1020,6 +1020,7 @@ pub const DeclGen = struct { .func_type, .error_set_type, .inferred_error_set_type, + .type_alias, // memoization, not values .memoized_call, => unreachable, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 8f2a27c5148a..c99c32b96a7f 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -3315,7 +3315,7 @@ pub const Object = struct { .var_args_param_type, .none, => unreachable, - else => switch (ip.indexToKey(t.toIntern())) { + else => switch (ip.indexToKeyExtra(t.toIntern(), true)) { .int_type => |int_type| try o.builder.intType(int_type.bits), .ptr_type => |ptr_type| type: { const ptr_ty = try o.builder.ptrType( @@ -3630,6 +3630,10 @@ pub const Object = struct { .enum_type => |enum_type| try o.lowerType(Type.fromInterned(enum_type.tag_ty)), .func_type => |func_type| try o.lowerTypeFn(func_type), .error_set_type, .inferred_error_set_type => try o.errorIntType(), + .type_alias => |alias| { + // Recurses once. + return o.lowerTypeInner(Type.fromInterned(alias.ty)); + }, // values, not types .undef, .simple_value, @@ -3768,6 +3772,7 @@ pub const Object = struct { .func_type, .error_set_type, .inferred_error_set_type, + .type_alias, => unreachable, // types, not values .undef => unreachable, // handled above diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 6b2587e3cb87..cbd93a1e6511 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -768,6 +768,7 @@ const DeclGen = struct { .func_type, .error_set_type, .inferred_error_set_type, + .type_alias, => unreachable, // types, not values .undef => unreachable, // handled above diff --git a/src/type.zig b/src/type.zig index dbf73c0eb2db..90d0aeac7570 100644 --- a/src/type.zig +++ b/src/type.zig @@ -129,7 +129,9 @@ pub const Type = struct { @compileError("do not format types directly; use either ty.fmtDebug() or ty.fmt()"); } - pub fn fmt(ty: Type, module: *Module) std.fmt.Formatter(format2) { + pub const Formatter = std.fmt.Formatter(format2); + + pub fn fmt(ty: Type, module: *Module) Formatter { return .{ .data = .{ .ty = ty, .module = module, @@ -172,7 +174,7 @@ pub const Type = struct { /// Prints a name suitable for `@typeName`. pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void { const ip = &mod.intern_pool; - switch (ip.indexToKey(ty.toIntern())) { + switch (ip.indexToKeyExtra(ty.toIntern(), true)) { .int_type => |int_type| { const sign_char: u8 = switch (int_type.signedness) { .signed => 'i', @@ -411,6 +413,10 @@ pub const Type = struct { try writer.writeAll("anyframe->"); return print(Type.fromInterned(child), writer, mod); }, + .type_alias => |alias| { + const decl = mod.declPtr(alias.decl); + return decl.renderFullyQualifiedName(mod, writer); + }, // values, not types .undef, @@ -656,6 +662,8 @@ pub const Type = struct { .un, // memoization, not types .memoized_call, + // never returned from indexToKey + .type_alias, => unreachable, }, }; @@ -763,6 +771,8 @@ pub const Type = struct { .un, // memoization, not types .memoized_call, + // never returned from indexToKey + .type_alias, => unreachable, }; } @@ -1078,6 +1088,8 @@ pub const Type = struct { .un, // memoization, not types .memoized_call, + // never returned from indexToKey + .type_alias, => unreachable, }, } @@ -1435,6 +1447,8 @@ pub const Type = struct { .un, // memoization, not types .memoized_call, + // never returned from indexToKey + .type_alias, => unreachable, }, } @@ -1657,6 +1671,8 @@ pub const Type = struct { .un, // memoization, not types .memoized_call, + // never returned from indexToKey + .type_alias, => unreachable, } } @@ -2192,6 +2208,8 @@ pub const Type = struct { .un, // memoization, not types .memoized_call, + // never returned from indexToKey + .type_alias, => unreachable, }, }; @@ -2535,6 +2553,9 @@ pub const Type = struct { .un, // memoization, not types .memoized_call, + + // never returned from indexToKey + .type_alias, => unreachable, }, }; @@ -2728,6 +2749,9 @@ pub const Type = struct { .un, // memoization, not types .memoized_call, + + // never returned from indexToKey + .type_alias, => unreachable, }, }; @@ -3123,6 +3147,13 @@ pub const Type = struct { }; } + pub fn getTypeAlias(ty: Type, mod: *Module) ?InternPool.Key.TypeAlias { + return switch (mod.intern_pool.indexToKeyExtra(ty.toIntern(), true)) { + .type_alias => |alias| alias, + else => null, + }; + } + pub fn getOwnerDecl(ty: Type, mod: *Module) InternPool.DeclIndex { return ty.getOwnerDeclOrNull(mod) orelse unreachable; } diff --git a/src/value.zig b/src/value.zig index 896ca108a7c2..1ac31ccaa91a 100644 --- a/src/value.zig +++ b/src/value.zig @@ -411,6 +411,8 @@ pub const Value = struct { }), .memoized_call => unreachable, + // never returned from indexToKey + .type_alias => unreachable, }; }