github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/runtime/error.go (about) 1 // Copyright 2010 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package runtime 6 7 import "internal/bytealg" 8 9 // The Error interface identifies a run time error. 10 type Error interface { 11 error 12 13 // RuntimeError is a no-op function but 14 // serves to distinguish types that are run time 15 // errors from ordinary errors: a type is a 16 // run time error if it has a RuntimeError method. 17 RuntimeError() 18 } 19 20 // A TypeAssertionError explains a failed type assertion. 21 type TypeAssertionError struct { 22 _interface *_type 23 concrete *_type 24 asserted *_type 25 missingMethod string // one method needed by Interface, missing from Concrete 26 } 27 28 func (*TypeAssertionError) RuntimeError() {} 29 30 func (e *TypeAssertionError) Error() string { 31 inter := "interface" 32 if e._interface != nil { 33 inter = toRType(e._interface).string() 34 } 35 as := toRType(e.asserted).string() 36 if e.concrete == nil { 37 return "interface conversion: " + inter + " is nil, not " + as 38 } 39 cs := toRType(e.concrete).string() 40 if e.missingMethod == "" { 41 msg := "interface conversion: " + inter + " is " + cs + ", not " + as 42 if cs == as { 43 // provide slightly clearer error message 44 if toRType(e.concrete).pkgpath() != toRType(e.asserted).pkgpath() { 45 msg += " (types from different packages)" 46 } else { 47 msg += " (types from different scopes)" 48 } 49 } 50 return msg 51 } 52 return "interface conversion: " + cs + " is not " + as + 53 ": missing method " + e.missingMethod 54 } 55 56 // itoa converts val to a decimal representation. The result is 57 // written somewhere within buf and the location of the result is returned. 58 // buf must be at least 20 bytes. 59 // 60 //go:nosplit 61 func itoa(buf []byte, val uint64) []byte { 62 i := len(buf) - 1 63 for val >= 10 { 64 buf[i] = byte(val%10 + '0') 65 i-- 66 val /= 10 67 } 68 buf[i] = byte(val + '0') 69 return buf[i:] 70 } 71 72 // An errorString represents a runtime error described by a single string. 73 type errorString string 74 75 func (e errorString) RuntimeError() {} 76 77 func (e errorString) Error() string { 78 return "runtime error: " + string(e) 79 } 80 81 type errorAddressString struct { 82 msg string // error message 83 addr uintptr // memory address where the error occurred 84 } 85 86 func (e errorAddressString) RuntimeError() {} 87 88 func (e errorAddressString) Error() string { 89 return "runtime error: " + e.msg 90 } 91 92 // Addr returns the memory address where a fault occurred. 93 // The address provided is best-effort. 94 // The veracity of the result may depend on the platform. 95 // Errors providing this method will only be returned as 96 // a result of using runtime/debug.SetPanicOnFault. 97 func (e errorAddressString) Addr() uintptr { 98 return e.addr 99 } 100 101 // plainError represents a runtime error described a string without 102 // the prefix "runtime error: " after invoking errorString.Error(). 103 // See Issue #14965. 104 type plainError string 105 106 func (e plainError) RuntimeError() {} 107 108 func (e plainError) Error() string { 109 return string(e) 110 } 111 112 // A boundsError represents an indexing or slicing operation gone wrong. 113 type boundsError struct { 114 x int64 115 y int 116 // Values in an index or slice expression can be signed or unsigned. 117 // That means we'd need 65 bits to encode all possible indexes, from -2^63 to 2^64-1. 118 // Instead, we keep track of whether x should be interpreted as signed or unsigned. 119 // y is known to be nonnegative and to fit in an int. 120 signed bool 121 code boundsErrorCode 122 } 123 124 type boundsErrorCode uint8 125 126 const ( 127 boundsIndex boundsErrorCode = iota // s[x], 0 <= x < len(s) failed 128 129 boundsSliceAlen // s[?:x], 0 <= x <= len(s) failed 130 boundsSliceAcap // s[?:x], 0 <= x <= cap(s) failed 131 boundsSliceB // s[x:y], 0 <= x <= y failed (but boundsSliceA didn't happen) 132 133 boundsSlice3Alen // s[?:?:x], 0 <= x <= len(s) failed 134 boundsSlice3Acap // s[?:?:x], 0 <= x <= cap(s) failed 135 boundsSlice3B // s[?:x:y], 0 <= x <= y failed (but boundsSlice3A didn't happen) 136 boundsSlice3C // s[x:y:?], 0 <= x <= y failed (but boundsSlice3A/B didn't happen) 137 138 boundsConvert // (*[x]T)(s), 0 <= x <= len(s) failed 139 // Note: in the above, len(s) and cap(s) are stored in y 140 ) 141 142 // boundsErrorFmts provide error text for various out-of-bounds panics. 143 // Note: if you change these strings, you should adjust the size of the buffer 144 // in boundsError.Error below as well. 145 var boundsErrorFmts = [...]string{ 146 boundsIndex: "index out of range [%x] with length %y", 147 boundsSliceAlen: "slice bounds out of range [:%x] with length %y", 148 boundsSliceAcap: "slice bounds out of range [:%x] with capacity %y", 149 boundsSliceB: "slice bounds out of range [%x:%y]", 150 boundsSlice3Alen: "slice bounds out of range [::%x] with length %y", 151 boundsSlice3Acap: "slice bounds out of range [::%x] with capacity %y", 152 boundsSlice3B: "slice bounds out of range [:%x:%y]", 153 boundsSlice3C: "slice bounds out of range [%x:%y:]", 154 boundsConvert: "cannot convert slice with length %y to array or pointer to array with length %x", 155 } 156 157 // boundsNegErrorFmts are overriding formats if x is negative. In this case there's no need to report y. 158 var boundsNegErrorFmts = [...]string{ 159 boundsIndex: "index out of range [%x]", 160 boundsSliceAlen: "slice bounds out of range [:%x]", 161 boundsSliceAcap: "slice bounds out of range [:%x]", 162 boundsSliceB: "slice bounds out of range [%x:]", 163 boundsSlice3Alen: "slice bounds out of range [::%x]", 164 boundsSlice3Acap: "slice bounds out of range [::%x]", 165 boundsSlice3B: "slice bounds out of range [:%x:]", 166 boundsSlice3C: "slice bounds out of range [%x::]", 167 } 168 169 func (e boundsError) RuntimeError() {} 170 171 func appendIntStr(b []byte, v int64, signed bool) []byte { 172 if signed && v < 0 { 173 b = append(b, '-') 174 v = -v 175 } 176 var buf [20]byte 177 b = append(b, itoa(buf[:], uint64(v))...) 178 return b 179 } 180 181 func (e boundsError) Error() string { 182 fmt := boundsErrorFmts[e.code] 183 if e.signed && e.x < 0 { 184 fmt = boundsNegErrorFmts[e.code] 185 } 186 // max message length is 99: "runtime error: slice bounds out of range [::%x] with capacity %y" 187 // x can be at most 20 characters. y can be at most 19. 188 b := make([]byte, 0, 100) 189 b = append(b, "runtime error: "...) 190 for i := 0; i < len(fmt); i++ { 191 c := fmt[i] 192 if c != '%' { 193 b = append(b, c) 194 continue 195 } 196 i++ 197 switch fmt[i] { 198 case 'x': 199 b = appendIntStr(b, e.x, e.signed) 200 case 'y': 201 b = appendIntStr(b, int64(e.y), true) 202 } 203 } 204 return string(b) 205 } 206 207 type stringer interface { 208 String() string 209 } 210 211 // printany prints an argument passed to panic. 212 // If panic is called with a value that has a String or Error method, 213 // it has already been converted into a string by preprintpanics. 214 func printany(i any) { 215 switch v := i.(type) { 216 case nil: 217 print("nil") 218 case bool: 219 print(v) 220 case int: 221 print(v) 222 case int8: 223 print(v) 224 case int16: 225 print(v) 226 case int32: 227 print(v) 228 case int64: 229 print(v) 230 case uint: 231 print(v) 232 case uint8: 233 print(v) 234 case uint16: 235 print(v) 236 case uint32: 237 print(v) 238 case uint64: 239 print(v) 240 case uintptr: 241 print(v) 242 case float32: 243 print(v) 244 case float64: 245 print(v) 246 case complex64: 247 print(v) 248 case complex128: 249 print(v) 250 case string: 251 print(v) 252 default: 253 printanycustomtype(i) 254 } 255 } 256 257 func printanycustomtype(i any) { 258 eface := efaceOf(&i) 259 typestring := toRType(eface._type).string() 260 261 switch eface._type.Kind_ { 262 case kindString: 263 print(typestring, `("`, *(*string)(eface.data), `")`) 264 case kindBool: 265 print(typestring, "(", *(*bool)(eface.data), ")") 266 case kindInt: 267 print(typestring, "(", *(*int)(eface.data), ")") 268 case kindInt8: 269 print(typestring, "(", *(*int8)(eface.data), ")") 270 case kindInt16: 271 print(typestring, "(", *(*int16)(eface.data), ")") 272 case kindInt32: 273 print(typestring, "(", *(*int32)(eface.data), ")") 274 case kindInt64: 275 print(typestring, "(", *(*int64)(eface.data), ")") 276 case kindUint: 277 print(typestring, "(", *(*uint)(eface.data), ")") 278 case kindUint8: 279 print(typestring, "(", *(*uint8)(eface.data), ")") 280 case kindUint16: 281 print(typestring, "(", *(*uint16)(eface.data), ")") 282 case kindUint32: 283 print(typestring, "(", *(*uint32)(eface.data), ")") 284 case kindUint64: 285 print(typestring, "(", *(*uint64)(eface.data), ")") 286 case kindUintptr: 287 print(typestring, "(", *(*uintptr)(eface.data), ")") 288 case kindFloat32: 289 print(typestring, "(", *(*float32)(eface.data), ")") 290 case kindFloat64: 291 print(typestring, "(", *(*float64)(eface.data), ")") 292 case kindComplex64: 293 print(typestring, *(*complex64)(eface.data)) 294 case kindComplex128: 295 print(typestring, *(*complex128)(eface.data)) 296 default: 297 print("(", typestring, ") ", eface.data) 298 } 299 } 300 301 // panicwrap generates a panic for a call to a wrapped value method 302 // with a nil pointer receiver. 303 // 304 // It is called from the generated wrapper code. 305 func panicwrap() { 306 pc := getcallerpc() 307 name := funcNameForPrint(funcname(findfunc(pc))) 308 // name is something like "main.(*T).F". 309 // We want to extract pkg ("main"), typ ("T"), and meth ("F"). 310 // Do it by finding the parens. 311 i := bytealg.IndexByteString(name, '(') 312 if i < 0 { 313 throw("panicwrap: no ( in " + name) 314 } 315 pkg := name[:i-1] 316 if i+2 >= len(name) || name[i-1:i+2] != ".(*" { 317 throw("panicwrap: unexpected string after package name: " + name) 318 } 319 name = name[i+2:] 320 i = bytealg.IndexByteString(name, ')') 321 if i < 0 { 322 throw("panicwrap: no ) in " + name) 323 } 324 if i+2 >= len(name) || name[i:i+2] != ")." { 325 throw("panicwrap: unexpected string after type name: " + name) 326 } 327 typ := name[:i] 328 meth := name[i+2:] 329 panic(plainError("value method " + pkg + "." + typ + "." + meth + " called using nil *" + typ + " pointer")) 330 }