From cbdb93d5a743700e57d92125a356d18fa2d3ece7 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 19 Jun 2020 18:27:49 -0700 Subject: [PATCH] [dev.go2go] go/types: a type constraint must be an interface In particular, it cannot be a type parameter with an operational type that is an interface. Fixes #39723. Change-Id: Ia6b65eaecd472dd71b1c9f7631ce1872f06e5a6d Reviewed-on: https://go-review.googlesource.com/c/go/+/239161 Reviewed-by: Robert Griesemer --- src/go/types/check_test.go | 1 + src/go/types/decl.go | 12 +++++++----- src/go/types/fixedbugs/issue39723.go2 | 9 +++++++++ 3 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 src/go/types/fixedbugs/issue39723.go2 diff --git a/src/go/types/check_test.go b/src/go/types/check_test.go index b84ef2e0a4..dbb50269b6 100644 --- a/src/go/types/check_test.go +++ b/src/go/types/check_test.go @@ -129,6 +129,7 @@ var tests = [][]string{ {"fixedbugs/issue39693.go2"}, {"fixedbugs/issue39680.go2"}, {"fixedbugs/issue39711.go2"}, + {"fixedbugs/issue39723.go2"}, } var fset = token.NewFileSet() diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 5921d1ce4e..65b2e7be82 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -615,17 +615,19 @@ func (check *Checker) collectTypeParams(list *ast.FieldList) (tparams []*TypeNam } index := 0 + var bound Type for _, f := range list.List { if f.Type == nil { goto next } // type bound must be an interface - // TODO(gri) We should try to delay the IsInterface check - // as it may expand a possibly incomplete type. - // Worse, it could be a type parameter that is - // not yet instantiated if we accept #39723. - if bound := check.anyType(f.Type); IsInterface(bound) { + // TODO(gri) We should delay the interface check because + // we may not have a complete interface yet: + // type C(type T C) interface {} + // (issue #39724). + bound = check.anyType(f.Type) + if _, ok := bound.Under().(*Interface); ok { // If the type bound expects exactly one type argument, permit leaving // it away and use the corresponding type parameter as implicit argument. // This allows us to write (type p b(p), q b(q), r b(r)) as (type p, q, r b). diff --git a/src/go/types/fixedbugs/issue39723.go2 b/src/go/types/fixedbugs/issue39723.go2 new file mode 100644 index 0000000000..c0ca89e8b9 --- /dev/null +++ b/src/go/types/fixedbugs/issue39723.go2 @@ -0,0 +1,9 @@ +// Copyright 2020 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 + +// A constraint must be an interface; it cannot +// be a type parameter, for instance. +func _(type A interface{ type interface{} }, B A /* ERROR not an interface */ )()