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 if T != nil {
262
263 var desc string
264 if _, ok := T.Underlying().(*Signature); ok {
265 desc = ExprString(lhs)
266 }
267 target = newTarget(T, desc)
268 }
269 x = new(operand)
270 check.expr(target, x, rhs)
271 }
272
273 if T == nil && context == "assignment" {
274 context = "assignment to _ identifier"
275 }
276 check.assignment(x, T, context)
277 }
278
279
280 func operandTypes(list []*operand) (res []Type) {
281 for _, x := range list {
282 res = append(res, x.typ())
283 }
284 return res
285 }
286
287
288 func varTypes(list []*Var) (res []Type) {
289 for _, x := range list {
290 res = append(res, x.typ)
291 }
292 return res
293 }
294
295
296
297
298
299
300
301
302 func (check *Checker) typesSummary(list []Type, variadic, hasDots bool) string {
303 assert(!(variadic && hasDots))
304 var res []string
305 for i, t := range list {
306 var s string
307 switch {
308 case t == nil:
309 fallthrough
310 case !isValid(t):
311 s = "unknown type"
312 case isUntyped(t):
313 if isNumeric(t) {
314
315
316
317
318 s = "number"
319 } else {
320
321
322 s = strings.ReplaceAll(t.(*Basic).name, "untyped ", "")
323 }
324 default:
325 s = check.sprintf("%s", t)
326 }
327
328 if i == len(list)-1 {
329 switch {
330 case variadic:
331
332 if t, _ := t.(*Slice); t != nil {
333 s = check.sprintf("%s", t.elem)
334 }
335 s = "..." + s
336 case hasDots:
337 s += "..."
338 }
339 }
340 res = append(res, s)
341 }
342 return "(" + strings.Join(res, ", ") + ")"
343 }
344
345 func measure(x int, unit string) string {
346 if x != 1 {
347 unit += "s"
348 }
349 return fmt.Sprintf("%d %s", x, unit)
350 }
351
352 func (check *Checker) assignError(rhs []syntax.Expr, l, r int) {
353 vars := measure(l, "variable")
354 vals := measure(r, "value")
355 rhs0 := rhs[0]
356
357 if len(rhs) == 1 {
358 if call, _ := syntax.Unparen(rhs0).(*syntax.CallExpr); call != nil {
359 check.errorf(rhs0, WrongAssignCount, "assignment mismatch: %s but %s returns %s", vars, call.Fun, vals)
360 return
361 }
362 }
363 check.errorf(rhs0, WrongAssignCount, "assignment mismatch: %s but %s", vars, vals)
364 }
365
366 func (check *Checker) returnError(at poser, lhs []*Var, rhs []*operand) {
367 l, r := len(lhs), len(rhs)
368 qualifier := "not enough"
369 if r > l {
370 at = rhs[l]
371 qualifier = "too many"
372 } else if r > 0 {
373 at = rhs[r-1]
374 }
375 err := check.newError(WrongResultCount)
376 err.addf(at, "%s return values", qualifier)
377 err.addf(nopos, "have %s", check.typesSummary(operandTypes(rhs), false, false))
378 err.addf(nopos, "want %s", check.typesSummary(varTypes(lhs), false, false))
379 err.report()
380 }
381
382
383
384
385
386 func (check *Checker) initVars(lhs []*Var, orig_rhs []syntax.Expr, returnStmt syntax.Stmt) {
387 l, r := len(lhs), len(orig_rhs)
388
389 context := "assignment"
390 if returnStmt != nil {
391 context = "return statement"
392 } else if l > 1 {
393 context = "multiple assignment"
394 }
395
396
397
398 isCall := false
399 if r == 1 {
400 _, isCall = syntax.Unparen(orig_rhs[0]).(*syntax.CallExpr)
401 }
402
403
404
405 if l == r && !isCall {
406 var x operand
407 for i, lhs := range lhs {
408 desc := lhs.name
409 if returnStmt != nil && desc == "" {
410 desc = "result variable"
411 }
412 check.expr(newTarget(lhs.typ, desc), &x, orig_rhs[i])
413 check.initVar(lhs, &x, context)
414 }
415 return
416 }
417
418
419
420 if r != 1 {
421
422 if check.use(orig_rhs...) {
423 if returnStmt != nil {
424 rhs := check.exprList(orig_rhs)
425 check.returnError(returnStmt, lhs, rhs)
426 } else {
427 check.assignError(orig_rhs, l, r)
428 }
429 }
430
431 for _, v := range lhs {
432 if v.typ == nil {
433 v.typ = Typ[Invalid]
434 }
435 }
436 return
437 }
438
439 rhs, commaOk := check.multiExpr(orig_rhs[0], l == 2 && returnStmt == nil)
440 r = len(rhs)
441 if l == r {
442 for i, lhs := range lhs {
443 check.initVar(lhs, rhs[i], context)
444 }
445
446
447 if commaOk && rhs[0].mode() != invalid && rhs[1].mode() != invalid {
448 check.recordCommaOkTypes(orig_rhs[0], rhs)
449 }
450 return
451 }
452
453
454
455 if rhs[0].mode() != invalid {
456 if returnStmt != nil {
457 check.returnError(returnStmt, lhs, rhs)
458 } else {
459 check.assignError(orig_rhs, l, r)
460 }
461 }
462
463 for _, v := range lhs {
464 if v.typ == nil {
465 v.typ = Typ[Invalid]
466 }
467 }
468
469 }
470
471
472 func (check *Checker) assignVars(lhs, orig_rhs []syntax.Expr) {
473 l, r := len(lhs), len(orig_rhs)
474
475 context := "assignment"
476 if l > 1 {
477 context = "multiple assignment"
478 }
479
480
481
482 isCall := false
483 if r == 1 {
484 _, isCall = syntax.Unparen(orig_rhs[0]).(*syntax.CallExpr)
485 }
486
487
488
489 if l == r && !isCall {
490 for i, lhs := range lhs {
491 check.assignVar(lhs, orig_rhs[i], nil, context)
492 }
493 return
494 }
495
496
497
498 if r != 1 {
499
500 okLHS := check.useLHS(lhs...)
501 okRHS := check.use(orig_rhs...)
502 if okLHS && okRHS {
503 check.assignError(orig_rhs, l, r)
504 }
505 return
506 }
507
508 rhs, commaOk := check.multiExpr(orig_rhs[0], l == 2)
509 r = len(rhs)
510 if l == r {
511 for i, lhs := range lhs {
512 check.assignVar(lhs, nil, rhs[i], context)
513 }
514
515
516 if commaOk && rhs[0].mode() != invalid && rhs[1].mode() != invalid {
517 check.recordCommaOkTypes(orig_rhs[0], rhs)
518 }
519 return
520 }
521
522
523
524 if rhs[0].mode() != invalid {
525 check.assignError(orig_rhs, l, r)
526 }
527 check.useLHS(lhs...)
528
529 }
530
531 func (check *Checker) shortVarDecl(pos poser, lhs, rhs []syntax.Expr) {
532 top := len(check.delayed)
533 scope := check.scope
534
535
536 seen := make(map[string]bool, len(lhs))
537 lhsVars := make([]*Var, len(lhs))
538 newVars := make([]*Var, 0, len(lhs))
539 hasErr := false
540 for i, lhs := range lhs {
541 ident, _ := lhs.(*syntax.Name)
542 if ident == nil {
543 check.useLHS(lhs)
544
545 check.errorf(lhs, BadDecl, "non-name %s on left side of :=", lhs)
546 hasErr = true
547 continue
548 }
549
550 name := ident.Value
551 if name != "_" {
552 if seen[name] {
553 check.errorf(lhs, RepeatedDecl, "%s repeated on left side of :=", lhs)
554 hasErr = true
555 continue
556 }
557 seen[name] = true
558 }
559
560
561
562
563
564 if alt := scope.Lookup(name); alt != nil {
565 check.recordUse(ident, alt)
566
567 if obj, _ := alt.(*Var); obj != nil {
568 lhsVars[i] = obj
569 } else {
570 check.errorf(lhs, UnassignableOperand, "cannot assign to %s", lhs)
571 hasErr = true
572 }
573 continue
574 }
575
576
577 obj := newVar(LocalVar, ident.Pos(), check.pkg, name, nil)
578 lhsVars[i] = obj
579 if name != "_" {
580 newVars = append(newVars, obj)
581 }
582 check.recordDef(ident, obj)
583 }
584
585
586 for i, obj := range lhsVars {
587 if obj == nil {
588 lhsVars[i] = newVar(LocalVar, lhs[i].Pos(), check.pkg, "_", nil)
589 }
590 }
591
592 check.initVars(lhsVars, rhs, nil)
593
594
595 check.processDelayed(top)
596
597 if len(newVars) == 0 && !hasErr {
598 check.softErrorf(pos, NoNewVar, "no new variables on left side of :=")
599 return
600 }
601
602
603
604
605
606
607 scopePos := endPos(rhs[len(rhs)-1])
608 for _, obj := range newVars {
609 check.declare(scope, nil, obj, scopePos)
610 }
611 }
612
View as plain text