| author | |
| committer | |
| log | 54d196bb300770394fd57db718ff1768edd552f8 |
| tree | bea1eab99aeed800b92fc589ad505cb84a86f122 |
| parent | be6f76655fb355426dc8f3824368376608bc0ba1 |
| parent | d63298da65df7fa2712bf9e9d65d36cd91af22fa |
| signature |
Fix bad error location on field init with field access 5 files changed, 54 insertions(+), 4 deletions(-)
src/InternPool.zig+7| ... | @@ -8301,6 +8301,13 @@ pub fn funcZirBodyInst(ip: *const InternPool, i: Index) Zir.Inst.Index { | ... | @@ -8301,6 +8301,13 @@ pub fn funcZirBodyInst(ip: *const InternPool, i: Index) Zir.Inst.Index { |
| 8301 | assert(ip.items.items(.tag)[func_decl_index] == .func_decl); | 8301 | assert(ip.items.items(.tag)[func_decl_index] == .func_decl); |
| 8302 | break :b ip.items.items(.data)[func_decl_index] + zir_body_inst_field_index; | 8302 | break :b ip.items.items(.data)[func_decl_index] + zir_body_inst_field_index; |
| 8303 | }, | 8303 | }, |
| 8304 | .func_coerced => { | ||
| 8305 | const datas = ip.items.items(.data); | ||
| 8306 | const uncoerced_func_index: Index = @enumFromInt(ip.extra.items[ | ||
| 8307 | datas[@intFromEnum(i)] + std.meta.fieldIndex(Tag.FuncCoerced, "func").? | ||
| 8308 | ]); | ||
| 8309 | return ip.funcZirBodyInst(uncoerced_func_index); | ||
| 8310 | }, | ||
| 8304 | else => unreachable, | 8311 | else => unreachable, |
| 8305 | }; | 8312 | }; |
| 8306 | return @enumFromInt(ip.extra.items[extra_index]); | 8313 | return @enumFromInt(ip.extra.items[extra_index]); |
src/Module.zig+15-2| ... | @@ -1467,6 +1467,14 @@ pub const SrcLoc = struct { | ... | @@ -1467,6 +1467,14 @@ pub const SrcLoc = struct { |
| 1467 | const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len)); | 1467 | const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len)); |
| 1468 | return Span{ .start = start, .end = end, .main = start }; | 1468 | return Span{ .start = start, .end = end, .main = start }; |
| 1469 | }, | 1469 | }, |
| 1470 | .node_offset_field_name_init => |node_off| { | ||
| 1471 | const tree = try src_loc.file_scope.getTree(gpa); | ||
| 1472 | const node = src_loc.declRelativeToNodeIndex(node_off); | ||
| 1473 | const tok_index = tree.firstToken(node) - 2; | ||
| 1474 | const start = tree.tokens.items(.start)[tok_index]; | ||
| 1475 | const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len)); | ||
| 1476 | return Span{ .start = start, .end = end, .main = start }; | ||
| 1477 | }, | ||
| 1470 | .node_offset_deref_ptr => |node_off| { | 1478 | .node_offset_deref_ptr => |node_off| { |
| 1471 | const tree = try src_loc.file_scope.getTree(gpa); | 1479 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1472 | const node = src_loc.declRelativeToNodeIndex(node_off); | 1480 | const node = src_loc.declRelativeToNodeIndex(node_off); |
| ... | @@ -2132,10 +2140,14 @@ pub const LazySrcLoc = union(enum) { | ... | @@ -2132,10 +2140,14 @@ pub const LazySrcLoc = union(enum) { |
| 2132 | /// The payload is offset from the containing Decl AST node. | 2140 | /// The payload is offset from the containing Decl AST node. |
| 2133 | /// The source location points to the field name of: | 2141 | /// The source location points to the field name of: |
| 2134 | /// * a field access expression (`a.b`), or | 2142 | /// * a field access expression (`a.b`), or |
| 2135 | /// * the callee of a method call (`a.b()`), or | 2143 | /// * the callee of a method call (`a.b()`) |
| 2136 | /// * the operand ("b" node) of a field initialization expression (`.a = b`), or | ||
| 2137 | /// The Decl is determined contextually. | 2144 | /// The Decl is determined contextually. |
| 2138 | node_offset_field_name: i32, | 2145 | node_offset_field_name: i32, |
| 2146 | /// The payload is offset from the containing Decl AST node. | ||
| 2147 | /// The source location points to the field name of the operand ("b" node) | ||
| 2148 | /// of a field initialization expression (`.a = b`) | ||
| 2149 | /// The Decl is determined contextually. | ||
| 2150 | node_offset_field_name_init: i32, | ||
| 2139 | /// The source location points to the pointer of a pointer deref expression, | 2151 | /// The source location points to the pointer of a pointer deref expression, |
| 2140 | /// found by taking this AST node index offset from the containing | 2152 | /// found by taking this AST node index offset from the containing |
| 2141 | /// Decl AST node, which points to a pointer deref AST node. Next, navigate | 2153 | /// Decl AST node, which points to a pointer deref AST node. Next, navigate |
| ... | @@ -2374,6 +2386,7 @@ pub const LazySrcLoc = union(enum) { | ... | @@ -2374,6 +2386,7 @@ pub const LazySrcLoc = union(enum) { |
| 2374 | .node_offset_slice_sentinel, | 2386 | .node_offset_slice_sentinel, |
| 2375 | .node_offset_call_func, | 2387 | .node_offset_call_func, |
| 2376 | .node_offset_field_name, | 2388 | .node_offset_field_name, |
| 2389 | .node_offset_field_name_init, | ||
| 2377 | .node_offset_deref_ptr, | 2390 | .node_offset_deref_ptr, |
| 2378 | .node_offset_asm_source, | 2391 | .node_offset_asm_source, |
| 2379 | .node_offset_asm_ret_ty, | 2392 | .node_offset_asm_ret_ty, |
src/Sema.zig+2-2| ... | @@ -9931,7 +9931,7 @@ fn zirStructInitFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi | ... | @@ -9931,7 +9931,7 @@ fn zirStructInitFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi |
| 9931 | const mod = sema.mod; | 9931 | const mod = sema.mod; |
| 9932 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; | 9932 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 9933 | const src = inst_data.src(); | 9933 | const src = inst_data.src(); |
| 9934 | const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node }; | 9934 | const field_name_src: LazySrcLoc = .{ .node_offset_field_name_init = inst_data.src_node }; |
| 9935 | const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data; | 9935 | const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data; |
| 9936 | const field_name = try mod.intern_pool.getOrPutString(sema.gpa, sema.code.nullTerminatedString(extra.field_name_start)); | 9936 | const field_name = try mod.intern_pool.getOrPutString(sema.gpa, sema.code.nullTerminatedString(extra.field_name_start)); |
| 9937 | const object_ptr = try sema.resolveInst(extra.lhs); | 9937 | const object_ptr = try sema.resolveInst(extra.lhs); |
| ... | @@ -19921,7 +19921,7 @@ fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp | ... | @@ -19921,7 +19921,7 @@ fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp |
| 19921 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; | 19921 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 19922 | const extra = sema.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data; | 19922 | const extra = sema.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data; |
| 19923 | const ty_src = inst_data.src(); | 19923 | const ty_src = inst_data.src(); |
| 19924 | const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node }; | 19924 | const field_name_src: LazySrcLoc = .{ .node_offset_field_name_init = inst_data.src_node }; |
| 19925 | const wrapped_aggregate_ty = sema.resolveType(block, ty_src, extra.container_type) catch |err| switch (err) { | 19925 | const wrapped_aggregate_ty = sema.resolveType(block, ty_src, extra.container_type) catch |err| switch (err) { |
| 19926 | // Since this is a ZIR instruction that returns a type, encountering | 19926 | // Since this is a ZIR instruction that returns a type, encountering |
| 19927 | // generic poison should not result in a failed compilation, but the | 19927 | // generic poison should not result in a failed compilation, but the |
test/behavior/call.zig+21| ... | @@ -499,3 +499,24 @@ test "call inline fn through pointer" { | ... | @@ -499,3 +499,24 @@ test "call inline fn through pointer" { |
| 499 | const f = &S.foo; | 499 | const f = &S.foo; |
| 500 | try f(123); | 500 | try f(123); |
| 501 | } | 501 | } |
| 502 | |||
| 503 | test "call coerced function" { | ||
| 504 | const T = struct { | ||
| 505 | x: f64, | ||
| 506 | const T = @This(); | ||
| 507 | usingnamespace Implement(1); | ||
| 508 | const F = fn (comptime f64) type; | ||
| 509 | const Implement: F = opaque { | ||
| 510 | fn implementer(comptime val: anytype) type { | ||
| 511 | return opaque { | ||
| 512 | fn incr(self: T) T { | ||
| 513 | return .{ .x = self.x + val }; | ||
| 514 | } | ||
| 515 | }; | ||
| 516 | } | ||
| 517 | }.implementer; | ||
| 518 | }; | ||
| 519 | |||
| 520 | const a = T{ .x = 3 }; | ||
| 521 | try std.testing.expect(a.incr().x == 4); | ||
| 522 | } |
test/cases/compile_errors/invalid_field_in_struct_value_expression.zig+9| ... | @@ -21,6 +21,13 @@ pub export fn entry() void { | ... | @@ -21,6 +21,13 @@ pub export fn entry() void { |
| 21 | dump(.{ .field_1 = 123, .field_3 = 456 }); | 21 | dump(.{ .field_1 = 123, .field_3 = 456 }); |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | pub export fn entry1() void { | ||
| 25 | const x = Object{ | ||
| 26 | .abc = 1, | ||
| 27 | }; | ||
| 28 | _ = x; | ||
| 29 | } | ||
| 30 | |||
| 24 | // error | 31 | // error |
| 25 | // backend=stage2 | 32 | // backend=stage2 |
| 26 | // target=native | 33 | // target=native |
| ... | @@ -29,3 +36,5 @@ pub export fn entry() void { | ... | @@ -29,3 +36,5 @@ pub export fn entry() void { |
| 29 | // :1:11: note: struct declared here | 36 | // :1:11: note: struct declared here |
| 30 | // :21:30: error: no field named 'field_3' in struct 'tmp.Object' | 37 | // :21:30: error: no field named 'field_3' in struct 'tmp.Object' |
| 31 | // :15:16: note: struct declared here | 38 | // :15:16: note: struct declared here |
| 39 | // :26:10: error: no field named 'abc' in struct 'tmp.Object' | ||
| 40 | // :15:16: note: struct declared here |