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