1
0
mirror of https://github.com/golang/go synced 2024-11-18 20:44:45 -07:00

go.types/ssa: add back Signature.Recv to interface method wrappers.

It is needed after all, as I discovered in the pointer analysis.
(ssa needs more API test coverage.)

Also:
- sanity: remove debugging cruft
- promote: don't redundantly include the function's
  own name in its Synthetic string.
- print: IntuitiveMethodSet utility fixes a bug in the
  printing logic (for interface types, mset(*T) is empty).
  The function is also used by the Oracle.

R=crawshaw
CC=golang-dev
https://golang.org/cl/13116043
This commit is contained in:
Alan Donovan 2013-08-20 14:50:13 -04:00
parent 74ecc2c09b
commit 99ac9493e1
4 changed files with 42 additions and 18 deletions

View File

@ -63,7 +63,6 @@ func main() {
// Print out the package.
mainPkg.DumpTo(os.Stdout)
fmt.Println()
// Build SSA code for bodies of functions in mainPkg.
mainPkg.Build()

View File

@ -49,6 +49,8 @@ func relName(v Value, i Instruction) string {
// when displaying receiver, params, locals, captures of a Function;
// and in the RHS type column for Value-defining Instructions.
//
// TODO(adonovan): fix: unsafe.Pointer has no ssa.Package.
//
func relType(t types.Type, from *Package) string {
if from != nil {
t2 := t
@ -418,17 +420,7 @@ func (p *Package) DumpTo(w io.Writer) {
case *Type:
fmt.Fprintf(w, " type %-*s %s\n", maxname, name, mem.Type().Underlying())
// Iterate over the keys of mset(*T) since they
// are a superset of mset(T)'s keys.
// The keys of a types.MethodSet are sorted (by Id).
mset := mem.Type().MethodSet()
pmset := types.NewPointer(mem.Type()).MethodSet()
for i, n := 0, pmset.Len(); i < n; i++ {
meth := pmset.At(i)
// If the method also exists in mset(T), show that instead.
if m := mset.Lookup(meth.Obj().Pkg(), meth.Obj().Name()); m != nil {
meth = m
}
for _, meth := range IntuitiveMethodSet(mem.Type()) {
fmt.Fprintf(w, " %s\n", meth)
}
@ -436,6 +428,39 @@ func (p *Package) DumpTo(w io.Writer) {
fmt.Fprintf(w, " var %-*s %s\n", maxname, name, mem.Type())
}
}
fmt.Fprintf(w, "\n")
}
// IntuitiveMethodSet returns the intuitive method set of a type, T.
//
// The result contains MethodSet(T) and additionally, if T is a
// concrete type, methods belonging to *T if there is no similarly
// named method on T itself. This corresponds to user intuition about
// method sets; this function is intended only for user interfaces.
//
// The order of the result is as for types.MethodSet(T).
//
// TODO(gri): move this to go/types?
//
func IntuitiveMethodSet(T types.Type) []*types.Selection {
var result []*types.Selection
mset := T.MethodSet()
if _, ok := T.Underlying().(*types.Interface); ok {
for i, n := 0, mset.Len(); i < n; i++ {
result = append(result, mset.At(i))
}
} else {
pmset := types.NewPointer(T).MethodSet()
for i, n := 0, pmset.Len(); i < n; i++ {
meth := pmset.At(i)
if m := mset.Lookup(meth.Obj().Pkg(), meth.Obj().Name()); m != nil {
meth = m
}
result = append(result, meth)
}
}
return result
}
func commaOk(x bool) string {

View File

@ -5,7 +5,7 @@ package ssa
//
// Wrappers include:
// - indirection/promotion wrappers for methods of embedded fields.
// - interface method wrappers for closures of I.f.
// - interface method wrappers for expressions I.f.
// - bound method wrappers, for uncalled obj.Method closures.
// TODO(adonovan): rename to wrappers.go.
@ -199,7 +199,7 @@ func createParams(fn *Function) {
//
// The wrapper is defined as if by:
//
// func I.f(i I, x int, ...) R {
// func (i I) f(x int, ...) R {
// return i.f(x, ...)
// }
//
@ -220,14 +220,14 @@ func interfaceMethodWrapper(prog *Program, typ types.Type, obj *types.Func) *Fun
// a problem, we should include 'typ' in the memoization key.
fn, ok := prog.ifaceMethodWrappers[obj]
if !ok {
description := fmt.Sprintf("interface method wrapper for (%s).%s", typ, obj.Name())
description := "interface method wrapper"
if prog.mode&LogSource != 0 {
defer logStack("%s", description)()
defer logStack("(%s).%s, %s", typ, obj.Name(), description)()
}
fn = &Function{
name: obj.Name(),
object: obj,
Signature: changeRecv(obj.Type().(*types.Signature), nil), // drop receiver
Signature: obj.Type().(*types.Signature),
Synthetic: description,
pos: obj.Pos(),
Prog: prog,

View File

@ -329,7 +329,7 @@ func (s *sanity) checkFunction(fn *Function) bool {
strings.HasSuffix(fn.name, "Error") {
// wrapper for error.Error() has no package.
} else {
s.errorf("nil Pkg %q %q", fn.Synthetic, fn.name)
s.errorf("nil Pkg")
}
}
for i, l := range fn.Locals {