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