diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index d5495304fa3..d61d2a8b0d9 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -657,33 +657,24 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list []*syntax.Fiel // 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 { diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50321.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50321.go2 new file mode 100644 index 00000000000..199e66eb6ca --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50321.go2 @@ -0,0 +1,8 @@ +// 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) { +} diff --git a/src/go/types/decl.go b/src/go/types/decl.go index db29f11920a..02af0d5f3ea 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -708,34 +708,29 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list *ast.FieldList 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 { diff --git a/src/go/types/testdata/fixedbugs/issue50321.go2 b/src/go/types/testdata/fixedbugs/issue50321.go2 new file mode 100644 index 00000000000..199e66eb6ca --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue50321.go2 @@ -0,0 +1,8 @@ +// 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) { +}