aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2022-01-08 14:39:43 -0800
committerRobert Griesemer <gri@golang.org>2022-01-10 22:48:57 +0000
commit91edf2b7f2fe219f1af1df4031a210d8160da47c (patch)
treeae126bedf19cc8e2b7c6165648696497b84bc1b5 /src/cmd/compile
parent6019a52d4dab7c243ee9088c3522c821c0c95cfa (diff)
downloadgo-91edf2b7f2fe219f1af1df4031a210d8160da47c.tar.gz
go-91edf2b7f2fe219f1af1df4031a210d8160da47c.zip
go/types, types2: better error message for type parameter field access
Fixes #50516. Also call DefPredeclaredTestFuncs in TestFixedbugs so it can be run independently again. Change-Id: I78d4cc11790b1543a2545a7ab297a223b3d5e3c8 Reviewed-on: https://go-review.googlesource.com/c/go/+/376954 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
Diffstat (limited to 'src/cmd/compile')
-rw-r--r--src/cmd/compile/internal/types2/call.go43
-rw-r--r--src/cmd/compile/internal/types2/check_test.go11
-rw-r--r--src/cmd/compile/internal/types2/testdata/check/typeparams.go26
-rw-r--r--src/cmd/compile/internal/types2/testdata/fixedbugs/issue50417.go22
-rw-r--r--src/cmd/compile/internal/types2/testdata/fixedbugs/issue50516.go213
5 files changed, 39 insertions, 36 deletions
diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go
index bd62e825af..1c3bf48b08 100644
--- a/src/cmd/compile/internal/types2/call.go
+++ b/src/cmd/compile/internal/types2/call.go
@@ -542,39 +542,26 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) {
goto Error
}
- if isInterfacePtr(x.typ) {
- check.errorf(e.Sel, "%s.%s undefined (type %s is pointer to interface, not interface)", x.expr, sel, x.typ)
- goto Error
- }
-
var why string
- if tpar, _ := x.typ.(*TypeParam); tpar != nil {
- // Type parameter bounds don't specify fields, so don't mention "field".
- // TODO(gri) Type constraints may have accessible fields now. Revisit this.
- if tname := tpar.iface().obj; tname != nil {
- why = check.sprintf("interface %s has no method %s", tname.name, sel)
- } else {
- why = check.sprintf("type bound for %s has no method %s", x.typ, sel)
- }
+ if isInterfacePtr(x.typ) {
+ why = check.sprintf("type %s is pointer to interface, not interface", x.typ)
} else {
why = check.sprintf("type %s has no field or method %s", x.typ, sel)
- }
-
- // Check if capitalization of sel matters and provide better error message in that case.
- // TODO(gri) This code only looks at the first character but LookupFieldOrMethod has an
- // (internal) mechanism for case-insensitive lookup. Should use that instead.
- if len(sel) > 0 {
- var changeCase string
- if r := rune(sel[0]); unicode.IsUpper(r) {
- changeCase = string(unicode.ToLower(r)) + sel[1:]
- } else {
- changeCase = string(unicode.ToUpper(r)) + sel[1:]
- }
- if obj, _, _ = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, changeCase); obj != nil {
- why += ", but does have " + changeCase
+ // Check if capitalization of sel matters and provide better error message in that case.
+ // TODO(gri) This code only looks at the first character but LookupFieldOrMethod has an
+ // (internal) mechanism for case-insensitive lookup. Should use that instead.
+ if len(sel) > 0 {
+ var changeCase string
+ if r := rune(sel[0]); unicode.IsUpper(r) {
+ changeCase = string(unicode.ToLower(r)) + sel[1:]
+ } else {
+ changeCase = string(unicode.ToUpper(r)) + sel[1:]
+ }
+ if obj, _, _ = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, changeCase); obj != nil {
+ why += ", but does have " + changeCase
+ }
}
}
-
check.errorf(e.Sel, "%s.%s undefined (%s)", x.expr, sel, why)
goto Error
}
diff --git a/src/cmd/compile/internal/types2/check_test.go b/src/cmd/compile/internal/types2/check_test.go
index 1868ad0c6e..7efa512164 100644
--- a/src/cmd/compile/internal/types2/check_test.go
+++ b/src/cmd/compile/internal/types2/check_test.go
@@ -295,10 +295,13 @@ func TestManual(t *testing.T) {
// TODO(gri) go/types has extra TestLongConstants and TestIndexRepresentability tests
-func TestCheck(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/check", 55, false) } // TODO(gri) narrow column tolerance
-func TestSpec(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/spec", 0, false) }
-func TestExamples(t *testing.T) { testDirFiles(t, "testdata/examples", 0, false) }
-func TestFixedbugs(t *testing.T) { testDirFiles(t, "testdata/fixedbugs", 0, false) }
+func TestCheck(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/check", 55, false) } // TODO(gri) narrow column tolerance
+func TestSpec(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/spec", 0, false) }
+func TestExamples(t *testing.T) { testDirFiles(t, "testdata/examples", 0, false) }
+func TestFixedbugs(t *testing.T) {
+ DefPredeclaredTestFuncs()
+ testDirFiles(t, "testdata/fixedbugs", 0, false)
+}
func testDirFiles(t *testing.T, dir string, colDelta uint, manual bool) {
testenv.MustHaveGoBuild(t)
diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2
index 007157ea0f..ef58241519 100644
--- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2
+++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2
@@ -519,13 +519,13 @@ func _[P C[P]] (x P) {
type I interface {}
func _[P I] (x P) {
- x.m /* ERROR interface I has no method m */ ()
+ x.m /* ERROR type P has no field or method m */ ()
}
func _[P interface{}] (x P) {
- x.m /* ERROR type bound for P has no method m */ ()
+ x.m /* ERROR type P has no field or method m */ ()
}
func _[P any] (x P) {
- x.m /* ERROR type bound for P has no method m */ ()
+ x.m /* ERROR type P has no field or method m */ ()
}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50417.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50417.go2
index c05987e5ea..b6454ab003 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50417.go2
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50417.go2
@@ -58,7 +58,7 @@ type PSfm *Sfm
func f3[P interface{ PSfm }](p P) {
_ = p.f
p.f = 0
- p.m /* ERROR type bound for P has no method m */ ()
+ p.m /* ERROR type P has no field or method m */ ()
}
var _ = f3[PSfm]
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50516.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50516.go2
new file mode 100644
index 0000000000..f73015e2be
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50516.go2
@@ -0,0 +1,13 @@
+// Copyright 2022 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
+
+func _[P struct{ f int }](x P) {
+ _ = x.g // ERROR type P has no field or method g
+}
+
+func _[P struct{ f int } | struct{ g int }](x P) {
+ _ = x.g // ERROR type P has no field or method g
+}