aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCuong Manh Le <cuong.manhle.vn@gmail.com>2021-09-10 07:44:02 +0700
committerCuong Manh Le <cuong.manhle.vn@gmail.com>2021-09-14 02:52:21 +0000
commitb8c802b1161528fcf8ba78b1dff5720dd5b4eb9f (patch)
tree62146563d7f6a5014c132fd02ca9aa115643c371
parent4a4221e8187189adcc6463d2d96fe2e8da290132 (diff)
downloadgo-b8c802b1161528fcf8ba78b1dff5720dd5b4eb9f.tar.gz
go-b8c802b1161528fcf8ba78b1dff5720dd5b4eb9f.zip
cmd/compile: prevent importReader reading type parameter twice
The importReader always reads type parameter before declaring type stub declaration. Thus, for recursive type, the type parameter is going to be read twice, cause the bound more than once error. To fix this, only read the type parameter after declaring stub obj, thus r.doDecl can see the type was already inserted and terminate the recursive call earlier. Fixes #48280 Change-Id: I272e2f214f739fb8ec71a8628ba297477e1b7755 Reviewed-on: https://go-review.googlesource.com/c/go/+/349009 Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com> Trust: Dan Scales <danscales@google.com> Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Dan Scales <danscales@google.com>
-rw-r--r--src/cmd/compile/internal/importer/iimport.go12
-rw-r--r--test/typeparam/issue48280.dir/a.go11
-rw-r--r--test/typeparam/issue48280.dir/main.go11
-rw-r--r--test/typeparam/issue48280.go7
4 files changed, 35 insertions, 6 deletions
diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go
index b61b1e97fb..7f7143dcfe 100644
--- a/src/cmd/compile/internal/importer/iimport.go
+++ b/src/cmd/compile/internal/importer/iimport.go
@@ -318,17 +318,17 @@ func (r *importReader) obj(name string) {
r.declare(types2.NewFunc(pos, r.currPkg, name, sig))
case 'T', 'U':
- var tparams []*types2.TypeParam
- if tag == 'U' {
- tparams = r.tparamList()
- }
-
// Types can be recursive. We need to setup a stub
// declaration before recursing.
obj := types2.NewTypeName(pos, r.currPkg, name, nil)
named := types2.NewNamed(obj, nil, nil)
- named.SetTypeParams(tparams)
+ // Declare obj before calling r.tparamList, so the new type name is recognized
+ // if used in the constraint of one of its own typeparams (see #48280).
r.declare(obj)
+ if tag == 'U' {
+ tparams := r.tparamList()
+ named.SetTypeParams(tparams)
+ }
underlying := r.p.typAt(r.uint64(), named).Underlying()
named.SetUnderlying(underlying)
diff --git a/test/typeparam/issue48280.dir/a.go b/test/typeparam/issue48280.dir/a.go
new file mode 100644
index 0000000000..17859e6aa9
--- /dev/null
+++ b/test/typeparam/issue48280.dir/a.go
@@ -0,0 +1,11 @@
+// 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 a
+
+type I[T I[T]] interface {
+ F() T
+}
+
+type S struct{}
diff --git a/test/typeparam/issue48280.dir/main.go b/test/typeparam/issue48280.dir/main.go
new file mode 100644
index 0000000000..b9981c6f61
--- /dev/null
+++ b/test/typeparam/issue48280.dir/main.go
@@ -0,0 +1,11 @@
+// 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 main
+
+import "a"
+
+func main() {
+ _ = a.S{}
+}
diff --git a/test/typeparam/issue48280.go b/test/typeparam/issue48280.go
new file mode 100644
index 0000000000..76930e5e4f
--- /dev/null
+++ b/test/typeparam/issue48280.go
@@ -0,0 +1,7 @@
+// rundir -G=3
+
+// 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 ignored