1
0
mirror of https://github.com/golang/go synced 2024-09-29 16:34:31 -06:00

cmd/compile/internal/types2: better error message for missing ~ in constraint

If a constraint could be satisfied if one of its type elements
had a ~, provide this information in the error message.

Fixes #49179.

Change-Id: I59f1a855a0646ad7254a978420b0334f1f52ec22
Reviewed-on: https://go-review.googlesource.com/c/go/+/366758
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Robert Griesemer 2021-11-23 15:55:11 -08:00
parent 8cdfe408bb
commit b77f5f9667
3 changed files with 43 additions and 4 deletions

View File

@ -238,9 +238,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

View File

@ -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)
}

View File

@ -108,6 +108,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.