aboutsummaryrefslogtreecommitdiff
path: root/src/go/types/check.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/go/types/check.go')
-rw-r--r--src/go/types/check.go84
1 files changed, 46 insertions, 38 deletions
diff --git a/src/go/types/check.go b/src/go/types/check.go
index d1672837b8..69e9466a8b 100644
--- a/src/go/types/check.go
+++ b/src/go/types/check.go
@@ -8,6 +8,7 @@ package types
import (
"errors"
+ "fmt"
"go/ast"
"go/constant"
"go/token"
@@ -69,6 +70,12 @@ type importKey struct {
path, dir string
}
+// A dotImportKey describes a dot-imported object in the given scope.
+type dotImportKey struct {
+ scope *Scope
+ obj Object
+}
+
// A Checker maintains the state of the type checker.
// It must be created with NewChecker.
type Checker struct {
@@ -78,18 +85,20 @@ type Checker struct {
fset *token.FileSet
pkg *Package
*Info
- 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
- posMap map[*Interface][]token.Pos // maps interface types to lists of embedded interface positions
- typMap map[string]*Named // maps an instantiated named type hash to a *Named type
- pkgCnt map[string]int // counts number of imported packages with a given name (for better error messages)
+ version version // accepted 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
+ posMap map[*Interface][]token.Pos // maps interface types to lists of embedded interface positions
+ typMap map[string]*Named // maps an instantiated named type hash to a *Named type
+ pkgCnt map[string]int // counts number of imported packages with a given name (for better error messages)
// information collected during type-checking of a set of package files
// (initialized by Files, valid only for the duration of check.Files;
// maps and lists are allocated on demand)
- files []*ast.File // package files
- unusedDotImports map[*Scope]map[*Package]*ast.ImportSpec // unused dot-imported packages
+ files []*ast.File // package files
+ imports []*PkgName // list of imported packages
+ dotImportMap map[dotImportKey]*PkgName // maps dot-imported objects to the package they were dot-imported through
firstErr error // first error encountered
methods map[*TypeName][]*Func // maps package scope type names to associated non-blank (non-interface) methods
@@ -106,22 +115,6 @@ type Checker struct {
indent int // indentation for tracing
}
-// addUnusedImport adds the position of a dot-imported package
-// pkg to the map of dot imports for the given file scope.
-func (check *Checker) addUnusedDotImport(scope *Scope, pkg *Package, spec *ast.ImportSpec) {
- mm := check.unusedDotImports
- if mm == nil {
- mm = make(map[*Scope]map[*Package]*ast.ImportSpec)
- check.unusedDotImports = mm
- }
- m := mm[scope]
- if m == nil {
- m = make(map[*Package]*ast.ImportSpec)
- mm[scope] = m
- }
- m[pkg] = spec
-}
-
// addDeclDep adds the dependency edge (check.decl -> to) if check.decl exists
func (check *Checker) addDeclDep(to Object) {
from := check.decl
@@ -187,17 +180,23 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch
info = new(Info)
}
+ version, err := parseGoVersion(conf.GoVersion)
+ if err != nil {
+ panic(fmt.Sprintf("invalid Go version %q (%v)", conf.GoVersion, err))
+ }
+
return &Checker{
- conf: conf,
- fset: fset,
- pkg: pkg,
- Info: info,
- nextId: 1,
- objMap: make(map[Object]*declInfo),
- impMap: make(map[importKey]*Package),
- posMap: make(map[*Interface][]token.Pos),
- typMap: make(map[string]*Named),
- pkgCnt: make(map[string]int),
+ conf: conf,
+ fset: fset,
+ pkg: pkg,
+ Info: info,
+ version: version,
+ nextId: 1,
+ objMap: make(map[Object]*declInfo),
+ impMap: make(map[importKey]*Package),
+ posMap: make(map[*Interface][]token.Pos),
+ typMap: make(map[string]*Named),
+ pkgCnt: make(map[string]int),
}
}
@@ -206,7 +205,8 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch
func (check *Checker) initFiles(files []*ast.File) {
// start with a clean slate (check.Files may be called multiple times)
check.files = nil
- check.unusedDotImports = nil
+ check.imports = nil
+ check.dotImportMap = nil
check.firstErr = nil
check.methods = nil
@@ -276,6 +276,9 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) {
if !check.conf.DisableUnusedImportCheck {
check.unusedImports()
}
+ // no longer needed - release memory
+ check.imports = nil
+ check.dotImportMap = nil
check.recordUntyped()
@@ -284,6 +287,9 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) {
}
check.pkg.complete = true
+
+ // TODO(rFindley) There's more memory we should release at this point.
+
return
}
@@ -334,7 +340,9 @@ func (check *Checker) recordTypeAndValue(x ast.Expr, mode operandMode, typ Type,
}
if mode == constant_ {
assert(val != nil)
- assert(typ == Typ[Invalid] || isConstType(typ))
+ // We check is(typ, IsConstType) here as constant expressions may be
+ // recorded as type parameters.
+ assert(typ == Typ[Invalid] || is(typ, IsConstType))
}
if m := check.Types; m != nil {
m[x] = TypeAndValue{mode, typ, val}
@@ -388,8 +396,8 @@ func (check *Checker) recordCommaOkTypes(x ast.Expr, a [2]Type) {
func (check *Checker) recordInferred(call ast.Expr, targs []Type, sig *Signature) {
assert(call != nil)
assert(sig != nil)
- if m := check.Inferred; m != nil {
- m[call] = Inferred{targs, sig}
+ if m := check._Inferred; m != nil {
+ m[call] = _Inferred{targs, sig}
}
}