From: David Crawshaw Date: Tue, 24 May 2016 23:04:51 +0000 (-0400) Subject: reflect: remove type info for unexported methods X-Git-Tag: go1.7beta1~102 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=9f38796270a017de8d9e1f102b28576826e6a188;p=gostls13.git 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/23410 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index f09ffeb566..c801bfc1ec 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -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 diff --git a/src/reflect/type.go b/src/reflect/type.go index c9389199d8..1dff74df62 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -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()))