// 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, bound := range bounds {
if isTypeParam(bound) {
// We may be able to allow this since it is now well-defined what
// the underlying type and thus type set of a type parameter is.
// But we may need some additional form of cycle detection within
// type parameter lists.
- check.error(posers[i], "cannot use a type parameter as constraint")
+ check.error(f.Type, "cannot use a type parameter as constraint")
+ bound = Typ[Invalid]
}
+ bounds = append(bounds, bound)
}
- for _, tpar := range tparams {
- tpar.iface() // compute type set
- }
- })
+ tparams[i].bound = bound
+ }
}
func (check *Checker) bound(x syntax.Expr) Type {
--- /dev/null
+// Copyright 2021 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 Ln[A A /* ERROR cannot use a type parameter as constraint */ ](p A) {
+}
index := 0
var bounds []Type
- var posns []positioner // bound positions
for _, f := range list.List {
- // TODO(rfindley) we should be able to rely on f.Type != nil at this point
+ var bound Type
+ // NOTE: we may be able to assert that f.Type != nil here, but this is not
+ // an invariant of the AST, so we are cautious.
if f.Type != nil {
- bound := check.bound(f.Type)
- bounds = append(bounds, bound)
- posns = append(posns, f.Type)
- for i := range f.Names {
- tparams[index+i].bound = bound
- }
- }
- index += len(f.Names)
- }
-
- check.later(func() {
- for i, bound := range bounds {
+ bound = check.bound(f.Type)
if isTypeParam(bound) {
// We may be able to allow this since it is now well-defined what
// the underlying type and thus type set of a type parameter is.
// But we may need some additional form of cycle detection within
// type parameter lists.
- check.error(posns[i], _MisplacedTypeParam, "cannot use a type parameter as constraint")
+ check.error(f.Type, _MisplacedTypeParam, "cannot use a type parameter as constraint")
+ bound = Typ[Invalid]
}
+ } else {
+ bound = Typ[Invalid]
}
- for _, tpar := range tparams {
- tpar.iface() // compute type set
+ bounds = append(bounds, bound)
+ for i := range f.Names {
+ tparams[index+i].bound = bound
}
- })
+ index += len(f.Names)
+ }
}
func (check *Checker) bound(x ast.Expr) Type {
--- /dev/null
+// Copyright 2021 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 Ln[A A /* ERROR cannot use a type parameter as constraint */ ](p A) {
+}