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, _ := Unalias(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 origT := T
264 V := Unalias(x.typ)
265 T = Unalias(T)
266
267
268 if Identical(V, T) {
269 return true, 0
270 }
271
272 Vu := under(V)
273 Tu := under(T)
274 Vp, _ := V.(*TypeParam)
275 Tp, _ := T.(*TypeParam)
276
277
278 if isUntyped(Vu) {
279 assert(Vp == nil)
280 if Tp != nil {
281
282
283 return Tp.is(func(t *term) bool {
284 if t == nil {
285 return false
286 }
287
288
289
290 newType, _, _ := check.implicitTypeAndValue(x, t.typ)
291 return newType != nil
292 }), IncompatibleAssign
293 }
294 newType, _, _ := check.implicitTypeAndValue(x, T)
295 return newType != nil, IncompatibleAssign
296 }
297
298
299
300
301
302 if Identical(Vu, Tu) && (!hasName(V) || !hasName(T)) && Vp == nil && Tp == nil {
303 return true, 0
304 }
305
306
307
308
309 if _, ok := Tu.(*Interface); ok && Tp == nil || isInterfacePtr(Tu) {
310 if check.implements(x.Pos(), V, T, false, cause) {
311 return true, 0
312 }
313
314
315 if Vp == nil {
316 return false, InvalidIfaceAssign
317 }
318 if cause != nil {
319 *cause = ""
320 }
321 }
322
323
324 if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil {
325 if check.implements(x.Pos(), T, V, false, nil) {
326
327 if cause != nil {
328 *cause = "need type assertion"
329 }
330 return false, IncompatibleAssign
331 }
332 }
333
334
335
336
337 if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv {
338 if Tc, ok := Tu.(*Chan); ok && Identical(Vc.elem, Tc.elem) {
339 return !hasName(V) || !hasName(T), InvalidChanAssign
340 }
341 }
342
343
344 if Vp == nil && Tp == nil {
345 return false, IncompatibleAssign
346 }
347
348 errorf := func(format string, args ...any) {
349 if check != nil && cause != nil {
350 msg := check.sprintf(format, args...)
351 if *cause != "" {
352 msg += "\n\t" + *cause
353 }
354 *cause = msg
355 }
356 }
357
358
359
360 if !hasName(V) && Tp != nil {
361 ok := false
362 code := IncompatibleAssign
363 Tp.is(func(T *term) bool {
364 if T == nil {
365 return false
366 }
367 ok, code = x.assignableTo(check, T.typ, cause)
368 if !ok {
369 errorf("cannot assign %s to %s (in %s)", x.typ, T.typ, Tp)
370 return false
371 }
372 return true
373 })
374 return ok, code
375 }
376
377
378
379
380 if Vp != nil && !hasName(T) {
381 x := *x
382 ok := false
383 code := IncompatibleAssign
384 Vp.is(func(V *term) bool {
385 if V == nil {
386 return false
387 }
388 x.typ = V.typ
389 ok, code = x.assignableTo(check, T, cause)
390 if !ok {
391 errorf("cannot assign %s (in %s) to %s", V.typ, Vp, origT)
392 return false
393 }
394 return true
395 })
396 return ok, code
397 }
398
399 return false, IncompatibleAssign
400 }
401
View as plain text