From 2d37c2077854e225204a7c4c26c10453a20de6d1 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 21 Jan 2026 14:40:04 -0800 Subject: [PATCH] go/types, types2: better error when selecting field on type rather than value Fixes #6814. Change-Id: I659670998f8e89400d03d40189e8c54f7e705cdc Reviewed-on: https://go-review.googlesource.com/c/go/+/738040 Reviewed-by: Alan Donovan Auto-Submit: Robert Griesemer LUCI-TryBot-Result: Go LUCI Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/call.go | 3 +- src/go/types/call.go | 3 +- src/internal/types/testdata/check/expr3.go | 6 ++-- src/internal/types/testdata/check/issues0.go | 2 +- .../types/testdata/fixedbugs/issue6814.go | 35 +++++++++++++++++++ 5 files changed, 43 insertions(+), 6 deletions(-) create mode 100644 src/internal/types/testdata/fixedbugs/issue6814.go diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 3461c890a8..dfbb0a5491 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -835,6 +835,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, wantType bool check.errorf(e.Sel, MissingFieldOrMethod, "%s.%s undefined (%s)", x.expr, sel, why) goto Error } + // obj != nil // methods may not have a fully set up signature yet if m, _ := obj.(*Func); m != nil { @@ -845,7 +846,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, wantType bool // method expression m, _ := obj.(*Func) if m == nil { - check.errorf(e.Sel, MissingFieldOrMethod, "%s.%s undefined (type %s has no method %s)", x.expr, sel, x.typ, sel) + check.errorf(e.X, MissingFieldOrMethod, "operand for field selector %s must be value of type %s", sel, x.typ) goto Error } diff --git a/src/go/types/call.go b/src/go/types/call.go index 50aa7caba6..56800c0ac8 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -838,6 +838,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr, wantType bool) { check.errorf(e.Sel, MissingFieldOrMethod, "%s.%s undefined (%s)", x.expr, sel, why) goto Error } + // obj != nil // methods may not have a fully set up signature yet if m, _ := obj.(*Func); m != nil { @@ -848,7 +849,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr, wantType bool) { // method expression m, _ := obj.(*Func) if m == nil { - check.errorf(e.Sel, MissingFieldOrMethod, "%s.%s undefined (type %s has no method %s)", x.expr, sel, x.typ, sel) + check.errorf(e.X, MissingFieldOrMethod, "operand for field selector %s must be value of type %s", sel, x.typ) goto Error } diff --git a/src/internal/types/testdata/check/expr3.go b/src/internal/types/testdata/check/expr3.go index 91534cdd62..012369c445 100644 --- a/src/internal/types/testdata/check/expr3.go +++ b/src/internal/types/testdata/check/expr3.go @@ -156,7 +156,7 @@ func (*T) m() {} func method_expressions() { _ = T.a /* ERROR "no field or method" */ - _ = T.x /* ERROR "has no method" */ + _ = T /* ERROR "operand for field selector x must be value of type T" */ .x _ = T.m /* ERROR "invalid method expression T.m (needs pointer receiver (*T).m)" */ _ = (*T).m @@ -164,8 +164,8 @@ func method_expressions() { var g func(*T) = (*T).m _, _ = f, g - _ = T.y /* ERROR "has no method" */ - _ = (*T).y /* ERROR "has no method" */ + _ = T /* ERROR "operand for field selector y must be value of type T" */ .y + _ = ( /* ERROR "operand for field selector y must be value of type *T" */ *T).y } func struct_literals() { diff --git a/src/internal/types/testdata/check/issues0.go b/src/internal/types/testdata/check/issues0.go index fb4e1282f9..2690281ef0 100644 --- a/src/internal/types/testdata/check/issues0.go +++ b/src/internal/types/testdata/check/issues0.go @@ -351,7 +351,7 @@ func issue26234b(x T) { } func issue26234c() { - T.x /* ERROR "T.x undefined (type T has no method x)" */ () + T /* ERROR "operand for field selector x must be value of type T" */ .x() } func issue35895() { diff --git a/src/internal/types/testdata/fixedbugs/issue6814.go b/src/internal/types/testdata/fixedbugs/issue6814.go new file mode 100644 index 0000000000..779d5361b6 --- /dev/null +++ b/src/internal/types/testdata/fixedbugs/issue6814.go @@ -0,0 +1,35 @@ +// Copyright 2026 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type E struct { + e int +} + +func (E) m() {} + +type S struct { + E + x int +} + +func (S) n() {} + +func _() { + _ = S.X // ERROR "S.X undefined (type S has no field or method X, but does have field x)" + _ = S /* ERROR "operand for field selector E must be value of type S" */ .E + _ = S /* ERROR "operand for field selector x must be value of type S" */ .x + _ = S /* ERROR "operand for field selector e must be value of type S" */ .e + _ = S.m + _ = S.n + + var s S + _ = s.X // ERROR "s.X undefined (type S has no field or method X, but does have field x)" + _ = s.E + _ = s.x + _ = s.e + _ = s.m + _ = s.n +} -- 2.52.0