Source file
src/go/types/errors.go
1
2
3
4
5
6
7 package types
8
9 import (
10 "errors"
11 "fmt"
12 "go/ast"
13 "go/token"
14 "strconv"
15 "strings"
16 )
17
18 func assert(p bool) {
19 if !p {
20 panic("assertion failed")
21 }
22 }
23
24 func unreachable() {
25 panic("unreachable")
26 }
27
28 func (check *Checker) qualifier(pkg *Package) string {
29
30 if pkg != check.pkg {
31 if check.pkgPathMap == nil {
32 check.pkgPathMap = make(map[string]map[string]bool)
33 check.seenPkgMap = make(map[*Package]bool)
34 check.markImports(check.pkg)
35 }
36
37 if len(check.pkgPathMap[pkg.name]) > 1 {
38 return strconv.Quote(pkg.path)
39 }
40 return pkg.name
41 }
42 return ""
43 }
44
45
46
47 func (check *Checker) markImports(pkg *Package) {
48 if check.seenPkgMap[pkg] {
49 return
50 }
51 check.seenPkgMap[pkg] = true
52
53 forName, ok := check.pkgPathMap[pkg.name]
54 if !ok {
55 forName = make(map[string]bool)
56 check.pkgPathMap[pkg.name] = forName
57 }
58 forName[pkg.path] = true
59
60 for _, imp := range pkg.imports {
61 check.markImports(imp)
62 }
63 }
64
65 func (check *Checker) sprintf(format string, args ...interface{}) string {
66 for i, arg := range args {
67 switch a := arg.(type) {
68 case nil:
69 arg = "<nil>"
70 case operand:
71 panic("internal error: should always pass *operand")
72 case *operand:
73 arg = operandString(a, check.qualifier)
74 case token.Pos:
75 arg = check.fset.Position(a).String()
76 case ast.Expr:
77 arg = ExprString(a)
78 case Object:
79 arg = ObjectString(a, check.qualifier)
80 case Type:
81 arg = TypeString(a, check.qualifier)
82 }
83 args[i] = arg
84 }
85 return fmt.Sprintf(format, args...)
86 }
87
88 func (check *Checker) trace(pos token.Pos, format string, args ...interface{}) {
89 fmt.Printf("%s:\t%s%s\n",
90 check.fset.Position(pos),
91 strings.Repeat(". ", check.indent),
92 check.sprintf(format, args...),
93 )
94 }
95
96
97 func (check *Checker) dump(format string, args ...interface{}) {
98 fmt.Println(check.sprintf(format, args...))
99 }
100
101 func (check *Checker) err(err error) {
102 if err == nil {
103 return
104 }
105 var e Error
106 isInternal := errors.As(err, &e)
107
108
109
110
111
112 isInvalidErr := isInternal && (strings.Index(e.Msg, "invalid operand") > 0 || strings.Index(e.Msg, "invalid type") > 0)
113 if check.firstErr != nil && isInvalidErr {
114 return
115 }
116
117 if isInternal {
118 e.Msg = stripAnnotations(e.Msg)
119 if check.errpos != nil {
120
121
122
123
124 span := spanOf(check.errpos)
125 e.Pos = span.pos
126 e.go116start = span.start
127 e.go116end = span.end
128 }
129 err = e
130 }
131
132 if check.firstErr == nil {
133 check.firstErr = err
134 }
135
136 if trace {
137 pos := e.Pos
138 msg := e.Msg
139 if !isInternal {
140 msg = err.Error()
141 pos = token.NoPos
142 }
143 check.trace(pos, "ERROR: %s", msg)
144 }
145
146 f := check.conf.Error
147 if f == nil {
148 panic(bailout{})
149 }
150 f(err)
151 }
152
153 func (check *Checker) newError(at positioner, code errorCode, soft bool, msg string) error {
154 span := spanOf(at)
155 return Error{
156 Fset: check.fset,
157 Pos: span.pos,
158 Msg: msg,
159 Soft: soft,
160 go116code: code,
161 go116start: span.start,
162 go116end: span.end,
163 }
164 }
165
166
167 func (check *Checker) newErrorf(at positioner, code errorCode, soft bool, format string, args ...interface{}) error {
168 msg := check.sprintf(format, args...)
169 return check.newError(at, code, soft, msg)
170 }
171
172 func (check *Checker) error(at positioner, code errorCode, msg string) {
173 check.err(check.newError(at, code, false, msg))
174 }
175
176 func (check *Checker) errorf(at positioner, code errorCode, format string, args ...interface{}) {
177 check.error(at, code, check.sprintf(format, args...))
178 }
179
180 func (check *Checker) softErrorf(at positioner, code errorCode, format string, args ...interface{}) {
181 check.err(check.newErrorf(at, code, true, format, args...))
182 }
183
184 func (check *Checker) invalidAST(at positioner, format string, args ...interface{}) {
185 check.errorf(at, 0, "invalid AST: "+format, args...)
186 }
187
188 func (check *Checker) invalidArg(at positioner, code errorCode, format string, args ...interface{}) {
189 check.errorf(at, code, "invalid argument: "+format, args...)
190 }
191
192 func (check *Checker) invalidOp(at positioner, code errorCode, format string, args ...interface{}) {
193 check.errorf(at, code, "invalid operation: "+format, args...)
194 }
195
196
197
198 type positioner interface {
199 Pos() token.Pos
200 }
201
202
203
204
205
206
207 type posSpan struct {
208 start, pos, end token.Pos
209 }
210
211 func (e posSpan) Pos() token.Pos {
212 return e.pos
213 }
214
215
216
217
218 func inNode(node ast.Node, pos token.Pos) posSpan {
219 start, end := node.Pos(), node.End()
220 if debug {
221 assert(start <= pos && pos < end)
222 }
223 return posSpan{start, pos, end}
224 }
225
226
227 type atPos token.Pos
228
229 func (s atPos) Pos() token.Pos {
230 return token.Pos(s)
231 }
232
233
234
235
236 func spanOf(at positioner) posSpan {
237 switch x := at.(type) {
238 case nil:
239 panic("internal error: nil")
240 case posSpan:
241 return x
242 case ast.Node:
243 pos := x.Pos()
244 return posSpan{pos, pos, x.End()}
245 case *operand:
246 if x.expr != nil {
247 pos := x.Pos()
248 return posSpan{pos, pos, x.expr.End()}
249 }
250 return posSpan{token.NoPos, token.NoPos, token.NoPos}
251 default:
252 pos := at.Pos()
253 return posSpan{pos, pos, pos}
254 }
255 }
256
257
258 func stripAnnotations(s string) string {
259 var b strings.Builder
260 for _, r := range s {
261
262 if r != instanceMarker && !('₀' <= r && r < '₀'+10) {
263 b.WriteRune(r)
264 }
265 }
266 if b.Len() < len(s) {
267 return b.String()
268 }
269 return s
270 }
271
View as plain text