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 desc string
182 if isGeneric(x.typ) {
183 desc = "generic "
184 }
185
186
187
188
189
190 tpar, _ := Unalias(x.typ).(*TypeParam)
191 if tpar == nil {
192 switch x.typ.(type) {
193 case *Alias, *Named:
194 what := compositeKind(x.typ)
195 if what == "" {
196
197 what = under(x.typ).(*Basic).name
198 }
199 desc += what + " "
200 }
201 }
202
203
204 buf.WriteString(" of " + desc + "type ")
205 WriteType(&buf, x.typ, qf)
206
207 if tpar != nil {
208 buf.WriteString(" constrained by ")
209 WriteType(&buf, tpar.bound, qf)
210
211 if hasEmptyTypeset(tpar) {
212 buf.WriteString(" with empty type set")
213 }
214 }
215 } else {
216 buf.WriteString(" with invalid type")
217 }
218 }
219
220
221 if expr != "" {
222 buf.WriteByte(')')
223 }
224
225 return buf.String()
226 }
227
228
229
230
231 func compositeKind(typ Type) string {
232 switch under(typ).(type) {
233 case *Basic:
234 return ""
235 case *Array:
236 return "array"
237 case *Slice:
238 return "slice"
239 case *Struct:
240 return "struct"
241 case *Pointer:
242 return "pointer"
243 case *Signature:
244 return "func"
245 case *Interface:
246 return "interface"
247 case *Map:
248 return "map"
249 case *Chan:
250 return "chan"
251 case *Tuple:
252 return "tuple"
253 case *Union:
254 return "union"
255 default:
256 panic("unreachable")
257 }
258 }
259
260 func (x *operand) String() string {
261 return operandString(x, nil)
262 }
263
264
265 func (x *operand) setConst(k syntax.LitKind, lit string) {
266 var kind BasicKind
267 switch k {
268 case syntax.IntLit:
269 kind = UntypedInt
270 case syntax.FloatLit:
271 kind = UntypedFloat
272 case syntax.ImagLit:
273 kind = UntypedComplex
274 case syntax.RuneLit:
275 kind = UntypedRune
276 case syntax.StringLit:
277 kind = UntypedString
278 default:
279 panic("unreachable")
280 }
281
282 val := makeFromLiteral(lit, k)
283 if val.Kind() == constant.Unknown {
284 x.mode = invalid
285 x.typ = Typ[Invalid]
286 return
287 }
288 x.mode = constant_
289 x.typ = Typ[kind]
290 x.val = val
291 }
292
293
294 func (x *operand) isNil() bool {
295 if isTypes2 {
296 return x.mode == nilvalue
297 } else {
298 return x.mode == value && x.typ == Typ[UntypedNil]
299 }
300 }
301
302
303
304
305
306
307
308 func (x *operand) assignableTo(check *Checker, T Type, cause *string) (bool, Code) {
309 if x.mode == invalid || !isValid(T) {
310 return true, 0
311 }
312
313 origT := T
314 V := Unalias(x.typ)
315 T = Unalias(T)
316
317
318 if Identical(V, T) {
319 return true, 0
320 }
321
322 Vu := under(V)
323 Tu := under(T)
324 Vp, _ := V.(*TypeParam)
325 Tp, _ := T.(*TypeParam)
326
327
328 if isUntyped(Vu) {
329 assert(Vp == nil)
330 if Tp != nil {
331
332
333 return Tp.is(func(t *term) bool {
334 if t == nil {
335 return false
336 }
337
338
339
340 newType, _, _ := check.implicitTypeAndValue(x, t.typ)
341 return newType != nil
342 }), IncompatibleAssign
343 }
344 newType, _, _ := check.implicitTypeAndValue(x, T)
345 return newType != nil, IncompatibleAssign
346 }
347
348
349
350
351
352 if Identical(Vu, Tu) && (!hasName(V) || !hasName(T)) && Vp == nil && Tp == nil {
353 return true, 0
354 }
355
356
357
358
359 if _, ok := Tu.(*Interface); ok && Tp == nil || isInterfacePtr(Tu) {
360 if check.implements(V, T, false, cause) {
361 return true, 0
362 }
363
364
365 if Vp == nil {
366 return false, InvalidIfaceAssign
367 }
368 if cause != nil {
369 *cause = ""
370 }
371 }
372
373
374 if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil {
375 if check.implements(T, V, false, nil) {
376
377 if cause != nil {
378 *cause = "need type assertion"
379 }
380 return false, IncompatibleAssign
381 }
382 }
383
384
385
386
387 if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv {
388 if Tc, ok := Tu.(*Chan); ok && Identical(Vc.elem, Tc.elem) {
389 return !hasName(V) || !hasName(T), InvalidChanAssign
390 }
391 }
392
393
394 if Vp == nil && Tp == nil {
395 return false, IncompatibleAssign
396 }
397
398 errorf := func(format string, args ...any) {
399 if check != nil && cause != nil {
400 msg := check.sprintf(format, args...)
401 if *cause != "" {
402 msg += "\n\t" + *cause
403 }
404 *cause = msg
405 }
406 }
407
408
409
410 if !hasName(V) && Tp != nil {
411 ok := false
412 code := IncompatibleAssign
413 Tp.is(func(T *term) bool {
414 if T == nil {
415 return false
416 }
417 ok, code = x.assignableTo(check, T.typ, cause)
418 if !ok {
419 errorf("cannot assign %s to %s (in %s)", x.typ, T.typ, Tp)
420 return false
421 }
422 return true
423 })
424 return ok, code
425 }
426
427
428
429
430 if Vp != nil && !hasName(T) {
431 x := *x
432 ok := false
433 code := IncompatibleAssign
434 Vp.is(func(V *term) bool {
435 if V == nil {
436 return false
437 }
438 x.typ = V.typ
439 ok, code = x.assignableTo(check, T, cause)
440 if !ok {
441 errorf("cannot assign %s (in %s) to %s", V.typ, Vp, origT)
442 return false
443 }
444 return true
445 })
446 return ok, code
447 }
448
449 return false, IncompatibleAssign
450 }
451
View as plain text