]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: better error when selecting field on type rather than value
authorRobert Griesemer <gri@google.com>
Wed, 21 Jan 2026 22:40:04 +0000 (14:40 -0800)
committerGopher Robot <gobot@golang.org>
Thu, 22 Jan 2026 00:01:08 +0000 (16:01 -0800)
Fixes #6814.

Change-Id: I659670998f8e89400d03d40189e8c54f7e705cdc
Reviewed-on: https://go-review.googlesource.com/c/go/+/738040
Reviewed-by: Alan Donovan <adonovan@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Griesemer <gri@google.com>
src/cmd/compile/internal/types2/call.go
src/go/types/call.go
src/internal/types/testdata/check/expr3.go
src/internal/types/testdata/check/issues0.go
src/internal/types/testdata/fixedbugs/issue6814.go [new file with mode: 0644]

index 3461c890a8b7ddb84cce52c46612943bad9edd9a..dfbb0a5491eaebd7b6c91448a8b0e5dc7a2934d1 100644 (file)
@@ -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
                }
 
index 50aa7caba6da57c6cf58a7aab753f0396f96cb8c..56800c0ac8c4f8c833f1fb210358459d1a674ea1 100644 (file)
@@ -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
                }
 
index 91534cdd629b4007ce0241b7563223eddfdc7332..012369c445f3a8eea99936f77c047f758ac4a439 100644 (file)
@@ -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() {
index fb4e1282f920afed68eebd5faa9174755406efe8..2690281ef0333820743aac9e66a408e5032059b1 100644 (file)
@@ -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 (file)
index 0000000..779d536
--- /dev/null
@@ -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
+}