]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: add Environment to Config
authorRobert Griesemer <gri@golang.org>
Wed, 8 Sep 2021 23:03:57 +0000 (16:03 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 8 Sep 2021 23:59:02 +0000 (23:59 +0000)
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>

16 files changed:
src/cmd/compile/internal/noder/import.go
src/cmd/compile/internal/noder/irgen.go
src/cmd/compile/internal/noder/reader2.go
src/cmd/compile/internal/noder/unified.go
src/cmd/compile/internal/types2/api.go
src/cmd/compile/internal/types2/check.go
src/cmd/compile/internal/types2/decl.go
src/cmd/compile/internal/types2/instantiate.go
src/cmd/compile/internal/types2/named.go
src/cmd/compile/internal/types2/subst.go
src/go/types/api.go
src/go/types/check.go
src/go/types/decl.go
src/go/types/instantiate.go
src/go/types/named.go
src/go/types/subst.go

index c26340c96045e816885df57fb6b6da7eb95cdf60..f13f8ca7f5ef7eb8dadef5a125cf797f901203a8 100644 (file)
@@ -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
index a67b3994da1936037c957cc6d9dc87f21f54e30f..414875615f62c40e66f7a5f128e912fbfe28910e 100644 (file)
@@ -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 {
index 3886d571b598c79c42ee80bd8694fe89c2fc8027..6e2d1f2e76ea775e2dd9f09864d0bc583118030b 100644 (file)
@@ -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()
index bf63608bf1a0e9f2deadd663b1aec72b0d973d96..02f64d00ac9779c6c123bacc7fd903f9c9983eaf 100644 (file)
@@ -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
        }
 
index b2938b84da1e6abfd9a06734a2139fc7fdfd0f0c..6914e6c89f7ca28337b7b4c4bae1420a96cc1eba 100644 (file)
@@ -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.
index c7b45d86d11796bcc1b45a52701ba6da10463389..24a05e6b370f5436c74dcb64f5b1acd967610a3a 100644 (file)
@@ -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(),
        }
 }
 
index 4181be9fa83d47cc3f8ed1f589ce6c91d8b14916..905c21426c4b8950c1130fe6d2a01adc3a35d681 100644 (file)
@@ -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)
index 3ea21f921b814a286d4379ae3a8d8d83b7aba905..469ceea5c4cc7ca46b266fed95c64d586b65ee35 100644 (file)
@@ -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() {
index eb1ecd9595f8aabf77e8c209985b6ca37a83dc66..99410aedfbe8e94e6e0274571582062fd0abaacf 100644 (file)
@@ -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
index 752e107e1163963fd20fb76788d8658c5300bb4c..4627dd3c5ba96ec163c4d8215c9e9e13aa08cad3 100644 (file)
@@ -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 {
index 5beeff530c002f9cfa2566ba672f36d7fc7dc055..ebc3a012668ec9cbad7f05c5a96b617dd027384e 100644 (file)
@@ -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.
index 0383a58c64564245638ea5bcd309cd74f20412c8..63f4cbd4a0b0c62777712c43e43e40c65f6f7572 100644 (file)
@@ -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(),
        }
 }
 
index d132d30b9da41465dcf4ebc64fe43bae5a8c9927..f679c33a94e77ee278336c4183ff4d12886910cc 100644 (file)
@@ -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 {
index 040877829ca767b08b26d64ed45ce613bc3889b3..50be07b8fd794aef901cde5ca6356677f828fb39 100644 (file)
@@ -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() {
index 51c4a236da7f15c9e1c7968a8c0723ec16057889..74681ab2d43f217b3e79dcefd6baddd5668bf8d1 100644 (file)
@@ -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
index 4f9d76d598dc32f8edbc4e43ef027ff407369ddc..07fe6a6b6e2ebc58bc7934beea8b5a698be032cd 100644 (file)
@@ -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 {