Commit a947f97331

Veikka Tuominen <git@vexu.eu>
2023-11-21 12:23:24
Sema: fix bad error location on field init with field access
Closes #14753
1 parent f64f342
Changed files (3)
src/Module.zig
@@ -1467,6 +1467,14 @@ pub const SrcLoc = struct {
                 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
                 return Span{ .start = start, .end = end, .main = start };
             },
+            .node_offset_field_name_init => |node_off| {
+                const tree = try src_loc.file_scope.getTree(gpa);
+                const node = src_loc.declRelativeToNodeIndex(node_off);
+                const tok_index = tree.firstToken(node) - 2;
+                const start = tree.tokens.items(.start)[tok_index];
+                const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
+                return Span{ .start = start, .end = end, .main = start };
+            },
             .node_offset_deref_ptr => |node_off| {
                 const tree = try src_loc.file_scope.getTree(gpa);
                 const node = src_loc.declRelativeToNodeIndex(node_off);
@@ -2132,10 +2140,14 @@ pub const LazySrcLoc = union(enum) {
     /// The payload is offset from the containing Decl AST node.
     /// The source location points to the field name of:
     ///  * a field access expression (`a.b`), or
-    ///  * the callee of a method call (`a.b()`), or
-    ///  * the operand ("b" node) of a field initialization expression (`.a = b`), or
+    ///  * the callee of a method call (`a.b()`)
     /// The Decl is determined contextually.
     node_offset_field_name: i32,
+    /// The payload is offset from the containing Decl AST node.
+    /// The source location points to the field name of the operand ("b" node)
+    /// of a field initialization expression (`.a = b`)
+    /// The Decl is determined contextually.
+    node_offset_field_name_init: i32,
     /// The source location points to the pointer of a pointer deref expression,
     /// found by taking this AST node index offset from the containing
     /// Decl AST node, which points to a pointer deref AST node. Next, navigate
@@ -2374,6 +2386,7 @@ pub const LazySrcLoc = union(enum) {
             .node_offset_slice_sentinel,
             .node_offset_call_func,
             .node_offset_field_name,
+            .node_offset_field_name_init,
             .node_offset_deref_ptr,
             .node_offset_asm_source,
             .node_offset_asm_ret_ty,
src/Sema.zig
@@ -9931,7 +9931,7 @@ fn zirStructInitFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi
     const mod = sema.mod;
     const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
     const src = inst_data.src();
-    const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node };
+    const field_name_src: LazySrcLoc = .{ .node_offset_field_name_init = inst_data.src_node };
     const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
     const field_name = try mod.intern_pool.getOrPutString(sema.gpa, sema.code.nullTerminatedString(extra.field_name_start));
     const object_ptr = try sema.resolveInst(extra.lhs);
@@ -19921,7 +19921,7 @@ fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
     const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
     const extra = sema.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;
     const ty_src = inst_data.src();
-    const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node };
+    const field_name_src: LazySrcLoc = .{ .node_offset_field_name_init = inst_data.src_node };
     const wrapped_aggregate_ty = sema.resolveType(block, ty_src, extra.container_type) catch |err| switch (err) {
         // Since this is a ZIR instruction that returns a type, encountering
         // generic poison should not result in a failed compilation, but the
test/cases/compile_errors/invalid_field_in_struct_value_expression.zig
@@ -21,6 +21,13 @@ pub export fn entry() void {
     dump(.{ .field_1 = 123, .field_3 = 456 });
 }
 
+pub export fn entry1() void {
+    const x = Object{
+        .abc = 1,
+    };
+    _ = x;
+}
+
 // error
 // backend=stage2
 // target=native
@@ -29,3 +36,5 @@ pub export fn entry() void {
 // :1:11: note: struct declared here
 // :21:30: error: no field named 'field_3' in struct 'tmp.Object'
 // :15:16: note: struct declared here
+// :26:10: error: no field named 'abc' in struct 'tmp.Object'
+// :15:16: note: struct declared here