diff --git a/src/Sema.zig b/src/Sema.zig index 41685890f7..6c24746da8 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -23605,10 +23605,13 @@ fn fieldCallBind( } // If we get here, we need to look for a decl in the struct type instead. - switch (concrete_ty.zigTypeTag()) { - .Struct, .Opaque, .Union, .Enum => { + const found_decl = switch (concrete_ty.zigTypeTag()) { + .Struct, .Opaque, .Union, .Enum => found_decl: { if (concrete_ty.getNamespace()) |namespace| { - if (try sema.namespaceLookupRef(block, src, namespace, field_name)) |inst| { + if (try sema.namespaceLookup(block, src, namespace, field_name)) |decl_idx| { + try sema.addReferencedBy(block, src, decl_idx); + const inst = try sema.analyzeDeclRef(decl_idx); + const decl_val = try sema.analyzeLoad(block, src, inst, src); const decl_type = sema.typeOf(decl_val); if (decl_type.zigTypeTag() == .Fn and @@ -23625,7 +23628,7 @@ fn fieldCallBind( first_param_type.ptrSize() == .C) and first_param_type.childType().eql(concrete_ty, sema.mod))) { - // zig fmt: on + // zig fmt: on // TODO: bound fn calls on rvalues should probably // generate a by-value argument somehow. const ty = Type.Tag.bound_fn.init(); @@ -23664,16 +23667,22 @@ fn fieldCallBind( return sema.addConstant(ty, value); } } + break :found_decl decl_idx; } } + break :found_decl null; }, - else => {}, - } + else => null, + }; const msg = msg: { const msg = try sema.errMsg(block, src, "no field or member function named '{s}' in '{}'", .{ field_name, concrete_ty.fmt(sema.mod) }); errdefer msg.destroy(sema.gpa); try sema.addDeclaredHereNote(msg, concrete_ty); + if (found_decl) |decl_idx| { + const decl = sema.mod.declPtr(decl_idx); + try sema.mod.errNoteNonLazy(decl.srcLoc(), msg, "'{s}' is not a member function", .{field_name}); + } break :msg msg; }; return sema.failWithOwnedErrorMsg(msg); diff --git a/test/cases/compile_errors/method_call_with_first_arg_type_primitive.zig b/test/cases/compile_errors/method_call_with_first_arg_type_primitive.zig index 1cecac6fac..2a5167adf2 100644 --- a/test/cases/compile_errors/method_call_with_first_arg_type_primitive.zig +++ b/test/cases/compile_errors/method_call_with_first_arg_type_primitive.zig @@ -2,7 +2,7 @@ const Foo = struct { x: i32, fn init(x: i32) Foo { - return Foo { + return Foo{ .x = x, }; } @@ -20,3 +20,4 @@ export fn f() void { // // :14:9: error: no field or member function named 'init' in 'tmp.Foo' // :1:13: note: struct declared here +// :4:5: note: 'init' is not a member function diff --git a/test/cases/compile_errors/method_call_with_first_arg_type_wrong_container.zig b/test/cases/compile_errors/method_call_with_first_arg_type_wrong_container.zig index ad481a6158..0653bda3ea 100644 --- a/test/cases/compile_errors/method_call_with_first_arg_type_wrong_container.zig +++ b/test/cases/compile_errors/method_call_with_first_arg_type_wrong_container.zig @@ -29,3 +29,4 @@ export fn foo() void { // // :23:6: error: no field or member function named 'init' in 'tmp.List' // :1:18: note: struct declared here +// :5:9: note: 'init' is not a member function