]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: better error message for some inference failures
authorRobert Griesemer <gri@golang.org>
Wed, 31 May 2023 22:15:13 +0000 (15:15 -0700)
committerGopher Robot <gobot@golang.org>
Wed, 31 May 2023 22:48:09 +0000 (22:48 +0000)
For a unification failure involving a constraint, rather than just
reporting (for instance)

        S does not match []E

now report the inferred type for the type parameter, use spec
terminology when referring to the constraint, and print the
constraint in full:

        S (type func()) does not satisfy ~[]E

There's more we can do, but this is better than what we had.

For #60542.

Change-Id: I033369fa0dfc475f0ec0da0582e8cbefb109f3cf
Reviewed-on: https://go-review.googlesource.com/c/go/+/499639
Reviewed-by: Robert Griesemer <gri@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/infer.go
src/go/types/infer.go
src/internal/types/testdata/examples/inference.go
src/internal/types/testdata/fixedbugs/issue45985.go
src/internal/types/testdata/fixedbugs/issue49112.go
src/internal/types/testdata/fixedbugs/issue51472.go
src/internal/types/testdata/fixedbugs/issue60542.go [new file with mode: 0644]

index c323344ca7138f8903c2ca6b4e55e7a6e8789dab..c2b1395953fdf0efdc8ef6189a054d3ff6d053b7 100644 (file)
@@ -231,7 +231,10 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
                                        // 2) If the core type doesn't have a tilde, we also must unify tx
                                        //    with the core type.
                                        if !u.unify(tx, core.typ, 0) {
-                                               check.errorf(pos, CannotInferTypeArgs, "%s does not match %s", tpar, core.typ)
+                                               // TODO(gri) Type parameters that appear in the constraint and
+                                               //           for which we have type arguments inferred should
+                                               //           use those type arguments for a better error message.
+                                               check.errorf(pos, CannotInferTypeArgs, "%s (type %s) does not satisfy %s", tpar, tx, tpar.Constraint())
                                                return nil
                                        }
                                case single && !core.tilde:
@@ -249,7 +252,8 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
                                        var cause string
                                        constraint := tpar.iface()
                                        if m, _ := check.missingMethod(tx, constraint, true, func(x, y Type) bool { return u.unify(x, y, 0) }, &cause); m != nil {
-                                               check.errorf(pos, CannotInferTypeArgs, "%s does not satisfy %s %s", tx, constraint, cause)
+                                               // TODO(gri) better error message (see TODO above)
+                                               check.errorf(pos, CannotInferTypeArgs, "%s (type %s) does not satisfy %s %s", tpar, tx, tpar.Constraint(), cause)
                                                return nil
                                        }
                                }
index 015edb5fbec6329d161226eaba8c654bec0f0d95..f39ef4141544f724e39512658bbabc4cf9d22484 100644 (file)
@@ -233,7 +233,10 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type,
                                        // 2) If the core type doesn't have a tilde, we also must unify tx
                                        //    with the core type.
                                        if !u.unify(tx, core.typ, 0) {
-                                               check.errorf(posn, CannotInferTypeArgs, "%s does not match %s", tpar, core.typ)
+                                               // TODO(gri) Type parameters that appear in the constraint and
+                                               //           for which we have type arguments inferred should
+                                               //           use those type arguments for a better error message.
+                                               check.errorf(posn, CannotInferTypeArgs, "%s (type %s) does not satisfy %s", tpar, tx, tpar.Constraint())
                                                return nil
                                        }
                                case single && !core.tilde:
@@ -251,7 +254,8 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type,
                                        var cause string
                                        constraint := tpar.iface()
                                        if m, _ := check.missingMethod(tx, constraint, true, func(x, y Type) bool { return u.unify(x, y, 0) }, &cause); m != nil {
-                                               check.errorf(posn, CannotInferTypeArgs, "%s does not satisfy %s %s", tx, constraint, cause)
+                                               // TODO(gri) better error message (see TODO above)
+                                               check.errorf(posn, CannotInferTypeArgs, "%s (type %s) does not satisfy %s %s", tpar, tx, tpar.Constraint(), cause)
                                                return nil
                                        }
                                }
index b6f735263e89b7d6b548451bfaf5af2a09e60e37..f55dd09bded834f2f916945280d4d9e247ff7373 100644 (file)
@@ -99,7 +99,7 @@ func _() {
        // last.
        related2(1.2, []float64{})
        related2(1.0, []int{})
-       related2 /* ERROR "Slice does not match []Elem" */ (float64(1.0), []int{}) // TODO(gri) better error message
+       related2 /* ERROR "Slice (type []int) does not satisfy interface{[]Elem}" */ (float64(1.0), []int{}) // TODO(gri) better error message
 }
 
 type List[P any] []P
@@ -117,7 +117,11 @@ func _() {
        related3 /* ERROR "cannot infer Slice" */ [int]()
 }
 
-func wantsMethods[P interface{ m1(Q); m2() R }, Q, R any](P) {}
+func wantsMethods[P interface {
+       m1(Q)
+       m2() R
+}, Q, R any](P) {
+}
 
 type hasMethods1 struct{}
 
@@ -129,12 +133,12 @@ type hasMethods2 struct{}
 func (*hasMethods2) m1(int)
 func (*hasMethods2) m2() string
 
-type hasMethods3 interface{
+type hasMethods3 interface {
        m1(float64)
        m2() complex128
 }
 
-type hasMethods4 interface{
+type hasMethods4 interface {
        m1()
 }
 
@@ -144,11 +148,11 @@ func _() {
        // signatures.
        wantsMethods(hasMethods1{})
        wantsMethods(&hasMethods1{})
-       wantsMethods /* ERROR "hasMethods2 does not satisfy interface{m1(Q); m2() R} (method m1 has pointer receiver)" */ (hasMethods2{})
+       wantsMethods /* ERROR "P (type hasMethods2) does not satisfy interface{m1(Q); m2() R} (method m1 has pointer receiver)" */ (hasMethods2{})
        wantsMethods(&hasMethods2{})
        wantsMethods(hasMethods3(nil))
-       wantsMethods /* ERROR "any does not satisfy interface{m1(Q); m2() R} (missing method m1)" */ (any(nil))
-       wantsMethods /* ERROR "hasMethods4 does not satisfy interface{m1(Q); m2() R} (wrong type for method m1)" */ (hasMethods4(nil))
+       wantsMethods /* ERROR "P (type any) does not satisfy interface{m1(Q); m2() R} (missing method m1)" */ (any(nil))
+       wantsMethods /* ERROR "P (type hasMethods4) does not satisfy interface{m1(Q); m2() R} (wrong type for method m1)" */ (hasMethods4(nil))
 }
 
 // "Reverse" type inference is not yet permitted.
index 9e321a0d8e2087681a4e2d9adb59acfdb83ed8d3..c486150cb39f24c8a3e8083f28d17d8c46baae52 100644 (file)
@@ -9,5 +9,5 @@ func app[S interface{ ~[]T }, T any](s S, e T) S {
 }
 
 func _() {
-       _ = app /* ERROR "S does not match []T" */ [int] // TODO(gri) better error message
+       _ = app /* ERROR "S (type int) does not satisfy interface{~[]T}" */ [int] // TODO(gri) better error message
 }
index 02e98ca417ccf1a56e5dc05122e564141024ac89..e87d1c07dcfb4dc774fe060dd43a5a9b56433a02 100644 (file)
@@ -7,9 +7,9 @@ package p
 func f[P int](P) {}
 
 func _() {
-        _ = f[int]
-        _ = f[[ /* ERROR "[]int does not satisfy int" */ ]int]
+       _ = f[int]
+       _ = f[[ /* ERROR "[]int does not satisfy int ([]int missing in int)" */ ]int]
 
-        f(0)
-        f /* ERROR "P does not match int" */ ([]int{}) // TODO(gri) better error message
+       f(0)
+       f /* ERROR "P (type []int) does not satisfy int" */ ([]int{}) // TODO(gri) better error message
 }
index d366a3c18ee869c0b14eaa7349ccd689597a2b66..6dfff05395979ce22b3a08e369dfbb8653b60b59 100644 (file)
@@ -49,6 +49,6 @@ func f[T interface{comparable; []byte|string}](x T) {
 }
 
 func _(s []byte) {
-       f /* ERROR "T does not match string" */ (s) // TODO(gri) better error message (T's type set only contains string!)
+       f /* ERROR "T (type []byte) does not satisfy interface{comparable; []byte | string}" */ (s) // TODO(gri) better error message (T's type set only contains string!)
         _ = f[[ /* ERROR "does not satisfy" */ ]byte]
 }
diff --git a/src/internal/types/testdata/fixedbugs/issue60542.go b/src/internal/types/testdata/fixedbugs/issue60542.go
new file mode 100644 (file)
index 0000000..b536ddb
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2023 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 Clip[S ~[]E, E any](s S) S {
+       return s
+}
+
+var versions func()
+var _ = Clip /* ERROR "S (type func()) does not satisfy ~[]E" */ (versions)