]> Cypherpunks repositories - gostls13.git/commitdiff
internal/reflectlite, runtime: move more constants and types into internal/abi
authorDavid Chase <drchase@google.com>
Fri, 14 Apr 2023 18:09:12 +0000 (14:09 -0400)
committerDavid Chase <drchase@google.com>
Wed, 10 May 2023 22:43:30 +0000 (22:43 +0000)
Change-Id: If5da1057ead34eb3e4c7f42bbe6ad3d350b97725
Reviewed-on: https://go-review.googlesource.com/c/go/+/484856
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/internal/reflectlite/all_test.go
src/internal/reflectlite/reflect_mirror_test.go
src/internal/reflectlite/type.go
src/internal/reflectlite/value.go
src/runtime/alg.go
src/runtime/cgocall.go
src/runtime/cgocheck.go
src/runtime/syscall_windows.go
src/runtime/type.go

index bb3cad470c2f28932b448e720fc0ff54a8f5bdce..820b4aeaf80d296877c54a52a8999a226f96c94a 100644 (file)
@@ -7,6 +7,7 @@ package reflectlite_test
 import (
        "encoding/base64"
        "fmt"
+       "internal/abi"
        . "internal/reflectlite"
        "math"
        "reflect"
@@ -240,37 +241,37 @@ func TestSetValue(t *testing.T) {
        for i, tt := range valueTests {
                v := ValueOf(tt.i).Elem()
                switch v.Kind() {
-               case Int:
+               case abi.Int:
                        v.Set(ValueOf(int(132)))
-               case Int8:
+               case abi.Int8:
                        v.Set(ValueOf(int8(8)))
-               case Int16:
+               case abi.Int16:
                        v.Set(ValueOf(int16(16)))
-               case Int32:
+               case abi.Int32:
                        v.Set(ValueOf(int32(32)))
-               case Int64:
+               case abi.Int64:
                        v.Set(ValueOf(int64(64)))
-               case Uint:
+               case abi.Uint:
                        v.Set(ValueOf(uint(132)))
-               case Uint8:
+               case abi.Uint8:
                        v.Set(ValueOf(uint8(8)))
-               case Uint16:
+               case abi.Uint16:
                        v.Set(ValueOf(uint16(16)))
-               case Uint32:
+               case abi.Uint32:
                        v.Set(ValueOf(uint32(32)))
-               case Uint64:
+               case abi.Uint64:
                        v.Set(ValueOf(uint64(64)))
-               case Float32:
+               case abi.Float32:
                        v.Set(ValueOf(float32(256.25)))
-               case Float64:
+               case abi.Float64:
                        v.Set(ValueOf(512.125))
-               case Complex64:
+               case abi.Complex64:
                        v.Set(ValueOf(complex64(532.125 + 10i)))
-               case Complex128:
+               case abi.Complex128:
                        v.Set(ValueOf(complex128(564.25 + 1i)))
-               case String:
+               case abi.String:
                        v.Set(ValueOf("stringy cheese"))
-               case Bool:
+               case abi.Bool:
                        v.Set(ValueOf(true))
                }
                s := valueToString(v)
@@ -946,7 +947,7 @@ func TestInvalid(t *testing.T) {
                t.Errorf("field: IsValid=%v, Kind=%v, want true, Interface", v.IsValid(), v.Kind())
        }
        v = v.Elem()
-       if v.IsValid() != false || v.Kind() != Invalid {
+       if v.IsValid() != false || v.Kind() != abi.Invalid {
                t.Errorf("field elem: IsValid=%v, Kind=%v, want false, Invalid", v.IsValid(), v.Kind())
        }
 }
index 9b28b13550e0c779c284a80fcec9e8d89f3f32a8..dd13ab782a94702bc15ab7d79b3f340c13a09ac5 100644 (file)
@@ -19,7 +19,6 @@ import (
 )
 
 var typeNames = []string{
-       "rtype",
        "uncommonType",
        "arrayType",
        "chanType",
@@ -115,7 +114,7 @@ func TestMirrorWithReflect(t *testing.T) {
        wg.Wait()
 
        if len(rl.m) != len(r.m) {
-               t.Fatalf("number of types mismatch, reflect: %d, reflectlite: %d", len(r.m), len(rl.m))
+               t.Fatalf("number of types mismatch, reflect: %d, reflectlite: %d (%+v, %+v)", len(r.m), len(rl.m), r.m, rl.m)
        }
 
        for typName := range r.m {
index 5796b8f16819b137112b63572000e6bce860bb23..d562cbe8743f3e3015b0b895ac107d3d97de1acb 100644 (file)
@@ -75,45 +75,25 @@ type Type interface {
 
 // A Kind represents the specific kind of type that a Type represents.
 // The zero Kind is not a valid kind.
-type Kind uint
+type Kind = abi.Kind
+
+const Ptr = abi.Pointer
 
 const (
-       Invalid Kind = iota
-       Bool
-       Int
-       Int8
-       Int16
-       Int32
-       Int64
-       Uint
-       Uint8
-       Uint16
-       Uint32
-       Uint64
-       Uintptr
-       Float32
-       Float64
-       Complex64
-       Complex128
-       Array
-       Chan
-       Func
-       Interface
-       Map
-       Pointer
-       Slice
-       String
-       Struct
-       UnsafePointer
+       // Import-and-export these constants as necessary
+       Interface = abi.Interface
+       Slice     = abi.Slice
+       String    = abi.String
+       Struct    = abi.Struct
 )
 
-const Ptr = Pointer
-
 type nameOff = abi.NameOff
 type typeOff = abi.TypeOff
 type textOff = abi.TextOff
 
-type rtype abi.Type
+type rtype struct {
+       abi.Type
+}
 
 // uncommonType is present only for defined types or types with methods
 // (if T is a defined type, the uncommonTypes for T and *T have methods).
@@ -304,50 +284,6 @@ func (n name) pkgPath() string {
  * The compiler does not know about the data structures and methods below.
  */
 
-const (
-       kindDirectIface = 1 << 5
-       kindGCProg      = 1 << 6 // Type.gc points to GC program
-       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",
-}
-
 // resolveNameOff resolves a name offset from a base pointer.
 // The (*rtype).nameOff method is a convenience wrapper for this function.
 // Implemented in the runtime package.
@@ -367,61 +303,7 @@ func (t *rtype) typeOff(off typeOff) *rtype {
 }
 
 func (t *rtype) uncommon() *uncommonType {
-       if t.TFlag&abi.TFlagUncommon == 0 {
-               return nil
-       }
-       switch t.Kind() {
-       case Struct:
-               return &(*structTypeUncommon)(unsafe.Pointer(t)).u
-       case Ptr:
-               type u struct {
-                       ptrType
-                       u uncommonType
-               }
-               return &(*u)(unsafe.Pointer(t)).u
-       case Func:
-               type u struct {
-                       funcType
-                       u uncommonType
-               }
-               return &(*u)(unsafe.Pointer(t)).u
-       case Slice:
-               type u struct {
-                       sliceType
-                       u uncommonType
-               }
-               return &(*u)(unsafe.Pointer(t)).u
-       case Array:
-               type u struct {
-                       arrayType
-                       u uncommonType
-               }
-               return &(*u)(unsafe.Pointer(t)).u
-       case Chan:
-               type u struct {
-                       chanType
-                       u uncommonType
-               }
-               return &(*u)(unsafe.Pointer(t)).u
-       case Map:
-               type u struct {
-                       mapType
-                       u uncommonType
-               }
-               return &(*u)(unsafe.Pointer(t)).u
-       case Interface:
-               type u struct {
-                       interfaceType
-                       u uncommonType
-               }
-               return &(*u)(unsafe.Pointer(t)).u
-       default:
-               type u struct {
-                       rtype
-                       u uncommonType
-               }
-               return &(*u)(unsafe.Pointer(t)).u
-       }
+       return t.Uncommon()
 }
 
 func (t *rtype) String() string {
@@ -432,10 +314,6 @@ func (t *rtype) String() string {
        return s
 }
 
-func (t *rtype) Size() uintptr { return t.Size_ }
-
-func (t *rtype) Kind() Kind { return Kind(t.Kind_ & kindMask) }
-
 func (t *rtype) pointers() bool { return t.PtrBytes != 0 }
 
 func (t *rtype) common() *rtype { return t }
@@ -491,28 +369,32 @@ func (t *rtype) Name() string {
 }
 
 func (t *rtype) chanDir() chanDir {
-       if t.Kind() != Chan {
+       if t.Kind() != abi.Chan {
                panic("reflect: chanDir of non-chan type")
        }
        tt := (*chanType)(unsafe.Pointer(t))
        return chanDir(tt.dir)
 }
 
+func toRType(t *abi.Type) *rtype {
+       return (*rtype)(unsafe.Pointer(t))
+}
+
 func (t *rtype) Elem() Type {
        switch t.Kind() {
-       case Array:
+       case abi.Array:
                tt := (*arrayType)(unsafe.Pointer(t))
-               return toType((*rtype)(tt.Elem))
-       case Chan:
+               return toType(toRType(tt.Elem))
+       case abi.Chan:
                tt := (*chanType)(unsafe.Pointer(t))
                return toType(tt.elem)
-       case Map:
+       case abi.Map:
                tt := (*mapType)(unsafe.Pointer(t))
                return toType(tt.elem)
-       case Ptr:
+       case abi.Pointer:
                tt := (*ptrType)(unsafe.Pointer(t))
                return toType(tt.elem)
-       case Slice:
+       case abi.Slice:
                tt := (*sliceType)(unsafe.Pointer(t))
                return toType(tt.elem)
        }
@@ -520,7 +402,7 @@ func (t *rtype) Elem() Type {
 }
 
 func (t *rtype) In(i int) Type {
-       if t.Kind() != Func {
+       if t.Kind() != abi.Func {
                panic("reflect: In of non-func type")
        }
        tt := (*funcType)(unsafe.Pointer(t))
@@ -528,7 +410,7 @@ func (t *rtype) In(i int) Type {
 }
 
 func (t *rtype) Key() Type {
-       if t.Kind() != Map {
+       if t.Kind() != abi.Map {
                panic("reflect: Key of non-map type")
        }
        tt := (*mapType)(unsafe.Pointer(t))
@@ -536,7 +418,7 @@ func (t *rtype) Key() Type {
 }
 
 func (t *rtype) Len() int {
-       if t.Kind() != Array {
+       if t.Kind() != abi.Array {
                panic("reflect: Len of non-array type")
        }
        tt := (*arrayType)(unsafe.Pointer(t))
@@ -544,7 +426,7 @@ func (t *rtype) Len() int {
 }
 
 func (t *rtype) NumField() int {
-       if t.Kind() != Struct {
+       if t.Kind() != abi.Struct {
                panic("reflect: NumField of non-struct type")
        }
        tt := (*structType)(unsafe.Pointer(t))
@@ -552,7 +434,7 @@ func (t *rtype) NumField() int {
 }
 
 func (t *rtype) NumIn() int {
-       if t.Kind() != Func {
+       if t.Kind() != abi.Func {
                panic("reflect: NumIn of non-func type")
        }
        tt := (*funcType)(unsafe.Pointer(t))
@@ -560,7 +442,7 @@ func (t *rtype) NumIn() int {
 }
 
 func (t *rtype) NumOut() int {
-       if t.Kind() != Func {
+       if t.Kind() != abi.Func {
                panic("reflect: NumOut of non-func type")
        }
        tt := (*funcType)(unsafe.Pointer(t))
@@ -568,7 +450,7 @@ func (t *rtype) NumOut() int {
 }
 
 func (t *rtype) Out(i int) Type {
-       if t.Kind() != Func {
+       if t.Kind() != abi.Func {
                panic("reflect: Out of non-func type")
        }
        tt := (*funcType)(unsafe.Pointer(t))
@@ -771,16 +653,16 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
 
        // Non-composite types of equal kind have same underlying type
        // (the predefined instance of the type).
-       if Bool <= kind && kind <= Complex128 || kind == String || kind == UnsafePointer {
+       if abi.Bool <= kind && kind <= abi.Complex128 || kind == abi.String || kind == abi.UnsafePointer {
                return true
        }
 
        // Composite types.
        switch kind {
-       case Array:
+       case abi.Array:
                return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
 
-       case Chan:
+       case abi.Chan:
                // Special case:
                // x is a bidirectional channel value, T is a channel type,
                // and x's type V and T have identical element types.
@@ -791,7 +673,7 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
                // Otherwise continue test for identical underlying type.
                return V.chanDir() == T.chanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
 
-       case Func:
+       case abi.Func:
                t := (*funcType)(unsafe.Pointer(T))
                v := (*funcType)(unsafe.Pointer(V))
                if t.outCount != v.outCount || t.inCount != v.inCount {
@@ -819,13 +701,13 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
                // need a run time conversion.
                return false
 
-       case Map:
+       case abi.Map:
                return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
 
-       case Ptr, Slice:
+       case Ptr, abi.Slice:
                return haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
 
-       case Struct:
+       case abi.Struct:
                t := (*structType)(unsafe.Pointer(T))
                v := (*structType)(unsafe.Pointer(V))
                if len(t.fields) != len(v.fields) {
@@ -878,5 +760,5 @@ func toType(t *rtype) Type {
 
 // ifaceIndir reports whether t is stored indirectly in an interface value.
 func ifaceIndir(t *rtype) bool {
-       return t.Kind_&kindDirectIface == 0
+       return t.Kind_&abi.KindDirectIface == 0
 }
index c5b9596617c330367576565476aadffcdb6b3908..c14ed7c102d7392a7a3a5ef579841f2a6313ce76 100644 (file)
@@ -5,6 +5,7 @@
 package reflectlite
 
 import (
+       "internal/abi"
        "internal/goarch"
        "internal/unsafeheader"
        "runtime"
@@ -89,7 +90,7 @@ func (f flag) ro() flag {
 // pointer returns the underlying pointer represented by v.
 // v.Kind() must be Pointer, Map, Chan, Func, or UnsafePointer
 func (v Value) pointer() unsafe.Pointer {
-       if v.typ.Size_ != goarch.PtrSize || !v.typ.pointers() {
+       if v.typ.Size() != goarch.PtrSize || !v.typ.pointers() {
                panic("can't call pointer on a non-pointer Value")
        }
        if v.flag&flagIndir != 0 {
@@ -198,7 +199,7 @@ func (f flag) mustBeExported() {
 // or it is not addressable.
 func (f flag) mustBeAssignable() {
        if f == 0 {
-               panic(&ValueError{methodName(), Invalid})
+               panic(&ValueError{methodName(), abi.Invalid})
        }
        // Assignable if addressable and not read-only.
        if f&flagRO != 0 {
@@ -225,7 +226,7 @@ func (v Value) CanSet() bool {
 func (v Value) Elem() Value {
        k := v.kind()
        switch k {
-       case Interface:
+       case abi.Interface:
                var eface any
                if v.typ.NumMethod() == 0 {
                        eface = *(*any)(v.ptr)
@@ -239,7 +240,7 @@ func (v Value) Elem() Value {
                        x.flag |= v.flag.ro()
                }
                return x
-       case Pointer:
+       case abi.Pointer:
                ptr := v.ptr
                if v.flag&flagIndir != 0 {
                        ptr = *(*unsafe.Pointer)(ptr)
@@ -262,7 +263,7 @@ func valueInterface(v Value) any {
                panic(&ValueError{"reflectlite.Value.Interface", 0})
        }
 
-       if v.kind() == Interface {
+       if v.kind() == abi.Interface {
                // Special case: return the element inside the interface.
                // Empty interface has one layout, all interfaces with
                // methods have a second layout.
@@ -288,7 +289,7 @@ func valueInterface(v Value) any {
 func (v Value) IsNil() bool {
        k := v.kind()
        switch k {
-       case Chan, Func, Map, Pointer, UnsafePointer:
+       case abi.Chan, abi.Func, abi.Map, abi.Pointer, abi.UnsafePointer:
                // if v.flag&flagMethod != 0 {
                //      return false
                // }
@@ -297,7 +298,7 @@ func (v Value) IsNil() bool {
                        ptr = *(*unsafe.Pointer)(ptr)
                }
                return ptr == nil
-       case Interface, Slice:
+       case abi.Interface, abi.Slice:
                // Both interface and slice are nil if first word is 0.
                // Both are always bigger than a word; assume flagIndir.
                return *(*unsafe.Pointer)(v.ptr) == nil
@@ -329,17 +330,17 @@ func maplen(unsafe.Pointer) int
 func (v Value) Len() int {
        k := v.kind()
        switch k {
-       case Array:
+       case abi.Array:
                tt := (*arrayType)(unsafe.Pointer(v.typ))
                return int(tt.Len)
-       case Chan:
+       case abi.Chan:
                return chanlen(v.pointer())
-       case Map:
+       case abi.Map:
                return maplen(v.pointer())
-       case Slice:
+       case abi.Slice:
                // Slice is bigger than a word; assume flagIndir.
                return (*unsafeheader.Slice)(v.ptr).Len
-       case String:
+       case abi.String:
                // String is bigger than a word; assume flagIndir.
                return (*unsafeheader.String)(v.ptr).Len
        }
@@ -349,7 +350,7 @@ func (v Value) Len() int {
 // NumMethod returns the number of exported methods in the value's method set.
 func (v Value) numMethod() int {
        if v.typ == nil {
-               panic(&ValueError{"reflectlite.Value.NumMethod", Invalid})
+               panic(&ValueError{"reflectlite.Value.NumMethod", abi.Invalid})
        }
        return v.typ.NumMethod()
 }
@@ -361,7 +362,7 @@ func (v Value) Set(x Value) {
        v.mustBeAssignable()
        x.mustBeExported() // do not let unexported x leak
        var target unsafe.Pointer
-       if v.kind() == Interface {
+       if v.kind() == abi.Interface {
                target = v.ptr
        }
        x = x.assignTo("reflectlite.Set", v.typ, target)
@@ -376,7 +377,7 @@ func (v Value) Set(x Value) {
 func (v Value) Type() Type {
        f := v.flag
        if f == 0 {
-               panic(&ValueError{"reflectlite.Value.Type", Invalid})
+               panic(&ValueError{"reflectlite.Value.Type", abi.Invalid})
        }
        // Method values not supported.
        return v.typ
@@ -425,11 +426,11 @@ func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value
                if target == nil {
                        target = unsafe_New(dst)
                }
-               if v.Kind() == Interface && v.IsNil() {
+               if v.Kind() == abi.Interface && v.IsNil() {
                        // A nil ReadWriter passed to nil Reader is OK,
                        // but using ifaceE2I below will panic.
                        // Avoid the panic by returning a nil dst (e.g., Reader) explicitly.
-                       return Value{dst, nil, flag(Interface)}
+                       return Value{dst, nil, flag(abi.Interface)}
                }
                x := valueInterface(v)
                if dst.NumMethod() == 0 {
@@ -437,7 +438,7 @@ func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value
                } else {
                        ifaceE2I(dst, x, target)
                }
-               return Value{dst, target, flagIndir | flag(Interface)}
+               return Value{dst, target, flagIndir | flag(abi.Interface)}
        }
 
        // Failed.
index 4619abf4f5517d6c152b3cfa4bdf85c5aca20c78..e40eb9b47b869b28537a9465ca5c0b83e5db02b9 100644 (file)
@@ -174,7 +174,7 @@ func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr {
        case kindArray:
                a := (*arraytype)(unsafe.Pointer(t))
                for i := uintptr(0); i < a.Len; i++ {
-                       h = typehash((*_type)(a.Elem), add(p, i*a.Elem.Size_), h)
+                       h = typehash(toType(a.Elem), add(p, i*a.Elem.Size_), h)
                }
                return h
        case kindStruct:
index e92b7e4fedf6d2d6977fe72172e185f0892bee09..e2e37284a212ecaf7de79c4e48613d2b1f8198c4 100644 (file)
@@ -466,11 +466,11 @@ func cgoCheckArg(t *_type, p unsafe.Pointer, indir, top bool, msg string) {
                        if at.Len != 1 {
                                throw("can't happen")
                        }
-                       cgoCheckArg((*_type)(at.Elem), p, at.Elem.Kind_&kindDirectIface == 0, top, msg)
+                       cgoCheckArg(toType(at.Elem), p, at.Elem.Kind_&kindDirectIface == 0, top, msg)
                        return
                }
                for i := uintptr(0); i < at.Len; i++ {
-                       cgoCheckArg((*_type)(at.Elem), p, true, top, msg)
+                       cgoCheckArg(toType(at.Elem), p, true, top, msg)
                        p = add(p, at.Elem.Size_)
                }
        case kindChan, kindMap:
index cc11ef046961c1d5ad78949a8e082d22d6f7f99e..1acf0f9233c3efa5cc656790924fa62a95342aa5 100644 (file)
@@ -249,7 +249,7 @@ func cgoCheckUsingType(typ *_type, src unsafe.Pointer, off, size uintptr) {
                at := (*arraytype)(unsafe.Pointer(typ))
                for i := uintptr(0); i < at.Len; i++ {
                        if off < at.Elem.Size_ {
-                               cgoCheckUsingType((*_type)(at.Elem), src, off, size)
+                               cgoCheckUsingType(toType(at.Elem), src, off, size)
                        }
                        src = add(src, at.Elem.Size_)
                        skipped := off
index 5177f614c8eecf2989dac573c894b8e02c6f226f..37f86d0d7fd1173701696f057258d7905898e87f 100644 (file)
@@ -186,7 +186,7 @@ func (p *abiDesc) tryRegAssignArg(t *_type, offset uintptr) bool {
        case kindArray:
                at := (*arraytype)(unsafe.Pointer(t))
                if at.Len == 1 {
-                       return p.tryRegAssignArg((*_type)(at.Elem), offset)
+                       return p.tryRegAssignArg((*_type)(unsafe.Pointer(at.Elem)), offset) // TODO fix when runtime is fully commoned up w/ abi.Type
                }
        case kindStruct:
                st := (*structtype)(unsafe.Pointer(t))
index 85d576379ccdaab5462aa80b5dac670071762eff..bc8ded28211e1851d64cf3fe5f1a4f71c30d2157 100644 (file)
@@ -19,7 +19,9 @@ type textOff = abi.TextOff
 // ../cmd/compile/internal/reflectdata/reflect.go:/^func.dcommontype and
 // ../reflect/type.go:/^type.rtype.
 // ../internal/reflectlite/type.go:/^type.rtype.
-type _type abi.Type
+type _type struct {
+       abi.Type
+}
 
 func (t *_type) string() string {
        s := t.nameOff(t.Str).name()
@@ -30,65 +32,7 @@ func (t *_type) string() string {
 }
 
 func (t *_type) uncommon() *uncommontype {
-       if t.TFlag&abi.TFlagUncommon == 0 {
-               return nil
-       }
-       switch t.Kind_ & kindMask {
-       case kindStruct:
-               type u struct {
-                       structtype
-                       u uncommontype
-               }
-               return &(*u)(unsafe.Pointer(t)).u
-       case kindPtr:
-               type u struct {
-                       ptrtype
-                       u uncommontype
-               }
-               return &(*u)(unsafe.Pointer(t)).u
-       case kindFunc:
-               type u struct {
-                       functype
-                       u uncommontype
-               }
-               return &(*u)(unsafe.Pointer(t)).u
-       case kindSlice:
-               type u struct {
-                       slicetype
-                       u uncommontype
-               }
-               return &(*u)(unsafe.Pointer(t)).u
-       case kindArray:
-               type u struct {
-                       arraytype
-                       u uncommontype
-               }
-               return &(*u)(unsafe.Pointer(t)).u
-       case kindChan:
-               type u struct {
-                       chantype
-                       u uncommontype
-               }
-               return &(*u)(unsafe.Pointer(t)).u
-       case kindMap:
-               type u struct {
-                       maptype
-                       u uncommontype
-               }
-               return &(*u)(unsafe.Pointer(t)).u
-       case kindInterface:
-               type u struct {
-                       interfacetype
-                       u uncommontype
-               }
-               return &(*u)(unsafe.Pointer(t)).u
-       default:
-               type u struct {
-                       _type
-                       u uncommontype
-               }
-               return &(*u)(unsafe.Pointer(t)).u
-       }
+       return t.Uncommon()
 }
 
 func (t *_type) name() string {
@@ -500,6 +444,10 @@ type _typePair struct {
        t2 *_type
 }
 
+func toType(t *abi.Type) *_type {
+       return (*_type)(unsafe.Pointer(t))
+}
+
 // typesEqual reports whether two types are equal.
 //
 // Everywhere in the runtime and reflect packages, it is assumed that
@@ -554,7 +502,7 @@ func typesEqual(t, v *_type, seen map[_typePair]struct{}) bool {
        case kindArray:
                at := (*arraytype)(unsafe.Pointer(t))
                av := (*arraytype)(unsafe.Pointer(v))
-               return typesEqual((*_type)(at.Elem), (*_type)(av.Elem), seen) && at.Len == av.Len
+               return typesEqual(toType(at.Elem), toType(av.Elem), seen) && at.Len == av.Len
        case kindChan:
                ct := (*chantype)(unsafe.Pointer(t))
                cv := (*chantype)(unsafe.Pointer(v))