Commit 4e8fb9e6a5
Changed files (5)
src/Module.zig
@@ -366,6 +366,13 @@ pub const ErrorSet = struct {
/// The string bytes are stored in the owner Decl arena.
/// They are in the same order they appear in the AST.
names_ptr: [*]const []const u8,
+
+ pub fn srcLoc(self: ErrorSet) SrcLoc {
+ return .{
+ .container = .{ .decl = self.owner_decl },
+ .lazy = .{ .node_offset = self.node_offset },
+ };
+ }
};
/// Represents the data that a struct declaration provides.
@@ -408,6 +415,13 @@ pub const EnumSimple = struct {
fields: std.StringArrayHashMapUnmanaged(void),
/// Offset from `owner_decl`, points to the enum decl AST node.
node_offset: i32,
+
+ pub fn srcLoc(self: EnumSimple) SrcLoc {
+ return .{
+ .container = .{ .decl = self.owner_decl },
+ .lazy = .{ .node_offset = self.node_offset },
+ };
+ }
};
/// Represents the data that an enum declaration provides, when there is
@@ -429,6 +443,13 @@ pub const EnumFull = struct {
node_offset: i32,
pub const ValueMap = std.ArrayHashMapUnmanaged(Value, void, Value.hash_u32, Value.eql, false);
+
+ pub fn srcLoc(self: EnumFull) SrcLoc {
+ return .{
+ .container = .{ .decl = self.owner_decl },
+ .lazy = .{ .node_offset = self.node_offset },
+ };
+ }
};
/// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator.
src/Sema.zig
@@ -897,7 +897,7 @@ fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Ind
try mod.errNoteNonLazy(
struct_obj.srcLoc(),
msg,
- "'{s}' declared here",
+ "struct '{s}' declared here",
.{fqn},
);
return mod.failWithOwnedErrorMsg(&block.base, msg);
@@ -925,7 +925,7 @@ fn failWithBadFieldAccess(
.{ field_name, fqn },
);
errdefer msg.destroy(gpa);
- try mod.errNoteNonLazy(struct_obj.srcLoc(), msg, "'{s}' declared here", .{fqn});
+ try mod.errNoteNonLazy(struct_obj.srcLoc(), msg, "struct declared here", .{});
break :msg msg;
};
return mod.failWithOwnedErrorMsg(&block.base, msg);
@@ -4479,21 +4479,24 @@ fn namedFieldPtr(
return sema.analyzeDeclRef(block, src, decl);
}
}
- const maybe_field_index: ?usize = switch (child_type.tag()) {
- .enum_full, .enum_nonexhaustive => blk: {
- const enum_full = child_type.castTag(.enum_full).?.data;
- break :blk enum_full.fields.getIndex(field_name);
- },
- .enum_simple => blk: {
- const enum_simple = child_type.castTag(.enum_simple).?.data;
- break :blk enum_simple.fields.getIndex(field_name);
- },
- else => unreachable,
- };
- const field_index = maybe_field_index orelse {
- return mod.fail(&block.base, src, "enum '{}' has no member named '{s}'", .{
- child_type, field_name,
- });
+ const field_index = child_type.enumFieldIndex(field_name) orelse {
+ const msg = msg: {
+ const msg = try mod.errMsg(
+ &block.base,
+ src,
+ "enum '{}' has no member named '{s}'",
+ .{ child_type, field_name },
+ );
+ errdefer msg.destroy(sema.gpa);
+ try mod.errNoteNonLazy(
+ child_type.declSrcLoc(),
+ msg,
+ "enum declared here",
+ .{},
+ );
+ break :msg msg;
+ };
+ return mod.failWithOwnedErrorMsg(&block.base, msg);
};
const field_index_u32 = @intCast(u32, field_index);
const enum_val = try Value.Tag.enum_field_index.create(arena, field_index_u32);
@@ -4593,10 +4596,13 @@ fn coerce(
return sema.bitcast(block, dest_type, inst);
}
+ const mod = sema.mod;
+ const arena = sema.arena;
+
// undefined to anything
if (inst.value()) |val| {
if (val.isUndef() or inst.ty.zigTypeTag() == .Undefined) {
- return sema.mod.constInst(sema.arena, inst_src, .{ .ty = dest_type, .val = val });
+ return mod.constInst(arena, inst_src, .{ .ty = dest_type, .val = val });
}
}
assert(inst.ty.zigTypeTag() != .Undefined);
@@ -4610,13 +4616,13 @@ fn coerce(
if (try sema.coerceNum(block, dest_type, inst)) |some|
return some;
- const target = sema.mod.getTarget();
+ const target = mod.getTarget();
switch (dest_type.zigTypeTag()) {
.Optional => {
// null to ?T
if (inst.ty.zigTypeTag() == .Null) {
- return sema.mod.constInst(sema.arena, inst_src, .{ .ty = dest_type, .val = Value.initTag(.null_value) });
+ return mod.constInst(arena, inst_src, .{ .ty = dest_type, .val = Value.initTag(.null_value) });
}
// T to ?T
@@ -4703,63 +4709,39 @@ fn coerce(
}
},
.Enum => {
+ // enum literal to enum
if (inst.ty.zigTypeTag() == .EnumLiteral) {
- const val = (try sema.resolveDefinedValue(block, inst_src, inst)).?;
+ const val = try sema.resolveConstValue(block, inst_src, inst);
const bytes = val.castTag(.enum_literal).?.data;
- switch (dest_type.tag()) {
- .enum_full => {
- const enumeration = dest_type.castTag(.enum_full).?.data;
- const enum_fields = enumeration.fields;
- const i = enum_fields.getIndex(bytes) orelse return sema.mod.fail(
+ const field_index = dest_type.enumFieldIndex(bytes) orelse {
+ const msg = msg: {
+ const msg = try mod.errMsg(
&block.base,
inst_src,
- "enum '{s}' has no field named '{s}'",
- .{ enumeration.owner_decl.name, bytes },
+ "enum '{}' has no field named '{s}'",
+ .{ dest_type, bytes },
);
- const val_pl = try Value.Tag.enum_field_index.create(sema.arena, @intCast(u32, i));
- return sema.mod.constInst(sema.arena, inst_src, .{
- .ty = dest_type,
- .val = val_pl,
- });
- },
- .enum_simple => {
- const enumeration = dest_type.castTag(.enum_simple).?.data;
- const enum_fields = enumeration.fields;
- const i = enum_fields.getIndex(bytes) orelse return sema.mod.fail(
- &block.base,
- inst_src,
- "enum '{s}' has no field named '{s}'",
- .{ enumeration.owner_decl.name, bytes },
- );
- const val_pl = try Value.Tag.enum_field_index.create(sema.arena, @intCast(u32, i));
- return sema.mod.constInst(sema.arena, inst_src, .{
- .ty = dest_type,
- .val = val_pl,
- });
- },
- .enum_nonexhaustive => {
- const enumeration = dest_type.castTag(.enum_nonexhaustive).?.data;
- const enum_fields = enumeration.fields;
- const i = enum_fields.getIndex(bytes) orelse return sema.mod.fail(
- &block.base,
- inst_src,
- "enum '{s}' has no field named '{s}'",
- .{ enumeration.owner_decl.name, bytes },
+ errdefer msg.destroy(sema.gpa);
+ try mod.errNoteNonLazy(
+ dest_type.declSrcLoc(),
+ msg,
+ "enum declared here",
+ .{},
);
- const val_pl = try Value.Tag.enum_field_index.create(sema.arena, @intCast(u32, i));
- return sema.mod.constInst(sema.arena, inst_src, .{
- .ty = dest_type,
- .val = val_pl,
- });
- },
- else => unreachable,
- }
+ break :msg msg;
+ };
+ return mod.failWithOwnedErrorMsg(&block.base, msg);
+ };
+ return mod.constInst(arena, inst_src, .{
+ .ty = dest_type,
+ .val = try Value.Tag.enum_field_index.create(arena, @intCast(u32, field_index)),
+ });
}
},
else => {},
}
- return sema.mod.fail(&block.base, inst_src, "expected {}, found {}", .{ dest_type, inst.ty });
+ return mod.fail(&block.base, inst_src, "expected {}, found {}", .{ dest_type, inst.ty });
}
const InMemoryCoercionResult = enum {
src/type.zig
@@ -2090,6 +2090,42 @@ pub const Type = extern union {
};
}
+ pub fn enumFieldIndex(ty: Type, field_name: []const u8) ?usize {
+ switch (ty.tag()) {
+ .enum_full, .enum_nonexhaustive => {
+ const enum_full = ty.cast(Payload.EnumFull).?.data;
+ return enum_full.fields.getIndex(field_name);
+ },
+ .enum_simple => {
+ const enum_simple = ty.castTag(.enum_simple).?.data;
+ return enum_simple.fields.getIndex(field_name);
+ },
+ else => unreachable,
+ }
+ }
+
+ pub fn declSrcLoc(ty: Type) Module.SrcLoc {
+ switch (ty.tag()) {
+ .enum_full, .enum_nonexhaustive => {
+ const enum_full = ty.cast(Payload.EnumFull).?.data;
+ return enum_full.srcLoc();
+ },
+ .enum_simple => {
+ const enum_simple = ty.castTag(.enum_simple).?.data;
+ return enum_simple.srcLoc();
+ },
+ .@"struct" => {
+ const struct_obj = ty.castTag(.@"struct").?.data;
+ return struct_obj.srcLoc();
+ },
+ .error_set => {
+ const error_set = ty.castTag(.error_set).?.data;
+ return error_set.srcLoc();
+ },
+ else => unreachable,
+ }
+ }
+
/// Asserts the type is an enum.
pub fn enumHasInt(ty: Type, int: Value, target: Target) bool {
const S = struct {
test/stage2/cbe.zig
@@ -508,7 +508,7 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
, &.{
":3:21: error: mising struct field: x",
- ":1:15: note: 'Point' declared here",
+ ":1:15: note: struct 'Point' declared here",
});
case.addError(
\\const Point = struct { x: i32, y: i32 };
@@ -522,7 +522,7 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
, &.{
":6:10: error: no field named 'z' in struct 'Point'",
- ":1:15: note: 'Point' declared here",
+ ":1:15: note: struct declared here",
});
case.addCompareOutput(
\\const Point = struct { x: i32, y: i32 };
test/stage2/test.zig
@@ -1022,7 +1022,7 @@ pub fn addCases(ctx: *TestContext) !void {
"Hello, World!\n",
);
try case.files.append(.{
- .src =
+ .src =
\\pub fn print() void {
\\ asm volatile ("syscall"
\\ :
@@ -1621,11 +1621,11 @@ pub fn addCases(ctx: *TestContext) !void {
"",
);
case.addError(
- \\const E = enum { a, b };
\\export fn _start() noreturn {
\\ const a: E = .c;
\\ exit();
\\}
+ \\const E = enum { a, b };
\\fn exit() noreturn {
\\ asm volatile ("syscall"
\\ :
@@ -1635,6 +1635,9 @@ pub fn addCases(ctx: *TestContext) !void {
\\ );
\\ unreachable;
\\}
- , &.{":3:19: error: enum 'E' has no field named 'c'"});
+ , &.{
+ ":2:19: error: enum 'E' has no field named 'c'",
+ ":5:11: note: enum declared here",
+ });
}
}