internal/gcimporter: port CL 424876 from std importer
This is a port of CL 424876, except it temporarily maintains a
fallback path for older cmd/compile behavior before CL 455279, to
avoid breaking users following Go tip.
Updates golang/go#57015.
Change-Id: I168d171153d96485e92be19645422fe65ab4b345
Reviewed-on: https://go-review.googlesource.com/c/tools/+/456376
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Matthew Dempsky <mdempsky@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
diff --git a/internal/gcimporter/gcimporter_test.go b/internal/gcimporter/gcimporter_test.go
index ab9a4db..bdae455 100644
--- a/internal/gcimporter/gcimporter_test.go
+++ b/internal/gcimporter/gcimporter_test.go
@@ -796,6 +796,21 @@
_ = importPkg(t, "./testdata/aa", tmpdir)
}
+func TestIssue57015(t *testing.T) {
+ testenv.NeedsGo1Point(t, 18) // requires generics
+
+ // This package only handles gc export data.
+ needsCompiler(t, "gc")
+
+ // On windows, we have to set the -D option for the compiler to avoid having a drive
+ // letter and an illegal ':' in the import path - just skip it (see also issue #3483).
+ if runtime.GOOS == "windows" {
+ t.Skip("avoid dealing with relative paths/drive letters on windows")
+ }
+
+ compileAndImportPkg(t, "issue57015")
+}
+
// apkg returns the package "a" prefixed by (as a package) testoutdir
func apkg(testoutdir string) string {
apkg := testoutdir + "/a"
diff --git a/internal/gcimporter/testdata/issue57015.go b/internal/gcimporter/testdata/issue57015.go
new file mode 100644
index 0000000..b6be811
--- /dev/null
+++ b/internal/gcimporter/testdata/issue57015.go
@@ -0,0 +1,16 @@
+// Copyright 2022 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 issue57015
+
+type E error
+
+type X[T any] struct {}
+
+func F() X[interface {
+ E
+}] {
+ panic(0)
+}
+
diff --git a/internal/gcimporter/ureader_yes.go b/internal/gcimporter/ureader_yes.go
index 20b9990..b285a11 100644
--- a/internal/gcimporter/ureader_yes.go
+++ b/internal/gcimporter/ureader_yes.go
@@ -559,18 +559,7 @@
named.SetTypeParams(r.typeParamNames())
- rhs := r.typ()
- pk := r.p
- pk.laterFor(named, func() {
- // First be sure that the rhs is initialized, if it needs to be initialized.
- delete(pk.laterFors, named) // prevent cycles
- if i, ok := pk.laterFors[rhs]; ok {
- f := pk.laterFns[i]
- pk.laterFns[i] = func() {} // function is running now, so replace it with a no-op
- f() // initialize RHS
- }
- underlying := rhs.Underlying()
-
+ setUnderlying := func(underlying types.Type) {
// If the underlying type is an interface, we need to
// duplicate its methods so we can replace the receiver
// parameter's type (#49906).
@@ -595,7 +584,31 @@
}
named.SetUnderlying(underlying)
- })
+ }
+
+ // Since go.dev/cl/455279, we can assume rhs.Underlying() will
+ // always be non-nil. However, to temporarily support users of
+ // older snapshot releases, we continue to fallback to the old
+ // behavior for now.
+ //
+ // TODO(mdempsky): Remove fallback code and simplify after
+ // allowing time for snapshot users to upgrade.
+ rhs := r.typ()
+ if underlying := rhs.Underlying(); underlying != nil {
+ setUnderlying(underlying)
+ } else {
+ pk := r.p
+ pk.laterFor(named, func() {
+ // First be sure that the rhs is initialized, if it needs to be initialized.
+ delete(pk.laterFors, named) // prevent cycles
+ if i, ok := pk.laterFors[rhs]; ok {
+ f := pk.laterFns[i]
+ pk.laterFns[i] = func() {} // function is running now, so replace it with a no-op
+ f() // initialize RHS
+ }
+ setUnderlying(rhs.Underlying())
+ })
+ }
for i, n := 0, r.Len(); i < n; i++ {
named.AddMethod(r.method())