This CL is a clean port of CL 363175 from go/types to types2.
Change-Id: I149789be07c0ca7ddef7bfaa4ea9507778a63775
Reviewed-on: https://go-review.googlesource.com/c/go/+/364454
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
}()
}
- 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 {
// package information
// (initialized by NewChecker, valid for the life-time of checker)
conf *Config
+ ctxt *Context // context for de-duplicating instances
pkg *Package
*Info
version version // accepted language version
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)
return &Checker{
conf: conf,
+ ctxt: conf.Context,
pkg: pkg,
Info: info,
version: version,
check.seenPkgMap = nil
check.recvTParamMap = nil
check.defTypes = nil
+ check.ctxt = nil
// TODO(gri) There's more memory we should release at this point.
// 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
// 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()
}
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 {
}
// 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
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)
// 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