@@ -806,3 +806,89 @@ func (m *Map) Clone(typ *abi.SwissMapType) *Map {
806806
807807 return m
808808}
809+
810+ func OldMapKeyError (t * abi.OldMapType , p unsafe.Pointer ) error {
811+ if ! t .HashMightPanic () {
812+ return nil
813+ }
814+ return mapKeyError2 (t .Key , p )
815+ }
816+
817+ func mapKeyError (t * abi.SwissMapType , p unsafe.Pointer ) error {
818+ if ! t .HashMightPanic () {
819+ return nil
820+ }
821+ return mapKeyError2 (t .Key , p )
822+ }
823+
824+ func mapKeyError2 (t * abi.Type , p unsafe.Pointer ) error {
825+ if t .TFlag & abi .TFlagRegularMemory != 0 {
826+ return nil
827+ }
828+ switch t .Kind () {
829+ case abi .Float32 , abi .Float64 , abi .Complex64 , abi .Complex128 , abi .String :
830+ return nil
831+ case abi .Interface :
832+ i := (* abi .InterfaceType )(unsafe .Pointer (t ))
833+ var t * abi.Type
834+ var pdata * unsafe.Pointer
835+ if len (i .Methods ) == 0 {
836+ a := (* abi .EmptyInterface )(p )
837+ t = a .Type
838+ if t == nil {
839+ return nil
840+ }
841+ pdata = & a .Data
842+ } else {
843+ a := (* abi .NonEmptyInterface )(p )
844+ if a .ITab == nil {
845+ return nil
846+ }
847+ t = a .ITab .Type
848+ pdata = & a .Data
849+ }
850+
851+ if t .Equal == nil {
852+ return unhashableTypeError {t }
853+ }
854+
855+ if t .Kind_ & abi .KindDirectIface != 0 {
856+ return mapKeyError2 (t , unsafe .Pointer (pdata ))
857+ } else {
858+ return mapKeyError2 (t , * pdata )
859+ }
860+ case abi .Array :
861+ a := (* abi .ArrayType )(unsafe .Pointer (t ))
862+ for i := uintptr (0 ); i < a .Len ; i ++ {
863+ if err := mapKeyError2 (a .Elem , unsafe .Pointer (uintptr (p )+ i * a .Elem .Size_ )); err != nil {
864+ return err
865+ }
866+ }
867+ return nil
868+ case abi .Struct :
869+ s := (* abi .StructType )(unsafe .Pointer (t ))
870+ for _ , f := range s .Fields {
871+ if f .Name .IsBlank () {
872+ continue
873+ }
874+ if err := mapKeyError2 (f .Typ , unsafe .Pointer (uintptr (p )+ f .Offset )); err != nil {
875+ return err
876+ }
877+ }
878+ return nil
879+ default :
880+ // Should never happen, keep this case for robustness.
881+ return unhashableTypeError {t }
882+ }
883+ }
884+
885+ type unhashableTypeError struct { typ * abi.Type }
886+
887+ func (unhashableTypeError ) RuntimeError () {}
888+
889+ func (e unhashableTypeError ) Error () string { return "hash of unhashable type: " + typeString (e .typ ) }
890+
891+ // Pushed from runtime
892+ //
893+ //go:linkname typeString
894+ func typeString (typ * abi.Type ) string
0 commit comments