diff --git a/go/pointer/reflect.go b/go/pointer/reflect.go index ec71d9e892..6238910bf3 100644 --- a/go/pointer/reflect.go +++ b/go/pointer/reflect.go @@ -1566,6 +1566,8 @@ func (c *rtypeMethodByNameConstraint) solve(a *analysis, _ *node, delta nodeset) for tObj := range delta { T := a.nodes[tObj].obj.data.(types.Type) + _, isInterface := T.Underlying().(*types.Interface) + // We don't use Lookup(c.name) when c.name != "" to avoid // ambiguity: >1 unexported methods could match. mset := a.prog.MethodSets.MethodSet(T) @@ -1582,8 +1584,17 @@ func (c *rtypeMethodByNameConstraint) solve(a *analysis, _ *node, delta nodeset) // } fn := a.prog.Method(sel) + sig := fn.Signature + if isInterface { + // discard receiver + sig = types.NewSignature(nil, nil, sig.Params(), sig.Results(), sig.Variadic()) + } else { + // move receiver to params[0] + sig = changeRecv(sig) + + } // a.offsetOf(Type) is 3. - if id := c.result + 3; a.addLabel(id, a.makeRtype(changeRecv(fn.Signature))) { + if id := c.result + 3; a.addLabel(id, a.makeRtype(sig)) { a.addWork(id) } // a.offsetOf(Func) is 4. diff --git a/go/pointer/testdata/funcreflect.go b/go/pointer/testdata/funcreflect.go index f6cff52f5e..448740ff41 100644 --- a/go/pointer/testdata/funcreflect.go +++ b/go/pointer/testdata/funcreflect.go @@ -82,6 +82,10 @@ type U struct{} func (U) F(int) {} func (U) g(string) {} +type I interface { + f() +} + var nonconst string func reflectTypeMethodByName() { @@ -101,6 +105,14 @@ func reflectTypeMethodByName() { X, _ := U.MethodByName(nonconst) print(reflect.Zero(X.Type)) // @types func(U, int) | func(U, string) print(X.Func) // @pointsto (main.U).F | (main.U).g + + // Interface methods. + rThasF := reflect.TypeOf(new(hasF)).Elem() + print(reflect.Zero(rThasF)) // @types hasF + F2, _ := rThasF.MethodByName("F") + print(reflect.Zero(F2.Type)) // @types func() + print(F2.Func) // @pointsto (main.hasF).F + } func reflectTypeMethod() {