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