diff options
author | Matthew Dempsky <mdempsky@google.com> | 2022-08-18 13:47:43 -0700 |
---|---|---|
committer | Matthew Dempsky <mdempsky@google.com> | 2022-12-07 03:45:50 +0000 |
commit | a3989632031c4282a6770e76516238368035d713 (patch) | |
tree | 8bda9453f074197cf926ace4d564aabb323e0950 | |
parent | dddc1ba847467524c397eda22b69862773e9f21a (diff) | |
download | go-a3989632031c4282a6770e76516238368035d713.tar.gz go-a3989632031c4282a6770e76516238368035d713.zip |
go/internal/gcimporter: simplify unified IR importer
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>
-rw-r--r-- | src/go/internal/gcimporter/gcimporter_test.go | 17 | ||||
-rw-r--r-- | src/go/internal/gcimporter/testdata/issue57015.go | 16 | ||||
-rw-r--r-- | src/go/internal/gcimporter/ureader.go | 68 |
3 files changed, 56 insertions, 45 deletions
diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go index 675bf222ce..f2202ab478 100644 --- a/src/go/internal/gcimporter/gcimporter_test.go +++ b/src/go/internal/gcimporter/gcimporter_test.go @@ -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 index 0000000000..b6be81191f --- /dev/null +++ b/src/go/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/src/go/internal/gcimporter/ureader.go b/src/go/internal/gcimporter/ureader.go index c2b9a58ee7..ffd8402202 100644 --- a/src/go/internal/gcimporter/ureader.go +++ b/src/go/internal/gcimporter/ureader.go @@ -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()) |