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