Skip to content

Commit

Permalink
go/ssa: bound functions are now unique per instantiation.
Browse files Browse the repository at this point in the history
Updates golang/go#48525

Change-Id: I028ee12c2b85bb4c1761e5255711eaab52912491
Reviewed-on: https://go-review.googlesource.com/c/tools/+/397794
Reviewed-by: Robert Findley <rfindley@google.com>
Reviewed-by: Zvonimir Pavlinovic <zpavlinovic@google.com>
Trust: Tim King <taking@google.com>
Run-TryBot: Tim King <taking@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
  • Loading branch information
timothy-king committed Apr 8, 2022
1 parent 7dd9f20 commit ce5936c
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 4 deletions.
2 changes: 1 addition & 1 deletion go/ssa/create.go
Expand Up @@ -29,7 +29,7 @@ func NewProgram(fset *token.FileSet, mode BuilderMode) *Program {
imported: make(map[string]*Package),
packages: make(map[*types.Package]*Package),
thunks: make(map[selectionKey]*Function),
bounds: make(map[*types.Func]*Function),
bounds: make(map[boundsKey]*Function),
mode: mode,
canon: newCanonizer(),
ctxt: typeparams.NewContext(),
Expand Down
2 changes: 1 addition & 1 deletion go/ssa/ssa.go
Expand Up @@ -33,7 +33,7 @@ type Program struct {
methodsMu sync.Mutex // guards the following maps:
methodSets typeutil.Map // maps type to its concrete methodSet
runtimeTypes typeutil.Map // types for which rtypes are needed
bounds map[*types.Func]*Function // bounds for curried x.Method closures
bounds map[boundsKey]*Function // bounds for curried x.Method closures
thunks map[selectionKey]*Function // thunks for T.Method expressions
instances map[*Function]*instanceSet // instances of generic functions
}
Expand Down
25 changes: 25 additions & 0 deletions go/ssa/util.go
Expand Up @@ -141,6 +141,31 @@ func isGeneric(m Member) bool {
}
}

// receiverTypeArgs returns the type arguments to a function's reciever.
// Returns an empty list if obj does not have a reciever or its reciever does not have type arguments.
func receiverTypeArgs(obj *types.Func) []types.Type {
rtype := recvType(obj)
if rtype == nil {
return nil
}
if isPointer(rtype) {
rtype = rtype.(*types.Pointer).Elem()
}
named, ok := rtype.(*types.Named)
if !ok {
return nil
}
ts := typeparams.NamedTypeArgs(named)
if ts.Len() == 0 {
return nil
}
targs := make([]types.Type, ts.Len())
for i := 0; i < ts.Len(); i++ {
targs[i] = ts.At(i)
}
return targs
}

// Mapping of a type T to a canonical instance C s.t. types.Indentical(T, C).
// Thread-safe.
type canonizer struct {
Expand Down
13 changes: 11 additions & 2 deletions go/ssa/wrappers.go
Expand Up @@ -179,9 +179,12 @@ func createParams(fn *Function, start int) {
// EXCLUSIVE_LOCKS_ACQUIRED(meth.Prog.methodsMu)
//
func makeBound(prog *Program, obj *types.Func, cr *creator) *Function {
targs := receiverTypeArgs(obj)
key := boundsKey{obj, prog.canon.List(targs)}

prog.methodsMu.Lock()
defer prog.methodsMu.Unlock()
fn, ok := prog.bounds[obj]
fn, ok := prog.bounds[key]
if !ok {
description := fmt.Sprintf("bound method wrapper for %s", obj)
if prog.mode&LogSource != 0 {
Expand Down Expand Up @@ -218,7 +221,7 @@ func makeBound(prog *Program, obj *types.Func, cr *creator) *Function {
fn.finishBody()
fn.done()

prog.bounds[obj] = fn
prog.bounds[key] = fn
}
return fn
}
Expand Down Expand Up @@ -289,3 +292,9 @@ type selectionKey struct {
index string
indirect bool
}

// boundsKey is a unique for the object and a type instantiation.
type boundsKey struct {
obj types.Object // t.meth
inst *typeList // canonical type instantiation list.
}

0 comments on commit ce5936c

Please sign in to comment.