mirror of
https://github.com/golang/go
synced 2024-11-23 03:50:03 -07:00
runtime: redefine _type to abi.Type; add rtype for methods.
Change-Id: I1c478b704d84811caa209006c657dda82d9c4cf9 Reviewed-on: https://go-review.googlesource.com/c/go/+/488435 Reviewed-by: Keith Randall <khr@golang.org> Run-TryBot: David Chase <drchase@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Keith Randall <khr@google.com>
This commit is contained in:
parent
48f8c5c037
commit
a2838ec5f2
@ -1802,7 +1802,7 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
|
||||
|
||||
// Needed by the prettyprinter code for interface inspection.
|
||||
for _, typ := range []string{
|
||||
"type:runtime._type",
|
||||
"type:internal/abi.Type",
|
||||
"type:internal/abi.ArrayType",
|
||||
"type:internal/abi.ChanType",
|
||||
"type:runtime.functype",
|
||||
|
@ -56,7 +56,7 @@ func TestRuntimeTypesPresent(t *testing.T) {
|
||||
}
|
||||
|
||||
want := map[string]bool{
|
||||
"runtime._type": true,
|
||||
"internal/abi.Type": true,
|
||||
"internal/abi.ArrayType": true,
|
||||
"internal/abi.ChanType": true,
|
||||
"runtime.functype": true,
|
||||
|
@ -279,8 +279,7 @@ const Ptr = Pointer
|
||||
// to describe a non-defined type with no methods.
|
||||
type uncommonType = abi.UncommonType
|
||||
|
||||
// rtype is the common implementation of most values.
|
||||
// It is embedded in other struct types.
|
||||
// rtype is a wrapper that allows us to define exactly the type.Reflect methods.
|
||||
type rtype struct {
|
||||
t *abi.Type
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ func interhash(p unsafe.Pointer, h uintptr) uintptr {
|
||||
// typehash, but we want to report the topmost type in
|
||||
// the error text (e.g. in a struct with a field of slice type
|
||||
// we want to report the struct, not the slice).
|
||||
panic(errorString("hash of unhashable type " + t.string()))
|
||||
panic(errorString("hash of unhashable type " + toRType(t).string()))
|
||||
}
|
||||
if isDirectIface(t) {
|
||||
return c1 * typehash(t, unsafe.Pointer(&a.data), h^c0)
|
||||
@ -123,7 +123,7 @@ func nilinterhash(p unsafe.Pointer, h uintptr) uintptr {
|
||||
}
|
||||
if t.Equal == nil {
|
||||
// See comment in interhash above.
|
||||
panic(errorString("hash of unhashable type " + t.string()))
|
||||
panic(errorString("hash of unhashable type " + toRType(t).string()))
|
||||
}
|
||||
if isDirectIface(t) {
|
||||
return c1 * typehash(t, unsafe.Pointer(&a.data), h^c0)
|
||||
@ -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(toType(a.Elem), add(p, i*a.Elem.Size_), h)
|
||||
h = typehash(a.Elem, add(p, i*a.Elem.Size_), h)
|
||||
}
|
||||
return h
|
||||
case kindStruct:
|
||||
@ -189,7 +189,7 @@ func typehash(t *_type, p unsafe.Pointer, h uintptr) uintptr {
|
||||
default:
|
||||
// Should never happen, as typehash should only be called
|
||||
// with comparable types.
|
||||
panic(errorString("hash of unhashable type " + t.string()))
|
||||
panic(errorString("hash of unhashable type " + toRType(t).string()))
|
||||
}
|
||||
}
|
||||
|
||||
@ -247,7 +247,7 @@ func efaceeq(t *_type, x, y unsafe.Pointer) bool {
|
||||
}
|
||||
eq := t.Equal
|
||||
if eq == nil {
|
||||
panic(errorString("comparing uncomparable type " + t.string()))
|
||||
panic(errorString("comparing uncomparable type " + toRType(t).string()))
|
||||
}
|
||||
if isDirectIface(t) {
|
||||
// Direct interface types are ptr, chan, map, func, and single-element structs/arrays thereof.
|
||||
@ -264,7 +264,7 @@ func ifaceeq(tab *itab, x, y unsafe.Pointer) bool {
|
||||
t := tab._type
|
||||
eq := t.Equal
|
||||
if eq == nil {
|
||||
panic(errorString("comparing uncomparable type " + t.string()))
|
||||
panic(errorString("comparing uncomparable type " + toRType(t).string()))
|
||||
}
|
||||
if isDirectIface(t) {
|
||||
// See comment in efaceeq.
|
||||
|
@ -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(toType(at.Elem), p, at.Elem.Kind_&kindDirectIface == 0, top, msg)
|
||||
cgoCheckArg(at.Elem, p, at.Elem.Kind_&kindDirectIface == 0, top, msg)
|
||||
return
|
||||
}
|
||||
for i := uintptr(0); i < at.Len; i++ {
|
||||
cgoCheckArg(toType(at.Elem), p, true, top, msg)
|
||||
cgoCheckArg(at.Elem, p, true, top, msg)
|
||||
p = add(p, at.Elem.Size_)
|
||||
}
|
||||
case kindChan, kindMap:
|
||||
|
@ -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(toType(at.Elem), src, off, size)
|
||||
cgoCheckUsingType(at.Elem, src, off, size)
|
||||
}
|
||||
src = add(src, at.Elem.Size_)
|
||||
skipped := off
|
||||
|
@ -104,11 +104,11 @@ func makechan(t *chantype, size int) *hchan {
|
||||
default:
|
||||
// Elements contain pointers.
|
||||
c = new(hchan)
|
||||
c.buf = mallocgc(mem, toType(elem), true)
|
||||
c.buf = mallocgc(mem, elem, true)
|
||||
}
|
||||
|
||||
c.elemsize = uint16(elem.Size_)
|
||||
c.elemtype = toType(elem)
|
||||
c.elemtype = elem
|
||||
c.dataqsiz = uint(size)
|
||||
lockInit(&c.lock, lockRankHchan)
|
||||
|
||||
|
@ -30,18 +30,18 @@ func (*TypeAssertionError) RuntimeError() {}
|
||||
func (e *TypeAssertionError) Error() string {
|
||||
inter := "interface"
|
||||
if e._interface != nil {
|
||||
inter = e._interface.string()
|
||||
inter = toRType(e._interface).string()
|
||||
}
|
||||
as := e.asserted.string()
|
||||
as := toRType(e.asserted).string()
|
||||
if e.concrete == nil {
|
||||
return "interface conversion: " + inter + " is nil, not " + as
|
||||
}
|
||||
cs := e.concrete.string()
|
||||
cs := toRType(e.concrete).string()
|
||||
if e.missingMethod == "" {
|
||||
msg := "interface conversion: " + inter + " is " + cs + ", not " + as
|
||||
if cs == as {
|
||||
// provide slightly clearer error message
|
||||
if e.concrete.pkgpath() != e.asserted.pkgpath() {
|
||||
if toRType(e.concrete).pkgpath() != toRType(e.asserted).pkgpath() {
|
||||
msg += " (types from different packages)"
|
||||
} else {
|
||||
msg += " (types from different scopes)"
|
||||
@ -256,7 +256,7 @@ func printany(i any) {
|
||||
|
||||
func printanycustomtype(i any) {
|
||||
eface := efaceOf(&i)
|
||||
typestring := eface._type.string()
|
||||
typestring := toRType(eface._type).string()
|
||||
|
||||
switch eface._type.Kind_ {
|
||||
case kindString:
|
||||
|
@ -194,11 +194,12 @@ func dumptype(t *_type) {
|
||||
dumpint(tagType)
|
||||
dumpint(uint64(uintptr(unsafe.Pointer(t))))
|
||||
dumpint(uint64(t.Size_))
|
||||
if x := t.uncommon(); x == nil || t.nameOff(x.PkgPath).name() == "" {
|
||||
dumpstr(t.string())
|
||||
rt := toRType(t)
|
||||
if x := t.Uncommon(); x == nil || rt.nameOff(x.PkgPath).name() == "" {
|
||||
dumpstr(rt.string())
|
||||
} else {
|
||||
pkgpath := t.nameOff(x.PkgPath).name()
|
||||
name := t.name()
|
||||
pkgpath := rt.nameOff(x.PkgPath).name()
|
||||
name := rt.name()
|
||||
dumpint(uint64(uintptr(len(pkgpath)) + 1 + uintptr(len(name))))
|
||||
dwrite(unsafe.Pointer(unsafe.StringData(pkgpath)), uintptr(len(pkgpath)))
|
||||
dwritebyte('.')
|
||||
|
@ -41,7 +41,7 @@ func getitab(inter *interfacetype, typ *_type, canfail bool) *itab {
|
||||
if canfail {
|
||||
return nil
|
||||
}
|
||||
name := inter.typ.nameOff(inter.mhdr[0].Name)
|
||||
name := toRType(&inter.typ).nameOff(inter.mhdr[0].Name)
|
||||
panic(&TypeAssertionError{nil, typ, &inter.typ, name.name()})
|
||||
}
|
||||
|
||||
@ -192,7 +192,7 @@ func (t *itabTableType) add(m *itab) {
|
||||
func (m *itab) init() string {
|
||||
inter := m.inter
|
||||
typ := m._type
|
||||
x := typ.uncommon()
|
||||
x := typ.Uncommon()
|
||||
|
||||
// both inter and typ have method sorted by name,
|
||||
// and interface names are unique,
|
||||
@ -207,8 +207,8 @@ func (m *itab) init() string {
|
||||
imethods:
|
||||
for k := 0; k < ni; k++ {
|
||||
i := &inter.mhdr[k]
|
||||
itype := inter.typ.typeOff(i.Typ)
|
||||
name := inter.typ.nameOff(i.Name)
|
||||
itype := toRType(&inter.typ).typeOff(i.Typ)
|
||||
name := toRType(&inter.typ).nameOff(i.Name)
|
||||
iname := name.name()
|
||||
ipkg := name.pkgPath()
|
||||
if ipkg == "" {
|
||||
@ -216,15 +216,16 @@ imethods:
|
||||
}
|
||||
for ; j < nt; j++ {
|
||||
t := &xmhdr[j]
|
||||
tname := typ.nameOff(t.Name)
|
||||
if typ.typeOff(t.Mtyp) == itype && tname.name() == iname {
|
||||
rtyp := toRType(typ)
|
||||
tname := rtyp.nameOff(t.Name)
|
||||
if rtyp.typeOff(t.Mtyp) == itype && tname.name() == iname {
|
||||
pkgPath := tname.pkgPath()
|
||||
if pkgPath == "" {
|
||||
pkgPath = typ.nameOff(x.PkgPath).name()
|
||||
pkgPath = rtyp.nameOff(x.PkgPath).name()
|
||||
}
|
||||
if tname.isExported() || pkgPath == ipkg {
|
||||
if m != nil {
|
||||
ifn := typ.textOff(t.Ifn)
|
||||
ifn := rtyp.textOff(t.Ifn)
|
||||
if k == 0 {
|
||||
fun0 = ifn // we'll set m.fun[0] at the end
|
||||
} else {
|
||||
|
@ -155,7 +155,7 @@ import (
|
||||
// anywhere in the bulk barrier or memmove.
|
||||
//
|
||||
//go:nosplit
|
||||
func typedmemmove(typ *_type, dst, src unsafe.Pointer) {
|
||||
func typedmemmove(typ *abi.Type, dst, src unsafe.Pointer) {
|
||||
if dst == src {
|
||||
return
|
||||
}
|
||||
|
@ -683,11 +683,11 @@ func typeBitsBulkBarrier(typ *_type, dst, src, size uintptr) {
|
||||
throw("runtime: typeBitsBulkBarrier without type")
|
||||
}
|
||||
if typ.Size_ != size {
|
||||
println("runtime: typeBitsBulkBarrier with type ", typ.string(), " of size ", typ.Size_, " but memory size", size)
|
||||
println("runtime: typeBitsBulkBarrier with type ", toRType(typ).string(), " of size ", typ.Size_, " but memory size", size)
|
||||
throw("runtime: invalid typeBitsBulkBarrier")
|
||||
}
|
||||
if typ.Kind_&kindGCProg != 0 {
|
||||
println("runtime: typeBitsBulkBarrier with type ", typ.string(), " with GC prog")
|
||||
println("runtime: typeBitsBulkBarrier with type ", toRType(typ).string(), " with GC prog")
|
||||
throw("runtime: invalid typeBitsBulkBarrier")
|
||||
}
|
||||
if !writeBarrier.needed {
|
||||
|
@ -372,7 +372,7 @@ func SetFinalizer(obj any, finalizer any) {
|
||||
throw("runtime.SetFinalizer: first argument is nil")
|
||||
}
|
||||
if etyp.Kind_&kindMask != kindPtr {
|
||||
throw("runtime.SetFinalizer: first argument is " + etyp.string() + ", not pointer")
|
||||
throw("runtime.SetFinalizer: first argument is " + toRType(etyp).string() + ", not pointer")
|
||||
}
|
||||
ot := (*ptrtype)(unsafe.Pointer(etyp))
|
||||
if ot.elem == nil {
|
||||
@ -431,14 +431,14 @@ func SetFinalizer(obj any, finalizer any) {
|
||||
}
|
||||
|
||||
if ftyp.Kind_&kindMask != kindFunc {
|
||||
throw("runtime.SetFinalizer: second argument is " + ftyp.string() + ", not a function")
|
||||
throw("runtime.SetFinalizer: second argument is " + toRType(ftyp).string() + ", not a function")
|
||||
}
|
||||
ft := (*functype)(unsafe.Pointer(ftyp))
|
||||
if ft.dotdotdot() {
|
||||
throw("runtime.SetFinalizer: cannot pass " + etyp.string() + " to finalizer " + ftyp.string() + " because dotdotdot")
|
||||
throw("runtime.SetFinalizer: cannot pass " + toRType(etyp).string() + " to finalizer " + toRType(ftyp).string() + " because dotdotdot")
|
||||
}
|
||||
if ft.inCount != 1 {
|
||||
throw("runtime.SetFinalizer: cannot pass " + etyp.string() + " to finalizer " + ftyp.string())
|
||||
throw("runtime.SetFinalizer: cannot pass " + toRType(etyp).string() + " to finalizer " + toRType(ftyp).string())
|
||||
}
|
||||
fint := ft.in()[0]
|
||||
switch {
|
||||
@ -446,7 +446,7 @@ func SetFinalizer(obj any, finalizer any) {
|
||||
// ok - same type
|
||||
goto okarg
|
||||
case fint.Kind_&kindMask == kindPtr:
|
||||
if (fint.uncommon() == nil || etyp.uncommon() == nil) && (*ptrtype)(unsafe.Pointer(fint)).elem == ot.elem {
|
||||
if (fint.Uncommon() == nil || etyp.Uncommon() == nil) && (*ptrtype)(unsafe.Pointer(fint)).elem == ot.elem {
|
||||
// ok - not same type, but both pointers,
|
||||
// one or the other is unnamed, and same element type, so assignable.
|
||||
goto okarg
|
||||
@ -461,7 +461,7 @@ func SetFinalizer(obj any, finalizer any) {
|
||||
goto okarg
|
||||
}
|
||||
}
|
||||
throw("runtime.SetFinalizer: cannot pass " + etyp.string() + " to finalizer " + ftyp.string())
|
||||
throw("runtime.SetFinalizer: cannot pass " + toRType(etyp).string() + " to finalizer " + toRType(ftyp).string())
|
||||
okarg:
|
||||
// compute size needed for return parameters
|
||||
nret := uintptr(0)
|
||||
|
@ -1230,7 +1230,7 @@ func tracealloc(p unsafe.Pointer, size uintptr, typ *_type) {
|
||||
if typ == nil {
|
||||
print("tracealloc(", p, ", ", hex(size), ")\n")
|
||||
} else {
|
||||
print("tracealloc(", p, ", ", hex(size), ", ", typ.string(), ")\n")
|
||||
print("tracealloc(", p, ", ", hex(size), ", ", toRType(typ).string(), ")\n")
|
||||
}
|
||||
if gp.m.curg == nil || gp == gp.m.curg {
|
||||
goroutineheader(gp)
|
||||
|
@ -573,7 +573,7 @@ func preprintpanics(p *_panic) {
|
||||
case string:
|
||||
throw(text + ": " + r)
|
||||
default:
|
||||
throw(text + ": type " + efaceOf(&r)._type.string())
|
||||
throw(text + ": type " + toRType(efaceOf(&r)._type).string())
|
||||
}
|
||||
}()
|
||||
for p != nil {
|
||||
|
@ -79,7 +79,7 @@ func plugin_lastmoduleinit() (path string, syms map[string]any, initTasks []*ini
|
||||
syms = make(map[string]any, len(md.ptab))
|
||||
for _, ptab := range md.ptab {
|
||||
symName := resolveNameOff(unsafe.Pointer(md.types), ptab.name)
|
||||
t := (*_type)(unsafe.Pointer(md.types)).typeOff(ptab.typ)
|
||||
t := toRType((*_type)(unsafe.Pointer(md.types))).typeOff(ptab.typ) // TODO can this stack of conversions be simpler?
|
||||
var val any
|
||||
valp := (*[2]unsafe.Pointer)(unsafe.Pointer(&val))
|
||||
(*valp)[0] = unsafe.Pointer(t)
|
||||
|
@ -608,14 +608,14 @@ func reflect_resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointe
|
||||
//
|
||||
//go:linkname reflect_resolveTypeOff reflect.resolveTypeOff
|
||||
func reflect_resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
|
||||
return unsafe.Pointer((*_type)(rtype).typeOff(typeOff(off)))
|
||||
return unsafe.Pointer(toRType((*_type)(rtype)).typeOff(typeOff(off)))
|
||||
}
|
||||
|
||||
// reflect_resolveTextOff resolves a function pointer offset from a base type.
|
||||
//
|
||||
//go:linkname reflect_resolveTextOff reflect.resolveTextOff
|
||||
func reflect_resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
|
||||
return (*_type)(rtype).textOff(textOff(off))
|
||||
return toRType((*_type)(rtype)).textOff(textOff(off))
|
||||
|
||||
}
|
||||
|
||||
@ -630,7 +630,7 @@ func reflectlite_resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Po
|
||||
//
|
||||
//go:linkname reflectlite_resolveTypeOff internal/reflectlite.resolveTypeOff
|
||||
func reflectlite_resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
|
||||
return unsafe.Pointer((*_type)(rtype).typeOff(typeOff(off)))
|
||||
return unsafe.Pointer(toRType((*_type)(rtype)).typeOff(typeOff(off)))
|
||||
}
|
||||
|
||||
// reflect_addReflectOff adds a pointer to the reflection offset lookup map.
|
||||
|
@ -200,7 +200,7 @@ func (p *abiDesc) tryRegAssignArg(t *_type, offset uintptr) bool {
|
||||
}
|
||||
// Pointer-sized types such as maps and channels are currently
|
||||
// not supported.
|
||||
panic("compileCallabck: type " + t.string() + " is currently not supported for use in system callbacks")
|
||||
panic("compileCallback: type " + toRType(t).string() + " is currently not supported for use in system callbacks")
|
||||
}
|
||||
|
||||
// assignReg attempts to assign a single register for an
|
||||
|
@ -15,15 +15,14 @@ type nameOff = abi.NameOff
|
||||
type typeOff = abi.TypeOff
|
||||
type textOff = abi.TextOff
|
||||
|
||||
// Needs to be in sync with ../cmd/link/internal/ld/decodesym.go:/^func.commonsize,
|
||||
// ../cmd/compile/internal/reflectdata/reflect.go:/^func.dcommontype and
|
||||
// ../reflect/type.go:/^type.rtype.
|
||||
// ../internal/reflectlite/type.go:/^type.rtype.
|
||||
type _type struct {
|
||||
abi.Type
|
||||
type _type = abi.Type
|
||||
|
||||
// rtype is a wrapper that allows us to define additional methods.
|
||||
type rtype struct {
|
||||
*abi.Type // embedding is okay here (unlike reflect) because none of this is public
|
||||
}
|
||||
|
||||
func (t *_type) string() string {
|
||||
func (t rtype) string() string {
|
||||
s := t.nameOff(t.Str).name()
|
||||
if t.TFlag&abi.TFlagExtraStar != 0 {
|
||||
return s[1:]
|
||||
@ -31,11 +30,11 @@ func (t *_type) string() string {
|
||||
return s
|
||||
}
|
||||
|
||||
func (t *_type) uncommon() *uncommontype {
|
||||
func (t rtype) uncommon() *uncommontype {
|
||||
return t.Uncommon()
|
||||
}
|
||||
|
||||
func (t *_type) name() string {
|
||||
func (t rtype) name() string {
|
||||
if t.TFlag&abi.TFlagNamed == 0 {
|
||||
return ""
|
||||
}
|
||||
@ -58,16 +57,16 @@ func (t *_type) name() string {
|
||||
// available. This is not the same as the reflect package's PkgPath
|
||||
// method, in that it returns the package path for struct and interface
|
||||
// types, not just named types.
|
||||
func (t *_type) pkgpath() string {
|
||||
func (t rtype) pkgpath() string {
|
||||
if u := t.uncommon(); u != nil {
|
||||
return t.nameOff(u.PkgPath).name()
|
||||
}
|
||||
switch t.Kind_ & kindMask {
|
||||
case kindStruct:
|
||||
st := (*structtype)(unsafe.Pointer(t))
|
||||
st := (*structtype)(unsafe.Pointer(t.Type))
|
||||
return st.pkgPath.name()
|
||||
case kindInterface:
|
||||
it := (*interfacetype)(unsafe.Pointer(t))
|
||||
it := (*interfacetype)(unsafe.Pointer(t.Type))
|
||||
return it.pkgpath.name()
|
||||
}
|
||||
return ""
|
||||
@ -137,8 +136,8 @@ func resolveNameOff(ptrInModule unsafe.Pointer, off nameOff) name {
|
||||
return name{(*byte)(res)}
|
||||
}
|
||||
|
||||
func (t *_type) nameOff(off nameOff) name {
|
||||
return resolveNameOff(unsafe.Pointer(t), off)
|
||||
func (t rtype) nameOff(off nameOff) name {
|
||||
return resolveNameOff(unsafe.Pointer(t.Type), off)
|
||||
}
|
||||
|
||||
func resolveTypeOff(ptrInModule unsafe.Pointer, off typeOff) *_type {
|
||||
@ -179,17 +178,17 @@ func resolveTypeOff(ptrInModule unsafe.Pointer, off typeOff) *_type {
|
||||
return (*_type)(unsafe.Pointer(res))
|
||||
}
|
||||
|
||||
func (t *_type) typeOff(off typeOff) *_type {
|
||||
return resolveTypeOff(unsafe.Pointer(t), off)
|
||||
func (t rtype) typeOff(off typeOff) *_type {
|
||||
return resolveTypeOff(unsafe.Pointer(t.Type), off)
|
||||
}
|
||||
|
||||
func (t *_type) textOff(off textOff) unsafe.Pointer {
|
||||
func (t rtype) textOff(off textOff) unsafe.Pointer {
|
||||
if off == -1 {
|
||||
// -1 is the sentinel value for unreachable code.
|
||||
// See cmd/link/internal/ld/data.go:relocsym.
|
||||
return unsafe.Pointer(abi.FuncPCABIInternal(unreachableMethod))
|
||||
}
|
||||
base := uintptr(unsafe.Pointer(t))
|
||||
base := uintptr(unsafe.Pointer(t.Type))
|
||||
var md *moduledata
|
||||
for next := &firstmoduledata; next != nil; next = next.next {
|
||||
if base >= next.types && base < next.etypes {
|
||||
@ -440,8 +439,8 @@ type _typePair struct {
|
||||
t2 *_type
|
||||
}
|
||||
|
||||
func toType(t *abi.Type) *_type {
|
||||
return (*_type)(unsafe.Pointer(t))
|
||||
func toRType(t *abi.Type) rtype {
|
||||
return rtype{t}
|
||||
}
|
||||
|
||||
// typesEqual reports whether two types are equal.
|
||||
@ -474,17 +473,18 @@ func typesEqual(t, v *_type, seen map[_typePair]struct{}) bool {
|
||||
if kind != v.Kind_&kindMask {
|
||||
return false
|
||||
}
|
||||
if t.string() != v.string() {
|
||||
rt, rv := toRType(t), toRType(v)
|
||||
if rt.string() != rv.string() {
|
||||
return false
|
||||
}
|
||||
ut := t.uncommon()
|
||||
uv := v.uncommon()
|
||||
ut := t.Uncommon()
|
||||
uv := v.Uncommon()
|
||||
if ut != nil || uv != nil {
|
||||
if ut == nil || uv == nil {
|
||||
return false
|
||||
}
|
||||
pkgpatht := t.nameOff(ut.PkgPath).name()
|
||||
pkgpathv := v.nameOff(uv.PkgPath).name()
|
||||
pkgpatht := rt.nameOff(ut.PkgPath).name()
|
||||
pkgpathv := rv.nameOff(uv.PkgPath).name()
|
||||
if pkgpatht != pkgpathv {
|
||||
return false
|
||||
}
|
||||
@ -498,11 +498,11 @@ func typesEqual(t, v *_type, seen map[_typePair]struct{}) bool {
|
||||
case kindArray:
|
||||
at := (*arraytype)(unsafe.Pointer(t))
|
||||
av := (*arraytype)(unsafe.Pointer(v))
|
||||
return typesEqual(toType(at.Elem), toType(av.Elem), seen) && at.Len == av.Len
|
||||
return typesEqual(at.Elem, av.Elem, seen) && at.Len == av.Len
|
||||
case kindChan:
|
||||
ct := (*chantype)(unsafe.Pointer(t))
|
||||
cv := (*chantype)(unsafe.Pointer(v))
|
||||
return ct.Dir == cv.Dir && typesEqual(toType(ct.Elem), toType(cv.Elem), seen)
|
||||
return ct.Dir == cv.Dir && typesEqual(ct.Elem, cv.Elem, seen)
|
||||
case kindFunc:
|
||||
ft := (*functype)(unsafe.Pointer(t))
|
||||
fv := (*functype)(unsafe.Pointer(v))
|
||||
|
Loading…
Reference in New Issue
Block a user