github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/runtime/interface.go (about) 1 package runtime 2 3 // This file implements Go interfaces. 4 // 5 // Interfaces are represented as a pair of {typecode, value}, where value can be 6 // anything (including non-pointers). 7 8 import ( 9 "reflect" 10 "unsafe" 11 ) 12 13 type _interface struct { 14 typecode unsafe.Pointer 15 value unsafe.Pointer 16 } 17 18 //go:inline 19 func composeInterface(typecode, value unsafe.Pointer) _interface { 20 return _interface{typecode, value} 21 } 22 23 //go:inline 24 func decomposeInterface(i _interface) (unsafe.Pointer, unsafe.Pointer) { 25 return i.typecode, i.value 26 } 27 28 // Return true iff both interfaces are equal. 29 func interfaceEqual(x, y interface{}) bool { 30 return reflectValueEqual(reflect.ValueOf(x), reflect.ValueOf(y)) 31 } 32 33 func reflectValueEqual(x, y reflect.Value) bool { 34 // Note: doing a x.Type() == y.Type() comparison would not work here as that 35 // would introduce an infinite recursion: comparing two reflect.Type values 36 // is done with this reflectValueEqual runtime call. 37 if x.RawType() == nil || y.RawType() == nil { 38 // One of them is nil. 39 return x.RawType() == y.RawType() 40 } 41 42 if x.RawType() != y.RawType() { 43 // The type is not the same, which means the interfaces are definitely 44 // not the same. 45 return false 46 } 47 48 switch x.RawType().Kind() { 49 case reflect.Bool: 50 return x.Bool() == y.Bool() 51 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 52 return x.Int() == y.Int() 53 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 54 return x.Uint() == y.Uint() 55 case reflect.Float32, reflect.Float64: 56 return x.Float() == y.Float() 57 case reflect.Complex64, reflect.Complex128: 58 return x.Complex() == y.Complex() 59 case reflect.String: 60 return x.String() == y.String() 61 case reflect.Chan, reflect.Ptr, reflect.UnsafePointer: 62 return x.UnsafePointer() == y.UnsafePointer() 63 case reflect.Array: 64 for i := 0; i < x.Len(); i++ { 65 if !reflectValueEqual(x.Index(i), y.Index(i)) { 66 return false 67 } 68 } 69 return true 70 case reflect.Struct: 71 for i := 0; i < x.NumField(); i++ { 72 if !reflectValueEqual(x.Field(i), y.Field(i)) { 73 return false 74 } 75 } 76 return true 77 case reflect.Interface: 78 return reflectValueEqual(x.Elem(), y.Elem()) 79 default: 80 runtimePanic("comparing un-comparable type") 81 return false // unreachable 82 } 83 } 84 85 // interfaceTypeAssert is called when a type assert without comma-ok still 86 // returns false. 87 func interfaceTypeAssert(ok bool) { 88 if !ok { 89 runtimePanic("type assert failed") 90 } 91 } 92 93 // The following declarations are only used during IR construction. They are 94 // lowered to inline IR in the interface lowering pass. 95 // See compiler/interface-lowering.go for details. 96 97 type structField struct { 98 typecode unsafe.Pointer // type of this struct field 99 data *uint8 // pointer to byte array containing name, tag, varint-encoded offset, and some flags 100 } 101 102 // Pseudo function call used during a type assert. It is used during interface 103 // lowering, to assign the lowest type numbers to the types with the most type 104 // asserts. Also, it is replaced with const false if this type assert can never 105 // happen. 106 func typeAssert(actualType unsafe.Pointer, assertedType *uint8) bool