aboutsummaryrefslogtreecommitdiff
path: root/src/internal/reflectlite/type.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/internal/reflectlite/type.go')
-rw-r--r--src/internal/reflectlite/type.go73
1 files changed, 62 insertions, 11 deletions
diff --git a/src/internal/reflectlite/type.go b/src/internal/reflectlite/type.go
index eb7f1a4b78..37cf03594f 100644
--- a/src/internal/reflectlite/type.go
+++ b/src/internal/reflectlite/type.go
@@ -234,10 +234,13 @@ type imethod struct {
// interfaceType represents an interface type.
type interfaceType struct {
rtype
- pkgPath name // import path
- methods []imethod // sorted by hash
+ pkgPath name // import path
+ expMethods []imethod // sorted by name, see runtime/type.go:interfacetype to see how it is encoded.
}
+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
@@ -384,6 +387,44 @@ const (
kindMask = (1 << 5) - 1
)
+// String returns the name of k.
+func (k Kind) String() string {
+ if int(k) < len(kindNames) {
+ return kindNames[k]
+ }
+ return kindNames[0]
+}
+
+var kindNames = []string{
+ Invalid: "invalid",
+ Bool: "bool",
+ Int: "int",
+ Int8: "int8",
+ Int16: "int16",
+ Int32: "int32",
+ Int64: "int64",
+ Uint: "uint",
+ Uint8: "uint8",
+ Uint16: "uint16",
+ Uint32: "uint32",
+ Uint64: "uint64",
+ Uintptr: "uintptr",
+ Float32: "float32",
+ Float64: "float64",
+ Complex64: "complex64",
+ Complex128: "complex128",
+ Array: "array",
+ Chan: "chan",
+ Func: "func",
+ Interface: "interface",
+ Map: "map",
+ Ptr: "ptr",
+ Slice: "slice",
+ String: "string",
+ Struct: "struct",
+ UnsafePointer: "unsafe.Pointer",
+}
+
func (t *uncommonType) methods() []method {
if t.mcount == 0 {
return nil
@@ -657,7 +698,7 @@ func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
}
// NumMethod returns the number of interface methods in the type's method set.
-func (t *interfaceType) NumMethod() int { return len(t.methods) }
+func (t *interfaceType) NumMethod() int { return len(t.expMethods) }
// TypeOf returns the reflection Type that represents the dynamic type of i.
// If i is a nil interface value, TypeOf returns nil.
@@ -694,9 +735,10 @@ func implements(T, V *rtype) bool {
return false
}
t := (*interfaceType)(unsafe.Pointer(T))
- if len(t.methods) == 0 {
+ if t.isEmpty() {
return true
}
+ tmethods := t.methods()
// The same algorithm applies in both cases, but the
// method tables for an interface type and a concrete type
@@ -713,10 +755,11 @@ func implements(T, V *rtype) bool {
if V.Kind() == Interface {
v := (*interfaceType)(unsafe.Pointer(V))
i := 0
- for j := 0; j < len(v.methods); j++ {
- tm := &t.methods[i]
+ vmethods := v.methods()
+ for j := 0; j < len(vmethods); j++ {
+ tm := &tmethods[i]
tmName := t.nameOff(tm.name)
- vm := &v.methods[j]
+ vm := &vmethods[j]
vmName := V.nameOff(vm.name)
if vmName.name() == tmName.name() && V.typeOff(vm.typ) == t.typeOff(tm.typ) {
if !tmName.isExported() {
@@ -732,7 +775,7 @@ func implements(T, V *rtype) bool {
continue
}
}
- if i++; i >= len(t.methods) {
+ if i++; i >= len(tmethods) {
return true
}
}
@@ -747,7 +790,7 @@ func implements(T, V *rtype) bool {
i := 0
vmethods := v.methods()
for j := 0; j < int(v.mcount); j++ {
- tm := &t.methods[i]
+ tm := &tmethods[i]
tmName := t.nameOff(tm.name)
vm := vmethods[j]
vmName := V.nameOff(vm.name)
@@ -765,7 +808,7 @@ func implements(T, V *rtype) bool {
continue
}
}
- if i++; i >= len(t.methods) {
+ if i++; i >= len(tmethods) {
return true
}
}
@@ -859,7 +902,7 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
case Interface:
t := (*interfaceType)(unsafe.Pointer(T))
v := (*interfaceType)(unsafe.Pointer(V))
- if len(t.methods) == 0 && len(v.methods) == 0 {
+ if t.isEmpty() && v.isEmpty() {
return true
}
// Might have the same methods but still
@@ -924,3 +967,11 @@ func toType(t *rtype) Type {
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()
+}