Source file
src/runtime/error.go
1
2
3
4
5 package runtime
6
7 import (
8 "internal/abi"
9 "internal/bytealg"
10 )
11
12
13 type Error interface {
14 error
15
16
17
18
19
20 RuntimeError()
21 }
22
23
24 type TypeAssertionError struct {
25 _interface *_type
26 concrete *_type
27 asserted *_type
28 missingMethod string
29 }
30
31 func (*TypeAssertionError) RuntimeError() {}
32
33 func (e *TypeAssertionError) Error() string {
34 inter := "interface"
35 if e._interface != nil {
36 inter = toRType(e._interface).string()
37 }
38 as := toRType(e.asserted).string()
39 if e.concrete == nil {
40 return "interface conversion: " + inter + " is nil, not " + as
41 }
42 cs := toRType(e.concrete).string()
43 if e.missingMethod == "" {
44 msg := "interface conversion: " + inter + " is " + cs + ", not " + as
45 if cs == as {
46
47 if toRType(e.concrete).pkgpath() != toRType(e.asserted).pkgpath() {
48 msg += " (types from different packages)"
49 } else {
50 msg += " (types from different scopes)"
51 }
52 }
53 return msg
54 }
55 return "interface conversion: " + cs + " is not " + as +
56 ": missing method " + e.missingMethod
57 }
58
59
60
61
62
63
64 func itoa(buf []byte, val uint64) []byte {
65 i := len(buf) - 1
66 for val >= 10 {
67 buf[i] = byte(val%10 + '0')
68 i--
69 val /= 10
70 }
71 buf[i] = byte(val + '0')
72 return buf[i:]
73 }
74
75
76 type errorString string
77
78 func (e errorString) RuntimeError() {}
79
80 func (e errorString) Error() string {
81 return "runtime error: " + string(e)
82 }
83
84 type errorAddressString struct {
85 msg string
86 addr uintptr
87 }
88
89 func (e errorAddressString) RuntimeError() {}
90
91 func (e errorAddressString) Error() string {
92 return "runtime error: " + e.msg
93 }
94
95
96
97
98
99
100 func (e errorAddressString) Addr() uintptr {
101 return e.addr
102 }
103
104
105
106
107 type plainError string
108
109 func (e plainError) RuntimeError() {}
110
111 func (e plainError) Error() string {
112 return string(e)
113 }
114
115
116 type boundsError struct {
117 x int64
118 y int
119
120
121
122
123 signed bool
124 code boundsErrorCode
125 }
126
127 type boundsErrorCode uint8
128
129 const (
130 boundsIndex boundsErrorCode = iota
131
132 boundsSliceAlen
133 boundsSliceAcap
134 boundsSliceB
135
136 boundsSlice3Alen
137 boundsSlice3Acap
138 boundsSlice3B
139 boundsSlice3C
140
141 boundsConvert
142
143 )
144
145
146
147
148 var boundsErrorFmts = [...]string{
149 boundsIndex: "index out of range [%x] with length %y",
150 boundsSliceAlen: "slice bounds out of range [:%x] with length %y",
151 boundsSliceAcap: "slice bounds out of range [:%x] with capacity %y",
152 boundsSliceB: "slice bounds out of range [%x:%y]",
153 boundsSlice3Alen: "slice bounds out of range [::%x] with length %y",
154 boundsSlice3Acap: "slice bounds out of range [::%x] with capacity %y",
155 boundsSlice3B: "slice bounds out of range [:%x:%y]",
156 boundsSlice3C: "slice bounds out of range [%x:%y:]",
157 boundsConvert: "cannot convert slice with length %y to array or pointer to array with length %x",
158 }
159
160
161 var boundsNegErrorFmts = [...]string{
162 boundsIndex: "index out of range [%x]",
163 boundsSliceAlen: "slice bounds out of range [:%x]",
164 boundsSliceAcap: "slice bounds out of range [:%x]",
165 boundsSliceB: "slice bounds out of range [%x:]",
166 boundsSlice3Alen: "slice bounds out of range [::%x]",
167 boundsSlice3Acap: "slice bounds out of range [::%x]",
168 boundsSlice3B: "slice bounds out of range [:%x:]",
169 boundsSlice3C: "slice bounds out of range [%x::]",
170 }
171
172 func (e boundsError) RuntimeError() {}
173
174 func appendIntStr(b []byte, v int64, signed bool) []byte {
175 if signed && v < 0 {
176 b = append(b, '-')
177 v = -v
178 }
179 var buf [20]byte
180 b = append(b, itoa(buf[:], uint64(v))...)
181 return b
182 }
183
184 func (e boundsError) Error() string {
185 fmt := boundsErrorFmts[e.code]
186 if e.signed && e.x < 0 {
187 fmt = boundsNegErrorFmts[e.code]
188 }
189
190
191 b := make([]byte, 0, 100)
192 b = append(b, "runtime error: "...)
193 for i := 0; i < len(fmt); i++ {
194 c := fmt[i]
195 if c != '%' {
196 b = append(b, c)
197 continue
198 }
199 i++
200 switch fmt[i] {
201 case 'x':
202 b = appendIntStr(b, e.x, e.signed)
203 case 'y':
204 b = appendIntStr(b, int64(e.y), true)
205 }
206 }
207 return string(b)
208 }
209
210 type stringer interface {
211 String() string
212 }
213
214
215
216
217
218
219
220
221
222 func printpanicval(v any) {
223 switch v := v.(type) {
224 case nil:
225 print("nil")
226 case bool:
227 print(v)
228 case int:
229 print(v)
230 case int8:
231 print(v)
232 case int16:
233 print(v)
234 case int32:
235 print(v)
236 case int64:
237 print(v)
238 case uint:
239 print(v)
240 case uint8:
241 print(v)
242 case uint16:
243 print(v)
244 case uint32:
245 print(v)
246 case uint64:
247 print(v)
248 case uintptr:
249 print(v)
250 case float32:
251 print(v)
252 case float64:
253 print(v)
254 case complex64:
255 print(v)
256 case complex128:
257 print(v)
258 case string:
259 printindented(v)
260 default:
261 printanycustomtype(v)
262 }
263 }
264
265
266 func printanycustomtype(i any) {
267 eface := efaceOf(&i)
268 typestring := toRType(eface._type).string()
269
270 switch eface._type.Kind_ {
271 case abi.String:
272 print(typestring, `("`)
273 printindented(*(*string)(eface.data))
274 print(`")`)
275 case abi.Bool:
276 print(typestring, "(", *(*bool)(eface.data), ")")
277 case abi.Int:
278 print(typestring, "(", *(*int)(eface.data), ")")
279 case abi.Int8:
280 print(typestring, "(", *(*int8)(eface.data), ")")
281 case abi.Int16:
282 print(typestring, "(", *(*int16)(eface.data), ")")
283 case abi.Int32:
284 print(typestring, "(", *(*int32)(eface.data), ")")
285 case abi.Int64:
286 print(typestring, "(", *(*int64)(eface.data), ")")
287 case abi.Uint:
288 print(typestring, "(", *(*uint)(eface.data), ")")
289 case abi.Uint8:
290 print(typestring, "(", *(*uint8)(eface.data), ")")
291 case abi.Uint16:
292 print(typestring, "(", *(*uint16)(eface.data), ")")
293 case abi.Uint32:
294 print(typestring, "(", *(*uint32)(eface.data), ")")
295 case abi.Uint64:
296 print(typestring, "(", *(*uint64)(eface.data), ")")
297 case abi.Uintptr:
298 print(typestring, "(", *(*uintptr)(eface.data), ")")
299 case abi.Float32:
300 print(typestring, "(", *(*float32)(eface.data), ")")
301 case abi.Float64:
302 print(typestring, "(", *(*float64)(eface.data), ")")
303 case abi.Complex64:
304 print(typestring, *(*complex64)(eface.data))
305 case abi.Complex128:
306 print(typestring, *(*complex128)(eface.data))
307 default:
308 print("(", typestring, ") ", eface.data)
309 }
310 }
311
312
313 func printindented(s string) {
314 for {
315 i := bytealg.IndexByteString(s, '\n')
316 if i < 0 {
317 break
318 }
319 i += len("\n")
320 print(s[:i])
321 print("\t")
322 s = s[i:]
323 }
324 print(s)
325 }
326
327
328
329
330
331 func panicwrap() {
332 pc := getcallerpc()
333 name := funcNameForPrint(funcname(findfunc(pc)))
334
335
336
337 i := bytealg.IndexByteString(name, '(')
338 if i < 0 {
339 throw("panicwrap: no ( in " + name)
340 }
341 pkg := name[:i-1]
342 if i+2 >= len(name) || name[i-1:i+2] != ".(*" {
343 throw("panicwrap: unexpected string after package name: " + name)
344 }
345 name = name[i+2:]
346 i = bytealg.IndexByteString(name, ')')
347 if i < 0 {
348 throw("panicwrap: no ) in " + name)
349 }
350 if i+2 >= len(name) || name[i:i+2] != ")." {
351 throw("panicwrap: unexpected string after type name: " + name)
352 }
353 typ := name[:i]
354 meth := name[i+2:]
355 panic(plainError("value method " + pkg + "." + typ + "." + meth + " called using nil *" + typ + " pointer"))
356 }
357
View as plain text