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