]> Cypherpunks.ru repositories - gostls13.git/commitdiff
go/types: don't set a Config.Context if none is provided
authorRobert Findley <rfindley@google.com>
Wed, 10 Nov 2021 21:52:17 +0000 (16:52 -0500)
committerRobert Findley <rfindley@google.com>
Sat, 13 Nov 2021 00:49:51 +0000 (00:49 +0000)
Users can re-use a type checking context by passing it via types.Config.
There is no need for us to expose the internal type checking context
when the config context is unset, and in fact doing so could lead to a
memory leak for users that re-use types.Config, expecting it to be small
and immutable.

Keep track of the Context on Checker instead, and zero it out at the end
of type checking.

Change-Id: Iff5b328a09cd0af76fcd4869f5f15352131b5986
Reviewed-on: https://go-review.googlesource.com/c/go/+/363175
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
src/go/types/call.go
src/go/types/check.go
src/go/types/decl.go
src/go/types/named.go
src/go/types/signature.go
src/go/types/typexpr.go

index 890a2c7c5ad0c7dd8daa29c002f23cbf904e31fb..da4b72a0c7b78df601cf80a61733544b1cf3fabb 100644 (file)
@@ -81,7 +81,7 @@ func (check *Checker) instantiateSignature(pos token.Pos, typ *Signature, targs
                }()
        }
 
-       inst := check.instance(pos, typ, targs, check.conf.Context).(*Signature)
+       inst := check.instance(pos, typ, targs, check.bestContext(nil)).(*Signature)
        assert(len(posList) <= len(targs))
        tparams := typ.TypeParams().list()
        if i, err := check.verify(pos, tparams, targs); err != nil {
index 93e6ffa761a8ed2f26bf61d8031a92f0aa04fc14..ba7d26455f50bbdd7ac6bdcf9e28feb77e60a88c 100644 (file)
@@ -105,6 +105,7 @@ type Checker struct {
        // package information
        // (initialized by NewChecker, valid for the life-time of checker)
        conf *Config
+       ctxt *Context // context for de-duplicating instances
        fset *token.FileSet
        pkg  *Package
        *Info
@@ -203,11 +204,6 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch
                conf = new(Config)
        }
 
-       // make sure we have a context
-       if conf.Context == nil {
-               conf.Context = NewContext()
-       }
-
        // make sure we have an info struct
        if info == nil {
                info = new(Info)
@@ -220,6 +216,7 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch
 
        return &Checker{
                conf:    conf,
+               ctxt:    conf.Context,
                fset:    fset,
                pkg:     pkg,
                Info:    info,
@@ -322,6 +319,7 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) {
        check.seenPkgMap = nil
        check.recvTParamMap = nil
        check.defTypes = nil
+       check.ctxt = nil
 
        // TODO(rFindley) There's more memory we should release at this point.
 
index 64d5bd195e870766fab91fe5f82c30c0bbbb3bb9..6adace34849d9de28cb133a9d40482daa1c98477 100644 (file)
@@ -68,7 +68,7 @@ func (check *Checker) objDecl(obj Object, def *Named) {
        // Funcs with m.instRecv set have not yet be completed. Complete them now
        // so that they have a type when objDecl exits.
        if m, _ := obj.(*Func); m != nil && m.instRecv != nil {
-               check.completeMethod(check.conf.Context, m)
+               check.completeMethod(nil, m)
        }
 
        // Checking the declaration of obj means inferring its type
index 06b6d4692b585ec95eb1ff1a10f20d64208c1824..82a053dd0d2d344dcbc1cda52db410a89524618f 100644 (file)
@@ -222,15 +222,17 @@ func (n *Named) setUnderlying(typ Type) {
 
 // bestContext returns the best available context. In order of preference:
 // - the given ctxt, if non-nil
-// - check.Config.Context, if check is non-nil
+// - check.ctxt, if check is non-nil
 // - a new Context
 func (check *Checker) bestContext(ctxt *Context) *Context {
        if ctxt != nil {
                return ctxt
        }
        if check != nil {
-               assert(check.conf.Context != nil)
-               return check.conf.Context
+               if check.ctxt == nil {
+                       check.ctxt = NewContext()
+               }
+               return check.ctxt
        }
        return NewContext()
 }
index 3e0a046afa5e505263881d06fa29de2e86ccbc74..698b89c462f11a6e9bb3c963a8d204baab840d0c 100644 (file)
@@ -211,7 +211,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
                        var err string
                        switch T := rtyp.(type) {
                        case *Named:
-                               T.resolve(check.conf.Context)
+                               T.resolve(check.bestContext(nil))
                                // The receiver type may be an instantiated type referred to
                                // by an alias (which cannot have receiver parameters for now).
                                if T.TypeArgs() != nil && sig.RecvTypeParams() == nil {
index 09d14719857dc45e474c29976f5d325915791adf..cff99171858ed419fce9efff1755423eb82c0924 100644 (file)
@@ -409,9 +409,10 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named
        }
 
        // create the instance
-       h := check.conf.Context.instanceHash(orig, targs)
+       ctxt := check.bestContext(nil)
+       h := ctxt.instanceHash(orig, targs)
        // targs may be incomplete, and require inference. In any case we should de-duplicate.
-       inst, _ := check.conf.Context.lookup(h, orig, targs).(*Named)
+       inst, _ := ctxt.lookup(h, orig, targs).(*Named)
        // If inst is non-nil, we can't just return here. Inst may have been
        // constructed via recursive substitution, in which case we wouldn't do the
        // validation below. Ensure that the validation (and resulting errors) runs
@@ -420,7 +421,7 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named
                tname := NewTypeName(x.Pos(), orig.obj.pkg, orig.obj.name, nil)
                inst = check.newNamed(tname, orig, nil, nil, nil) // underlying, methods and tparams are set when named is resolved
                inst.targs = NewTypeList(targs)
-               inst = check.conf.Context.update(h, orig, targs, inst).(*Named)
+               inst = ctxt.update(h, orig, targs, inst).(*Named)
        }
        def.setUnderlying(inst)
 
@@ -446,7 +447,7 @@ func (check *Checker) instantiatedType(x ast.Expr, targsx []ast.Expr, def *Named
                // This is an instance from the source, not from recursive substitution,
                // and so it must be resolved during type-checking so that we can report
                // errors.
-               inst.resolve(check.conf.Context)
+               inst.resolve(ctxt)
                // Since check is non-nil, we can still mutate inst. Unpinning the resolver
                // frees some memory.
                inst.resolver = nil