Commit c4f7663c92

mparadinha <mparadinha@users.noreply.github.com>
2022-11-15 14:17:23
Fix error reporting the wrong line for struct field inits (#13502)
* point to init part of field delc when that's where the error occurs * update test to reflect fixed error message * only lookup source location in case of error
1 parent ceb9fed
src/Sema.zig
@@ -29768,9 +29768,20 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
                 extra_index += body.len;
                 const init = try sema.resolveBody(&block_scope, body, struct_obj.zir_index);
                 const field = &struct_obj.fields.values()[i];
-                const coerced = try sema.coerce(&block_scope, field.ty, init, src);
-                const default_val = (try sema.resolveMaybeUndefVal(coerced)) orelse
-                    return sema.failWithNeededComptime(&block_scope, src, "struct field default value must be comptime-known");
+                const coerced = sema.coerce(&block_scope, field.ty, init, .unneeded) catch |err| switch (err) {
+                    error.NeededSourceLocation => {
+                        const tree = try sema.getAstTree(&block_scope);
+                        const init_src = containerFieldInitSrcLoc(decl, tree.*, 0, i);
+                        _ = try sema.coerce(&block_scope, field.ty, init, init_src);
+                        return error.AnalysisFail;
+                    },
+                    else => |e| return e,
+                };
+                const default_val = (try sema.resolveMaybeUndefVal(coerced)) orelse {
+                    const tree = try sema.getAstTree(&block_scope);
+                    const init_src = containerFieldInitSrcLoc(decl, tree.*, 0, i);
+                    return sema.failWithNeededComptime(&block_scope, init_src, "struct field default value must be comptime-known");
+                };
                 field.default_val = try default_val.copy(decl_arena_allocator);
             }
         }
@@ -30553,11 +30564,49 @@ fn enumFieldSrcLoc(
     node_offset: i32,
     field_index: usize,
 ) LazySrcLoc {
+    @setCold(true);
+    const field_node = containerFieldNode(decl, tree, node_offset, field_index) orelse
+        return LazySrcLoc.nodeOffset(0);
+    return decl.nodeSrcLoc(field_node);
+}
+
+fn containerFieldInitSrcLoc(
+    decl: *Decl,
+    tree: std.zig.Ast,
+    node_offset: i32,
+    field_index: usize,
+) LazySrcLoc {
+    @setCold(true);
+    const node_tags = tree.nodes.items(.tag);
+    const field_node = containerFieldNode(decl, tree, node_offset, field_index) orelse
+        return LazySrcLoc.nodeOffset(0);
+    const node_data = tree.nodes.items(.data)[field_node];
+
+    const init_node = switch (node_tags[field_node]) {
+        .container_field_init => node_data.rhs,
+        .container_field => blk: {
+            const extra_data = tree.extraData(node_data.rhs, std.zig.Ast.Node.ContainerField);
+            break :blk extra_data.value_expr;
+        },
+        else => unreachable,
+    };
+
+    return decl.nodeSrcLoc(init_node);
+}
+
+fn containerFieldNode(
+    decl: *Decl,
+    tree: std.zig.Ast,
+    node_offset: i32,
+    field_index: usize,
+) ?std.zig.Ast.Node.Index {
     @setCold(true);
     const enum_node = decl.relativeToNodeIndex(node_offset);
     const node_tags = tree.nodes.items(.tag);
     var buffer: [2]std.zig.Ast.Node.Index = undefined;
     const container_decl = switch (node_tags[enum_node]) {
+        .root => tree.containerDeclRoot(),
+
         .container_decl,
         .container_decl_trailing,
         => tree.containerDecl(enum_node),
@@ -30580,8 +30629,7 @@ fn enumFieldSrcLoc(
         .tagged_union_enum_tag_trailing,
         => tree.taggedUnionEnumTag(enum_node),
 
-        // Container was constructed with `@Type`.
-        else => return LazySrcLoc.nodeOffset(0),
+        else => return null,
     };
     var it_index: usize = 0;
     for (container_decl.ast.members) |member_node| {
@@ -30590,9 +30638,7 @@ fn enumFieldSrcLoc(
             .container_field_align,
             .container_field,
             => {
-                if (it_index == field_index) {
-                    return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(member_node));
-                }
+                if (it_index == field_index) return member_node;
                 it_index += 1;
             },
 
test/cases/compile_errors/issue_5221_invalid_struct_init_type_referenced_by_typeInfo_and_passed_into_function.zig
@@ -1,4 +1,6 @@
-fn ignore(comptime param: anytype) void {_ = param;}
+fn ignore(comptime param: anytype) void {
+    _ = param;
+}
 
 export fn foo() void {
     const MyStruct = struct {
@@ -12,5 +14,5 @@ export fn foo() void {
 // backend=stage2
 // target=native
 //
-// :4:22: error: expected type '[]u8', found '*const [3:0]u8'
-// :4:22: note: cast discards const qualifier
+// :7:28: error: expected type '[]u8', found '*const [3:0]u8'
+// :7:28: note: cast discards const qualifier