package runtime // This file implements Go interfaces. // // Interfaces are represented as a pair of {typecode, value}, where value can be // anything (including non-pointers). import "unsafe" type _interface struct { typecode unsafe.Pointer value unsafe.Pointer } //go:inline func composeInterface(typecode, value unsafe.Pointer) _interface { return _interface{typecode, value} } //go:inline func decomposeInterface(i _interface) (unsafe.Pointer, unsafe.Pointer) { return i.typecode, i.value } // Return true iff both interfaces are equal. func interfaceEqual(x, y interface{}) bool { xi := (*_interface)(unsafe.Pointer(&x)) yi := (*_interface)(unsafe.Pointer(&y)) return rawValueEqual(xi.typecode, xi.value, yi.typecode, yi.value) } // rawValueEqual compares two values by their raw type codes and value pointers. // xt/yt are type code pointers; xv/yv are interface value slots (small values // packed directly, large values as pointers to data). func rawValueEqual(xt, xv, yt, yv unsafe.Pointer) bool { if xt == nil || yt == nil { return xt == yt } if xt != yt { return false } t := (*rawType)(xt) // Convert interface value representation to direct data pointer. // Small values (fit in a pointer) are stored directly in the value slot. // Large values are stored as a pointer to the data. xp, yp := xv, yv if t.size() <= unsafe.Sizeof(uintptr(0)) { xp = unsafe.Pointer(&xv) yp = unsafe.Pointer(&yv) } return rawPtrEqual(t, xp, yp) } // rawPtrEqual compares two values where xp and yp always point directly to the // value data. Used for recursive comparison of struct fields and array elements // where we already have direct pointers (no interface packing). func rawPtrEqual(t *rawType, xp, yp unsafe.Pointer) bool { k := t.kind() switch k { case Bool: return *(*bool)(xp) == *(*bool)(yp) case Int: return *(*int)(xp) == *(*int)(yp) case Int8: return *(*int8)(xp) == *(*int8)(yp) case Int16: return *(*int16)(xp) == *(*int16)(yp) case Int32: return *(*int32)(xp) == *(*int32)(yp) case Int64: return *(*int64)(xp) == *(*int64)(yp) case Uint: return *(*uint)(xp) == *(*uint)(yp) case Uint8: return *(*uint8)(xp) == *(*uint8)(yp) case Uint16: return *(*uint16)(xp) == *(*uint16)(yp) case Uint32: return *(*uint32)(xp) == *(*uint32)(yp) case Uint64: return *(*uint64)(xp) == *(*uint64)(yp) case Uintptr: return *(*uintptr)(xp) == *(*uintptr)(yp) case Float32: return *(*float32)(xp) == *(*float32)(yp) case Float64: return *(*float64)(xp) == *(*float64)(yp) case Complex64: return *(*complex64)(xp) == *(*complex64)(yp) case Complex128: return *(*complex128)(xp) == *(*complex128)(yp) case kindBytes: xs := *(*_string)(xp) ys := *(*_string)(yp) if xs.length != ys.length { return false } return memequal(unsafe.Pointer(xs.ptr), unsafe.Pointer(ys.ptr), xs.length) case kindChan, kindPointer, kindUnsafePointer: return *(*uintptr)(xp) == *(*uintptr)(yp) case kindArray: elemType := t.elem() elemSize := elemType.size() length := t.arrayLen() for i := 0; i < length; i++ { ex := unsafe.Add(xp, uintptr(i)*elemSize) ey := unsafe.Add(yp, uintptr(i)*elemSize) if !rawPtrEqual(elemType, ex, ey) { return false } } return true case kindStruct: nf := t.numField() for i := 0; i < nf; i++ { ft := t.structFieldType(i) off := t.structFieldOffset(i) fx := unsafe.Add(xp, off) fy := unsafe.Add(yp, off) if !rawPtrEqual(ft, fx, fy) { return false } } return true case kindInterface: xi := (*_interface)(xp) yi := (*_interface)(yp) return rawValueEqual(xi.typecode, xi.value, yi.typecode, yi.value) default: runtimePanic("comparing un-comparable type") return false } } // interfaceTypeAssert is called when a type assert without comma-ok still // returns false. func interfaceTypeAssert(ok bool) { if !ok { runtimePanic("type assert failed") } } // The following declarations are only used during IR construction. They are // lowered to inline IR in the interface lowering pass. // See compiler/interface-lowering.go for details. type structField struct { typecode unsafe.Pointer // type of this struct field data *uint8 // pointer to byte array containing name, tag, varint-encoded offset, and some flags } // Pseudo function call used during a type assert. It is used during interface // lowering, to assign the lowest type numbers to the types with the most type // asserts. Also, it is replaced with const false if this type assert can never // happen. func typeAssert(actualType unsafe.Pointer, assertedType *uint8) bool