зеркало из https://github.com/golang/tools.git
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:
Родитель
09886e004e
Коммит
2db563b1a3
|
@ -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
|
// apkg returns the package "a" prefixed by (as a package) testoutdir
|
||||||
func apkg(testoutdir string) string {
|
func apkg(testoutdir string) string {
|
||||||
apkg := testoutdir + "/a"
|
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 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.
|
// This step is not supported, but it does give test coverage for stdlib.
|
||||||
"goroot": func(t *testing.T) *types.Package {
|
"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.
|
// Write indexed export data file contents.
|
||||||
//
|
//
|
||||||
// TODO(taking): Slightly unclear to what extent this step should be supported by go/importer.
|
// TODO(taking): Slightly unclear to what extent this step should be supported by go/importer.
|
||||||
|
|
|
@ -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]{}
|
||||||
|
}
|
|
@ -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]
|
||||||
|
}
|
|
@ -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 } }{}
|
|
@ -52,8 +52,7 @@ func (pr *pkgReader) later(fn func()) {
|
||||||
|
|
||||||
// See cmd/compile/internal/noder.derivedInfo.
|
// See cmd/compile/internal/noder.derivedInfo.
|
||||||
type derivedInfo struct {
|
type derivedInfo struct {
|
||||||
idx pkgbits.Index
|
idx pkgbits.Index
|
||||||
needed bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// See cmd/compile/internal/noder.typeInfo.
|
// 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)
|
r := pr.newReader(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic)
|
||||||
pkg := r.pkg()
|
pkg := r.pkg()
|
||||||
r.Bool() // has init
|
if r.Version().Has(pkgbits.HasInit) {
|
||||||
|
r.Bool()
|
||||||
|
}
|
||||||
|
|
||||||
for i, n := 0, r.Len(); i < n; i++ {
|
for i, n := 0, r.Len(); i < n; i++ {
|
||||||
// As if r.obj(), but avoiding the Scope.Lookup call,
|
// As if r.obj(), but avoiding the Scope.Lookup call,
|
||||||
// to avoid eager loading of imports.
|
// to avoid eager loading of imports.
|
||||||
r.Sync(pkgbits.SyncObject)
|
r.Sync(pkgbits.SyncObject)
|
||||||
assert(!r.Bool())
|
if r.Version().Has(pkgbits.DerivedFuncInstance) {
|
||||||
|
assert(!r.Bool())
|
||||||
|
}
|
||||||
r.p.objIdx(r.Reloc(pkgbits.RelocObj))
|
r.p.objIdx(r.Reloc(pkgbits.RelocObj))
|
||||||
assert(r.Len() == 0)
|
assert(r.Len() == 0)
|
||||||
}
|
}
|
||||||
|
@ -165,7 +168,7 @@ type readerDict struct {
|
||||||
// tparams is a slice of the constructed TypeParams for the element.
|
// tparams is a slice of the constructed TypeParams for the element.
|
||||||
tparams []*types.TypeParam
|
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.
|
// instantiated while reading the current element.
|
||||||
derived []derivedInfo
|
derived []derivedInfo
|
||||||
derivedTypes []types.Type // lazily instantiated from derived
|
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) {
|
func (r *reader) obj() (types.Object, []types.Type) {
|
||||||
r.Sync(pkgbits.SyncObject)
|
r.Sync(pkgbits.SyncObject)
|
||||||
|
|
||||||
assert(!r.Bool())
|
if r.Version().Has(pkgbits.DerivedFuncInstance) {
|
||||||
|
assert(!r.Bool())
|
||||||
|
}
|
||||||
|
|
||||||
pkg, name := r.p.objIdx(r.Reloc(pkgbits.RelocObj))
|
pkg, name := r.p.objIdx(r.Reloc(pkgbits.RelocObj))
|
||||||
obj := pkgScope(pkg).Lookup(name)
|
obj := pkgScope(pkg).Lookup(name)
|
||||||
|
@ -525,8 +530,11 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
|
||||||
|
|
||||||
case pkgbits.ObjAlias:
|
case pkgbits.ObjAlias:
|
||||||
pos := r.pos()
|
pos := r.pos()
|
||||||
|
var tparams []*types.TypeParam
|
||||||
|
if r.Version().Has(pkgbits.AliasTypeParamNames) {
|
||||||
|
tparams = r.typeParamNames()
|
||||||
|
}
|
||||||
typ := r.typ()
|
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))
|
declare(aliases.NewAlias(r.p.aliases, pos, objPkg, objName, typ, tparams))
|
||||||
|
|
||||||
case pkgbits.ObjConst:
|
case pkgbits.ObjConst:
|
||||||
|
@ -633,7 +641,10 @@ func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict {
|
||||||
dict.derived = make([]derivedInfo, r.Len())
|
dict.derived = make([]derivedInfo, r.Len())
|
||||||
dict.derivedTypes = make([]types.Type, len(dict.derived))
|
dict.derivedTypes = make([]types.Type, len(dict.derived))
|
||||||
for i := range 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)
|
pr.retireReader(r)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче