Commit 9f387962 authored by David Crawshaw's avatar David Crawshaw

reflect: remove type info for unexported methods

Also remove some of the now unnecessary corner case handling and
tests I've been adding recently for unexported method data.

For #15673

Change-Id: Ie0c7b03f2370bbe8508cdc5be765028f08000bd7
Reviewed-on: https://go-review.googlesource.com/23410Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent f2f3b6cd
......@@ -1889,32 +1889,6 @@ type Tbigp [2]uintptr
func (p *Tbigp) M(x int, b byte) (byte, int) { return b, x + int(p[0]) + int(p[1]) }
// Again, with an unexported method.
type tsmallv byte
func (v tsmallv) m(x int, b byte) (byte, int) { return b, x + int(v) }
type tsmallp byte
func (p *tsmallp) m(x int, b byte) (byte, int) { return b, x + int(*p) }
type twordv uintptr
func (v twordv) m(x int, b byte) (byte, int) { return b, x + int(v) }
type twordp uintptr
func (p *twordp) m(x int, b byte) (byte, int) { return b, x + int(*p) }
type tbigv [2]uintptr
func (v tbigv) m(x int, b byte) (byte, int) { return b, x + int(v[0]) + int(v[1]) }
type tbigp [2]uintptr
func (p *tbigp) m(x int, b byte) (byte, int) { return b, x + int(p[0]) + int(p[1]) }
type tinter interface {
m(int, byte) (byte, int)
}
......@@ -1958,7 +1932,6 @@ func TestMethod5(t *testing.T) {
}
var TinterType = TypeOf(new(Tinter)).Elem()
var tinterType = TypeOf(new(tinter)).Elem()
CheckI := func(name string, i interface{}, inc int) {
v := ValueOf(i)
......@@ -2000,39 +1973,6 @@ func TestMethod5(t *testing.T) {
CheckI("t1", t1, 40)
CheckI("&t1", &t1, 40)
methodShouldPanic := func(name string, i interface{}) {
v := ValueOf(i)
m := v.Method(0)
shouldPanic(func() { m.Call([]Value{ValueOf(1000), ValueOf(byte(99))}) })
shouldPanic(func() { m.Interface() })
v = v.Convert(tinterType)
m = v.Method(0)
shouldPanic(func() { m.Call([]Value{ValueOf(1000), ValueOf(byte(99))}) })
shouldPanic(func() { m.Interface() })
}
_sv := tsmallv(1)
methodShouldPanic("_sv", _sv)
methodShouldPanic("&_sv", &_sv)
_sp := tsmallp(2)
methodShouldPanic("&_sp", &_sp)
_wv := twordv(3)
methodShouldPanic("_wv", _wv)
methodShouldPanic("&_wv", &_wv)
_wp := twordp(4)
methodShouldPanic("&_wp", &_wp)
_bv := tbigv([2]uintptr{5, 6})
methodShouldPanic("_bv", _bv)
methodShouldPanic("&_bv", &_bv)
_bp := tbigp([2]uintptr{7, 8})
methodShouldPanic("&_bp", &_bp)
var tnil Tinter
vnil := ValueOf(&tnil).Elem()
shouldPanic(func() { vnil.Method(0) })
......@@ -2416,14 +2356,8 @@ var unexpi unexpI = new(unexp)
func TestUnexportedMethods(t *testing.T) {
typ := TypeOf(unexpi)
if got := typ.NumMethod(); got != 1 {
t.Error("NumMethod=%d, want 1 satisfied method", got)
}
if typ.Method(0).Type == nil {
t.Error("missing type for satisfied method 'f'")
}
if !typ.Method(0).Func.IsValid() {
t.Error("missing func for satisfied method 'f'")
if got := typ.NumMethod(); got != 0 {
t.Errorf("NumMethod=%d, want 0 satisfied methods", got)
}
}
......@@ -2915,12 +2849,11 @@ func TestUnexported(t *testing.T) {
isValid(v.Elem().Field(1))
isValid(v.Elem().FieldByName("x"))
isValid(v.Elem().FieldByName("y"))
isValid(v.Type().Method(0).Func)
shouldPanic(func() { v.Elem().Field(0).Interface() })
shouldPanic(func() { v.Elem().Field(1).Interface() })
shouldPanic(func() { v.Elem().FieldByName("x").Interface() })
shouldPanic(func() { v.Elem().FieldByName("y").Interface() })
shouldPanic(func() { v.Type().Method(0).Func.Interface() })
shouldPanic(func() { v.Type().Method(0) })
}
func TestSetPanic(t *testing.T) {
......@@ -5769,17 +5702,6 @@ func TestNameBytesAreAligned(t *testing.T) {
}
}
func TestMethodPkgPathReadable(t *testing.T) {
// Reading the Method type for an unexported method triggers an
// offset resolution via p.name.pkgPath(). Make sure it uses a
// valid base pointer for the offset.
v := ValueOf(embed{})
m := v.Type().Method(0)
if m.PkgPath != "reflect" {
t.Errorf(`PkgPath=%q, want "reflect"`, m.PkgPath)
}
}
func TestTypeStrings(t *testing.T) {
type stringTest struct {
typ Type
......
......@@ -768,10 +768,7 @@ var methodCache struct {
m map[*rtype][]method
}
// satisfiedMethods returns methods of t that satisfy an interface.
// This may include unexported methods that satisfy an interface
// defined with unexported methods in the same package as t.
func (t *rtype) satisfiedMethods() []method {
func (t *rtype) exportedMethods() []method {
methodCache.RLock()
methods, found := methodCache.m[t]
methodCache.RUnlock()
......@@ -785,19 +782,21 @@ func (t *rtype) satisfiedMethods() []method {
return nil
}
allm := ut.methods()
allSatisfied := true
allExported := true
for _, m := range allm {
if m.mtyp == 0 {
allSatisfied = false
name := t.nameOff(m.name)
if !name.isExported() {
allExported = false
break
}
}
if allSatisfied {
if allExported {
methods = allm
} else {
methods = make([]method, 0, len(allm))
for _, m := range allm {
if m.mtyp != 0 {
name := t.nameOff(m.name)
if name.isExported() {
methods = append(methods, m)
}
}
......@@ -819,7 +818,7 @@ func (t *rtype) NumMethod() int {
tt := (*interfaceType)(unsafe.Pointer(t))
return tt.NumMethod()
}
return len(t.satisfiedMethods())
return len(t.exportedMethods())
}
func (t *rtype) Method(i int) (m Method) {
......@@ -827,7 +826,7 @@ func (t *rtype) Method(i int) (m Method) {
tt := (*interfaceType)(unsafe.Pointer(t))
return tt.Method(i)
}
methods := t.satisfiedMethods()
methods := t.exportedMethods()
if i < 0 || i >= len(methods) {
panic("reflect: Method index out of range")
}
......@@ -835,14 +834,6 @@ func (t *rtype) Method(i int) (m Method) {
pname := t.nameOff(p.name)
m.Name = pname.name()
fl := flag(Func)
if !pname.isExported() {
m.PkgPath = pname.pkgPath()
if m.PkgPath == "" {
ut := t.uncommon()
m.PkgPath = t.nameOff(ut.pkgPath).name()
}
fl |= flagStickyRO
}
mtyp := t.typeOff(p.mtyp)
ft := (*funcType)(unsafe.Pointer(mtyp))
in := make([]Type, 0, 1+len(ft.in()))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment