...
Source file src/runtime/error.go
1
2
3
4
5 package runtime
6
7 import "internal/bytealg"
8
9
10 type Error interface {
11 error
12
13
14
15
16
17 RuntimeError()
18 }
19
20
21 type TypeAssertionError struct {
22 _interface *_type
23 concrete *_type
24 asserted *_type
25 missingMethod string
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
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
57
58
59
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
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
81
82
83 type plainError string
84
85 func (e plainError) RuntimeError() {}
86
87 func (e plainError) Error() string {
88 return string(e)
89 }
90
91
92 type boundsError struct {
93 x int64
94 y int
95
96
97
98
99 signed bool
100 code boundsErrorCode
101 }
102
103 type boundsErrorCode uint8
104
105 const (
106 boundsIndex boundsErrorCode = iota
107
108 boundsSliceAlen
109 boundsSliceAcap
110 boundsSliceB
111
112 boundsSlice3Alen
113 boundsSlice3Acap
114 boundsSlice3B
115 boundsSlice3C
116
117
118 )
119
120
121
122
123 var boundsErrorFmts = [...]string{
124 boundsIndex: "index out of range [%x] with length %y",
125 boundsSliceAlen: "slice bounds out of range [:%x] with length %y",
126 boundsSliceAcap: "slice bounds out of range [:%x] with capacity %y",
127 boundsSliceB: "slice bounds out of range [%x:%y]",
128 boundsSlice3Alen: "slice bounds out of range [::%x] with length %y",
129 boundsSlice3Acap: "slice bounds out of range [::%x] with capacity %y",
130 boundsSlice3B: "slice bounds out of range [:%x:%y]",
131 boundsSlice3C: "slice bounds out of range [%x:%y:]",
132 }
133
134
135 var boundsNegErrorFmts = [...]string{
136 boundsIndex: "index out of range [%x]",
137 boundsSliceAlen: "slice bounds out of range [:%x]",
138 boundsSliceAcap: "slice bounds out of range [:%x]",
139 boundsSliceB: "slice bounds out of range [%x:]",
140 boundsSlice3Alen: "slice bounds out of range [::%x]",
141 boundsSlice3Acap: "slice bounds out of range [::%x]",
142 boundsSlice3B: "slice bounds out of range [:%x:]",
143 boundsSlice3C: "slice bounds out of range [%x::]",
144 }
145
146 func (e boundsError) RuntimeError() {}
147
148 func appendIntStr(b []byte, v int64, signed bool) []byte {
149 if signed && v < 0 {
150 b = append(b, '-')
151 v = -v
152 }
153 var buf [20]byte
154 b = append(b, itoa(buf[:], uint64(v))...)
155 return b
156 }
157
158 func (e boundsError) Error() string {
159 fmt := boundsErrorFmts[e.code]
160 if e.signed && e.x < 0 {
161 fmt = boundsNegErrorFmts[e.code]
162 }
163
164
165 b := make([]byte, 0, 100)
166 b = append(b, "runtime error: "...)
167 for i := 0; i < len(fmt); i++ {
168 c := fmt[i]
169 if c != '%' {
170 b = append(b, c)
171 continue
172 }
173 i++
174 switch fmt[i] {
175 case 'x':
176 b = appendIntStr(b, e.x, e.signed)
177 case 'y':
178 b = appendIntStr(b, int64(e.y), true)
179 }
180 }
181 return string(b)
182 }
183
184 type stringer interface {
185 String() string
186 }
187
188 func typestring(x interface{}) string {
189 e := efaceOf(&x)
190 return e._type.string()
191 }
192
193
194
195
196 func printany(i interface{}) {
197 switch v := i.(type) {
198 case nil:
199 print("nil")
200 case bool:
201 print(v)
202 case int:
203 print(v)
204 case int8:
205 print(v)
206 case int16:
207 print(v)
208 case int32:
209 print(v)
210 case int64:
211 print(v)
212 case uint:
213 print(v)
214 case uint8:
215 print(v)
216 case uint16:
217 print(v)
218 case uint32:
219 print(v)
220 case uint64:
221 print(v)
222 case uintptr:
223 print(v)
224 case float32:
225 print(v)
226 case float64:
227 print(v)
228 case complex64:
229 print(v)
230 case complex128:
231 print(v)
232 case string:
233 print(v)
234 default:
235 print("(", typestring(i), ") ", i)
236 }
237 }
238
239
240
241
242
243 func panicwrap() {
244 pc := getcallerpc()
245 name := funcname(findfunc(pc))
246
247
248
249 i := bytealg.IndexByteString(name, '(')
250 if i < 0 {
251 throw("panicwrap: no ( in " + name)
252 }
253 pkg := name[:i-1]
254 if i+2 >= len(name) || name[i-1:i+2] != ".(*" {
255 throw("panicwrap: unexpected string after package name: " + name)
256 }
257 name = name[i+2:]
258 i = bytealg.IndexByteString(name, ')')
259 if i < 0 {
260 throw("panicwrap: no ) in " + name)
261 }
262 if i+2 >= len(name) || name[i:i+2] != ")." {
263 throw("panicwrap: unexpected string after type name: " + name)
264 }
265 typ := name[:i]
266 meth := name[i+2:]
267 panic(plainError("value method " + pkg + "." + typ + "." + meth + " called using nil *" + typ + " pointer"))
268 }
269
View as plain text