Commit 6cc2b26163

John Schmidt <john.schmidt.h@gmail.com>
2022-09-24 02:23:22
sema: load the correct AST in addFieldErrNote
The enum we want to get the fields from might not be declared in the same file as the block we are analyzing, so we should get the AST from the decl's file instead. Closes #12950.
1 parent 6d7b069
src/Sema.zig
@@ -1908,7 +1908,6 @@ fn errNote(
 
 fn addFieldErrNote(
     sema: *Sema,
-    block: *Block,
     container_ty: Type,
     field_index: usize,
     parent: *Module.ErrorMsg,
@@ -1918,7 +1917,10 @@ fn addFieldErrNote(
     const mod = sema.mod;
     const decl_index = container_ty.getOwnerDecl();
     const decl = mod.declPtr(decl_index);
-    const tree = try sema.getAstTree(block);
+    const tree = decl.getFileScope().getTree(sema.gpa) catch |err| {
+        log.err("unable to load AST to report compile error: {s}", .{@errorName(err)});
+        return error.AnalysisFail;
+    };
     const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_index);
     try mod.errNoteNonLazy(field_src.toSrcLoc(decl), parent, format, args);
 }
@@ -9371,7 +9373,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
 
                         const field_name = operand_ty.enumFieldName(i);
                         try sema.addFieldErrNote(
-                            block,
                             operand_ty,
                             i,
                             msg,
@@ -17379,7 +17380,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
                         const enum_ty = union_obj.tag_ty;
                         for (names.keys()) |field_name| {
                             const field_index = enum_ty.enumFieldIndex(field_name).?;
-                            try sema.addFieldErrNote(block, enum_ty, field_index, msg, "field '{s}' missing, declared here", .{field_name});
+                            try sema.addFieldErrNote(enum_ty, field_index, msg, "field '{s}' missing, declared here", .{field_name});
                         }
                         try sema.addDeclaredHereNote(msg, union_obj.tag_ty);
                         break :msg msg;
@@ -17667,7 +17668,7 @@ fn reifyStruct(
             sema.resolveTypeLayout(block, src, field.ty) catch |err| switch (err) {
                 error.AnalysisFail => {
                     const msg = sema.err orelse return err;
-                    try sema.addFieldErrNote(block, struct_ty, index, msg, "while checking this field", .{});
+                    try sema.addFieldErrNote(struct_ty, index, msg, "while checking this field", .{});
                     return err;
                 },
                 else => return err,
@@ -22270,7 +22271,7 @@ fn unionFieldPtr(
             const msg = try sema.errMsg(block, src, "cannot initialize 'noreturn' field of union", .{});
             errdefer msg.destroy(sema.gpa);
 
-            try sema.addFieldErrNote(block, union_ty, field_index, msg, "field '{s}' declared here", .{field_name});
+            try sema.addFieldErrNote(union_ty, field_index, msg, "field '{s}' declared here", .{field_name});
             try sema.addDeclaredHereNote(msg, union_ty);
             break :msg msg;
         };
@@ -25748,7 +25749,7 @@ fn coerceEnumToUnion(
                 errdefer msg.destroy(sema.gpa);
 
                 const field_name = union_obj.fields.keys()[field_index];
-                try sema.addFieldErrNote(block, union_ty, field_index, msg, "field '{s}' declared here", .{field_name});
+                try sema.addFieldErrNote(union_ty, field_index, msg, "field '{s}' declared here", .{field_name});
                 try sema.addDeclaredHereNote(msg, union_ty);
                 break :msg msg;
             };
@@ -25762,7 +25763,7 @@ fn coerceEnumToUnion(
                 });
                 errdefer msg.destroy(sema.gpa);
 
-                try sema.addFieldErrNote(block, union_ty, field_index, msg, "field '{s}' declared here", .{field_name});
+                try sema.addFieldErrNote(union_ty, field_index, msg, "field '{s}' declared here", .{field_name});
                 try sema.addDeclaredHereNote(msg, union_ty);
                 break :msg msg;
             };
@@ -25804,7 +25805,7 @@ fn coerceEnumToUnion(
                 );
                 msg = err_msg;
 
-                try sema.addFieldErrNote(block, union_ty, i, err_msg, "'noreturn' field here", .{});
+                try sema.addFieldErrNote(union_ty, i, err_msg, "'noreturn' field here", .{});
             }
         }
         if (msg) |some| {
@@ -25834,7 +25835,7 @@ fn coerceEnumToUnion(
             const field_name = field.key_ptr.*;
             const field_ty = field.value_ptr.ty;
             if (!field_ty.hasRuntimeBits()) continue;
-            try sema.addFieldErrNote(block, union_ty, field_index, msg, "field '{s}' has type '{}'", .{ field_name, field_ty.fmt(sema.mod) });
+            try sema.addFieldErrNote(union_ty, field_index, msg, "field '{s}' has type '{}'", .{ field_name, field_ty.fmt(sema.mod) });
         }
         try sema.addDeclaredHereNote(msg, union_ty);
         break :msg msg;
@@ -28056,7 +28057,7 @@ fn resolveStructLayout(
             sema.resolveTypeLayout(block, src, field.ty) catch |err| switch (err) {
                 error.AnalysisFail => {
                     const msg = sema.err orelse return err;
-                    try sema.addFieldErrNote(block, ty, i, msg, "while checking this field", .{});
+                    try sema.addFieldErrNote(ty, i, msg, "while checking this field", .{});
                     return err;
                 },
                 else => return err,
@@ -28076,7 +28077,7 @@ fn resolveStructLayout(
             _ = sema.typeRequiresComptime(field.ty) catch |err| switch (err) {
                 error.AnalysisFail => {
                     const msg = sema.err orelse return err;
-                    try sema.addFieldErrNote(block, ty, i, msg, "while checking this field", .{});
+                    try sema.addFieldErrNote(ty, i, msg, "while checking this field", .{});
                     return err;
                 },
                 else => return err,
@@ -28215,7 +28216,7 @@ fn resolveUnionLayout(
         sema.resolveTypeLayout(block, src, field.ty) catch |err| switch (err) {
             error.AnalysisFail => {
                 const msg = sema.err orelse return err;
-                try sema.addFieldErrNote(block, ty, i, msg, "while checking this field", .{});
+                try sema.addFieldErrNote(ty, i, msg, "while checking this field", .{});
                 return err;
             },
             else => return err,
@@ -29101,7 +29102,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
                 const enum_ty = union_obj.tag_ty;
                 for (names.keys()) |field_name| {
                     const field_index = enum_ty.enumFieldIndex(field_name).?;
-                    try sema.addFieldErrNote(&block_scope, enum_ty, field_index, msg, "field '{s}' missing, declared here", .{field_name});
+                    try sema.addFieldErrNote(enum_ty, field_index, msg, "field '{s}' missing, declared here", .{field_name});
                 }
                 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);
                 break :msg msg;
@@ -29376,7 +29377,7 @@ pub fn typeHasOnePossibleValue(
                         "struct '{}' depends on itself",
                         .{ty.fmt(sema.mod)},
                     );
-                    try sema.addFieldErrNote(block, resolved_ty, i, msg, "while checking this field", .{});
+                    try sema.addFieldErrNote(resolved_ty, i, msg, "while checking this field", .{});
                     return sema.failWithOwnedErrorMsg(msg);
                 }
                 if ((try sema.typeHasOnePossibleValue(block, src, field.ty)) == null) {
@@ -29462,7 +29463,7 @@ pub fn typeHasOnePossibleValue(
                     "union '{}' depends on itself",
                     .{ty.fmt(sema.mod)},
                 );
-                try sema.addFieldErrNote(block, resolved_ty, 0, msg, "while checking this field", .{});
+                try sema.addFieldErrNote(resolved_ty, 0, msg, "while checking this field", .{});
                 return sema.failWithOwnedErrorMsg(msg);
             }
             const val_val = (try sema.typeHasOnePossibleValue(block, src, only_field.ty)) orelse
test/cases/compile_errors/unhandled_enum_value_in_switch_with_enum_declared_in_other_file.zig
@@ -0,0 +1,16 @@
+const std = @import("std");
+
+pub export fn entry1() void {
+    const order: std.math.Order = .lt;
+    switch (order) {}
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :5:5: error: switch must handle all possibilities
+// :?:?: note: unhandled enumeration value: 'lt'
+// :?:?: note: unhandled enumeration value: 'eq'
+// :?:?: note: unhandled enumeration value: 'gt'
+// :?:?: note: enum 'math.Order' declared here