Skip to content

Commit 642329f

Browse files
cuonglmrsc
authored andcommitted
Revert "cmd/compile: split exported/non-exported methods for interface type"
This reverts commit 8f26b57. Reason for revert: break a bunch of code, include standard library. Fixes #42123 Change-Id: Ife90ecbafd2cb395623d1db555fbfc9c1b0098e0 Reviewed-on: https://go-review.googlesource.com/c/go/+/264026 Trust: Cuong Manh Le <[email protected]> Run-TryBot: Cuong Manh Le <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Russ Cox <[email protected]>
1 parent e3c58bb commit 642329f

File tree

11 files changed

+64
-125
lines changed

11 files changed

+64
-125
lines changed

doc/go1.16.html

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -264,15 +264,6 @@ <h3 id="net"><a href="/pkg/net/">net</a></h3>
264264
On Linux kernel version 4.1 and above, the maximum is now <code>4294967295</code>.
265265
</p>
266266

267-
<h3 id="reflect"><a href="/pkg/reflect/">reflect</a></h3>
268-
269-
<p><!-- CL 259237, golang.org/issue/22075 -->
270-
For interface types and values, <a href="/pkg/reflect/#Value.Method">Method</a>,
271-
<a href="/pkg/reflect/#Value.MethodByName">MethodByName</a>, and
272-
<a href="/pkg/reflect/#Value.NumMethod">NumMethod</a> now
273-
operate on the interface's exported method set, rather than its full method set.
274-
</p>
275-
276267
<h3 id="text/template/parse"><a href="/pkg/text/template/parse/">text/template/parse</a></h3>
277268

278269
<p><!-- CL 229398, golang.org/issue/34652 -->

src/cmd/compile/internal/gc/reflect.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,9 +1275,8 @@ func dtypesym(t *types.Type) *obj.LSym {
12751275
}
12761276
ot = dgopkgpath(lsym, ot, tpkg)
12771277

1278-
xcount := sort.Search(n, func(i int) bool { return !types.IsExported(m[i].name.Name) })
12791278
ot = dsymptr(lsym, ot, lsym, ot+3*Widthptr+uncommonSize(t))
1280-
ot = duintptr(lsym, ot, uint64(xcount))
1279+
ot = duintptr(lsym, ot, uint64(n))
12811280
ot = duintptr(lsym, ot, uint64(n))
12821281
dataAdd := imethodSize() * n
12831282
ot = dextratype(lsym, ot, t, dataAdd)

src/internal/reflectlite/type.go

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -234,13 +234,10 @@ type imethod struct {
234234
// interfaceType represents an interface type.
235235
type interfaceType struct {
236236
rtype
237-
pkgPath name // import path
238-
expMethods []imethod // sorted by name, see runtime/type.go:interfacetype to see how it is encoded.
237+
pkgPath name // import path
238+
methods []imethod // sorted by hash
239239
}
240240

241-
func (t *interfaceType) methods() []imethod { return t.expMethods[:cap(t.expMethods)] }
242-
func (t *interfaceType) isEmpty() bool { return cap(t.expMethods) == 0 }
243-
244241
// mapType represents a map type.
245242
type mapType struct {
246243
rtype
@@ -698,7 +695,7 @@ func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
698695
}
699696

700697
// NumMethod returns the number of interface methods in the type's method set.
701-
func (t *interfaceType) NumMethod() int { return len(t.expMethods) }
698+
func (t *interfaceType) NumMethod() int { return len(t.methods) }
702699

703700
// TypeOf returns the reflection Type that represents the dynamic type of i.
704701
// If i is a nil interface value, TypeOf returns nil.
@@ -735,10 +732,9 @@ func implements(T, V *rtype) bool {
735732
return false
736733
}
737734
t := (*interfaceType)(unsafe.Pointer(T))
738-
if t.isEmpty() {
735+
if len(t.methods) == 0 {
739736
return true
740737
}
741-
tmethods := t.methods()
742738

743739
// The same algorithm applies in both cases, but the
744740
// method tables for an interface type and a concrete type
@@ -755,11 +751,10 @@ func implements(T, V *rtype) bool {
755751
if V.Kind() == Interface {
756752
v := (*interfaceType)(unsafe.Pointer(V))
757753
i := 0
758-
vmethods := v.methods()
759-
for j := 0; j < len(vmethods); j++ {
760-
tm := &tmethods[i]
754+
for j := 0; j < len(v.methods); j++ {
755+
tm := &t.methods[i]
761756
tmName := t.nameOff(tm.name)
762-
vm := &vmethods[j]
757+
vm := &v.methods[j]
763758
vmName := V.nameOff(vm.name)
764759
if vmName.name() == tmName.name() && V.typeOff(vm.typ) == t.typeOff(tm.typ) {
765760
if !tmName.isExported() {
@@ -775,7 +770,7 @@ func implements(T, V *rtype) bool {
775770
continue
776771
}
777772
}
778-
if i++; i >= len(tmethods) {
773+
if i++; i >= len(t.methods) {
779774
return true
780775
}
781776
}
@@ -790,7 +785,7 @@ func implements(T, V *rtype) bool {
790785
i := 0
791786
vmethods := v.methods()
792787
for j := 0; j < int(v.mcount); j++ {
793-
tm := &tmethods[i]
788+
tm := &t.methods[i]
794789
tmName := t.nameOff(tm.name)
795790
vm := vmethods[j]
796791
vmName := V.nameOff(vm.name)
@@ -808,7 +803,7 @@ func implements(T, V *rtype) bool {
808803
continue
809804
}
810805
}
811-
if i++; i >= len(tmethods) {
806+
if i++; i >= len(t.methods) {
812807
return true
813808
}
814809
}
@@ -902,7 +897,7 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
902897
case Interface:
903898
t := (*interfaceType)(unsafe.Pointer(T))
904899
v := (*interfaceType)(unsafe.Pointer(V))
905-
if t.isEmpty() && v.isEmpty() {
900+
if len(t.methods) == 0 && len(v.methods) == 0 {
906901
return true
907902
}
908903
// Might have the same methods but still
@@ -967,11 +962,3 @@ func toType(t *rtype) Type {
967962
func ifaceIndir(t *rtype) bool {
968963
return t.kind&kindDirectIface == 0
969964
}
970-
971-
func isEmptyIface(t *rtype) bool {
972-
if t.Kind() != Interface {
973-
return false
974-
}
975-
tt := (*interfaceType)(unsafe.Pointer(t))
976-
return tt.isEmpty()
977-
}

src/internal/reflectlite/value.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ func (v Value) Elem() Value {
228228
switch k {
229229
case Interface:
230230
var eface interface{}
231-
if isEmptyIface(v.typ) {
231+
if v.typ.NumMethod() == 0 {
232232
eface = *(*interface{})(v.ptr)
233233
} else {
234234
eface = (interface{})(*(*interface {
@@ -433,7 +433,7 @@ func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value
433433
return Value{dst, nil, flag(Interface)}
434434
}
435435
x := valueInterface(v)
436-
if isEmptyIface(dst) {
436+
if dst.NumMethod() == 0 {
437437
*(*interface{})(target) = x
438438
} else {
439439
ifaceE2I(dst, x, target)

src/reflect/all_test.go

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2995,14 +2995,6 @@ func TestUnexportedMethods(t *testing.T) {
29952995
if got := typ.NumMethod(); got != 0 {
29962996
t.Errorf("NumMethod=%d, want 0 satisfied methods", got)
29972997
}
2998-
2999-
var i unexpI
3000-
if got := TypeOf(&i).Elem().NumMethod(); got != 0 {
3001-
t.Errorf("NumMethod=%d, want 0 satisfied methods", got)
3002-
}
3003-
if got := ValueOf(&i).Elem().NumMethod(); got != 0 {
3004-
t.Errorf("NumMethod=%d, want 0 satisfied methods", got)
3005-
}
30062998
}
30072999

30083000
type InnerInt struct {
@@ -3656,21 +3648,21 @@ func TestCallPanic(t *testing.T) {
36563648
v := ValueOf(T{i, i, i, i, T2{i, i}, i, i, T2{i, i}})
36573649
badCall(func() { call(v.Field(0).Method(0)) }) // .t0.W
36583650
badCall(func() { call(v.Field(0).Elem().Method(0)) }) // .t0.W
3659-
badMethod(func() { call(v.Field(0).Method(1)) }) // .t0.w
3651+
badCall(func() { call(v.Field(0).Method(1)) }) // .t0.w
36603652
badMethod(func() { call(v.Field(0).Elem().Method(2)) }) // .t0.w
36613653
ok(func() { call(v.Field(1).Method(0)) }) // .T1.Y
36623654
ok(func() { call(v.Field(1).Elem().Method(0)) }) // .T1.Y
3663-
badMethod(func() { call(v.Field(1).Method(1)) }) // .T1.y
3655+
badCall(func() { call(v.Field(1).Method(1)) }) // .T1.y
36643656
badMethod(func() { call(v.Field(1).Elem().Method(2)) }) // .T1.y
36653657

36663658
ok(func() { call(v.Field(2).Method(0)) }) // .NamedT0.W
36673659
ok(func() { call(v.Field(2).Elem().Method(0)) }) // .NamedT0.W
3668-
badMethod(func() { call(v.Field(2).Method(1)) }) // .NamedT0.w
3660+
badCall(func() { call(v.Field(2).Method(1)) }) // .NamedT0.w
36693661
badMethod(func() { call(v.Field(2).Elem().Method(2)) }) // .NamedT0.w
36703662

36713663
ok(func() { call(v.Field(3).Method(0)) }) // .NamedT1.Y
36723664
ok(func() { call(v.Field(3).Elem().Method(0)) }) // .NamedT1.Y
3673-
badMethod(func() { call(v.Field(3).Method(1)) }) // .NamedT1.y
3665+
badCall(func() { call(v.Field(3).Method(1)) }) // .NamedT1.y
36743666
badMethod(func() { call(v.Field(3).Elem().Method(3)) }) // .NamedT1.y
36753667

36763668
ok(func() { call(v.Field(4).Field(0).Method(0)) }) // .NamedT2.T1.Y
@@ -3680,7 +3672,7 @@ func TestCallPanic(t *testing.T) {
36803672

36813673
badCall(func() { call(v.Field(5).Method(0)) }) // .namedT0.W
36823674
badCall(func() { call(v.Field(5).Elem().Method(0)) }) // .namedT0.W
3683-
badMethod(func() { call(v.Field(5).Method(1)) }) // .namedT0.w
3675+
badCall(func() { call(v.Field(5).Method(1)) }) // .namedT0.w
36843676
badMethod(func() { call(v.Field(5).Elem().Method(2)) }) // .namedT0.w
36853677

36863678
badCall(func() { call(v.Field(6).Method(0)) }) // .namedT1.Y

src/reflect/type.go

Lines changed: 22 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -386,14 +386,10 @@ type imethod struct {
386386
// interfaceType represents an interface type.
387387
type interfaceType struct {
388388
rtype
389-
pkgPath name // import path
390-
expMethods []imethod // sorted by name, see runtime/type.go:interfacetype to see how it is encoded.
389+
pkgPath name // import path
390+
methods []imethod // sorted by hash
391391
}
392392

393-
// methods returns t's full method set, both exported and non-exported.
394-
func (t *interfaceType) methods() []imethod { return t.expMethods[:cap(t.expMethods)] }
395-
func (t *interfaceType) isEmpty() bool { return cap(t.expMethods) == 0 }
396-
397393
// mapType represents a map type.
398394
type mapType struct {
399395
rtype
@@ -1053,31 +1049,34 @@ func (d ChanDir) String() string {
10531049

10541050
// Method returns the i'th method in the type's method set.
10551051
func (t *interfaceType) Method(i int) (m Method) {
1056-
if i < 0 || i >= len(t.expMethods) {
1057-
panic("reflect: Method index out of range")
1052+
if i < 0 || i >= len(t.methods) {
1053+
return
10581054
}
1059-
p := &t.expMethods[i]
1055+
p := &t.methods[i]
10601056
pname := t.nameOff(p.name)
10611057
m.Name = pname.name()
10621058
if !pname.isExported() {
1063-
panic("reflect: unexported method: " + pname.name())
1059+
m.PkgPath = pname.pkgPath()
1060+
if m.PkgPath == "" {
1061+
m.PkgPath = t.pkgPath.name()
1062+
}
10641063
}
10651064
m.Type = toType(t.typeOff(p.typ))
10661065
m.Index = i
10671066
return
10681067
}
10691068

1070-
// NumMethod returns the number of exported interface methods in the type's method set.
1071-
func (t *interfaceType) NumMethod() int { return len(t.expMethods) }
1069+
// NumMethod returns the number of interface methods in the type's method set.
1070+
func (t *interfaceType) NumMethod() int { return len(t.methods) }
10721071

10731072
// MethodByName method with the given name in the type's method set.
10741073
func (t *interfaceType) MethodByName(name string) (m Method, ok bool) {
10751074
if t == nil {
10761075
return
10771076
}
10781077
var p *imethod
1079-
for i := range t.expMethods {
1080-
p = &t.expMethods[i]
1078+
for i := range t.methods {
1079+
p = &t.methods[i]
10811080
if t.nameOff(p.name).name() == name {
10821081
return t.Method(i), true
10831082
}
@@ -1486,10 +1485,9 @@ func implements(T, V *rtype) bool {
14861485
return false
14871486
}
14881487
t := (*interfaceType)(unsafe.Pointer(T))
1489-
if t.isEmpty() {
1488+
if len(t.methods) == 0 {
14901489
return true
14911490
}
1492-
tmethods := t.methods()
14931491

14941492
// The same algorithm applies in both cases, but the
14951493
// method tables for an interface type and a concrete type
@@ -1506,11 +1504,10 @@ func implements(T, V *rtype) bool {
15061504
if V.Kind() == Interface {
15071505
v := (*interfaceType)(unsafe.Pointer(V))
15081506
i := 0
1509-
vmethods := v.methods()
1510-
for j := 0; j < len(vmethods); j++ {
1511-
tm := &tmethods[i]
1507+
for j := 0; j < len(v.methods); j++ {
1508+
tm := &t.methods[i]
15121509
tmName := t.nameOff(tm.name)
1513-
vm := &vmethods[j]
1510+
vm := &v.methods[j]
15141511
vmName := V.nameOff(vm.name)
15151512
if vmName.name() == tmName.name() && V.typeOff(vm.typ) == t.typeOff(tm.typ) {
15161513
if !tmName.isExported() {
@@ -1526,7 +1523,7 @@ func implements(T, V *rtype) bool {
15261523
continue
15271524
}
15281525
}
1529-
if i++; i >= len(tmethods) {
1526+
if i++; i >= len(t.methods) {
15301527
return true
15311528
}
15321529
}
@@ -1541,7 +1538,7 @@ func implements(T, V *rtype) bool {
15411538
i := 0
15421539
vmethods := v.methods()
15431540
for j := 0; j < int(v.mcount); j++ {
1544-
tm := &tmethods[i]
1541+
tm := &t.methods[i]
15451542
tmName := t.nameOff(tm.name)
15461543
vm := vmethods[j]
15471544
vmName := V.nameOff(vm.name)
@@ -1559,7 +1556,7 @@ func implements(T, V *rtype) bool {
15591556
continue
15601557
}
15611558
}
1562-
if i++; i >= len(tmethods) {
1559+
if i++; i >= len(t.methods) {
15631560
return true
15641561
}
15651562
}
@@ -1661,7 +1658,7 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
16611658
case Interface:
16621659
t := (*interfaceType)(unsafe.Pointer(T))
16631660
v := (*interfaceType)(unsafe.Pointer(V))
1664-
if t.isEmpty() && v.isEmpty() {
1661+
if len(t.methods) == 0 && len(v.methods) == 0 {
16651662
return true
16661663
}
16671664
// Might have the same methods but still
@@ -2445,7 +2442,7 @@ func StructOf(fields []StructField) Type {
24452442
switch f.typ.Kind() {
24462443
case Interface:
24472444
ift := (*interfaceType)(unsafe.Pointer(ft))
2448-
for im, m := range ift.methods() {
2445+
for im, m := range ift.methods {
24492446
if ift.nameOff(m.name).pkgPath() != "" {
24502447
// TODO(sbinet). Issue 15924.
24512448
panic("reflect: embedded interface with unexported method(s) not implemented")
@@ -3152,11 +3149,3 @@ func addTypeBits(bv *bitVector, offset uintptr, t *rtype) {
31523149
}
31533150
}
31543151
}
3155-
3156-
func isEmptyIface(rt *rtype) bool {
3157-
if rt.Kind() != Interface {
3158-
return false
3159-
}
3160-
tt := (*interfaceType)(unsafe.Pointer(rt))
3161-
return len(tt.methods()) == 0
3162-
}

0 commit comments

Comments
 (0)