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