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>
// 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
}
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
}
// 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
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
}
// 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
// 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 {
type pkgReader2 struct {
pkgDecoder
- check *types2.Checker
+ env *types2.Environment
imports map[string]*types2.Package
posBases []*syntax.PosBase
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)),
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()
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
}
// 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.
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
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)
version: version,
objMap: make(map[Object]*declInfo),
impMap: make(map[importKey]*Package),
- env: NewEnvironment(),
}
}
}
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)
}()
}
- 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() {
// 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
if check != nil {
subst.check = check
if env == nil {
- env = check.env
+ env = check.conf.Environment
}
}
if env == nil {
// 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.
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
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)
version: version,
objMap: make(map[Object]*declInfo),
impMap: make(map[importKey]*Package),
- env: NewEnvironment(),
}
}
}
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 {
}()
}
- 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() {
// 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
if check != nil {
subst.check = check
if env == nil {
- env = check.env
+ env = check.conf.Environment
}
}
if env == nil {