Source file
src/go/types/errors.go
1
2
3
4
5
6
7 package types
8
9 import (
10 "fmt"
11 "go/ast"
12 "go/token"
13 . "internal/types/errors"
14 "runtime"
15 "strings"
16 )
17
18 func assert(p bool) {
19 if !p {
20 msg := "assertion failed"
21
22
23 if _, file, line, ok := runtime.Caller(1); ok {
24 msg = fmt.Sprintf("%s:%d: %s", file, line, msg)
25 }
26 panic(msg)
27 }
28 }
29
30
31 type errorDesc struct {
32 posn positioner
33 msg string
34 }
35
36
37
38
39 type error_ struct {
40 check *Checker
41 desc []errorDesc
42 code Code
43 soft bool
44 }
45
46
47 func (check *Checker) newError(code Code) *error_ {
48 if code == 0 {
49 panic("error code must not be 0")
50 }
51 return &error_{check: check, code: code}
52 }
53
54
55
56
57
58
59
60 func (err *error_) addf(at positioner, format string, args ...interface{}) {
61 err.desc = append(err.desc, errorDesc{at, err.check.sprintf(format, args...)})
62 }
63
64
65 func (err *error_) addAltDecl(obj Object) {
66 if pos := obj.Pos(); pos.IsValid() {
67
68
69
70 err.addf(obj, "other declaration of %s", obj.Name())
71 }
72 }
73
74 func (err *error_) empty() bool {
75 return err.desc == nil
76 }
77
78 func (err *error_) posn() positioner {
79 if err.empty() {
80 return noposn
81 }
82 return err.desc[0].posn
83 }
84
85
86 func (err *error_) msg() string {
87 if err.empty() {
88 return "no error"
89 }
90
91 var buf strings.Builder
92 for i := range err.desc {
93 p := &err.desc[i]
94 if i > 0 {
95 fmt.Fprint(&buf, "\n\t")
96 if p.posn.Pos().IsValid() {
97 fmt.Fprintf(&buf, "%s: ", err.check.fset.Position(p.posn.Pos()))
98 }
99 }
100 buf.WriteString(p.msg)
101 }
102 return buf.String()
103 }
104
105
106 func (err *error_) report() {
107 if err.empty() {
108 panic("no error")
109 }
110
111
112
113
114
115
116 check := err.check
117 if check.firstErr != nil {
118
119 msg := err.desc[0].msg
120 if strings.Index(msg, "invalid operand") > 0 || strings.Index(msg, "invalid type") > 0 {
121 return
122 }
123 }
124
125 if check.conf._Trace {
126 check.trace(err.posn().Pos(), "ERROR: %s (code = %d)", err.desc[0].msg, err.code)
127 }
128
129
130
131
132 multiError := false
133 if !isTypes2 {
134 for i := 1; i < len(err.desc); i++ {
135 if err.desc[i].posn.Pos().IsValid() {
136 multiError = true
137 break
138 }
139 }
140 }
141
142 if multiError {
143 for i := range err.desc {
144 p := &err.desc[i]
145 check.handleError(i, p.posn, err.code, p.msg, err.soft)
146 }
147 } else {
148 check.handleError(0, err.posn(), err.code, err.msg(), err.soft)
149 }
150
151
152 err.desc = nil
153 }
154
155
156 func (check *Checker) handleError(index int, posn positioner, code Code, msg string, soft bool) {
157 assert(code != 0)
158
159 if index == 0 {
160
161
162
163
164
165
166 if check.errpos != nil && check.errpos.Pos().IsValid() {
167 assert(check.iota != nil)
168 posn = check.errpos
169 }
170
171
172 if code == InvalidSyntaxTree {
173 msg = "invalid syntax tree: " + msg
174 }
175
176
177 if check.conf._ErrorURL != "" {
178 url := fmt.Sprintf(check.conf._ErrorURL, code)
179 if i := strings.Index(msg, "\n"); i >= 0 {
180 msg = msg[:i] + url + msg[i:]
181 } else {
182 msg += url
183 }
184 }
185 } else {
186
187
188 msg = "\t" + msg
189 }
190
191 span := spanOf(posn)
192 e := Error{
193 Fset: check.fset,
194 Pos: span.pos,
195 Msg: stripAnnotations(msg),
196 Soft: soft,
197 go116code: code,
198 go116start: span.start,
199 go116end: span.end,
200 }
201
202 if check.errpos != nil {
203
204
205
206
207 span := spanOf(check.errpos)
208 e.Pos = span.pos
209 e.go116start = span.start
210 e.go116end = span.end
211 }
212
213 if check.firstErr == nil {
214 check.firstErr = e
215 }
216
217 f := check.conf.Error
218 if f == nil {
219 panic(bailout{})
220 }
221 f(e)
222 }
223
224 const (
225 invalidArg = "invalid argument: "
226 invalidOp = "invalid operation: "
227 )
228
229
230 type positioner interface {
231 Pos() token.Pos
232 }
233
234 func (check *Checker) error(at positioner, code Code, msg string) {
235 err := check.newError(code)
236 err.addf(at, "%s", msg)
237 err.report()
238 }
239
240 func (check *Checker) errorf(at positioner, code Code, format string, args ...any) {
241 err := check.newError(code)
242 err.addf(at, format, args...)
243 err.report()
244 }
245
246 func (check *Checker) softErrorf(at positioner, code Code, format string, args ...any) {
247 err := check.newError(code)
248 err.addf(at, format, args...)
249 err.soft = true
250 err.report()
251 }
252
253 func (check *Checker) versionErrorf(at positioner, v goVersion, format string, args ...any) {
254 msg := check.sprintf(format, args...)
255 err := check.newError(UnsupportedFeature)
256 err.addf(at, "%s requires %s or later", msg, v)
257 err.report()
258 }
259
260
261 type atPos token.Pos
262
263 func (s atPos) Pos() token.Pos {
264 return token.Pos(s)
265 }
266
267
268
269
270
271
272 type posSpan struct {
273 start, pos, end token.Pos
274 }
275
276 func (e posSpan) Pos() token.Pos {
277 return e.pos
278 }
279
280
281
282
283 func inNode(node ast.Node, pos token.Pos) posSpan {
284 start, end := node.Pos(), node.End()
285 if debug {
286 assert(start <= pos && pos < end)
287 }
288 return posSpan{start, pos, end}
289 }
290
291
292
293
294 func spanOf(at positioner) posSpan {
295 switch x := at.(type) {
296 case nil:
297 panic("nil positioner")
298 case posSpan:
299 return x
300 case ast.Node:
301 pos := x.Pos()
302 return posSpan{pos, pos, x.End()}
303 case *operand:
304 if x.expr != nil {
305 pos := x.Pos()
306 return posSpan{pos, pos, x.expr.End()}
307 }
308 return posSpan{nopos, nopos, nopos}
309 default:
310 pos := at.Pos()
311 return posSpan{pos, pos, pos}
312 }
313 }
314
View as plain text