Source file
src/go/types/operand.go
1
2
3
4
5
6
7 package types
8
9 import (
10 "bytes"
11 "go/ast"
12 "go/constant"
13 "go/token"
14 )
15
16
17 type operandMode byte
18
19 const (
20 invalid operandMode = iota
21 novalue
22 builtin
23 typexpr
24 constant_
25 variable
26 mapindex
27 value
28 commaok
29 commaerr
30 cgofunc
31 )
32
33 var operandModeString = [...]string{
34 invalid: "invalid operand",
35 novalue: "no value",
36 builtin: "built-in",
37 typexpr: "type",
38 constant_: "constant",
39 variable: "variable",
40 mapindex: "map index expression",
41 value: "value",
42 commaok: "comma, ok expression",
43 commaerr: "comma, error expression",
44 cgofunc: "cgo function",
45 }
46
47
48
49
50
51
52
53 type operand struct {
54 mode operandMode
55 expr ast.Expr
56 typ Type
57 val constant.Value
58 id builtinId
59 }
60
61
62
63
64 func (x *operand) Pos() token.Pos {
65
66 if x.expr == nil {
67 return token.NoPos
68 }
69 return x.expr.Pos()
70 }
71
72
73
74
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 func operandString(x *operand, qf Qualifier) string {
107
108 if x.mode == value && x.typ == Typ[UntypedNil] {
109 return "nil"
110 }
111
112 var buf bytes.Buffer
113
114 var expr string
115 if x.expr != nil {
116 expr = ExprString(x.expr)
117 } else {
118 switch x.mode {
119 case builtin:
120 expr = predeclaredFuncs[x.id].name
121 case typexpr:
122 expr = TypeString(x.typ, qf)
123 case constant_:
124 expr = x.val.String()
125 }
126 }
127
128
129 if expr != "" {
130 buf.WriteString(expr)
131 buf.WriteString(" (")
132 }
133
134
135 hasType := false
136 switch x.mode {
137 case invalid, novalue, builtin, typexpr:
138
139 default:
140
141 if x.typ != nil {
142 if isUntyped(x.typ) {
143 buf.WriteString(x.typ.(*Basic).name)
144 buf.WriteByte(' ')
145 break
146 }
147 hasType = true
148 }
149 }
150
151
152 buf.WriteString(operandModeString[x.mode])
153
154
155 if x.mode == constant_ {
156 if s := x.val.String(); s != expr {
157 buf.WriteByte(' ')
158 buf.WriteString(s)
159 }
160 }
161
162
163 if hasType {
164 if x.typ != Typ[Invalid] {
165 var intro string
166 if isGeneric(x.typ) {
167 intro = " of parameterized type "
168 } else {
169 intro = " of type "
170 }
171 buf.WriteString(intro)
172 WriteType(&buf, x.typ, qf)
173 if tpar, _ := x.typ.(*TypeParam); tpar != nil {
174 buf.WriteString(" constrained by ")
175 WriteType(&buf, tpar.bound, qf)
176 }
177 } else {
178 buf.WriteString(" with invalid type")
179 }
180 }
181
182
183 if expr != "" {
184 buf.WriteByte(')')
185 }
186
187 return buf.String()
188 }
189
190 func (x *operand) String() string {
191 return operandString(x, nil)
192 }
193
194
195 func (x *operand) setConst(tok token.Token, lit string) {
196 var kind BasicKind
197 switch tok {
198 case token.INT:
199 kind = UntypedInt
200 case token.FLOAT:
201 kind = UntypedFloat
202 case token.IMAG:
203 kind = UntypedComplex
204 case token.CHAR:
205 kind = UntypedRune
206 case token.STRING:
207 kind = UntypedString
208 default:
209 unreachable()
210 }
211
212 val := constant.MakeFromLiteral(lit, tok, 0)
213 if val.Kind() == constant.Unknown {
214 x.mode = invalid
215 x.typ = Typ[Invalid]
216 return
217 }
218 x.mode = constant_
219 x.typ = Typ[kind]
220 x.val = val
221 }
222
223
224 func (x *operand) isNil() bool {
225 return x.mode == value && x.typ == Typ[UntypedNil]
226 }
227
228
229
230
231
232
233
234 func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, errorCode) {
235 if x.mode == invalid || T == Typ[Invalid] {
236 return true, 0
237 }
238
239 V := x.typ
240
241
242 if Identical(V, T) {
243 return true, 0
244 }
245
246 Vu := under(V)
247 Tu := under(T)
248 Vp, _ := V.(*TypeParam)
249 Tp, _ := T.(*TypeParam)
250
251
252 if isUntyped(Vu) {
253 assert(Vp == nil)
254 if Tp != nil {
255
256
257 return Tp.is(func(t *term) bool {
258 if t == nil {
259 return false
260 }
261
262
263
264 newType, _, _ := check.implicitTypeAndValue(x, t.typ)
265 return newType != nil
266 }), _IncompatibleAssign
267 }
268 newType, _, _ := check.implicitTypeAndValue(x, T)
269 return newType != nil, _IncompatibleAssign
270 }
271
272
273
274
275
276 if Identical(Vu, Tu) && (!hasName(V) || !hasName(T)) && Vp == nil && Tp == nil {
277 return true, 0
278 }
279
280
281
282 if _, ok := Tu.(*Interface); ok && Tp == nil || isInterfacePtr(Tu) {
283 if err := check.implements(V, T); err != nil {
284 if reason != nil {
285 *reason = err.Error()
286 }
287 return false, _InvalidIfaceAssign
288 }
289 return true, 0
290 }
291
292
293 if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil {
294 if check.implements(T, V) == nil {
295
296 if reason != nil {
297 *reason = "need type assertion"
298 }
299 return false, _IncompatibleAssign
300 }
301 }
302
303
304
305
306 if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv {
307 if Tc, ok := Tu.(*Chan); ok && Identical(Vc.elem, Tc.elem) {
308 return !hasName(V) || !hasName(T), _InvalidChanAssign
309 }
310 }
311
312
313 if Vp == nil && Tp == nil {
314 return false, _IncompatibleAssign
315 }
316
317 errorf := func(format string, args ...any) {
318 if check != nil && reason != nil {
319 msg := check.sprintf(format, args...)
320 if *reason != "" {
321 msg += "\n\t" + *reason
322 }
323 *reason = msg
324 }
325 }
326
327
328
329 if !hasName(V) && Tp != nil {
330 ok := false
331 code := _IncompatibleAssign
332 Tp.is(func(T *term) bool {
333 if T == nil {
334 return false
335 }
336 ok, code = x.assignableTo(check, T.typ, reason)
337 if !ok {
338 errorf("cannot assign %s to %s (in %s)", x.typ, T.typ, Tp)
339 return false
340 }
341 return true
342 })
343 return ok, code
344 }
345
346
347
348
349 if Vp != nil && !hasName(T) {
350 x := *x
351 ok := false
352 code := _IncompatibleAssign
353 Vp.is(func(V *term) bool {
354 if V == nil {
355 return false
356 }
357 x.typ = V.typ
358 ok, code = x.assignableTo(check, T, reason)
359 if !ok {
360 errorf("cannot assign %s (in %s) to %s", V.typ, Vp, T)
361 return false
362 }
363 return true
364 })
365 return ok, code
366 }
367
368 return false, _IncompatibleAssign
369 }
370
View as plain text