Revert "cmd/compile: split exported/non-exported methods for interface type"

This reverts commit 8f26b57f9afc238bdecb9b7030bc2f4364093885.

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 <cuong.manhle.vn@gmail.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
diff --git a/doc/go1.16.html b/doc/go1.16.html
index ba2f80f..3592d0b 100644
--- a/doc/go1.16.html
+++ b/doc/go1.16.html
@@ -264,15 +264,6 @@
   On Linux kernel version 4.1 and above, the maximum is now <code>4294967295</code>.
 </p>
 
-<h3 id="reflect"><a href="/pkg/reflect/">reflect</a></h3>
-
-<p><!-- CL 259237, golang.org/issue/22075 -->
-  For interface types and values, <a href="/pkg/reflect/#Value.Method">Method</a>,
-  <a href="/pkg/reflect/#Value.MethodByName">MethodByName</a>, and
-  <a href="/pkg/reflect/#Value.NumMethod">NumMethod</a> now
-  operate on the interface's exported method set, rather than its full method set.
-</p>
-
 <h3 id="text/template/parse"><a href="/pkg/text/template/parse/">text/template/parse</a></h3>
 
 <p><!-- CL 229398, golang.org/issue/34652 -->
diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go
index 229fcfe..21429af 100644
--- a/src/cmd/compile/internal/gc/reflect.go
+++ b/src/cmd/compile/internal/gc/reflect.go
@@ -1275,9 +1275,8 @@
 		}
 		ot = dgopkgpath(lsym, ot, tpkg)
 
-		xcount := sort.Search(n, func(i int) bool { return !types.IsExported(m[i].name.Name) })
 		ot = dsymptr(lsym, ot, lsym, ot+3*Widthptr+uncommonSize(t))
-		ot = duintptr(lsym, ot, uint64(xcount))
+		ot = duintptr(lsym, ot, uint64(n))
 		ot = duintptr(lsym, ot, uint64(n))
 		dataAdd := imethodSize() * n
 		ot = dextratype(lsym, ot, t, dataAdd)
diff --git a/src/internal/reflectlite/type.go b/src/internal/reflectlite/type.go
index 37cf035..15ba30d 100644
--- a/src/internal/reflectlite/type.go
+++ b/src/internal/reflectlite/type.go
@@ -234,13 +234,10 @@
 // interfaceType represents an interface type.
 type interfaceType struct {
 	rtype
-	pkgPath    name      // import path
-	expMethods []imethod // sorted by name, see runtime/type.go:interfacetype to see how it is encoded.
+	pkgPath name      // import path
+	methods []imethod // sorted by hash
 }
 
-func (t *interfaceType) methods() []imethod { return t.expMethods[:cap(t.expMethods)] }
-func (t *interfaceType) isEmpty() bool      { return cap(t.expMethods) == 0 }
-
 // mapType represents a map type.
 type mapType struct {
 	rtype
@@ -698,7 +695,7 @@
 }
 
 // NumMethod returns the number of interface methods in the type's method set.
-func (t *interfaceType) NumMethod() int { return len(t.expMethods) }
+func (t *interfaceType) NumMethod() int { return len(t.methods) }
 
 // TypeOf returns the reflection Type that represents the dynamic type of i.
 // If i is a nil interface value, TypeOf returns nil.
@@ -735,10 +732,9 @@
 		return false
 	}
 	t := (*interfaceType)(unsafe.Pointer(T))
-	if t.isEmpty() {
+	if len(t.methods) == 0 {
 		return true
 	}
-	tmethods := t.methods()
 
 	// The same algorithm applies in both cases, but the
 	// method tables for an interface type and a concrete type
@@ -755,11 +751,10 @@
 	if V.Kind() == Interface {
 		v := (*interfaceType)(unsafe.Pointer(V))
 		i := 0
-		vmethods := v.methods()
-		for j := 0; j < len(vmethods); j++ {
-			tm := &tmethods[i]
+		for j := 0; j < len(v.methods); j++ {
+			tm := &t.methods[i]
 			tmName := t.nameOff(tm.name)
-			vm := &vmethods[j]
+			vm := &v.methods[j]
 			vmName := V.nameOff(vm.name)
 			if vmName.name() == tmName.name() && V.typeOff(vm.typ) == t.typeOff(tm.typ) {
 				if !tmName.isExported() {
@@ -775,7 +770,7 @@
 						continue
 					}
 				}
-				if i++; i >= len(tmethods) {
+				if i++; i >= len(t.methods) {
 					return true
 				}
 			}
@@ -790,7 +785,7 @@
 	i := 0
 	vmethods := v.methods()
 	for j := 0; j < int(v.mcount); j++ {
-		tm := &tmethods[i]
+		tm := &t.methods[i]
 		tmName := t.nameOff(tm.name)
 		vm := vmethods[j]
 		vmName := V.nameOff(vm.name)
@@ -808,7 +803,7 @@
 					continue
 				}
 			}
-			if i++; i >= len(tmethods) {
+			if i++; i >= len(t.methods) {
 				return true
 			}
 		}
@@ -902,7 +897,7 @@
 	case Interface:
 		t := (*interfaceType)(unsafe.Pointer(T))
 		v := (*interfaceType)(unsafe.Pointer(V))
-		if t.isEmpty() && v.isEmpty() {
+		if len(t.methods) == 0 && len(v.methods) == 0 {
 			return true
 		}
 		// Might have the same methods but still
@@ -967,11 +962,3 @@
 func ifaceIndir(t *rtype) bool {
 	return t.kind&kindDirectIface == 0
 }
-
-func isEmptyIface(t *rtype) bool {
-	if t.Kind() != Interface {
-		return false
-	}
-	tt := (*interfaceType)(unsafe.Pointer(t))
-	return tt.isEmpty()
-}
diff --git a/src/internal/reflectlite/value.go b/src/internal/reflectlite/value.go
index fb0ec77..0365eee 100644
--- a/src/internal/reflectlite/value.go
+++ b/src/internal/reflectlite/value.go
@@ -228,7 +228,7 @@
 	switch k {
 	case Interface:
 		var eface interface{}
-		if isEmptyIface(v.typ) {
+		if v.typ.NumMethod() == 0 {
 			eface = *(*interface{})(v.ptr)
 		} else {
 			eface = (interface{})(*(*interface {
@@ -433,7 +433,7 @@
 			return Value{dst, nil, flag(Interface)}
 		}
 		x := valueInterface(v)
-		if isEmptyIface(dst) {
+		if dst.NumMethod() == 0 {
 			*(*interface{})(target) = x
 		} else {
 			ifaceE2I(dst, x, target)
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index be15362..a12712d 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -2995,14 +2995,6 @@
 	if got := typ.NumMethod(); got != 0 {
 		t.Errorf("NumMethod=%d, want 0 satisfied methods", got)
 	}
-
-	var i unexpI
-	if got := TypeOf(&i).Elem().NumMethod(); got != 0 {
-		t.Errorf("NumMethod=%d, want 0 satisfied methods", got)
-	}
-	if got := ValueOf(&i).Elem().NumMethod(); got != 0 {
-		t.Errorf("NumMethod=%d, want 0 satisfied methods", got)
-	}
 }
 
 type InnerInt struct {
@@ -3656,21 +3648,21 @@
 	v := ValueOf(T{i, i, i, i, T2{i, i}, i, i, T2{i, i}})
 	badCall(func() { call(v.Field(0).Method(0)) })          // .t0.W
 	badCall(func() { call(v.Field(0).Elem().Method(0)) })   // .t0.W
-	badMethod(func() { call(v.Field(0).Method(1)) })        // .t0.w
+	badCall(func() { call(v.Field(0).Method(1)) })          // .t0.w
 	badMethod(func() { call(v.Field(0).Elem().Method(2)) }) // .t0.w
 	ok(func() { call(v.Field(1).Method(0)) })               // .T1.Y
 	ok(func() { call(v.Field(1).Elem().Method(0)) })        // .T1.Y
-	badMethod(func() { call(v.Field(1).Method(1)) })        // .T1.y
+	badCall(func() { call(v.Field(1).Method(1)) })          // .T1.y
 	badMethod(func() { call(v.Field(1).Elem().Method(2)) }) // .T1.y
 
 	ok(func() { call(v.Field(2).Method(0)) })               // .NamedT0.W
 	ok(func() { call(v.Field(2).Elem().Method(0)) })        // .NamedT0.W
-	badMethod(func() { call(v.Field(2).Method(1)) })        // .NamedT0.w
+	badCall(func() { call(v.Field(2).Method(1)) })          // .NamedT0.w
 	badMethod(func() { call(v.Field(2).Elem().Method(2)) }) // .NamedT0.w
 
 	ok(func() { call(v.Field(3).Method(0)) })               // .NamedT1.Y
 	ok(func() { call(v.Field(3).Elem().Method(0)) })        // .NamedT1.Y
-	badMethod(func() { call(v.Field(3).Method(1)) })        // .NamedT1.y
+	badCall(func() { call(v.Field(3).Method(1)) })          // .NamedT1.y
 	badMethod(func() { call(v.Field(3).Elem().Method(3)) }) // .NamedT1.y
 
 	ok(func() { call(v.Field(4).Field(0).Method(0)) })             // .NamedT2.T1.Y
@@ -3680,7 +3672,7 @@
 
 	badCall(func() { call(v.Field(5).Method(0)) })          // .namedT0.W
 	badCall(func() { call(v.Field(5).Elem().Method(0)) })   // .namedT0.W
-	badMethod(func() { call(v.Field(5).Method(1)) })        // .namedT0.w
+	badCall(func() { call(v.Field(5).Method(1)) })          // .namedT0.w
 	badMethod(func() { call(v.Field(5).Elem().Method(2)) }) // .namedT0.w
 
 	badCall(func() { call(v.Field(6).Method(0)) })        // .namedT1.Y
diff --git a/src/reflect/type.go b/src/reflect/type.go
index 0b34ca0..a3a6167 100644
--- a/src/reflect/type.go
+++ b/src/reflect/type.go
@@ -386,14 +386,10 @@
 // interfaceType represents an interface type.
 type interfaceType struct {
 	rtype
-	pkgPath    name      // import path
-	expMethods []imethod // sorted by name, see runtime/type.go:interfacetype to see how it is encoded.
+	pkgPath name      // import path
+	methods []imethod // sorted by hash
 }
 
-// methods returns t's full method set, both exported and non-exported.
-func (t *interfaceType) methods() []imethod { return t.expMethods[:cap(t.expMethods)] }
-func (t *interfaceType) isEmpty() bool      { return cap(t.expMethods) == 0 }
-
 // mapType represents a map type.
 type mapType struct {
 	rtype
@@ -1053,22 +1049,25 @@
 
 // Method returns the i'th method in the type's method set.
 func (t *interfaceType) Method(i int) (m Method) {
-	if i < 0 || i >= len(t.expMethods) {
-		panic("reflect: Method index out of range")
+	if i < 0 || i >= len(t.methods) {
+		return
 	}
-	p := &t.expMethods[i]
+	p := &t.methods[i]
 	pname := t.nameOff(p.name)
 	m.Name = pname.name()
 	if !pname.isExported() {
-		panic("reflect: unexported method: " + pname.name())
+		m.PkgPath = pname.pkgPath()
+		if m.PkgPath == "" {
+			m.PkgPath = t.pkgPath.name()
+		}
 	}
 	m.Type = toType(t.typeOff(p.typ))
 	m.Index = i
 	return
 }
 
-// NumMethod returns the number of exported interface methods in the type's method set.
-func (t *interfaceType) NumMethod() int { return len(t.expMethods) }
+// NumMethod returns the number of interface methods in the type's method set.
+func (t *interfaceType) NumMethod() int { return len(t.methods) }
 
 // MethodByName method with the given name in the type's method set.
 func (t *interfaceType) MethodByName(name string) (m Method, ok bool) {
@@ -1076,8 +1075,8 @@
 		return
 	}
 	var p *imethod
-	for i := range t.expMethods {
-		p = &t.expMethods[i]
+	for i := range t.methods {
+		p = &t.methods[i]
 		if t.nameOff(p.name).name() == name {
 			return t.Method(i), true
 		}
@@ -1486,10 +1485,9 @@
 		return false
 	}
 	t := (*interfaceType)(unsafe.Pointer(T))
-	if t.isEmpty() {
+	if len(t.methods) == 0 {
 		return true
 	}
-	tmethods := t.methods()
 
 	// The same algorithm applies in both cases, but the
 	// method tables for an interface type and a concrete type
@@ -1506,11 +1504,10 @@
 	if V.Kind() == Interface {
 		v := (*interfaceType)(unsafe.Pointer(V))
 		i := 0
-		vmethods := v.methods()
-		for j := 0; j < len(vmethods); j++ {
-			tm := &tmethods[i]
+		for j := 0; j < len(v.methods); j++ {
+			tm := &t.methods[i]
 			tmName := t.nameOff(tm.name)
-			vm := &vmethods[j]
+			vm := &v.methods[j]
 			vmName := V.nameOff(vm.name)
 			if vmName.name() == tmName.name() && V.typeOff(vm.typ) == t.typeOff(tm.typ) {
 				if !tmName.isExported() {
@@ -1526,7 +1523,7 @@
 						continue
 					}
 				}
-				if i++; i >= len(tmethods) {
+				if i++; i >= len(t.methods) {
 					return true
 				}
 			}
@@ -1541,7 +1538,7 @@
 	i := 0
 	vmethods := v.methods()
 	for j := 0; j < int(v.mcount); j++ {
-		tm := &tmethods[i]
+		tm := &t.methods[i]
 		tmName := t.nameOff(tm.name)
 		vm := vmethods[j]
 		vmName := V.nameOff(vm.name)
@@ -1559,7 +1556,7 @@
 					continue
 				}
 			}
-			if i++; i >= len(tmethods) {
+			if i++; i >= len(t.methods) {
 				return true
 			}
 		}
@@ -1661,7 +1658,7 @@
 	case Interface:
 		t := (*interfaceType)(unsafe.Pointer(T))
 		v := (*interfaceType)(unsafe.Pointer(V))
-		if t.isEmpty() && v.isEmpty() {
+		if len(t.methods) == 0 && len(v.methods) == 0 {
 			return true
 		}
 		// Might have the same methods but still
@@ -2445,7 +2442,7 @@
 			switch f.typ.Kind() {
 			case Interface:
 				ift := (*interfaceType)(unsafe.Pointer(ft))
-				for im, m := range ift.methods() {
+				for im, m := range ift.methods {
 					if ift.nameOff(m.name).pkgPath() != "" {
 						// TODO(sbinet).  Issue 15924.
 						panic("reflect: embedded interface with unexported method(s) not implemented")
@@ -3152,11 +3149,3 @@
 		}
 	}
 }
-
-func isEmptyIface(rt *rtype) bool {
-	if rt.Kind() != Interface {
-		return false
-	}
-	tt := (*interfaceType)(unsafe.Pointer(rt))
-	return len(tt.methods()) == 0
-}
diff --git a/src/reflect/value.go b/src/reflect/value.go
index 24eab6a..bf926a7 100644
--- a/src/reflect/value.go
+++ b/src/reflect/value.go
@@ -636,11 +636,10 @@
 	i := methodIndex
 	if v.typ.Kind() == Interface {
 		tt := (*interfaceType)(unsafe.Pointer(v.typ))
-		ttmethods := tt.methods()
-		if uint(i) >= uint(len(ttmethods)) {
+		if uint(i) >= uint(len(tt.methods)) {
 			panic("reflect: internal error: invalid method index")
 		}
-		m := &ttmethods[i]
+		m := &tt.methods[i]
 		if !tt.nameOff(m.name).isExported() {
 			panic("reflect: " + op + " of unexported method")
 		}
@@ -814,7 +813,7 @@
 	switch k {
 	case Interface:
 		var eface interface{}
-		if isEmptyIface(v.typ) {
+		if v.typ.NumMethod() == 0 {
 			eface = *(*interface{})(v.ptr)
 		} else {
 			eface = (interface{})(*(*interface {
@@ -1035,7 +1034,7 @@
 		// Special case: return the element inside the interface.
 		// Empty interface has one layout, all interfaces with
 		// methods have a second layout.
-		if isEmptyIface(v.typ) {
+		if v.NumMethod() == 0 {
 			return *(*interface{})(v.ptr)
 		}
 		return *(*interface {
@@ -1919,11 +1918,10 @@
 	if v.typ.Kind() == Interface {
 		// Method on interface.
 		tt := (*interfaceType)(unsafe.Pointer(v.typ))
-		ttmethods := tt.methods()
-		if uint(i) >= uint(len(ttmethods)) {
+		if uint(i) >= uint(len(tt.methods)) {
 			panic("reflect: internal error: invalid method index")
 		}
-		m := &ttmethods[i]
+		m := &tt.methods[i]
 		return v.typ.typeOff(m.typ)
 	}
 	// Method on concrete type.
@@ -2441,7 +2439,7 @@
 			return Value{dst, nil, flag(Interface)}
 		}
 		x := valueInterface(v, false)
-		if isEmptyIface(dst) {
+		if dst.NumMethod() == 0 {
 			*(*interface{})(target) = x
 		} else {
 			ifaceE2I(dst, x, target)
@@ -2730,11 +2728,10 @@
 func cvtT2I(v Value, typ Type) Value {
 	target := unsafe_New(typ.common())
 	x := valueInterface(v, false)
-	rt := typ.(*rtype)
-	if isEmptyIface(rt) {
+	if typ.NumMethod() == 0 {
 		*(*interface{})(target) = x
 	} else {
-		ifaceE2I(rt, x, target)
+		ifaceE2I(typ.(*rtype), x, target)
 	}
 	return Value{typ.common(), target, v.flag.ro() | flagIndir | flag(Interface)}
 }
diff --git a/src/runtime/alg.go b/src/runtime/alg.go
index 2ec3fc3..1b3bf11 100644
--- a/src/runtime/alg.go
+++ b/src/runtime/alg.go
@@ -166,7 +166,7 @@
 		return strhash(p, h)
 	case kindInterface:
 		i := (*interfacetype)(unsafe.Pointer(t))
-		if i.isEmpty() {
+		if len(i.mhdr) == 0 {
 			return nilinterhash(p, h)
 		}
 		return interhash(p, h)
diff --git a/src/runtime/iface.go b/src/runtime/iface.go
index f8b7d42..0504b89 100644
--- a/src/runtime/iface.go
+++ b/src/runtime/iface.go
@@ -31,17 +31,16 @@
 }
 
 func getitab(inter *interfacetype, typ *_type, canfail bool) *itab {
-	if inter.isEmpty() {
+	if len(inter.mhdr) == 0 {
 		throw("internal error - misuse of itab")
 	}
-	imethods := inter.methods()
 
 	// easy case
 	if typ.tflag&tflagUncommon == 0 {
 		if canfail {
 			return nil
 		}
-		name := inter.typ.nameOff(imethods[0].name)
+		name := inter.typ.nameOff(inter.mhdr[0].name)
 		panic(&TypeAssertionError{nil, typ, &inter.typ, name.name()})
 	}
 
@@ -64,7 +63,7 @@
 	}
 
 	// Entry doesn't exist yet. Make a new entry & add it.
-	m = (*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(imethods)-1)*sys.PtrSize, 0, &memstats.other_sys))
+	m = (*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(inter.mhdr)-1)*sys.PtrSize, 0, &memstats.other_sys))
 	m.inter = inter
 	m._type = typ
 	// The hash is used in type switches. However, compiler statically generates itab's
@@ -198,8 +197,7 @@
 	// and interface names are unique,
 	// so can iterate over both in lock step;
 	// the loop is O(ni+nt) not O(ni*nt).
-	imethods := inter.methods()
-	ni := len(imethods)
+	ni := len(inter.mhdr)
 	nt := int(x.mcount)
 	xmhdr := (*[1 << 16]method)(add(unsafe.Pointer(x), uintptr(x.moff)))[:nt:nt]
 	j := 0
@@ -207,7 +205,7 @@
 	var fun0 unsafe.Pointer
 imethods:
 	for k := 0; k < ni; k++ {
-		i := &imethods[k]
+		i := &inter.mhdr[k]
 		itype := inter.typ.typeOff(i.ityp)
 		name := inter.typ.nameOff(i.name)
 		iname := name.name()
diff --git a/src/runtime/mfinal.go b/src/runtime/mfinal.go
index 6ec5133..f4dbd77 100644
--- a/src/runtime/mfinal.go
+++ b/src/runtime/mfinal.go
@@ -210,7 +210,7 @@
 					// set up with empty interface
 					(*eface)(frame)._type = &f.ot.typ
 					(*eface)(frame).data = f.arg
-					if !ityp.isEmpty() {
+					if len(ityp.mhdr) != 0 {
 						// convert to interface with methods
 						// this conversion is guaranteed to succeed - we checked in SetFinalizer
 						*(*iface)(frame) = assertE2I(ityp, *(*eface)(frame))
@@ -394,7 +394,7 @@
 		}
 	case fint.kind&kindMask == kindInterface:
 		ityp := (*interfacetype)(unsafe.Pointer(fint))
-		if ityp.isEmpty() {
+		if len(ityp.mhdr) == 0 {
 			// ok - satisfies empty interface
 			goto okarg
 		}
diff --git a/src/runtime/type.go b/src/runtime/type.go
index 3649261..81455f3 100644
--- a/src/runtime/type.go
+++ b/src/runtime/type.go
@@ -366,19 +366,7 @@
 type interfacetype struct {
 	typ     _type
 	pkgpath name
-	// expMethods contains all interface methods.
-	//
-	// - len(expMethods) returns number of exported methods.
-	// - cap(expMethods) returns all interface methods, including both exported/non-exported methods.
-	expMethods []imethod
-}
-
-func (it *interfacetype) methods() []imethod {
-	return it.expMethods[:cap(it.expMethods)]
-}
-
-func (it *interfacetype) isEmpty() bool {
-	return cap(it.expMethods) == 0
+	mhdr    []imethod
 }
 
 type maptype struct {
@@ -676,15 +664,13 @@
 		if it.pkgpath.name() != iv.pkgpath.name() {
 			return false
 		}
-		itmethods := it.methods()
-		ivmethods := iv.methods()
-		if len(itmethods) != len(ivmethods) {
+		if len(it.mhdr) != len(iv.mhdr) {
 			return false
 		}
-		for i := range itmethods {
-			tm := &itmethods[i]
-			vm := &ivmethods[i]
-			// Note the expMethods array can be relocated from
+		for i := range it.mhdr {
+			tm := &it.mhdr[i]
+			vm := &iv.mhdr[i]
+			// Note the mhdr array can be relocated from
 			// another module. See #17724.
 			tname := resolveNameOff(unsafe.Pointer(tm), tm.name)
 			vname := resolveNameOff(unsafe.Pointer(vm), vm.name)