Skip to content

Commit 1079a5c

Browse files
griesemergopherbot
authored andcommitted
go/types, types2: better error message for some inference failures
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 <[email protected]> Run-TryBot: Robert Griesemer <[email protected]> Auto-Submit: Robert Griesemer <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent fdd9911 commit 1079a5c

File tree

7 files changed

+41
-17
lines changed

7 files changed

+41
-17
lines changed

src/cmd/compile/internal/types2/infer.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,10 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
231231
// 2) If the core type doesn't have a tilde, we also must unify tx
232232
// with the core type.
233233
if !u.unify(tx, core.typ, 0) {
234-
check.errorf(pos, CannotInferTypeArgs, "%s does not match %s", tpar, core.typ)
234+
// TODO(gri) Type parameters that appear in the constraint and
235+
// for which we have type arguments inferred should
236+
// use those type arguments for a better error message.
237+
check.errorf(pos, CannotInferTypeArgs, "%s (type %s) does not satisfy %s", tpar, tx, tpar.Constraint())
235238
return nil
236239
}
237240
case single && !core.tilde:
@@ -249,7 +252,8 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
249252
var cause string
250253
constraint := tpar.iface()
251254
if m, _ := check.missingMethod(tx, constraint, true, func(x, y Type) bool { return u.unify(x, y, 0) }, &cause); m != nil {
252-
check.errorf(pos, CannotInferTypeArgs, "%s does not satisfy %s %s", tx, constraint, cause)
255+
// TODO(gri) better error message (see TODO above)
256+
check.errorf(pos, CannotInferTypeArgs, "%s (type %s) does not satisfy %s %s", tpar, tx, tpar.Constraint(), cause)
253257
return nil
254258
}
255259
}

src/go/types/infer.go

+6-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/internal/types/testdata/examples/inference.go

+11-7
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ func _() {
9999
// last.
100100
related2(1.2, []float64{})
101101
related2(1.0, []int{})
102-
related2 /* ERROR "Slice does not match []Elem" */ (float64(1.0), []int{}) // TODO(gri) better error message
102+
related2 /* ERROR "Slice (type []int) does not satisfy interface{[]Elem}" */ (float64(1.0), []int{}) // TODO(gri) better error message
103103
}
104104

105105
type List[P any] []P
@@ -117,7 +117,11 @@ func _() {
117117
related3 /* ERROR "cannot infer Slice" */ [int]()
118118
}
119119

120-
func wantsMethods[P interface{ m1(Q); m2() R }, Q, R any](P) {}
120+
func wantsMethods[P interface {
121+
m1(Q)
122+
m2() R
123+
}, Q, R any](P) {
124+
}
121125

122126
type hasMethods1 struct{}
123127

@@ -129,12 +133,12 @@ type hasMethods2 struct{}
129133
func (*hasMethods2) m1(int)
130134
func (*hasMethods2) m2() string
131135

132-
type hasMethods3 interface{
136+
type hasMethods3 interface {
133137
m1(float64)
134138
m2() complex128
135139
}
136140

137-
type hasMethods4 interface{
141+
type hasMethods4 interface {
138142
m1()
139143
}
140144

@@ -144,11 +148,11 @@ func _() {
144148
// signatures.
145149
wantsMethods(hasMethods1{})
146150
wantsMethods(&hasMethods1{})
147-
wantsMethods /* ERROR "hasMethods2 does not satisfy interface{m1(Q); m2() R} (method m1 has pointer receiver)" */ (hasMethods2{})
151+
wantsMethods /* ERROR "P (type hasMethods2) does not satisfy interface{m1(Q); m2() R} (method m1 has pointer receiver)" */ (hasMethods2{})
148152
wantsMethods(&hasMethods2{})
149153
wantsMethods(hasMethods3(nil))
150-
wantsMethods /* ERROR "any does not satisfy interface{m1(Q); m2() R} (missing method m1)" */ (any(nil))
151-
wantsMethods /* ERROR "hasMethods4 does not satisfy interface{m1(Q); m2() R} (wrong type for method m1)" */ (hasMethods4(nil))
154+
wantsMethods /* ERROR "P (type any) does not satisfy interface{m1(Q); m2() R} (missing method m1)" */ (any(nil))
155+
wantsMethods /* ERROR "P (type hasMethods4) does not satisfy interface{m1(Q); m2() R} (wrong type for method m1)" */ (hasMethods4(nil))
152156
}
153157

154158
// "Reverse" type inference is not yet permitted.

src/internal/types/testdata/fixedbugs/issue45985.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ func app[S interface{ ~[]T }, T any](s S, e T) S {
99
}
1010

1111
func _() {
12-
_ = app /* ERROR "S does not match []T" */ [int] // TODO(gri) better error message
12+
_ = app /* ERROR "S (type int) does not satisfy interface{~[]T}" */ [int] // TODO(gri) better error message
1313
}

src/internal/types/testdata/fixedbugs/issue49112.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ package p
77
func f[P int](P) {}
88

99
func _() {
10-
_ = f[int]
11-
_ = f[[ /* ERROR "[]int does not satisfy int" */ ]int]
10+
_ = f[int]
11+
_ = f[[ /* ERROR "[]int does not satisfy int ([]int missing in int)" */ ]int]
1212

13-
f(0)
14-
f /* ERROR "P does not match int" */ ([]int{}) // TODO(gri) better error message
13+
f(0)
14+
f /* ERROR "P (type []int) does not satisfy int" */ ([]int{}) // TODO(gri) better error message
1515
}

src/internal/types/testdata/fixedbugs/issue51472.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,6 @@ func f[T interface{comparable; []byte|string}](x T) {
4949
}
5050

5151
func _(s []byte) {
52-
f /* ERROR "T does not match string" */ (s) // TODO(gri) better error message (T's type set only contains string!)
52+
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!)
5353
_ = f[[ /* ERROR "does not satisfy" */ ]byte]
5454
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright 2023 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package p
6+
7+
func Clip[S ~[]E, E any](s S) S {
8+
return s
9+
}
10+
11+
var versions func()
12+
var _ = Clip /* ERROR "S (type func()) does not satisfy ~[]E" */ (versions)

0 commit comments

Comments
 (0)