mirror of
https://github.com/golang/go
synced 2024-11-24 08:50:14 -07:00
go/types, types2: add Environment to Config
Port to types2 and adjust compiler accordingly. Change-Id: I2e72b151ef834977dca64cb2e62cedcac4e46062 Reviewed-on: https://go-review.googlesource.com/c/go/+/348578 Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Robert Findley <rfindley@google.com> TryBot-Result: Go Bot <gobot@golang.org>
This commit is contained in:
parent
f5f8a911d8
commit
a1f6208e56
@ -43,12 +43,12 @@ var haveLegacyImports = false
|
||||
// for an imported package by overloading writeNewExportFunc, then
|
||||
// that payload will be mapped into memory and passed to
|
||||
// newReadImportFunc.
|
||||
var newReadImportFunc = func(data string, pkg1 *types.Pkg, check *types2.Checker, packages map[string]*types2.Package) (pkg2 *types2.Package, err error) {
|
||||
var newReadImportFunc = func(data string, pkg1 *types.Pkg, env *types2.Environment, packages map[string]*types2.Package) (pkg2 *types2.Package, err error) {
|
||||
panic("unexpected new export data payload")
|
||||
}
|
||||
|
||||
type gcimports struct {
|
||||
check *types2.Checker
|
||||
env *types2.Environment
|
||||
packages map[string]*types2.Package
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ func (m *gcimports) ImportFrom(path, srcDir string, mode types2.ImportMode) (*ty
|
||||
panic("mode must be 0")
|
||||
}
|
||||
|
||||
_, pkg, err := readImportFile(path, typecheck.Target, m.check, m.packages)
|
||||
_, pkg, err := readImportFile(path, typecheck.Target, m.env, m.packages)
|
||||
return pkg, err
|
||||
}
|
||||
|
||||
@ -224,7 +224,7 @@ func parseImportPath(pathLit *syntax.BasicLit) (string, error) {
|
||||
// readImportFile reads the import file for the given package path and
|
||||
// returns its types.Pkg representation. If packages is non-nil, the
|
||||
// types2.Package representation is also returned.
|
||||
func readImportFile(path string, target *ir.Package, check *types2.Checker, packages map[string]*types2.Package) (pkg1 *types.Pkg, pkg2 *types2.Package, err error) {
|
||||
func readImportFile(path string, target *ir.Package, env *types2.Environment, packages map[string]*types2.Package) (pkg1 *types.Pkg, pkg2 *types2.Package, err error) {
|
||||
path, err = resolveImportPath(path)
|
||||
if err != nil {
|
||||
return
|
||||
@ -279,7 +279,7 @@ func readImportFile(path string, target *ir.Package, check *types2.Checker, pack
|
||||
return
|
||||
}
|
||||
|
||||
pkg2, err = newReadImportFunc(data, pkg1, check, packages)
|
||||
pkg2, err = newReadImportFunc(data, pkg1, env, packages)
|
||||
} else {
|
||||
// We only have old data. Oh well, fall back to the legacy importers.
|
||||
haveLegacyImports = true
|
||||
|
@ -34,10 +34,13 @@ func checkFiles(noders []*noder) (posMap, *types2.Package, *types2.Info) {
|
||||
}
|
||||
|
||||
// typechecking
|
||||
env := types2.NewEnvironment()
|
||||
importer := gcimports{
|
||||
env: env,
|
||||
packages: map[string]*types2.Package{"unsafe": types2.Unsafe},
|
||||
}
|
||||
conf := types2.Config{
|
||||
Environment: env,
|
||||
GoVersion: base.Flag.Lang,
|
||||
IgnoreLabels: true, // parser already checked via syntax.CheckBranches mode
|
||||
CompilerErrorMessages: true, // use error strings matching existing compiler errors
|
||||
@ -60,9 +63,7 @@ func checkFiles(noders []*noder) (posMap, *types2.Package, *types2.Info) {
|
||||
// expand as needed
|
||||
}
|
||||
|
||||
pkg := types2.NewPackage(base.Ctxt.Pkgpath, "")
|
||||
importer.check = types2.NewChecker(&conf, pkg, info)
|
||||
err := importer.check.Files(files)
|
||||
pkg, err := conf.Check(base.Ctxt.Pkgpath, files, info)
|
||||
|
||||
base.ExitIfErrors()
|
||||
if err != nil {
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
type pkgReader2 struct {
|
||||
pkgDecoder
|
||||
|
||||
check *types2.Checker
|
||||
env *types2.Environment
|
||||
imports map[string]*types2.Package
|
||||
|
||||
posBases []*syntax.PosBase
|
||||
@ -26,11 +26,11 @@ type pkgReader2 struct {
|
||||
typs []types2.Type
|
||||
}
|
||||
|
||||
func readPackage2(check *types2.Checker, imports map[string]*types2.Package, input pkgDecoder) *types2.Package {
|
||||
func readPackage2(env *types2.Environment, imports map[string]*types2.Package, input pkgDecoder) *types2.Package {
|
||||
pr := pkgReader2{
|
||||
pkgDecoder: input,
|
||||
|
||||
check: check,
|
||||
env: env,
|
||||
imports: imports,
|
||||
|
||||
posBases: make([]*syntax.PosBase, input.numElems(relocPosBase)),
|
||||
@ -233,9 +233,7 @@ func (r *reader2) doTyp() (res types2.Type) {
|
||||
obj, targs := r.obj()
|
||||
name := obj.(*types2.TypeName)
|
||||
if len(targs) != 0 {
|
||||
// TODO(mdempsky) should use a single shared environment here
|
||||
// (before, this used a shared checker)
|
||||
t, _ := types2.Instantiate(types2.NewEnvironment(), name.Type(), targs, false)
|
||||
t, _ := types2.Instantiate(r.p.env, name.Type(), targs, false)
|
||||
return t
|
||||
}
|
||||
return name.Type()
|
||||
|
@ -78,12 +78,12 @@ func unified(noders []*noder) {
|
||||
base.Errorf("cannot use -G and -d=quirksmode together")
|
||||
}
|
||||
|
||||
newReadImportFunc = func(data string, pkg1 *types.Pkg, check *types2.Checker, packages map[string]*types2.Package) (pkg2 *types2.Package, err error) {
|
||||
newReadImportFunc = func(data string, pkg1 *types.Pkg, env *types2.Environment, packages map[string]*types2.Package) (pkg2 *types2.Package, err error) {
|
||||
pr := newPkgDecoder(pkg1.Path, data)
|
||||
|
||||
// Read package descriptors for both types2 and compiler backend.
|
||||
readPackage(newPkgReader(pr), pkg1)
|
||||
pkg2 = readPackage2(check, packages, pr)
|
||||
pkg2 = readPackage2(env, packages, pr)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -108,6 +108,11 @@ type ImporterFrom interface {
|
||||
// A Config specifies the configuration for type checking.
|
||||
// The zero value for Config is a ready-to-use default configuration.
|
||||
type Config struct {
|
||||
// Environment is the environment used for resolving global
|
||||
// identifiers. If nil, the type checker will initialize this
|
||||
// field with a newly created environment.
|
||||
Environment *Environment
|
||||
|
||||
// GoVersion describes the accepted Go language version. The string
|
||||
// must follow the format "go%d.%d" (e.g. "go1.12") or ist must be
|
||||
// empty; an empty string indicates the latest language version.
|
||||
|
@ -86,7 +86,6 @@ type Checker struct {
|
||||
nextID uint64 // unique Id for type parameters (first valid Id is 1)
|
||||
objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info
|
||||
impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package
|
||||
env *Environment // for deduplicating identical instances
|
||||
|
||||
// pkgPathMap maps package names to the set of distinct import paths we've
|
||||
// seen for that name, anywhere in the import graph. It is used for
|
||||
@ -171,6 +170,11 @@ func NewChecker(conf *Config, pkg *Package, info *Info) *Checker {
|
||||
conf = new(Config)
|
||||
}
|
||||
|
||||
// make sure we have an environment
|
||||
if conf.Environment == nil {
|
||||
conf.Environment = NewEnvironment()
|
||||
}
|
||||
|
||||
// make sure we have an info struct
|
||||
if info == nil {
|
||||
info = new(Info)
|
||||
@ -188,7 +192,6 @@ func NewChecker(conf *Config, pkg *Package, info *Info) *Checker {
|
||||
version: version,
|
||||
objMap: make(map[Object]*declInfo),
|
||||
impMap: make(map[importKey]*Package),
|
||||
env: NewEnvironment(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,7 +317,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo {
|
||||
}
|
||||
|
||||
case *Named:
|
||||
t.expand(check.env)
|
||||
t.expand(check.conf.Environment)
|
||||
|
||||
// don't touch the type if it is from a different package or the Universe scope
|
||||
// (doing so would lead to a race condition - was issue #35049)
|
||||
|
@ -71,7 +71,7 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, posLis
|
||||
}()
|
||||
}
|
||||
|
||||
inst := check.instance(pos, typ, targs, check.env)
|
||||
inst := check.instance(pos, typ, targs, check.conf.Environment)
|
||||
|
||||
assert(len(posList) <= len(targs))
|
||||
check.later(func() {
|
||||
|
@ -254,7 +254,7 @@ func (n *Named) expand(env *Environment) *Named {
|
||||
// in subst) feels overly complicated. Can we simplify?
|
||||
if env == nil {
|
||||
if n.check != nil {
|
||||
env = n.check.env
|
||||
env = n.check.conf.Environment
|
||||
} else {
|
||||
// If we're instantiating lazily, we might be outside the scope of a
|
||||
// type-checking pass. In that case we won't have a pre-existing
|
||||
|
@ -59,7 +59,7 @@ func (check *Checker) subst(pos syntax.Pos, typ Type, smap substMap, env *Enviro
|
||||
if check != nil {
|
||||
subst.check = check
|
||||
if env == nil {
|
||||
env = check.env
|
||||
env = check.conf.Environment
|
||||
}
|
||||
}
|
||||
if env == nil {
|
||||
|
@ -115,6 +115,11 @@ type ImporterFrom interface {
|
||||
// A Config specifies the configuration for type checking.
|
||||
// The zero value for Config is a ready-to-use default configuration.
|
||||
type Config struct {
|
||||
// Environment is the environment used for resolving global
|
||||
// identifiers. If nil, the type checker will initialize this
|
||||
// field with a newly created environment.
|
||||
Environment *Environment
|
||||
|
||||
// GoVersion describes the accepted Go language version. The string
|
||||
// must follow the format "go%d.%d" (e.g. "go1.12") or it must be
|
||||
// empty; an empty string indicates the latest language version.
|
||||
|
@ -89,7 +89,6 @@ type Checker struct {
|
||||
nextID uint64 // unique Id for type parameters (first valid Id is 1)
|
||||
objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info
|
||||
impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package
|
||||
env *Environment // for deduplicating identical instances
|
||||
|
||||
// pkgPathMap maps package names to the set of distinct import paths we've
|
||||
// seen for that name, anywhere in the import graph. It is used for
|
||||
@ -174,6 +173,11 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch
|
||||
conf = new(Config)
|
||||
}
|
||||
|
||||
// make sure we have an environment
|
||||
if conf.Environment == nil {
|
||||
conf.Environment = NewEnvironment()
|
||||
}
|
||||
|
||||
// make sure we have an info struct
|
||||
if info == nil {
|
||||
info = new(Info)
|
||||
@ -192,7 +196,6 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch
|
||||
version: version,
|
||||
objMap: make(map[Object]*declInfo),
|
||||
impMap: make(map[importKey]*Package),
|
||||
env: NewEnvironment(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -316,7 +316,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo {
|
||||
}
|
||||
|
||||
case *Named:
|
||||
t.expand(check.env)
|
||||
t.expand(check.conf.Environment)
|
||||
// don't touch the type if it is from a different package or the Universe scope
|
||||
// (doing so would lead to a race condition - was issue #35049)
|
||||
if t.obj.pkg != check.pkg {
|
||||
|
@ -71,7 +71,7 @@ func (check *Checker) instantiate(pos token.Pos, typ Type, targs []Type, posList
|
||||
}()
|
||||
}
|
||||
|
||||
inst := check.instance(pos, typ, targs, check.env)
|
||||
inst := check.instance(pos, typ, targs, check.conf.Environment)
|
||||
|
||||
assert(len(posList) <= len(targs))
|
||||
check.later(func() {
|
||||
|
@ -254,7 +254,7 @@ func (n *Named) expand(env *Environment) *Named {
|
||||
// in subst) feels overly complicated. Can we simplify?
|
||||
if env == nil {
|
||||
if n.check != nil {
|
||||
env = n.check.env
|
||||
env = n.check.conf.Environment
|
||||
} else {
|
||||
// If we're instantiating lazily, we might be outside the scope of a
|
||||
// type-checking pass. In that case we won't have a pre-existing
|
||||
|
@ -62,7 +62,7 @@ func (check *Checker) subst(pos token.Pos, typ Type, smap substMap, env *Environ
|
||||
if check != nil {
|
||||
subst.check = check
|
||||
if env == nil {
|
||||
env = check.env
|
||||
env = check.conf.Environment
|
||||
}
|
||||
}
|
||||
if env == nil {
|
||||
|
Loading…
Reference in New Issue
Block a user