@@ -146,6 +146,20 @@ func (t Type) Kind() Kind {
146146 }
147147}
148148
149+ // isBasic returns true if (and only if) this is a basic type.
150+ func (t Type ) isBasic () bool {
151+ return t % 2 == 0
152+ }
153+
154+ // isNamed returns true if (and only if) this is a named type.
155+ func (t Type ) isNamed () bool {
156+ if t .isBasic () {
157+ return t >> 6 != 0
158+ } else {
159+ return (t >> 4 )% 2 != 0
160+ }
161+ }
162+
149163// Elem returns the element type for channel, slice and array types, the
150164// pointed-to value for pointer types, and the key type for map types.
151165func (t Type ) Elem () Type {
@@ -170,7 +184,7 @@ func (t Type) Elem() Type {
170184func (t Type ) stripPrefix () Type {
171185 // Look at the 'n' bit in the type code (see the top of this file) to see
172186 // whether this is a named type.
173- if ( t >> 4 ) % 2 != 0 {
187+ if t . isNamed () {
174188 // This is a named type. The data is stored in a sidetable.
175189 namedTypeNum := t >> 5
176190 n := * (* uintptr )(unsafe .Pointer (uintptr (unsafe .Pointer (& namedNonBasicTypesSidetable )) + uintptr (namedTypeNum )* unsafe .Sizeof (uintptr (0 ))))
@@ -188,7 +202,11 @@ func (t Type) Field(i int) StructField {
188202 }
189203 structIdentifier := t .stripPrefix ()
190204
191- numField , p := readVarint (unsafe .Pointer (uintptr (unsafe .Pointer (& structTypesSidetable )) + uintptr (structIdentifier )))
205+ // Skip past the NumMethod field.
206+ _ , p := readVarint (unsafe .Pointer (uintptr (unsafe .Pointer (& structTypesSidetable )) + uintptr (structIdentifier )))
207+
208+ // Read the NumField field.
209+ numField , p := readVarint (p )
192210 if uint (i ) >= uint (numField ) {
193211 panic ("reflect: field index out of range" )
194212 }
@@ -287,7 +305,10 @@ func (t Type) NumField() int {
287305 panic (& TypeError {"NumField" })
288306 }
289307 structIdentifier := t .stripPrefix ()
290- n , _ := readVarint (unsafe .Pointer (uintptr (unsafe .Pointer (& structTypesSidetable )) + uintptr (structIdentifier )))
308+ // Skip past the NumMethod field.
309+ _ , p := readVarint (unsafe .Pointer (uintptr (unsafe .Pointer (& structTypesSidetable )) + uintptr (structIdentifier )))
310+ // Read the NumField field.
311+ n , _ := readVarint (p )
291312 return int (n )
292313}
293314
@@ -405,10 +426,23 @@ func (t Type) AssignableTo(u Type) bool {
405426}
406427
407428func (t Type ) Implements (u Type ) bool {
408- if t .Kind () != Interface {
429+ if u .Kind () != Interface {
409430 panic ("reflect: non-interface type passed to Type.Implements" )
410431 }
411- return u .AssignableTo (t )
432+ if u .NumMethod () == 0 {
433+ // Empty interface (not even unexported methods, see NumNethod
434+ // implementation comments), therefore implements any type.
435+ return true
436+ }
437+ // Type u has (possibly unexported) methods.
438+ if t .Kind () == Interface && t .NumMethod () == 0 {
439+ // Type t has no methods (not even unexported methods since it is an
440+ // interface), while u has. Therefore, t cannot implement u.
441+ return false
442+ }
443+ // Now we'd have to compare individual methods.
444+ // This has not yet been implemented.
445+ panic ("unimplemented: (reflect.Type).Implements()" )
412446}
413447
414448// Comparable returns whether values of this type can be compared to each other.
@@ -454,7 +488,36 @@ func (t Type) ConvertibleTo(u Type) bool {
454488}
455489
456490func (t Type ) NumMethod () int {
457- panic ("unimplemented: (reflect.Type).NumMethod()" )
491+ if t .isBasic () {
492+ if ! t .isNamed () {
493+ // Not a named type, so can't have methods.
494+ return 0
495+ }
496+ // Named type methods are stored in a sidetable.
497+ namedTypeNum := t >> 6
498+ return int (* (* byte )(unsafe .Pointer (uintptr (unsafe .Pointer (& namedBasicNumMethodSidetable )) + uintptr (namedTypeNum ) - 1 )))
499+ } else {
500+ if ! t .isNamed () {
501+ // Most non-named types cannot have methods. However, structs can
502+ // because they can embed named values.
503+ switch t .Kind () {
504+ case Struct :
505+ structIdentifier := t .stripPrefix ()
506+ numMethod , _ := readVarint (unsafe .Pointer (uintptr (unsafe .Pointer (& structTypesSidetable )) + uintptr (structIdentifier )))
507+ return int (numMethod )
508+ case Interface :
509+ interfaceIdentifier := t .stripPrefix ()
510+ numMethod , _ := readVarint (unsafe .Pointer (uintptr (unsafe .Pointer (& interfaceTypesSidetable )) + uintptr (interfaceIdentifier )))
511+ return int (numMethod )
512+ default :
513+ // This type cannot have methods.
514+ return 0
515+ }
516+ }
517+ // Named non-basic type, so read the number of methods from a sidetable.
518+ namedTypeNum := t >> 5
519+ return int (* (* byte )(unsafe .Pointer (uintptr (unsafe .Pointer (& namedNonBasicNumMethodSidetable )) + uintptr (namedTypeNum ))))
520+ }
458521}
459522
460523func (t Type ) Name () string {
0 commit comments