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 5package runtime 6 7import "unsafe" 8 9// The Error interface identifies a run time error. 10type 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. 21type TypeAssertionError struct { 22 _interface *_type 23 concrete *_type 24 asserted *_type 25 missingMethod string // one method needed by Interface, missing from Concrete 26} 27 28func (*TypeAssertionError) RuntimeError() {} 29 30func (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// Remove quoted strings from gccgo reflection strings. 57func unquote(s string) string { 58 ls := len(s) 59 var i int 60 for i = 0; i < ls; i++ { 61 if s[i] == '\t' { 62 break 63 } 64 } 65 if i == ls { 66 return s 67 } 68 var q bool 69 r := make([]byte, len(s)) 70 j := 0 71 for i = 0; i < ls; i++ { 72 if s[i] == '\t' { 73 q = !q 74 } else if !q { 75 r[j] = s[i] 76 j++ 77 } 78 } 79 return string(r[:j]) 80} 81 82//go:nosplit 83// itoa converts val to a decimal representation. The result is 84// written somewhere within buf and the location of the result is returned. 85// buf must be at least 20 bytes. 86func itoa(buf []byte, val uint64) []byte { 87 i := len(buf) - 1 88 for val >= 10 { 89 buf[i] = byte(val%10 + '0') 90 i-- 91 val /= 10 92 } 93 buf[i] = byte(val + '0') 94 return buf[i:] 95} 96 97// An errorString represents a runtime error described by a single string. 98type errorString string 99 100func (e errorString) RuntimeError() {} 101 102func (e errorString) Error() string { 103 return "runtime error: " + string(e) 104} 105 106// An errorCString represents a runtime error described by a single C string. 107// Not "type errorCString uintptr" because of http://golang.org/issue/7084. 108type errorCString struct{ cstr uintptr } 109 110func (e errorCString) RuntimeError() {} 111 112func (e errorCString) Error() string { 113 return "runtime error: " + gostringnocopy((*byte)(unsafe.Pointer(e.cstr))) 114} 115 116// For calling from C. 117func NewErrorCString(s uintptr, ret *interface{}) { 118 *ret = errorCString{s} 119} 120 121// plainError represents a runtime error described a string without 122// the prefix "runtime error: " after invoking errorString.Error(). 123// See Issue #14965. 124type plainError string 125 126func (e plainError) RuntimeError() {} 127 128func (e plainError) Error() string { 129 return string(e) 130} 131 132// A boundsError represents an indexing or slicing operation gone wrong. 133type boundsError struct { 134 x int64 135 y int 136 // Values in an index or slice expression can be signed or unsigned. 137 // That means we'd need 65 bits to encode all possible indexes, from -2^63 to 2^64-1. 138 // Instead, we keep track of whether x should be interpreted as signed or unsigned. 139 // y is known to be nonnegative and to fit in an int. 140 signed bool 141 code boundsErrorCode 142} 143 144type boundsErrorCode uint8 145 146const ( 147 boundsIndex boundsErrorCode = iota // s[x], 0 <= x < len(s) failed 148 149 boundsSliceAlen // s[?:x], 0 <= x <= len(s) failed 150 boundsSliceAcap // s[?:x], 0 <= x <= cap(s) failed 151 boundsSliceB // s[x:y], 0 <= x <= y failed (but boundsSliceA didn't happen) 152 153 boundsSlice3Alen // s[?:?:x], 0 <= x <= len(s) failed 154 boundsSlice3Acap // s[?:?:x], 0 <= x <= cap(s) failed 155 boundsSlice3B // s[?:x:y], 0 <= x <= y failed (but boundsSlice3A didn't happen) 156 boundsSlice3C // s[x:y:?], 0 <= x <= y failed (but boundsSlice3A/B didn't happen) 157 158 // Note: in the above, len(s) and cap(s) are stored in y 159) 160 161// boundsErrorFmts provide error text for various out-of-bounds panics. 162// Note: if you change these strings, you should adjust the size of the buffer 163// in boundsError.Error below as well. 164var boundsErrorFmts = [...]string{ 165 boundsIndex: "index out of range [%x] with length %y", 166 boundsSliceAlen: "slice bounds out of range [:%x] with length %y", 167 boundsSliceAcap: "slice bounds out of range [:%x] with capacity %y", 168 boundsSliceB: "slice bounds out of range [%x:%y]", 169 boundsSlice3Alen: "slice bounds out of range [::%x] with length %y", 170 boundsSlice3Acap: "slice bounds out of range [::%x] with capacity %y", 171 boundsSlice3B: "slice bounds out of range [:%x:%y]", 172 boundsSlice3C: "slice bounds out of range [%x:%y:]", 173} 174 175// boundsNegErrorFmts are overriding formats if x is negative. In this case there's no need to report y. 176var boundsNegErrorFmts = [...]string{ 177 boundsIndex: "index out of range [%x]", 178 boundsSliceAlen: "slice bounds out of range [:%x]", 179 boundsSliceAcap: "slice bounds out of range [:%x]", 180 boundsSliceB: "slice bounds out of range [%x:]", 181 boundsSlice3Alen: "slice bounds out of range [::%x]", 182 boundsSlice3Acap: "slice bounds out of range [::%x]", 183 boundsSlice3B: "slice bounds out of range [:%x:]", 184 boundsSlice3C: "slice bounds out of range [%x::]", 185} 186 187func (e boundsError) RuntimeError() {} 188 189func appendIntStr(b []byte, v int64, signed bool) []byte { 190 if signed && v < 0 { 191 b = append(b, '-') 192 v = -v 193 } 194 var buf [20]byte 195 b = append(b, itoa(buf[:], uint64(v))...) 196 return b 197} 198 199func (e boundsError) Error() string { 200 fmt := boundsErrorFmts[e.code] 201 if e.signed && e.x < 0 { 202 fmt = boundsNegErrorFmts[e.code] 203 } 204 // max message length is 99: "runtime error: slice bounds out of range [::%x] with capacity %y" 205 // x can be at most 20 characters. y can be at most 19. 206 b := make([]byte, 0, 100) 207 b = append(b, "runtime error: "...) 208 for i := 0; i < len(fmt); i++ { 209 c := fmt[i] 210 if c != '%' { 211 b = append(b, c) 212 continue 213 } 214 i++ 215 switch fmt[i] { 216 case 'x': 217 b = appendIntStr(b, e.x, e.signed) 218 case 'y': 219 b = appendIntStr(b, int64(e.y), true) 220 } 221 } 222 return string(b) 223} 224 225type stringer interface { 226 String() string 227} 228 229func typestring(x interface{}) string { 230 e := efaceOf(&x) 231 return e._type.string() 232} 233 234// printany prints an argument passed to panic. 235// If panic is called with a value that has a String or Error method, 236// it has already been converted into a string by preprintpanics. 237func printany(i interface{}) { 238 switch v := i.(type) { 239 case nil: 240 print("nil") 241 case bool: 242 print(v) 243 case int: 244 print(v) 245 case int8: 246 print(v) 247 case int16: 248 print(v) 249 case int32: 250 print(v) 251 case int64: 252 print(v) 253 case uint: 254 print(v) 255 case uint8: 256 print(v) 257 case uint16: 258 print(v) 259 case uint32: 260 print(v) 261 case uint64: 262 print(v) 263 case uintptr: 264 print(v) 265 case float32: 266 print(v) 267 case float64: 268 print(v) 269 case complex64: 270 print(v) 271 case complex128: 272 print(v) 273 case string: 274 print(v) 275 default: 276 print("(", typestring(i), ") ", i) 277 } 278} 279