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