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 "go/token"
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 check.errorf(x, 0, "cannot assign %s to %s in %s", x, T, context)
32 return
33 }
34
35 if isUntyped(x.typ) {
36 target := T
37
38
39
40
41
42 if T == nil || isNonTypeParamInterface(T) {
43 if T == nil && x.typ == Typ[UntypedNil] {
44 check.errorf(x, _UntypedNil, "use of untyped nil in %s", context)
45 x.mode = invalid
46 return
47 }
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 default:
59 code = _IncompatibleAssign
60 }
61 check.error(x, code, msg)
62 x.mode = invalid
63 return
64 }
65 if val != nil {
66 x.val = val
67 check.updateExprVal(x.expr, val)
68 }
69 if newType != x.typ {
70 x.typ = newType
71 check.updateExprType(x.expr, newType, false)
72 }
73 }
74
75
76 if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 {
77 check.errorf(x, _WrongTypeArgCount, "cannot use generic function %s without instantiation in %s", x, context)
78 }
79
80
81
82
83 if T == nil {
84 return
85 }
86
87 reason := ""
88 if ok, code := x.assignableTo(check, T, &reason); !ok {
89 if compilerErrorMessages {
90 if reason != "" {
91 check.errorf(x, code, "cannot use %s as type %s in %s:\n\t%s", x, T, context, reason)
92 } else {
93 check.errorf(x, code, "cannot use %s as type %s in %s", x, T, context)
94 }
95 } else {
96 if reason != "" {
97 check.errorf(x, code, "cannot use %s as %s value in %s: %s", x, T, context, reason)
98 } else {
99 check.errorf(x, code, "cannot use %s as %s value in %s", x, T, context)
100 }
101 }
102 x.mode = invalid
103 }
104 }
105
106 func (check *Checker) initConst(lhs *Const, x *operand) {
107 if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
108 if lhs.typ == nil {
109 lhs.typ = Typ[Invalid]
110 }
111 return
112 }
113
114
115 if x.mode != constant_ {
116 check.errorf(x, _InvalidConstInit, "%s is not constant", x)
117 if lhs.typ == nil {
118 lhs.typ = Typ[Invalid]
119 }
120 return
121 }
122 assert(isConstType(x.typ))
123
124
125 if lhs.typ == nil {
126 lhs.typ = x.typ
127 }
128
129 check.assignment(x, lhs.typ, "constant declaration")
130 if x.mode == invalid {
131 return
132 }
133
134 lhs.val = x.val
135 }
136
137 func (check *Checker) initVar(lhs *Var, x *operand, context string) Type {
138 if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
139 if lhs.typ == nil {
140 lhs.typ = Typ[Invalid]
141 }
142 return nil
143 }
144
145
146 if lhs.typ == nil {
147 typ := x.typ
148 if isUntyped(typ) {
149
150 if typ == Typ[UntypedNil] {
151 check.errorf(x, _UntypedNil, "use of untyped nil in %s", context)
152 lhs.typ = Typ[Invalid]
153 return nil
154 }
155 typ = Default(typ)
156 }
157 lhs.typ = typ
158 }
159
160 check.assignment(x, lhs.typ, context)
161 if x.mode == invalid {
162 return nil
163 }
164
165 return x.typ
166 }
167
168 func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type {
169 if x.mode == invalid || x.typ == Typ[Invalid] {
170 check.useLHS(lhs)
171 return nil
172 }
173
174
175 ident, _ := unparen(lhs).(*ast.Ident)
176
177
178 if ident != nil && ident.Name == "_" {
179 check.recordDef(ident, nil)
180 check.assignment(x, nil, "assignment to _ identifier")
181 if x.mode == invalid {
182 return nil
183 }
184 return x.typ
185 }
186
187
188
189
190 var v *Var
191 var v_used bool
192 if ident != nil {
193 if obj := check.lookup(ident.Name); obj != nil {
194
195
196
197 if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {
198 v = w
199 v_used = v.used
200 }
201 }
202 }
203
204 var z operand
205 check.expr(&z, lhs)
206 if v != nil {
207 v.used = v_used
208 }
209
210 if z.mode == invalid || z.typ == Typ[Invalid] {
211 return nil
212 }
213
214
215
216 switch z.mode {
217 case invalid:
218 return nil
219 case variable, mapindex:
220
221 default:
222 if sel, ok := z.expr.(*ast.SelectorExpr); ok {
223 var op operand
224 check.expr(&op, sel.X)
225 if op.mode == mapindex {
226 check.errorf(&z, _UnaddressableFieldAssign, "cannot assign to struct field %s in map", ExprString(z.expr))
227 return nil
228 }
229 }
230 check.errorf(&z, _UnassignableOperand, "cannot assign to %s", &z)
231 return nil
232 }
233
234 check.assignment(x, z.typ, "assignment")
235 if x.mode == invalid {
236 return nil
237 }
238
239 return x.typ
240 }
241
242
243 func operandTypes(list []*operand) (res []Type) {
244 for _, x := range list {
245 res = append(res, x.typ)
246 }
247 return res
248 }
249
250
251 func varTypes(list []*Var) (res []Type) {
252 for _, x := range list {
253 res = append(res, x.typ)
254 }
255 return res
256 }
257
258
259
260
261
262 func (check *Checker) typesSummary(list []Type, variadic bool) string {
263 var res []string
264 for i, t := range list {
265 var s string
266 switch {
267 case t == nil:
268 fallthrough
269 case t == Typ[Invalid]:
270 s = "<T>"
271 case isUntyped(t):
272 if isNumeric(t) {
273
274
275
276
277 s = "number"
278 } else {
279
280
281 s = strings.Replace(t.(*Basic).name, "untyped ", "", -1)
282 }
283 case variadic && i == len(list)-1:
284 s = check.sprintf("...%s", t.(*Slice).elem)
285 }
286 if s == "" {
287 s = check.sprintf("%s", t)
288 }
289 res = append(res, s)
290 }
291 return "(" + strings.Join(res, ", ") + ")"
292 }
293
294 func measure(x int, unit string) string {
295 if x != 1 {
296 unit += "s"
297 }
298 return fmt.Sprintf("%d %s", x, unit)
299 }
300
301 func (check *Checker) assignError(rhs []ast.Expr, nvars, nvals int) {
302 vars := measure(nvars, "variable")
303 vals := measure(nvals, "value")
304 rhs0 := rhs[0]
305
306 if len(rhs) == 1 {
307 if call, _ := unparen(rhs0).(*ast.CallExpr); call != nil {
308 check.errorf(rhs0, _WrongAssignCount, "assignment mismatch: %s but %s returns %s", vars, call.Fun, vals)
309 return
310 }
311 }
312 check.errorf(rhs0, _WrongAssignCount, "assignment mismatch: %s but %s", vars, vals)
313 }
314
315
316
317 func (check *Checker) initVars(lhs []*Var, origRHS []ast.Expr, returnStmt ast.Stmt) {
318 rhs, commaOk := check.exprList(origRHS, len(lhs) == 2 && returnStmt == nil)
319
320 if len(lhs) != len(rhs) {
321
322 for _, obj := range lhs {
323 obj.used = true
324 if obj.typ == nil {
325 obj.typ = Typ[Invalid]
326 }
327 }
328
329 for _, x := range rhs {
330 if x.mode == invalid {
331 return
332 }
333 }
334 if returnStmt != nil {
335 var at positioner = returnStmt
336 qualifier := "not enough"
337 if len(rhs) > len(lhs) {
338 at = rhs[len(lhs)].expr
339 qualifier = "too many"
340 } else if len(rhs) > 0 {
341 at = rhs[len(rhs)-1].expr
342 }
343 err := newErrorf(at, _WrongResultCount, "%s return values", qualifier)
344 err.errorf(token.NoPos, "have %s", check.typesSummary(operandTypes(rhs), false))
345 err.errorf(token.NoPos, "want %s", check.typesSummary(varTypes(lhs), false))
346 check.report(err)
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