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