Skip to content

Commit c7f1191

Browse files
committed
go/internal/gcimporter: set underlying types in proper order; flatten imports
These are copied from go/internal, for processing export data from unified IR compilation. The underlying types order problem appeared in google-internal testing. If the run-later functions are run in the wrong order, type definitions won't resolve properly. Flatten imports makes the unified IR export/import match the behavior of export data from older compilers, though it's not clear that this behavior was intended, it is now expected. See https://go.dev/cl/419996 and https://go.dev/cl/419596 Change-Id: I4197fe9e93ee07eb7f24597ba9157ce083a1d086 Reviewed-on: https://go-review.googlesource.com/c/tools/+/420534 TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]> Run-TryBot: David Chase <[email protected]> gopls-CI: kokoro <[email protected]>
1 parent bd3f524 commit c7f1191

File tree

1 file changed

+45
-2
lines changed

1 file changed

+45
-2
lines changed

go/internal/gcimporter/ureader_yes.go

+45-2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ type pkgReader struct {
3636
// laterFns holds functions that need to be invoked at the end of
3737
// import reading.
3838
laterFns []func()
39+
// laterFors is used in case of 'type A B' to ensure that B is processed before A.
40+
laterFors map[types.Type]int
3941
}
4042

4143
// later adds a function to be invoked at the end of import reading.
@@ -63,6 +65,15 @@ func UImportData(fset *token.FileSet, imports map[string]*types.Package, data []
6365
return
6466
}
6567

68+
// laterFor adds a function to be invoked at the end of import reading, and records the type that function is finishing.
69+
func (pr *pkgReader) laterFor(t types.Type, fn func()) {
70+
if pr.laterFors == nil {
71+
pr.laterFors = make(map[types.Type]int)
72+
}
73+
pr.laterFors[t] = len(pr.laterFns)
74+
pr.laterFns = append(pr.laterFns, fn)
75+
}
76+
6677
// readUnifiedPackage reads a package description from the given
6778
// unified IR export data decoder.
6879
func readUnifiedPackage(fset *token.FileSet, ctxt *types.Context, imports map[string]*types.Package, input pkgbits.PkgDecoder) *types.Package {
@@ -231,11 +242,35 @@ func (r *reader) doPkg() *types.Package {
231242
for i := range imports {
232243
imports[i] = r.pkg()
233244
}
234-
pkg.SetImports(imports)
245+
pkg.SetImports(flattenImports(imports))
235246

236247
return pkg
237248
}
238249

250+
// flattenImports returns the transitive closure of all imported
251+
// packages rooted from pkgs.
252+
func flattenImports(pkgs []*types.Package) []*types.Package {
253+
var res []*types.Package
254+
255+
seen := make(map[*types.Package]bool)
256+
var add func(pkg *types.Package)
257+
add = func(pkg *types.Package) {
258+
if seen[pkg] {
259+
return
260+
}
261+
seen[pkg] = true
262+
res = append(res, pkg)
263+
for _, imp := range pkg.Imports() {
264+
add(imp)
265+
}
266+
}
267+
268+
for _, pkg := range pkgs {
269+
add(pkg)
270+
}
271+
return res
272+
}
273+
239274
// @@@ Types
240275

241276
func (r *reader) typ() types.Type {
@@ -482,7 +517,15 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
482517
// unit tests expected that), but cmd/compile doesn't care
483518
// about it, so maybe we can avoid worrying about that here.
484519
rhs := r.typ()
485-
r.p.later(func() {
520+
pk := r.p
521+
pk.laterFor(named, func() {
522+
// First be sure that the rhs is initialized, if it needs to be initialized.
523+
delete(pk.laterFors, named) // prevent cycles
524+
if i, ok := pk.laterFors[rhs]; ok {
525+
f := pk.laterFns[i]
526+
pk.laterFns[i] = func() {} // function is running now, so replace it with a no-op
527+
f() // initialize RHS
528+
}
486529
underlying := rhs.Underlying()
487530
named.SetUnderlying(underlying)
488531
})

0 commit comments

Comments
 (0)