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
68
69 func (x *operand) Pos() token.Pos {
70
71 if x.expr == nil {
72 return nopos
73 }
74 return x.expr.Pos()
75 }
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113 func operandString(x *operand, qf Qualifier) string {
114
115 if isTypes2 {
116 if x.mode == nilvalue {
117 switch x.typ {
118 case nil, Typ[Invalid]:
119 return "nil (with invalid type)"
120 case Typ[UntypedNil]:
121 return "nil"
122 default:
123 return fmt.Sprintf("nil (of type %s)", TypeString(x.typ, qf))
124 }
125 }
126 } else {
127 if x.mode == value && x.typ == Typ[UntypedNil] {
128 return "nil"
129 }
130 }
131
132 var buf bytes.Buffer
133
134 var expr string
135 if x.expr != nil {
136 expr = ExprString(x.expr)
137 } else {
138 switch x.mode {
139 case builtin:
140 expr = predeclaredFuncs[x.id].name
141 case typexpr:
142 expr = TypeString(x.typ, qf)
143 case constant_:
144 expr = x.val.String()
145 }
146 }
147
148
149 if expr != "" {
150 buf.WriteString(expr)
151 buf.WriteString(" (")
152 }
153
154
155 hasType := false
156 switch x.mode {
157 case invalid, novalue, builtin, typexpr:
158
159 default:
160
161 if x.typ != nil {
162 if isUntyped(x.typ) {
163 buf.WriteString(x.typ.(*Basic).name)
164 buf.WriteByte(' ')
165 break
166 }
167 hasType = true
168 }
169 }
170
171
172 buf.WriteString(operandModeString[x.mode])
173
174
175 if x.mode == constant_ {
176 if s := x.val.String(); s != expr {
177 buf.WriteByte(' ')
178 buf.WriteString(s)
179 }
180 }
181
182
183 if hasType {
184 if isValid(x.typ) {
185 var intro string
186 if isGeneric(x.typ) {
187 intro = " of generic type "
188 } else {
189 intro = " of type "
190 }
191 buf.WriteString(intro)
192 WriteType(&buf, x.typ, qf)
193 if tpar, _ := Unalias(x.typ).(*TypeParam); tpar != nil {
194 buf.WriteString(" constrained by ")
195 WriteType(&buf, tpar.bound, qf)
196
197 if hasEmptyTypeset(tpar) {
198 buf.WriteString(" with empty type set")
199 }
200 }
201 } else {
202 buf.WriteString(" with invalid type")
203 }
204 }
205
206
207 if expr != "" {
208 buf.WriteByte(')')
209 }
210
211 return buf.String()
212 }
213
214 func (x *operand) String() string {
215 return operandString(x, nil)
216 }
217
218
219 func (x *operand) setConst(k token.Token, lit string) {
220 var kind BasicKind
221 switch k {
222 case token.INT:
223 kind = UntypedInt
224 case token.FLOAT:
225 kind = UntypedFloat
226 case token.IMAG:
227 kind = UntypedComplex
228 case token.CHAR:
229 kind = UntypedRune
230 case token.STRING:
231 kind = UntypedString
232 default:
233 panic("unreachable")
234 }
235
236 val := makeFromLiteral(lit, k)
237 if val.Kind() == constant.Unknown {
238 x.mode = invalid
239 x.typ = Typ[Invalid]
240 return
241 }
242 x.mode = constant_
243 x.typ = Typ[kind]
244 x.val = val
245 }
246
247
248 func (x *operand) isNil() bool {
249 if isTypes2 {
250 return x.mode == nilvalue
251 } else {
252 return x.mode == value && x.typ == Typ[UntypedNil]
253 }
254 }
255
256
257
258
259
260
261
262 func (x *operand) assignableTo(check *Checker, T Type, cause *string) (bool, Code) {
263 if x.mode == invalid || !isValid(T) {
264 return true, 0
265 }
266
267 origT := T
268 V := Unalias(x.typ)
269 T = Unalias(T)
270
271
272 if Identical(V, T) {
273 return true, 0
274 }
275
276 Vu := under(V)
277 Tu := under(T)
278 Vp, _ := V.(*TypeParam)
279 Tp, _ := T.(*TypeParam)
280
281
282 if isUntyped(Vu) {
283 assert(Vp == nil)
284 if Tp != nil {
285
286
287 return Tp.is(func(t *term) bool {
288 if t == nil {
289 return false
290 }
291
292
293
294 newType, _, _ := check.implicitTypeAndValue(x, t.typ)
295 return newType != nil
296 }), IncompatibleAssign
297 }
298 newType, _, _ := check.implicitTypeAndValue(x, T)
299 return newType != nil, IncompatibleAssign
300 }
301
302
303
304
305
306 if Identical(Vu, Tu) && (!hasName(V) || !hasName(T)) && Vp == nil && Tp == nil {
307 return true, 0
308 }
309
310
311
312
313 if _, ok := Tu.(*Interface); ok && Tp == nil || isInterfacePtr(Tu) {
314 if check.implements(x.Pos(), V, T, false, cause) {
315 return true, 0
316 }
317
318
319 if Vp == nil {
320 return false, InvalidIfaceAssign
321 }
322 if cause != nil {
323 *cause = ""
324 }
325 }
326
327
328 if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil {
329 if check.implements(x.Pos(), T, V, false, nil) {
330
331 if cause != nil {
332 *cause = "need type assertion"
333 }
334 return false, IncompatibleAssign
335 }
336 }
337
338
339
340
341 if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv {
342 if Tc, ok := Tu.(*Chan); ok && Identical(Vc.elem, Tc.elem) {
343 return !hasName(V) || !hasName(T), InvalidChanAssign
344 }
345 }
346
347
348 if Vp == nil && Tp == nil {
349 return false, IncompatibleAssign
350 }
351
352 errorf := func(format string, args ...any) {
353 if check != nil && cause != nil {
354 msg := check.sprintf(format, args...)
355 if *cause != "" {
356 msg += "\n\t" + *cause
357 }
358 *cause = msg
359 }
360 }
361
362
363
364 if !hasName(V) && Tp != nil {
365 ok := false
366 code := IncompatibleAssign
367 Tp.is(func(T *term) bool {
368 if T == nil {
369 return false
370 }
371 ok, code = x.assignableTo(check, T.typ, cause)
372 if !ok {
373 errorf("cannot assign %s to %s (in %s)", x.typ, T.typ, Tp)
374 return false
375 }
376 return true
377 })
378 return ok, code
379 }
380
381
382
383
384 if Vp != nil && !hasName(T) {
385 x := *x
386 ok := false
387 code := IncompatibleAssign
388 Vp.is(func(V *term) bool {
389 if V == nil {
390 return false
391 }
392 x.typ = V.typ
393 ok, code = x.assignableTo(check, T, cause)
394 if !ok {
395 errorf("cannot assign %s (in %s) to %s", V.typ, Vp, origT)
396 return false
397 }
398 return true
399 })
400 return ok, code
401 }
402
403 return false, IncompatibleAssign
404 }
405
View as plain text