]> Cypherpunks repositories - gostls13.git/commitdiff
go/internal/gcimporter: simplify unified IR importer
authorMatthew Dempsky <mdempsky@google.com>
Thu, 18 Aug 2022 20:47:43 +0000 (13:47 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Wed, 7 Dec 2022 03:45:50 +0000 (03:45 +0000)
CL 424854 changed the unified IR writer's handling of type
declarations to write the underlying type rather than the RHS type
expression's type. This in turn allows us to simplify the go/types
importer, because now there's no need to delay caling SetUnderlying.

Fixes #57015.

Change-Id: I80caa61f6cad5b7f9d829939db733a66cfca621c
Reviewed-on: https://go-review.googlesource.com/c/go/+/424876
Reviewed-by: Robert Griesemer <gri@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/go/internal/gcimporter/gcimporter_test.go
src/go/internal/gcimporter/testdata/issue57015.go [new file with mode: 0644]
src/go/internal/gcimporter/ureader.go

index 675bf222ceeef254878df5ca6a8cc8aec1d66bd6..f2202ab478849807cab1ef6607d4af03ddeed3b4 100644 (file)
@@ -787,6 +787,23 @@ func TestIssue25596(t *testing.T) {
        compileAndImportPkg(t, "issue25596")
 }
 
+func TestIssue57015(t *testing.T) {
+       testenv.MustHaveGoBuild(t)
+
+       // This package only handles gc export data.
+       if runtime.Compiler != "gc" {
+               t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+       }
+
+       // 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")
+}
+
 func importPkg(t *testing.T, path, srcDir string) *types.Package {
        fset := token.NewFileSet()
        pkg, err := Import(fset, make(map[string]*types.Package), path, srcDir, nil)
diff --git a/src/go/internal/gcimporter/testdata/issue57015.go b/src/go/internal/gcimporter/testdata/issue57015.go
new file mode 100644 (file)
index 0000000..b6be811
--- /dev/null
@@ -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)
+}
+
index c2b9a58ee7478a7e5b4cbf71bd271aac8f30b0b1..ffd8402202e79c264279c4e1f7b399fc6c350709 100644 (file)
@@ -29,8 +29,6 @@ type pkgReader struct {
        // laterFns holds functions that need to be invoked at the end of
        // import reading.
        laterFns []func()
-       // laterFors is used in case of 'type A B' to ensure that B is processed before A.
-       laterFors map[types.Type]int
 
        // ifaces holds a list of constructed Interfaces, which need to have
        // Complete called after importing is done.
@@ -42,15 +40,6 @@ func (pr *pkgReader) later(fn func()) {
        pr.laterFns = append(pr.laterFns, fn)
 }
 
-// laterFor adds a function to be invoked at the end of import reading, and records the type that function is finishing.
-func (pr *pkgReader) laterFor(t types.Type, fn func()) {
-       if pr.laterFors == nil {
-               pr.laterFors = make(map[types.Type]int)
-       }
-       pr.laterFors[t] = len(pr.laterFns)
-       pr.laterFns = append(pr.laterFns, fn)
-}
-
 // readUnifiedPackage reads a package description from the given
 // unified IR export data decoder.
 func readUnifiedPackage(fset *token.FileSet, ctxt *types.Context, imports map[string]*types.Package, input pkgbits.PkgDecoder) *types.Package {
@@ -538,43 +527,32 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
 
                        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 := r.typ().Underlying()
+
+                       // If the underlying type is an interface, we need to
+                       // duplicate its methods so we can replace the receiver
+                       // parameter's type (#49906).
+                       if iface, ok := underlying.(*types.Interface); ok && iface.NumExplicitMethods() != 0 {
+                               methods := make([]*types.Func, iface.NumExplicitMethods())
+                               for i := range methods {
+                                       fn := iface.ExplicitMethod(i)
+                                       sig := fn.Type().(*types.Signature)
+
+                                       recv := types.NewVar(fn.Pos(), fn.Pkg(), "", named)
+                                       methods[i] = types.NewFunc(fn.Pos(), fn.Pkg(), fn.Name(), types.NewSignature(recv, sig.Params(), sig.Results(), sig.Variadic()))
                                }
-                               underlying := rhs.Underlying()
-
-                               // If the underlying type is an interface, we need to
-                               // duplicate its methods so we can replace the receiver
-                               // parameter's type (#49906).
-                               if iface, ok := underlying.(*types.Interface); ok && iface.NumExplicitMethods() != 0 {
-                                       methods := make([]*types.Func, iface.NumExplicitMethods())
-                                       for i := range methods {
-                                               fn := iface.ExplicitMethod(i)
-                                               sig := fn.Type().(*types.Signature)
-
-                                               recv := types.NewVar(fn.Pos(), fn.Pkg(), "", named)
-                                               methods[i] = types.NewFunc(fn.Pos(), fn.Pkg(), fn.Name(), types.NewSignature(recv, sig.Params(), sig.Results(), sig.Variadic()))
-                                       }
-
-                                       embeds := make([]types.Type, iface.NumEmbeddeds())
-                                       for i := range embeds {
-                                               embeds[i] = iface.EmbeddedType(i)
-                                       }
-
-                                       newIface := types.NewInterfaceType(methods, embeds)
-                                       r.p.ifaces = append(r.p.ifaces, newIface)
-                                       underlying = newIface
+
+                               embeds := make([]types.Type, iface.NumEmbeddeds())
+                               for i := range embeds {
+                                       embeds[i] = iface.EmbeddedType(i)
                                }
 
-                               named.SetUnderlying(underlying)
-                       })
+                               newIface := types.NewInterfaceType(methods, embeds)
+                               r.p.ifaces = append(r.p.ifaces, newIface)
+                               underlying = newIface
+                       }
+
+                       named.SetUnderlying(underlying)
 
                        for i, n := 0, r.Len(); i < n; i++ {
                                named.AddMethod(r.method())