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:
parent
74ecc2c09b
commit
99ac9493e1
@ -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()
|
||||
|
47
ssa/print.go
47
ssa/print.go
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user