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