From 950a56899aaf48da9691fbbfb8f48328863e02fa Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 5 Apr 2018 22:42:16 -0700 Subject: [PATCH] cmd/compile: fix method expressions with anonymous receivers Method expressions with anonymous receiver types like "struct { T }.m" require wrapper functions, which we weren't always creating. This in turn resulted in linker errors. This CL ensures that we generate wrapper functions for any anonymous receiver types used in a method expression. Fixes #22444. Change-Id: Ia8ac27f238c2898965e57b82a91d959792d2ddd4 Reviewed-on: https://go-review.googlesource.com/105044 Run-TryBot: Matthew Dempsky TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick --- src/cmd/compile/internal/gc/reflect.go | 1 + src/cmd/compile/internal/gc/typecheck.go | 10 ++++++++++ test/method7.go | 7 +++---- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go index bd837b140e..053e3cb031 100644 --- a/src/cmd/compile/internal/gc/reflect.go +++ b/src/cmd/compile/internal/gc/reflect.go @@ -1474,6 +1474,7 @@ func itabsym(it *obj.LSym, offset int64) *obj.LSym { return syms[methodnum] } +// addsignat ensures that a runtime type descriptor is emitted for t. func addsignat(t *types.Type) { signatset[t] = struct{}{} } diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index ea6c4c8dff..4254d5655d 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -2378,6 +2378,16 @@ func looktypedot(n *Node, t *types.Type, dostrcmp int) bool { return false } + // The method expression T.m requires a wrapper when T is + // different from m's declared receiver type. We normally + // generate these wrappers while writing out runtime type + // descriptors, which is always done for types declared at + // package scope. However, we need to make sure to generate + // wrappers for anonymous receiver types too. + if mt.Sym == nil { + addsignat(t) + } + n.Sym = methodSym(t, n.Sym) n.Xoffset = f2.Offset n.Type = f2.Type diff --git a/test/method7.go b/test/method7.go index 72c88b377d..15e123e85f 100644 --- a/test/method7.go +++ b/test/method7.go @@ -45,10 +45,9 @@ func main() { interface{ m1(string) }.m1(x, "d") want += " m1(d)" - // cannot link the call below - see #22444 - // g := struct{ T }.m2 - // g(struct{T}{}) - // want += " m2()" + g := struct{ T }.m2 + g(struct{ T }{}) + want += " m2()" if got != want { panic("got" + got + ", want" + want)