1
0
mirror of https://github.com/golang/go synced 2024-11-26 20:01:19 -07:00

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>
This commit is contained in:
Matthew Dempsky 2022-08-18 13:47:43 -07:00
parent dddc1ba847
commit a398963203
3 changed files with 55 additions and 44 deletions

View 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)

View File

@ -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)
}

View 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 := rhs.Underlying()
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)
// 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
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()))
}
named.SetUnderlying(underlying)
})
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
}
named.SetUnderlying(underlying)
for i, n := 0, r.Len(); i < n; i++ {
named.AddMethod(r.method())