cmd/compile/internal/types2: avoid duplicate errors for invalid bounds
Resolve a TODO from an earlier CL: we should only check type parameter
bounds once in collectTypeParams.
Change-Id: Icf6053ec359f8ac8143cf68ee2defd504f8f86e6
Reviewed-on: https://go-review.googlesource.com/c/go/+/355069
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go
index d427f26..26a16d9 100644
--- a/src/cmd/compile/internal/types2/decl.go
+++ b/src/cmd/compile/internal/types2/decl.go
@@ -627,24 +627,29 @@
// Example: type T[P T[P]] interface{}
*dst = bindTParams(tparams)
+ // Keep track of bounds for later validation.
var bound Type
+ var bounds []Type
+ var posers []poser
for i, f := range list {
// Optimization: Re-use the previous type bound if it hasn't changed.
// This also preserves the grouped output of type parameter lists
// when printing type strings.
if i == 0 || f.Type != list[i-1].Type {
bound = check.bound(f.Type)
+ bounds = append(bounds, bound)
+ posers = append(posers, f.Type)
}
tparams[i].bound = bound
}
check.later(func() {
- for i, tpar := range tparams {
- // TODO(rfindley): this results in duplicate error messages for type
- // parameters that share a constraint.
- if _, ok := under(tpar.bound).(*TypeParam); ok {
- check.error(list[i].Type, "cannot use a type parameter as constraint")
+ for i, bound := range bounds {
+ if _, ok := under(bound).(*TypeParam); ok {
+ check.error(posers[i], "cannot use a type parameter as constraint")
}
+ }
+ for _, tpar := range tparams {
tpar.iface() // compute type set
}
})
diff --git a/src/cmd/compile/internal/types2/testdata/examples/typesets.go2 b/src/cmd/compile/internal/types2/testdata/examples/typesets.go2
index cf01072..e19dcf8 100644
--- a/src/cmd/compile/internal/types2/testdata/examples/typesets.go2
+++ b/src/cmd/compile/internal/types2/testdata/examples/typesets.go2
@@ -46,6 +46,8 @@
// A type parameter may not be embedded in an interface;
// so it can also not be used as a constraint.
func _[A any, B A /* ERROR cannot use a type parameter as constraint */ ]() {}
+func _[A any, B, C A /* ERROR cannot use a type parameter as constraint */ ]() {}
+
// Error messages refer to the type constraint as it appears in the source.
// (No implicit interface should be exposed.)