return n
}
-// code to help generate trampoline
-// functions for methods on embedded
-// subtypes.
-// these are approx the same as
-// the corresponding adddot routines
-// except that they expect to be called
-// with unique tasks and they return
-// the actual methods.
+// Code to help generate trampoline functions for methods on embedded
+// types. These are approx the same as the corresponding adddot
+// routines except that they expect to be called with unique tasks and
+// they return the actual methods.
+
type Symlink struct {
- field *types.Field
- followptr bool
+ field *types.Field
}
var slist []Symlink
-func expand0(t *types.Type, followptr bool) {
+func expand0(t *types.Type) {
u := t
if u.IsPtr() {
- followptr = true
u = u.Elem()
}
continue
}
f.Sym.SetUniq(true)
- slist = append(slist, Symlink{field: f, followptr: followptr})
+ slist = append(slist, Symlink{field: f})
}
return
continue
}
f.Sym.SetUniq(true)
- slist = append(slist, Symlink{field: f, followptr: followptr})
+ slist = append(slist, Symlink{field: f})
}
}
}
-func expand1(t *types.Type, top, followptr bool) {
+func expand1(t *types.Type, top bool) {
if t.Recur() {
return
}
t.SetRecur(true)
if !top {
- expand0(t, followptr)
+ expand0(t)
}
u := t
if u.IsPtr() {
- followptr = true
u = u.Elem()
}
if f.Sym == nil {
continue
}
- expand1(f.Type, false, followptr)
+ expand1(f.Type, false)
}
}
// generate all reachable methods
slist = slist[:0]
- expand1(t, true, false)
+ expand1(t, true)
// check each method to be uniquely reachable
var ms []*types.Field
sl.field.Sym.SetUniq(false)
var f *types.Field
- if path, _ := dotpath(sl.field.Sym, t, &f, false); path == nil {
+ path, _ := dotpath(sl.field.Sym, t, &f, false)
+ if path == nil {
continue
}
// add it to the base type method list
f = f.Copy()
f.Embedded = 1 // needs a trampoline
- if sl.followptr {
- f.Embedded = 2
+ for _, d := range path {
+ if d.field.Type.IsPtr() {
+ f.Embedded = 2
+ break
+ }
}
ms = append(ms, f)
}
--- /dev/null
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// When computing method sets with shadowed methods, make sure we
+// compute whether a method promotion involved a pointer traversal
+// based on the promoted method, not the shadowed method.
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+)
+
+type mystruct struct {
+ f int
+}
+
+func (t mystruct) String() string {
+ return "FAIL"
+}
+
+func main() {
+ type deep struct {
+ mystruct
+ }
+ s := struct {
+ deep
+ *bytes.Buffer
+ }{
+ deep{},
+ bytes.NewBufferString("ok"),
+ }
+
+ if got := s.String(); got != "ok" {
+ panic(got)
+ }
+
+ var i fmt.Stringer = s
+ if got := i.String(); got != "ok" {
+ panic(got)
+ }
+}