1
2
3
4
5
6
7 package types2
8
9 import (
10 "cmd/compile/internal/syntax"
11 "fmt"
12 . "internal/types/errors"
13 "strings"
14 )
15
16
17
18
19
20
21 func (check *Checker) assignment(x *operand, T Type, context string) {
22 check.singleValue(x)
23
24 switch x.mode() {
25 case invalid:
26 return
27 case nilvalue:
28 assert(isTypes2)
29
30 case constant_, variable, mapindex, value, commaok, commaerr:
31
32 default:
33
34
35 check.errorf(x, IncompatibleAssign, "cannot assign %s to %s in %s", x, T, context)
36 x.invalidate()
37 return
38 }
39
40 if isUntyped(x.typ()) {
41 target := T
42
43
44
45
46
47 if isTypes2 {
48 if x.isNil() {
49 if T == nil {
50 check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context)
51 x.invalidate()
52 return
53 }
54 } else if T == nil || isNonTypeParamInterface(T) {
55 target = Default(x.typ())
56 }
57 } else {
58 if T == nil || isNonTypeParamInterface(T) {
59 if T == nil && x.typ() == Typ[UntypedNil] {
60 check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context)
61 x.invalidate()
62 return
63 }
64 target = Default(x.typ())
65 }
66 }
67 newType, val, code := check.implicitTypeAndValue(x, target)
68 if code != 0 {
69 msg := check.sprintf("cannot use %s as %s value in %s", x, target, context)
70 switch code {
71 case TruncatedFloat:
72 msg += " (truncated)"
73 case NumericOverflow:
74 msg += " (overflows)"
75 default:
76 code = IncompatibleAssign
77 }
78 check.error(x, code, msg)
79 x.invalidate()
80 return
81 }
82 if val != nil {
83 x.val = val
84 check.updateExprVal(x.expr, val)
85 }
86 if newType != x.typ() {
87 x.typ_ = newType
88 check.updateExprType(x.expr, newType, false)
89 }
90 }
91
92
93
94 check.nonGeneric(newTarget(T, context), x)
95 if !x.isValid() {
96 return
97 }
98
99
100
101
102 if T == nil {
103 return
104 }
105
106 cause := ""
107 if ok, code := x.assignableTo(check, T, &cause); !ok {
108 if cause != "" {
109 check.errorf(x, code, "cannot use %s as %s value in %s: %s", x, T, context, cause)
110 } else {
111 check.errorf(x, code, "cannot use %s as %s value in %s", x, T, context)
112 }
113 x.invalidate()
114 }
115 }
116
117 func (check *Checker) initConst(lhs *Const, x *operand) {
118 if !x.isValid() || !isValid(x.typ()) || !isValid(lhs.typ) {
119 if lhs.typ == nil {
120 lhs.typ = Typ[Invalid]
121 }
122 return
123 }
124
125
126 if x.mode() != constant_ {
127 check.errorf(x, InvalidConstInit, "%s is not constant", x)
128 if lhs.typ == nil {
129 lhs.typ = Typ[Invalid]
130 }
131 return
132 }
133 assert(isConstType(x.typ()))
134
135
136 if lhs.typ == nil {
137 lhs.typ = x.typ()
138 }
139
140 check.assignment(x, lhs.typ, "constant declaration")
141 if !x.isValid() {
142 return
143 }
144
145 lhs.val = x.val
146 }
147
148
149
150
151
152 func (check *Checker) initVar(lhs *Var, x *operand, context string) {
153 if !x.isValid() || !isValid(x.typ()) || !isValid(lhs.typ) {
154 if lhs.typ == nil {
155 lhs.typ = Typ[Invalid]
156 }
157 x.invalidate()
158 return
159 }
160
161
162 if lhs.typ == nil {
163 typ := x.typ()
164 if isUntyped(typ) {
165
166 if typ == Typ[UntypedNil] {
167 check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context)
168 lhs.typ = Typ[Invalid]
169 x.invalidate()
170 return
171 }
172 typ = Default(typ)
173 }
174 lhs.typ = typ
175 }
176
177 check.assignment(x, lhs.typ, context)
178 }
179
180
181
182
183
184 func (check *Checker) lhsVar(lhs syntax.Expr) Type {
185
186 ident, _ := syntax.Unparen(lhs).(*syntax.Name)
187
188
189 if ident != nil && ident.Value == "_" {
190 check.recordDef(ident, nil)
191 return nil
192 }
193
194
195
196
197 var v *Var
198 var v_used bool
199 if ident != nil {
200 if obj := check.lookup(ident.Value); obj != nil {
201
202
203
204 if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {
205 v = w
206 v_used = check.usedVars[v]
207 }
208 }
209 }
210
211 var x operand
212 check.expr(nil, &x, lhs)
213
214 if v != nil {
215 check.usedVars[v] = v_used
216 }
217
218 if !x.isValid() || !isValid(x.typ()) {
219 return Typ[Invalid]
220 }
221
222
223
224 switch x.mode() {
225 case invalid:
226 return Typ[Invalid]
227 case variable, mapindex:
228
229 default:
230 if sel, ok := x.expr.(*syntax.SelectorExpr); ok {
231 var op operand
232 check.expr(nil, &op, sel.X)
233 if op.mode() == mapindex {
234 check.errorf(&x, UnaddressableFieldAssign, "cannot assign to struct field %s in map", ExprString(x.expr))
235 return Typ[Invalid]
236 }
237 }
238 check.errorf(&x, UnassignableOperand, "cannot assign to %s (neither addressable nor a map index expression)", x.expr)
239 return Typ[Invalid]
240 }
241
242 return x.typ()
243 }
244
245
246
247
248 func (check *Checker) assignVar(lhs, rhs syntax.Expr, x *operand, context string) {
249 T := check.lhsVar(lhs)
250 if !isValid(T) {
251 if x != nil {
252 x.invalidate()
253 } else {
254 check.use(rhs)
255 }
256 return
257 }
258
259 if x == nil {
260 var target *target
261
262 if T != nil {
263 if _, ok := T.Underlying().(*Signature); ok {
264 target = newTarget(T, ExprString(lhs))
265 }
266 }
267 x = new(operand)
268 check.expr(target, x, rhs)
269 }
270
271 if T == nil && context == "assignment" {
272 context = "assignment to _ identifier"
273 }
274 check.assignment(x, T, context)
275 }
276
277
278 func operandTypes(list []*operand) (res []Type) {
279 for _, x := range list {
280 res = append(res, x.typ())
281 }
282 return res
283 }
284
285
286 func varTypes(list []*Var) (res []Type) {
287 for _, x := range list {
288 res = append(res, x.typ)
289 }
290 return res
291 }
292
293
294
295
296
297
298
299
300 func (check *Checker) typesSummary(list []Type, variadic, hasDots bool) string {
301 assert(!(variadic && hasDots))
302 var res []string
303 for i, t := range list {
304 var s string
305 switch {
306 case t == nil:
307 fallthrough
308 case !isValid(t):
309 s = "unknown type"
310 case isUntyped(t):
311 if isNumeric(t) {
312
313
314
315
316 s = "number"
317 } else {
318
319
320 s = strings.ReplaceAll(t.(*Basic).name, "untyped ", "")
321 }
322 default:
323 s = check.sprintf("%s", t)
324 }
325
326 if i == len(list)-1 {
327 switch {
328 case variadic:
329
330 if t, _ := t.(*Slice); t != nil {
331 s = check.sprintf("%s", t.elem)
332 }
333 s = "..." + s
334 case hasDots:
335 s += "..."
336 }
337 }
338 res = append(res, s)
339 }
340 return "(" + strings.Join(res, ", ") + ")"
341 }
342
343 func measure(x int, unit string) string {
344 if x != 1 {
345 unit += "s"
346 }
347 return fmt.Sprintf("%d %s", x, unit)
348 }
349
350 func (check *Checker) assignError(rhs []syntax.Expr, l, r int) {
351 vars := measure(l, "variable")
352 vals := measure(r, "value")
353 rhs0 := rhs[0]
354
355 if len(rhs) == 1 {
356 if call, _ := syntax.Unparen(rhs0).(*syntax.CallExpr); call != nil {
357 check.errorf(rhs0, WrongAssignCount, "assignment mismatch: %s but %s returns %s", vars, call.Fun, vals)
358 return
359 }
360 }
361 check.errorf(rhs0, WrongAssignCount, "assignment mismatch: %s but %s", vars, vals)
362 }
363
364 func (check *Checker) returnError(at poser, lhs []*Var, rhs []*operand) {
365 l, r := len(lhs), len(rhs)
366 qualifier := "not enough"
367 if r > l {
368 at = rhs[l]
369 qualifier = "too many"
370 } else if r > 0 {
371 at = rhs[r-1]
372 }
373 err := check.newError(WrongResultCount)
374 err.addf(at, "%s return values", qualifier)
375 err.addf(nopos, "have %s", check.typesSummary(operandTypes(rhs), false, false))
376 err.addf(nopos, "want %s", check.typesSummary(varTypes(lhs), false, false))
377 err.report()
378 }
379
380
381
382
383
384 func (check *Checker) initVars(lhs []*Var, orig_rhs []syntax.Expr, returnStmt syntax.Stmt) {
385 l, r := len(lhs), len(orig_rhs)
386
387 context := "assignment"
388 if returnStmt != nil {
389 context = "return statement"
390 } else if l > 1 {
391 context = "multiple assignment"
392 }
393
394
395
396 isCall := false
397 if r == 1 {
398 _, isCall = syntax.Unparen(orig_rhs[0]).(*syntax.CallExpr)
399 }
400
401
402
403 if l == r && !isCall {
404 var x operand
405 for i, lhs := range lhs {
406 desc := lhs.name
407 if returnStmt != nil && desc == "" {
408 desc = "result variable"
409 }
410 check.expr(newTarget(lhs.typ, desc), &x, orig_rhs[i])
411 check.initVar(lhs, &x, context)
412 }
413 return
414 }
415
416
417
418 if r != 1 {
419
420 if check.use(orig_rhs...) {
421 if returnStmt != nil {
422 rhs := check.exprList(orig_rhs)
423 check.returnError(returnStmt, lhs, rhs)
424 } else {
425 check.assignError(orig_rhs, l, r)
426 }
427 }
428
429 for _, v := range lhs {
430 if v.typ == nil {
431 v.typ = Typ[Invalid]
432 }
433 }
434 return
435 }
436
437 rhs, commaOk := check.multiExpr(orig_rhs[0], l == 2 && returnStmt == nil)
438 r = len(rhs)
439 if l == r {
440 for i, lhs := range lhs {
441 check.initVar(lhs, rhs[i], context)
442 }
443
444
445 if commaOk && rhs[0].mode() != invalid && rhs[1].mode() != invalid {
446 check.recordCommaOkTypes(orig_rhs[0], rhs)
447 }
448 return
449 }
450
451
452
453 if rhs[0].mode() != invalid {
454 if returnStmt != nil {
455 check.returnError(returnStmt, lhs, rhs)
456 } else {
457 check.assignError(orig_rhs, l, r)
458 }
459 }
460
461 for _, v := range lhs {
462 if v.typ == nil {
463 v.typ = Typ[Invalid]
464 }
465 }
466
467 }
468
469
470 func (check *Checker) assignVars(lhs, orig_rhs []syntax.Expr) {
471 l, r := len(lhs), len(orig_rhs)
472
473 context := "assignment"
474 if l > 1 {
475 context = "multiple assignment"
476 }
477
478
479
480 isCall := false
481 if r == 1 {
482 _, isCall = syntax.Unparen(orig_rhs[0]).(*syntax.CallExpr)
483 }
484
485
486
487 if l == r && !isCall {
488 for i, lhs := range lhs {
489 check.assignVar(lhs, orig_rhs[i], nil, context)
490 }
491 return
492 }
493
494
495
496 if r != 1 {
497
498 okLHS := check.useLHS(lhs...)
499 okRHS := check.use(orig_rhs...)
500 if okLHS && okRHS {
501 check.assignError(orig_rhs, l, r)
502 }
503 return
504 }
505
506 rhs, commaOk := check.multiExpr(orig_rhs[0], l == 2)
507 r = len(rhs)
508 if l == r {
509 for i, lhs := range lhs {
510 check.assignVar(lhs, nil, rhs[i], context)
511 }
512
513
514 if commaOk && rhs[0].mode() != invalid && rhs[1].mode() != invalid {
515 check.recordCommaOkTypes(orig_rhs[0], rhs)
516 }
517 return
518 }
519
520
521
522 if rhs[0].mode() != invalid {
523 check.assignError(orig_rhs, l, r)
524 }
525 check.useLHS(lhs...)
526
527 }
528
529 func (check *Checker) shortVarDecl(pos poser, lhs, rhs []syntax.Expr) {
530 top := len(check.delayed)
531 scope := check.scope
532
533
534 seen := make(map[string]bool, len(lhs))
535 lhsVars := make([]*Var, len(lhs))
536 newVars := make([]*Var, 0, len(lhs))
537 hasErr := false
538 for i, lhs := range lhs {
539 ident, _ := lhs.(*syntax.Name)
540 if ident == nil {
541 check.useLHS(lhs)
542
543 check.errorf(lhs, BadDecl, "non-name %s on left side of :=", lhs)
544 hasErr = true
545 continue
546 }
547
548 name := ident.Value
549 if name != "_" {
550 if seen[name] {
551 check.errorf(lhs, RepeatedDecl, "%s repeated on left side of :=", lhs)
552 hasErr = true
553 continue
554 }
555 seen[name] = true
556 }
557
558
559
560
561
562 if alt := scope.Lookup(name); alt != nil {
563 check.recordUse(ident, alt)
564
565 if obj, _ := alt.(*Var); obj != nil {
566 lhsVars[i] = obj
567 } else {
568 check.errorf(lhs, UnassignableOperand, "cannot assign to %s", lhs)
569 hasErr = true
570 }
571 continue
572 }
573
574
575 obj := newVar(LocalVar, ident.Pos(), check.pkg, name, nil)
576 lhsVars[i] = obj
577 if name != "_" {
578 newVars = append(newVars, obj)
579 }
580 check.recordDef(ident, obj)
581 }
582
583
584 for i, obj := range lhsVars {
585 if obj == nil {
586 lhsVars[i] = newVar(LocalVar, lhs[i].Pos(), check.pkg, "_", nil)
587 }
588 }
589
590 check.initVars(lhsVars, rhs, nil)
591
592
593 check.processDelayed(top)
594
595 if len(newVars) == 0 && !hasErr {
596 check.softErrorf(pos, NoNewVar, "no new variables on left side of :=")
597 return
598 }
599
600
601
602
603
604
605 scopePos := endPos(rhs[len(rhs)-1])
606 for _, obj := range newVars {
607 check.declare(scope, nil, obj, scopePos)
608 }
609 }
610
View as plain text