1
2
3
4
5
6
7 package types2
8
9 import (
10 "bytes"
11 "cmd/compile/internal/syntax"
12 "fmt"
13 . "internal/types/errors"
14 "runtime"
15 "strconv"
16 "strings"
17 )
18
19 func assert(p bool) {
20 if !p {
21 msg := "assertion failed"
22
23
24 if _, file, line, ok := runtime.Caller(1); ok {
25 msg = fmt.Sprintf("%s:%d: %s", file, line, msg)
26 }
27 panic(msg)
28 }
29 }
30
31 func unreachable() {
32 panic("unreachable")
33 }
34
35
36
37 type error_ struct {
38 desc []errorDesc
39 code Code
40 soft bool
41 }
42
43
44 type errorDesc struct {
45 pos syntax.Pos
46 format string
47 args []interface{}
48 }
49
50 func (err *error_) empty() bool {
51 return err.desc == nil
52 }
53
54 func (err *error_) pos() syntax.Pos {
55 if err.empty() {
56 return nopos
57 }
58 return err.desc[0].pos
59 }
60
61 func (err *error_) msg(qf Qualifier) string {
62 if err.empty() {
63 return "no error"
64 }
65 var buf strings.Builder
66 for i := range err.desc {
67 p := &err.desc[i]
68 if i > 0 {
69 fmt.Fprint(&buf, "\n\t")
70 if p.pos.IsKnown() {
71 fmt.Fprintf(&buf, "%s: ", p.pos)
72 }
73 }
74 buf.WriteString(sprintf(qf, false, p.format, p.args...))
75 }
76 return buf.String()
77 }
78
79
80 func (err *error_) String() string {
81 if err.empty() {
82 return "no error"
83 }
84 return fmt.Sprintf("%s: %s", err.pos(), err.msg(nil))
85 }
86
87
88
89 func (err *error_) errorf(at poser, format string, args ...interface{}) {
90 err.desc = append(err.desc, errorDesc{atPos(at), format, args})
91 }
92
93 func sprintf(qf Qualifier, tpSubscripts bool, format string, args ...interface{}) string {
94 for i, arg := range args {
95 switch a := arg.(type) {
96 case nil:
97 arg = "<nil>"
98 case operand:
99 panic("got operand instead of *operand")
100 case *operand:
101 arg = operandString(a, qf)
102 case syntax.Pos:
103 arg = a.String()
104 case syntax.Expr:
105 arg = syntax.String(a)
106 case []syntax.Expr:
107 var buf strings.Builder
108 buf.WriteByte('[')
109 for i, x := range a {
110 if i > 0 {
111 buf.WriteString(", ")
112 }
113 buf.WriteString(syntax.String(x))
114 }
115 buf.WriteByte(']')
116 arg = buf.String()
117 case Object:
118 arg = ObjectString(a, qf)
119 case Type:
120 var buf bytes.Buffer
121 w := newTypeWriter(&buf, qf)
122 w.tpSubscripts = tpSubscripts
123 w.typ(a)
124 arg = buf.String()
125 case []Type:
126 var buf bytes.Buffer
127 w := newTypeWriter(&buf, qf)
128 w.tpSubscripts = tpSubscripts
129 buf.WriteByte('[')
130 for i, x := range a {
131 if i > 0 {
132 buf.WriteString(", ")
133 }
134 w.typ(x)
135 }
136 buf.WriteByte(']')
137 arg = buf.String()
138 case []*TypeParam:
139 var buf bytes.Buffer
140 w := newTypeWriter(&buf, qf)
141 w.tpSubscripts = tpSubscripts
142 buf.WriteByte('[')
143 for i, x := range a {
144 if i > 0 {
145 buf.WriteString(", ")
146 }
147 w.typ(x)
148 }
149 buf.WriteByte(']')
150 arg = buf.String()
151 }
152 args[i] = arg
153 }
154 return fmt.Sprintf(format, args...)
155 }
156
157 func (check *Checker) qualifier(pkg *Package) string {
158
159 if pkg != check.pkg {
160 if check.pkgPathMap == nil {
161 check.pkgPathMap = make(map[string]map[string]bool)
162 check.seenPkgMap = make(map[*Package]bool)
163 check.markImports(check.pkg)
164 }
165
166 if len(check.pkgPathMap[pkg.name]) > 1 {
167 return strconv.Quote(pkg.path)
168 }
169 return pkg.name
170 }
171 return ""
172 }
173
174
175
176 func (check *Checker) markImports(pkg *Package) {
177 if check.seenPkgMap[pkg] {
178 return
179 }
180 check.seenPkgMap[pkg] = true
181
182 forName, ok := check.pkgPathMap[pkg.name]
183 if !ok {
184 forName = make(map[string]bool)
185 check.pkgPathMap[pkg.name] = forName
186 }
187 forName[pkg.path] = true
188
189 for _, imp := range pkg.imports {
190 check.markImports(imp)
191 }
192 }
193
194
195 func (check *Checker) sprintf(format string, args ...interface{}) string {
196 var qf Qualifier
197 if check != nil {
198 qf = check.qualifier
199 }
200 return sprintf(qf, false, format, args...)
201 }
202
203 func (check *Checker) report(err *error_) {
204 if err.empty() {
205 panic("no error to report")
206 }
207 check.err(err.pos(), err.code, err.msg(check.qualifier), err.soft)
208 }
209
210 func (check *Checker) trace(pos syntax.Pos, format string, args ...interface{}) {
211 fmt.Printf("%s:\t%s%s\n",
212 pos,
213 strings.Repeat(". ", check.indent),
214 sprintf(check.qualifier, true, format, args...),
215 )
216 }
217
218
219 func (check *Checker) dump(format string, args ...interface{}) {
220 fmt.Println(sprintf(check.qualifier, true, format, args...))
221 }
222
223 func (check *Checker) err(at poser, code Code, msg string, soft bool) {
224 switch code {
225 case InvalidSyntaxTree:
226 msg = "invalid syntax tree: " + msg
227 case 0:
228 panic("no error code provided")
229 }
230
231
232
233
234
235
236 if check.firstErr != nil && (strings.Index(msg, "invalid operand") > 0 || strings.Index(msg, "invalid type") > 0) {
237 return
238 }
239
240 pos := atPos(at)
241
242
243
244
245
246
247
248 if check.errpos.IsKnown() {
249 assert(check.iota != nil)
250 pos = check.errpos
251 }
252
253
254 if code != 0 && check.conf.ErrorURL != "" {
255 u := fmt.Sprintf(check.conf.ErrorURL, code)
256 if i := strings.Index(msg, "\n"); i >= 0 {
257 msg = msg[:i] + u + msg[i:]
258 } else {
259 msg += u
260 }
261 }
262
263 err := Error{pos, stripAnnotations(msg), msg, soft, code}
264 if check.firstErr == nil {
265 check.firstErr = err
266 }
267
268 if check.conf.Trace {
269 check.trace(pos, "ERROR: %s", msg)
270 }
271
272 f := check.conf.Error
273 if f == nil {
274 panic(bailout{})
275 }
276 f(err)
277 }
278
279 const (
280 invalidArg = "invalid argument: "
281 invalidOp = "invalid operation: "
282 )
283
284 type poser interface {
285 Pos() syntax.Pos
286 }
287
288 func (check *Checker) error(at poser, code Code, msg string) {
289 check.err(at, code, msg, false)
290 }
291
292 func (check *Checker) errorf(at poser, code Code, format string, args ...interface{}) {
293 check.err(at, code, check.sprintf(format, args...), false)
294 }
295
296 func (check *Checker) softErrorf(at poser, code Code, format string, args ...interface{}) {
297 check.err(at, code, check.sprintf(format, args...), true)
298 }
299
300 func (check *Checker) versionErrorf(at poser, v goVersion, format string, args ...interface{}) {
301 msg := check.sprintf(format, args...)
302 msg = fmt.Sprintf("%s requires %s or later", msg, v)
303 check.err(at, UnsupportedFeature, msg, true)
304 }
305
306
307 func atPos(at poser) syntax.Pos {
308 switch x := at.(type) {
309 case *operand:
310 if x.expr != nil {
311 return syntax.StartPos(x.expr)
312 }
313 case syntax.Node:
314 return syntax.StartPos(x)
315 }
316 return at.Pos()
317 }
318
319
320 func stripAnnotations(s string) string {
321 var buf strings.Builder
322 for _, r := range s {
323
324 if r < '₀' || '₀'+10 <= r {
325 buf.WriteRune(r)
326 }
327 }
328 if buf.Len() < len(s) {
329 return buf.String()
330 }
331 return s
332 }
333
View as plain text