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