Source file
src/go/types/operand.go
1
2
3
4
5
6
7
8
9
10 package types
11
12 import (
13 "bytes"
14 "fmt"
15 "go/ast"
16 "go/constant"
17 "go/token"
18 . "internal/types/errors"
19 )
20
21
22 type operandMode byte
23
24 const (
25 invalid operandMode = iota
26 novalue
27 builtin
28 typexpr
29 constant_
30 variable
31 mapindex
32 value
33 nilvalue
34 commaok
35 commaerr
36 cgofunc
37 )
38
39 var operandModeString = [...]string{
40 invalid: "invalid operand",
41 novalue: "no value",
42 builtin: "built-in",
43 typexpr: "type",
44 constant_: "constant",
45 variable: "variable",
46 mapindex: "map index expression",
47 value: "value",
48 nilvalue: "nil",
49 commaok: "comma, ok expression",
50 commaerr: "comma, error expression",
51 cgofunc: "cgo function",
52 }
53
54
55
56
57
58
59 type operand struct {
60 mode_ operandMode
61 expr ast.Expr
62 typ_ Type
63 val constant.Value
64 id builtinId
65 }
66
67 func (x *operand) mode() operandMode {
68 return x.mode_
69 }
70
71 func (x *operand) typ() Type {
72 return x.typ_
73 }
74
75 func (x *operand) isValid() bool {
76 return x.mode() != invalid
77 }
78
79 func (x *operand) invalidate() {
80 x.mode_ = invalid
81 }
82
83
84
85 func (x *operand) Pos() token.Pos {
86
87 if x.expr == nil {
88 return nopos
89 }
90 return x.expr.Pos()
91 }
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129 func operandString(x *operand, qf Qualifier) string {
130
131 if isTypes2 {
132 if x.mode() == nilvalue {
133 switch x.typ() {
134 case nil, Typ[Invalid]:
135 return "nil (with invalid type)"
136 case Typ[UntypedNil]:
137 return "nil"
138 default:
139 return fmt.Sprintf("nil (of type %s)", TypeString(x.typ(), qf))
140 }
141 }
142 } else {
143 if x.mode() == value && x.typ() == Typ[UntypedNil] {
144 return "nil"
145 }
146 }
147
148 var buf bytes.Buffer
149
150 var expr string
151 if x.expr != nil {
152 expr = ExprString(x.expr)
153 } else {
154 switch x.mode() {
155 case builtin:
156 expr = predeclaredFuncs[x.id].name
157 case typexpr:
158 expr = TypeString(x.typ(), qf)
159 case constant_:
160 expr = x.val.String()
161 }
162 }
163
164
165 if expr != "" {
166 buf.WriteString(expr)
167 buf.WriteString(" (")
168 }
169
170
171 hasType := false
172 switch x.mode() {
173 case invalid, novalue, builtin, typexpr:
174
175 default:
176
177 if x.typ() != nil {
178 if isUntyped(x.typ()) {
179 buf.WriteString(x.typ().(*Basic).name)
180 buf.WriteByte(' ')
181 break
182 }
183 hasType = true
184 }
185 }
186
187
188 buf.WriteString(operandModeString[x.mode()])
189
190
191 if x.mode() == constant_ {
192 if s := x.val.String(); s != expr {
193 buf.WriteByte(' ')
194 buf.WriteString(s)
195 }
196 }
197
198
199 if hasType {
200 if isValid(x.typ()) {
201 var desc string
202 if isGeneric(x.typ()) {
203 desc = "generic "
204 }
205
206
207
208
209
210 tpar, _ := Unalias(x.typ()).(*TypeParam)
211 if tpar == nil {
212 switch x.typ().(type) {
213 case *Alias, *Named:
214 what := compositeKind(x.typ())
215 if what == "" {
216
217 what = x.typ().Underlying().(*Basic).name
218 }
219 desc += what + " "
220 }
221 }
222
223
224 buf.WriteString(" of " + desc + "type ")
225 WriteType(&buf, x.typ(), qf)
226
227 if tpar != nil {
228 buf.WriteString(" constrained by ")
229 WriteType(&buf, tpar.bound, qf)
230
231 if hasEmptyTypeset(tpar) {
232 buf.WriteString(" with empty type set")
233 }
234 }
235 } else {
236 buf.WriteString(" with invalid type")
237 }
238 }
239
240
241 if expr != "" {
242 buf.WriteByte(')')
243 }
244
245 return buf.String()
246 }
247
248
249
250
251 func compositeKind(typ Type) string {
252 switch typ.Underlying().(type) {
253 case *Basic:
254 return ""
255 case *Array:
256 return "array"
257 case *Slice:
258 return "slice"
259 case *Struct:
260 return "struct"
261 case *Pointer:
262 return "pointer"
263 case *Signature:
264 return "func"
265 case *Interface:
266 return "interface"
267 case *Map:
268 return "map"
269 case *Chan:
270 return "chan"
271 case *Tuple:
272 return "tuple"
273 case *Union:
274 return "union"
275 default:
276 panic("unreachable")
277 }
278 }
279
280 func (x *operand) String() string {
281 return operandString(x, nil)
282 }
283
284
285 func (x *operand) setConst(k token.Token, lit string) {
286 var kind BasicKind
287 switch k {
288 case token.INT:
289 kind = UntypedInt
290 case token.FLOAT:
291 kind = UntypedFloat
292 case token.IMAG:
293 kind = UntypedComplex
294 case token.CHAR:
295 kind = UntypedRune
296 case token.STRING:
297 kind = UntypedString
298 default:
299 panic("unreachable")
300 }
301
302 val := makeFromLiteral(lit, k)
303 if val.Kind() == constant.Unknown {
304 x.invalidate()
305 x.typ_ = Typ[Invalid]
306 return
307 }
308 x.mode_ = constant_
309 x.typ_ = Typ[kind]
310 x.val = val
311 }
312
313
314 func (x *operand) isNil() bool {
315 if isTypes2 {
316 return x.mode() == nilvalue
317 } else {
318 return x.mode() == value && x.typ() == Typ[UntypedNil]
319 }
320 }
321
322
323
324
325
326
327
328 func (x *operand) assignableTo(check *Checker, T Type, cause *string) (bool, Code) {
329 if !x.isValid() || !isValid(T) {
330 return true, 0
331 }
332
333 origT := T
334 V := Unalias(x.typ())
335 T = Unalias(T)
336
337
338 if Identical(V, T) {
339 return true, 0
340 }
341
342 Vu := V.Underlying()
343 Tu := T.Underlying()
344 Vp, _ := V.(*TypeParam)
345 Tp, _ := T.(*TypeParam)
346
347
348 if isUntyped(Vu) {
349 assert(Vp == nil)
350 if Tp != nil {
351
352
353 return Tp.is(func(t *term) bool {
354 if t == nil {
355 return false
356 }
357
358
359
360 newType, _, _ := check.implicitTypeAndValue(x, t.typ)
361 return newType != nil
362 }), IncompatibleAssign
363 }
364 newType, _, _ := check.implicitTypeAndValue(x, T)
365 return newType != nil, IncompatibleAssign
366 }
367
368
369
370
371
372 if Identical(Vu, Tu) && (!hasName(V) || !hasName(T)) && Vp == nil && Tp == nil {
373 return true, 0
374 }
375
376
377
378
379 if _, ok := Tu.(*Interface); ok && Tp == nil || isInterfacePtr(Tu) {
380 if check.implements(V, T, false, cause) {
381 return true, 0
382 }
383
384
385 if Vp == nil {
386 return false, InvalidIfaceAssign
387 }
388 if cause != nil {
389 *cause = ""
390 }
391 }
392
393
394 if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil {
395 if check.implements(T, V, false, nil) {
396
397 if cause != nil {
398 *cause = "need type assertion"
399 }
400 return false, IncompatibleAssign
401 }
402 }
403
404
405
406
407 if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv {
408 if Tc, ok := Tu.(*Chan); ok && Identical(Vc.elem, Tc.elem) {
409 return !hasName(V) || !hasName(T), InvalidChanAssign
410 }
411 }
412
413
414 if Vp == nil && Tp == nil {
415 return false, IncompatibleAssign
416 }
417
418 errorf := func(format string, args ...any) {
419 if check != nil && cause != nil {
420 msg := check.sprintf(format, args...)
421 if *cause != "" {
422 msg += "\n\t" + *cause
423 }
424 *cause = msg
425 }
426 }
427
428
429
430 if !hasName(V) && Tp != nil {
431 ok := false
432 code := IncompatibleAssign
433 Tp.is(func(T *term) bool {
434 if T == nil {
435 return false
436 }
437 ok, code = x.assignableTo(check, T.typ, cause)
438 if !ok {
439 errorf("cannot assign %s to %s (in %s)", x.typ(), T.typ, Tp)
440 return false
441 }
442 return true
443 })
444 return ok, code
445 }
446
447
448
449
450 if Vp != nil && !hasName(T) {
451 x := *x
452 ok := false
453 code := IncompatibleAssign
454 Vp.is(func(V *term) bool {
455 if V == nil {
456 return false
457 }
458 x.typ_ = V.typ
459 ok, code = x.assignableTo(check, T, cause)
460 if !ok {
461 errorf("cannot assign %s (in %s) to %s", V.typ, Vp, origT)
462 return false
463 }
464 return true
465 })
466 return ok, code
467 }
468
469 return false, IncompatibleAssign
470 }
471
View as plain text