internal/gcimporter: copy over ureader changes

Copy over the ureader.go changes from GOROOT's
go/internal/gcimporter.

Adds a test that goes through gc export data.

Updates golang/go#68778

Change-Id: Ie4b91dfdb1ab9f952631a34c3691dc84be8831a7
Reviewed-on: https://go-review.googlesource.com/c/tools/+/609317
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Tim King 2024-08-29 12:40:58 -07:00
Родитель 09886e004e
Коммит 2db563b1a3
6 изменённых файлов: 131 добавлений и 10 удалений

Просмотреть файл

@ -956,6 +956,67 @@ func TestIssue58296(t *testing.T) {
}
}
func TestIssueAliases(t *testing.T) {
// This package only handles gc export data.
testenv.NeedsGo1Point(t, 24)
needsCompiler(t, "gc")
testenv.NeedsGoBuild(t) // to find stdlib export data in the build cache
testenv.NeedsGoExperiment(t, "aliastypeparams")
t.Setenv("GODEBUG", fmt.Sprintf("gotypesalias=%d", 1))
tmpdir := mktmpdir(t)
defer os.RemoveAll(tmpdir)
testoutdir := filepath.Join(tmpdir, "testdata")
apkg := filepath.Join(testoutdir, "a")
bpkg := filepath.Join(testoutdir, "b")
cpkg := filepath.Join(testoutdir, "c")
// compile a, b and c into gc export data.
srcdir := filepath.Join("testdata", "aliases")
compilePkg(t, filepath.Join(srcdir, "a"), "a.go", testoutdir, nil, apkg)
compilePkg(t, filepath.Join(srcdir, "b"), "b.go", testoutdir, map[string]string{apkg: filepath.Join(testoutdir, "a.o")}, bpkg)
compilePkg(t, filepath.Join(srcdir, "c"), "c.go", testoutdir,
map[string]string{apkg: filepath.Join(testoutdir, "a.o"), bpkg: filepath.Join(testoutdir, "b.o")},
cpkg,
)
// import c from gc export data using a and b.
pkg, err := Import(map[string]*types.Package{
apkg: types.NewPackage(apkg, "a"),
bpkg: types.NewPackage(bpkg, "b"),
}, "./c", testoutdir, nil)
if err != nil {
t.Fatal(err)
}
// Check c's objects and types.
var objs []string
for _, imp := range pkg.Scope().Names() {
obj := pkg.Scope().Lookup(imp)
s := fmt.Sprintf("%s : %s", obj.Name(), obj.Type())
s = strings.ReplaceAll(s, testoutdir, "testdata")
objs = append(objs, s)
}
sort.Strings(objs)
want := strings.Join([]string{
"S : struct{F int}",
"T : struct{F int}",
"U : testdata/a.A[string]",
"V : testdata/a.A[int]",
"W : testdata/b.B[string]",
"X : testdata/b.B[int]",
"Y : testdata/c.c[string]",
"Z : testdata/c.c[int]",
"c : testdata/c.c",
}, ",")
if got := strings.Join(objs, ","); got != want {
t.Errorf("got imports %v for package c. wanted %v", objs, want)
}
}
// apkg returns the package "a" prefixed by (as a package) testoutdir
func apkg(testoutdir string) string {
apkg := testoutdir + "/a"

Просмотреть файл

@ -517,8 +517,6 @@ type Chained = C[Named] // B[Named, A[Named]] = B[Named, *Named] = []*Named
// This means that it can be loaded by go/importer or go/types.
// This step is not supported, but it does give test coverage for stdlib.
"goroot": func(t *testing.T) *types.Package {
t.Skip("Fix bug in src/internal/gcimporter.IImportData for aliasType then reenable")
// Write indexed export data file contents.
//
// TODO(taking): Slightly unclear to what extent this step should be supported by go/importer.

14
internal/gcimporter/testdata/aliases/a/a.go поставляемый Normal file
Просмотреть файл

@ -0,0 +1,14 @@
// Copyright 2024 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 a
type A[T any] = *T
type B = struct{ F int }
func F() B {
type a[T any] = struct{ F T }
return a[int]{}
}

11
internal/gcimporter/testdata/aliases/b/b.go поставляемый Normal file
Просмотреть файл

@ -0,0 +1,11 @@
// Copyright 2024 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 b
import "./a"
type B[S any] = struct {
F a.A[[]S]
}

26
internal/gcimporter/testdata/aliases/c/c.go поставляемый Normal file
Просмотреть файл

@ -0,0 +1,26 @@
// Copyright 2024 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 c
import (
"./a"
"./b"
)
type c[V any] = struct {
G b.B[[3]V]
}
var S struct{ F int } = a.B{}
var T struct{ F int } = a.F()
var U a.A[string] = (*string)(nil)
var V a.A[int] = (*int)(nil)
var W b.B[string] = struct{ F *[]string }{}
var X b.B[int] = struct{ F *[]int }{}
var Y c[string] = struct{ G struct{ F *[][3]string } }{}
var Z c[int] = struct{ G struct{ F *[][3]int } }{}

Просмотреть файл

@ -53,7 +53,6 @@ func (pr *pkgReader) later(fn func()) {
// See cmd/compile/internal/noder.derivedInfo.
type derivedInfo struct {
idx pkgbits.Index
needed bool
}
// See cmd/compile/internal/noder.typeInfo.
@ -110,13 +109,17 @@ func readUnifiedPackage(fset *token.FileSet, ctxt *types.Context, imports map[st
r := pr.newReader(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic)
pkg := r.pkg()
r.Bool() // has init
if r.Version().Has(pkgbits.HasInit) {
r.Bool()
}
for i, n := 0, r.Len(); i < n; i++ {
// As if r.obj(), but avoiding the Scope.Lookup call,
// to avoid eager loading of imports.
r.Sync(pkgbits.SyncObject)
if r.Version().Has(pkgbits.DerivedFuncInstance) {
assert(!r.Bool())
}
r.p.objIdx(r.Reloc(pkgbits.RelocObj))
assert(r.Len() == 0)
}
@ -165,7 +168,7 @@ type readerDict struct {
// tparams is a slice of the constructed TypeParams for the element.
tparams []*types.TypeParam
// devived is a slice of types derived from tparams, which may be
// derived is a slice of types derived from tparams, which may be
// instantiated while reading the current element.
derived []derivedInfo
derivedTypes []types.Type // lazily instantiated from derived
@ -471,7 +474,9 @@ func (r *reader) param() *types.Var {
func (r *reader) obj() (types.Object, []types.Type) {
r.Sync(pkgbits.SyncObject)
if r.Version().Has(pkgbits.DerivedFuncInstance) {
assert(!r.Bool())
}
pkg, name := r.p.objIdx(r.Reloc(pkgbits.RelocObj))
obj := pkgScope(pkg).Lookup(name)
@ -525,8 +530,11 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
case pkgbits.ObjAlias:
pos := r.pos()
var tparams []*types.TypeParam
if r.Version().Has(pkgbits.AliasTypeParamNames) {
tparams = r.typeParamNames()
}
typ := r.typ()
var tparams []*types.TypeParam // TODO(#68778): read type params once pkgbits.V2 is available.
declare(aliases.NewAlias(r.p.aliases, pos, objPkg, objName, typ, tparams))
case pkgbits.ObjConst:
@ -633,7 +641,10 @@ func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict {
dict.derived = make([]derivedInfo, r.Len())
dict.derivedTypes = make([]types.Type, len(dict.derived))
for i := range dict.derived {
dict.derived[i] = derivedInfo{r.Reloc(pkgbits.RelocType), r.Bool()}
dict.derived[i] = derivedInfo{idx: r.Reloc(pkgbits.RelocType)}
if r.Version().Has(pkgbits.DerivedInfoNeeded) {
assert(!r.Bool())
}
}
pr.retireReader(r)