0c7f631988457080bb42b17c263eca090736db21
[platform/upstream/gcc.git] / libgo / go / runtime / error.go
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 "unsafe"
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 // Remove quoted strings from gccgo reflection strings.
57 func 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.
86 func 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.
98 type errorString string
99
100 func (e errorString) RuntimeError() {}
101
102 func (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.
108 type errorCString struct{ cstr uintptr }
109
110 func (e errorCString) RuntimeError() {}
111
112 func (e errorCString) Error() string {
113         return "runtime error: " + gostringnocopy((*byte)(unsafe.Pointer(e.cstr)))
114 }
115
116 // For calling from C.
117 func 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.
124 type plainError string
125
126 func (e plainError) RuntimeError() {}
127
128 func (e plainError) Error() string {
129         return string(e)
130 }
131
132 // An boundsError represents a an indexing or slicing operation gone wrong.
133 type 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
144 type boundsErrorCode uint8
145
146 const (
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.
164 var 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.
176 var 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
187 func (e boundsError) RuntimeError() {}
188
189 func 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
199 func (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
225 type stringer interface {
226         String() string
227 }
228
229 func 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.
237 func 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 }