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 "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, commaok, commaerr:
27
28 default:
29
30 check.errorf(x, 0, "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 T == nil || IsInterface(T) && !isTypeParam(T) {
42 if T == nil && x.typ == Typ[UntypedNil] {
43 check.errorf(x, _UntypedNil, "use of untyped nil in %s", context)
44 x.mode = invalid
45 return
46 }
47 target = Default(x.typ)
48 }
49 newType, val, code := check.implicitTypeAndValue(x, target)
50 if code != 0 {
51 msg := check.sprintf("cannot use %s as %s value in %s", x, target, context)
52 switch code {
53 case _TruncatedFloat:
54 msg += " (truncated)"
55 case _NumericOverflow:
56 msg += " (overflows)"
57 default:
58 code = _IncompatibleAssign
59 }
60 check.error(x, code, msg)
61 x.mode = invalid
62 return
63 }
64 if val != nil {
65 x.val = val
66 check.updateExprVal(x.expr, val)
67 }
68 if newType != x.typ {
69 x.typ = newType
70 check.updateExprType(x.expr, newType, false)
71 }
72 }
73
74
75 if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 {
76 check.errorf(x, _WrongTypeArgCount, "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, code := x.assignableTo(check, T, &reason); !ok {
88 if compilerErrorMessages {
89 if reason != "" {
90 check.errorf(x, code, "cannot use %s as type %s in %s:\n\t%s", x, T, context, reason)
91 } else {
92 check.errorf(x, code, "cannot use %s as type %s in %s", x, T, context)
93 }
94 } else {
95 if reason != "" {
96 check.errorf(x, code, "cannot use %s as %s value in %s: %s", x, T, context, reason)
97 } else {
98 check.errorf(x, code, "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, _InvalidConstInit, "%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 return nil
142 }
143
144
145 if lhs.typ == nil {
146 typ := x.typ
147 if isUntyped(typ) {
148
149 if typ == Typ[UntypedNil] {
150 check.errorf(x, _UntypedNil, "use of untyped nil in %s", context)
151 lhs.typ = Typ[Invalid]
152 return nil
153 }
154 typ = Default(typ)
155 }
156 lhs.typ = typ
157 }
158
159 check.assignment(x, lhs.typ, context)
160 if x.mode == invalid {
161 return nil
162 }
163
164 return x.typ
165 }
166
167 func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type {
168 if x.mode == invalid || x.typ == Typ[Invalid] {
169 check.useLHS(lhs)
170 return nil
171 }
172
173
174 ident, _ := unparen(lhs).(*ast.Ident)
175
176
177 if ident != nil && ident.Name == "_" {
178 check.recordDef(ident, nil)
179 check.assignment(x, nil, "assignment to _ identifier")
180 if x.mode == invalid {
181 return nil
182 }
183 return x.typ
184 }
185
186
187
188
189 var v *Var
190 var v_used bool
191 if ident != nil {
192 if obj := check.lookup(ident.Name); obj != nil {
193
194
195
196 if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {
197 v = w
198 v_used = v.used
199 }
200 }
201 }
202
203 var z operand
204 check.expr(&z, lhs)
205 if v != nil {
206 v.used = v_used
207 }
208
209 if z.mode == invalid || z.typ == Typ[Invalid] {
210 return nil
211 }
212
213
214
215 switch z.mode {
216 case invalid:
217 return nil
218 case variable, mapindex:
219
220 default:
221 if sel, ok := z.expr.(*ast.SelectorExpr); ok {
222 var op operand
223 check.expr(&op, sel.X)
224 if op.mode == mapindex {
225 check.errorf(&z, _UnaddressableFieldAssign, "cannot assign to struct field %s in map", ExprString(z.expr))
226 return nil
227 }
228 }
229 check.errorf(&z, _UnassignableOperand, "cannot assign to %s", &z)
230 return nil
231 }
232
233 check.assignment(x, z.typ, "assignment")
234 if x.mode == invalid {
235 return nil
236 }
237
238 return x.typ
239 }
240
241
242 func operandTypes(list []*operand) (res []Type) {
243 for _, x := range list {
244 res = append(res, x.typ)
245 }
246 return res
247 }
248
249
250 func varTypes(list []*Var) (res []Type) {
251 for _, x := range list {
252 res = append(res, x.typ)
253 }
254 return res
255 }
256
257
258
259
260
261 func (check *Checker) typesSummary(list []Type, variadic bool) string {
262 var res []string
263 for i, t := range list {
264 var s string
265 switch {
266 case t == nil:
267 fallthrough
268 case t == Typ[Invalid]:
269 s = "<T>"
270 case isUntyped(t):
271 if isNumeric(t) {
272
273
274
275
276 s = "number"
277 } else {
278
279
280 s = strings.Replace(t.(*Basic).name, "untyped ", "", -1)
281 }
282 case variadic && i == len(list)-1:
283 s = check.sprintf("...%s", t.(*Slice).elem)
284 }
285 if s == "" {
286 s = check.sprintf("%s", t)
287 }
288 res = append(res, s)
289 }
290 return "(" + strings.Join(res, ", ") + ")"
291 }
292
293 func measure(x int, unit string) string {
294 if x != 1 {
295 unit += "s"
296 }
297 return fmt.Sprintf("%d %s", x, unit)
298 }
299
300 func (check *Checker) assignError(rhs []ast.Expr, nvars, nvals int) {
301 vars := measure(nvars, "variable")
302 vals := measure(nvals, "value")
303 rhs0 := rhs[0]
304
305 if len(rhs) == 1 {
306 if call, _ := unparen(rhs0).(*ast.CallExpr); call != nil {
307 check.errorf(rhs0, _WrongAssignCount, "assignment mismatch: %s but %s returns %s", vars, call.Fun, vals)
308 return
309 }
310 }
311 check.errorf(rhs0, _WrongAssignCount, "assignment mismatch: %s but %s", vars, vals)
312 }
313
314
315
316 func (check *Checker) initVars(lhs []*Var, origRHS []ast.Expr, returnStmt ast.Stmt) {
317 rhs, commaOk := check.exprList(origRHS, len(lhs) == 2 && returnStmt == nil)
318
319 if len(lhs) != len(rhs) {
320
321 for _, obj := range lhs {
322 obj.used = true
323 if obj.typ == nil {
324 obj.typ = Typ[Invalid]
325 }
326 }
327
328 for _, x := range rhs {
329 if x.mode == invalid {
330 return
331 }
332 }
333 if returnStmt != nil {
334 var at positioner = returnStmt
335 qualifier := "not enough"
336 if len(rhs) > len(lhs) {
337 at = rhs[len(lhs)].expr
338 qualifier = "too many"
339 } else if len(rhs) > 0 {
340 at = rhs[len(rhs)-1].expr
341 }
342 check.errorf(at, _WrongResultCount, "%s return values\n\thave %s\n\twant %s",
343 qualifier,
344 check.typesSummary(operandTypes(rhs), false),
345 check.typesSummary(varTypes(lhs), false),
346 )
347 return
348 }
349 if compilerErrorMessages {
350 check.assignError(origRHS, len(lhs), len(rhs))
351 } else {
352 check.errorf(rhs[0], _WrongAssignCount, "cannot initialize %d variables with %d values", len(lhs), len(rhs))
353 }
354 return
355 }
356
357 context := "assignment"
358 if returnStmt != nil {
359 context = "return statement"
360 }
361
362 if commaOk {
363 var a [2]Type
364 for i := range a {
365 a[i] = check.initVar(lhs[i], rhs[i], context)
366 }
367 check.recordCommaOkTypes(origRHS[0], a)
368 return
369 }
370
371 for i, lhs := range lhs {
372 check.initVar(lhs, rhs[i], context)
373 }
374 }
375
376 func (check *Checker) assignVars(lhs, origRHS []ast.Expr) {
377 rhs, commaOk := check.exprList(origRHS, len(lhs) == 2)
378
379 if len(lhs) != len(rhs) {
380 check.useLHS(lhs...)
381
382 for _, x := range rhs {
383 if x.mode == invalid {
384 return
385 }
386 }
387 if compilerErrorMessages {
388 check.assignError(origRHS, len(lhs), len(rhs))
389 } else {
390 check.errorf(rhs[0], _WrongAssignCount, "cannot assign %d values to %d variables", len(rhs), len(lhs))
391 }
392 return
393 }
394
395 if commaOk {
396 var a [2]Type
397 for i := range a {
398 a[i] = check.assignVar(lhs[i], rhs[i])
399 }
400 check.recordCommaOkTypes(origRHS[0], a)
401 return
402 }
403
404 for i, lhs := range lhs {
405 check.assignVar(lhs, rhs[i])
406 }
407 }
408
409 func (check *Checker) shortVarDecl(pos positioner, lhs, rhs []ast.Expr) {
410 top := len(check.delayed)
411 scope := check.scope
412
413
414 seen := make(map[string]bool, len(lhs))
415 lhsVars := make([]*Var, len(lhs))
416 newVars := make([]*Var, 0, len(lhs))
417 hasErr := false
418 for i, lhs := range lhs {
419 ident, _ := lhs.(*ast.Ident)
420 if ident == nil {
421 check.useLHS(lhs)
422
423 check.errorf(lhs, _BadDecl, "non-name %s on left side of :=", lhs)
424 hasErr = true
425 continue
426 }
427
428 name := ident.Name
429 if name != "_" {
430 if seen[name] {
431 check.errorf(lhs, _RepeatedDecl, "%s repeated on left side of :=", lhs)
432 hasErr = true
433 continue
434 }
435 seen[name] = true
436 }
437
438
439
440
441
442 if alt := scope.Lookup(name); alt != nil {
443 check.recordUse(ident, alt)
444
445 if obj, _ := alt.(*Var); obj != nil {
446 lhsVars[i] = obj
447 } else {
448 check.errorf(lhs, _UnassignableOperand, "cannot assign to %s", lhs)
449 hasErr = true
450 }
451 continue
452 }
453
454
455 obj := NewVar(ident.Pos(), check.pkg, name, nil)
456 lhsVars[i] = obj
457 if name != "_" {
458 newVars = append(newVars, obj)
459 }
460 check.recordDef(ident, obj)
461 }
462
463
464 for i, obj := range lhsVars {
465 if obj == nil {
466 lhsVars[i] = NewVar(lhs[i].Pos(), check.pkg, "_", nil)
467 }
468 }
469
470 check.initVars(lhsVars, rhs, nil)
471
472
473 check.processDelayed(top)
474
475 if len(newVars) == 0 && !hasErr {
476 check.softErrorf(pos, _NoNewVar, "no new variables on left side of :=")
477 return
478 }
479
480
481
482
483
484
485 scopePos := rhs[len(rhs)-1].End()
486 for _, obj := range newVars {
487 check.declare(scope, nil, obj, scopePos)
488 }
489 }
490
View as plain text