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