mirror of
https://github.com/golang/go
synced 2024-11-23 18:50:05 -07:00
go/types: better error message for missing ~ in constraint
This is a port of CL 366758 from types2 to go/types. For #49179. Change-Id: I7e1c6ffb392d5c535cf901004b7acbe8c3be9b0f Reviewed-on: https://go-review.googlesource.com/c/go/+/367199 Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
bc32dd1b69
commit
ebd0b778c9
@ -239,9 +239,28 @@ func (check *Checker) implements(V, T Type, qf Qualifier) error {
|
||||
}
|
||||
|
||||
// Otherwise, V's type must be included in the iface type set.
|
||||
if !Ti.typeSet().includes(V) {
|
||||
// TODO(gri) report which type is missing
|
||||
return errorf("%s does not implement %s", V, T)
|
||||
var alt Type
|
||||
if Ti.typeSet().is(func(t *term) bool {
|
||||
if !t.includes(V) {
|
||||
// If V ∉ t.typ but V ∈ ~t.typ then remember this type
|
||||
// so we can suggest it as an alternative in the error
|
||||
// message.
|
||||
if alt == nil && !t.tilde && Identical(t.typ, under(t.typ)) {
|
||||
tt := *t
|
||||
tt.tilde = true
|
||||
if tt.includes(V) {
|
||||
alt = t.typ
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}) {
|
||||
if alt != nil {
|
||||
return errorf("%s does not implement %s (possibly missing ~ for %s in constraint %s)", V, T, alt, T)
|
||||
} else {
|
||||
return errorf("%s does not implement %s", V, T)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
20
src/go/types/testdata/fixedbugs/issue49179.go2
vendored
20
src/go/types/testdata/fixedbugs/issue49179.go2
vendored
@ -4,6 +4,24 @@
|
||||
|
||||
package p
|
||||
|
||||
func f1[P int | string]() {}
|
||||
func f2[P ~int | string | float64]() {}
|
||||
func f3[P int](x P) {}
|
||||
|
||||
type myInt int
|
||||
type myFloat float64
|
||||
|
||||
func _() {
|
||||
_ = f1[int]
|
||||
_ = f1[myInt /* ERROR possibly missing ~ for int in constraint int\|string */]
|
||||
_ = f2[myInt]
|
||||
_ = f2[myFloat /* ERROR possibly missing ~ for float64 in constraint int\|string|float64 */]
|
||||
var x myInt
|
||||
f3 /* ERROR myInt does not implement int \(possibly missing ~ for int in constraint int\) */ (x)
|
||||
}
|
||||
|
||||
// test case from the issue
|
||||
|
||||
type SliceConstraint[T any] interface {
|
||||
[]T
|
||||
}
|
||||
@ -15,5 +33,5 @@ func Map[S SliceConstraint[E], E any](s S, f func(E) E) S {
|
||||
type MySlice []int
|
||||
|
||||
func f(s MySlice) {
|
||||
Map[MySlice /* ERROR MySlice does not implement SliceConstraint\[int\] */, int](s, nil)
|
||||
Map[MySlice /* ERROR MySlice does not implement SliceConstraint\[int\] \(possibly missing ~ for \[\]int in constraint SliceConstraint\[int\]\) */, int](s, nil)
|
||||
}
|
||||
|
@ -106,6 +106,8 @@ func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll
|
||||
func (s *_TypeSet) singleType() Type { return s.terms.singleType() }
|
||||
|
||||
// includes reports whether t ∈ s.
|
||||
// TODO(gri) This function is not used anywhere anymore. Remove once we
|
||||
// are clear that we don't need it elsewhere in the future.
|
||||
func (s *_TypeSet) includes(t Type) bool { return s.terms.includes(t) }
|
||||
|
||||
// subsetOf reports whether s1 ⊆ s2.
|
||||
|
Loading…
Reference in New Issue
Block a user