Source file
src/go/types/assignments.go
1
2
3
4
5
6
7 package types
8
9 import (
10 "go/ast"
11 "go/token"
12 )
13
14
15
16
17
18
19 func (check *Checker) assignment(x *operand, T Type, context string) {
20 check.singleValue(x)
21
22 switch x.mode {
23 case invalid:
24 return
25 case constant_, variable, mapindex, value, commaok, commaerr:
26
27 default:
28
29 check.errorf(x, 0, "cannot assign %s to %s in %s", x, T, context)
30 return
31 }
32
33 if isUntyped(x.typ) {
34 target := T
35
36
37
38
39
40 if T == nil || IsInterface(T) {
41 if T == nil && x.typ == Typ[UntypedNil] {
42 check.errorf(x, _UntypedNil, "use of untyped nil in %s", context)
43 x.mode = invalid
44 return
45 }
46 target = Default(x.typ)
47 }
48 newType, val, code := check.implicitTypeAndValue(x, target)
49 if code != 0 {
50 msg := check.sprintf("cannot use %s as %s value in %s", x, target, context)
51 switch code {
52 case _TruncatedFloat:
53 msg += " (truncated)"
54 case _NumericOverflow:
55 msg += " (overflows)"
56 default:
57 code = _IncompatibleAssign
58 }
59 check.error(x, code, 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 if sig := asSignature(x.typ); sig != nil && len(sig.tparams) > 0 {
75 check.errorf(x, _Todo, "cannot use generic function %s without instantiation in %s", x, context)
76 }
77
78
79
80
81 if T == nil {
82 return
83 }
84
85 reason := ""
86 if ok, code := x.assignableTo(check, T, &reason); !ok {
87 if reason != "" {
88 check.errorf(x, code, "cannot use %s as %s value in %s: %s", x, T, context, reason)
89 } else {
90 check.errorf(x, code, "cannot use %s as %s value in %s", x, T, context)
91 }
92 x.mode = invalid
93 }
94 }
95
96 func (check *Checker) initConst(lhs *Const, x *operand) {
97 if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
98 if lhs.typ == nil {
99 lhs.typ = Typ[Invalid]
100 }
101 return
102 }
103
104
105 if x.mode != constant_ {
106 check.errorf(x, _InvalidConstInit, "%s is not constant", x)
107 if lhs.typ == nil {
108 lhs.typ = Typ[Invalid]
109 }
110 return
111 }
112 assert(isConstType(x.typ))
113
114
115 if lhs.typ == nil {
116 lhs.typ = x.typ
117 }
118
119 check.assignment(x, lhs.typ, "constant declaration")
120 if x.mode == invalid {
121 return
122 }
123
124 lhs.val = x.val
125 }
126
127 func (check *Checker) initVar(lhs *Var, x *operand, context string) Type {
128 if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
129 if lhs.typ == nil {
130 lhs.typ = Typ[Invalid]
131 }
132 return nil
133 }
134
135
136 if lhs.typ == nil {
137 typ := x.typ
138 if isUntyped(typ) {
139
140 if typ == Typ[UntypedNil] {
141 check.errorf(x, _UntypedNil, "use of untyped nil in %s", context)
142 lhs.typ = Typ[Invalid]
143 return nil
144 }
145 typ = Default(typ)
146 }
147 lhs.typ = typ
148 }
149
150 check.assignment(x, lhs.typ, context)
151 if x.mode == invalid {
152 return nil
153 }
154
155 return x.typ
156 }
157
158 func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type {
159 if x.mode == invalid || x.typ == Typ[Invalid] {
160 check.useLHS(lhs)
161 return nil
162 }
163
164
165 ident, _ := unparen(lhs).(*ast.Ident)
166
167
168 if ident != nil && ident.Name == "_" {
169 check.recordDef(ident, nil)
170 check.assignment(x, nil, "assignment to _ identifier")
171 if x.mode == invalid {
172 return nil
173 }
174 return x.typ
175 }
176
177
178
179
180 var v *Var
181 var v_used bool
182 if ident != nil {
183 if obj := check.lookup(ident.Name); obj != nil {
184
185
186
187 if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {
188 v = w
189 v_used = v.used
190 }
191 }
192 }
193
194 var z operand
195 check.expr(&z, lhs)
196 if v != nil {
197 v.used = v_used
198 }
199
200 if z.mode == invalid || z.typ == Typ[Invalid] {
201 return nil
202 }
203
204
205
206 switch z.mode {
207 case invalid:
208 return nil
209 case variable, mapindex:
210
211 default:
212 if sel, ok := z.expr.(*ast.SelectorExpr); ok {
213 var op operand
214 check.expr(&op, sel.X)
215 if op.mode == mapindex {
216 check.errorf(&z, _UnaddressableFieldAssign, "cannot assign to struct field %s in map", ExprString(z.expr))
217 return nil
218 }
219 }
220 check.errorf(&z, _UnassignableOperand, "cannot assign to %s", &z)
221 return nil
222 }
223
224 check.assignment(x, z.typ, "assignment")
225 if x.mode == invalid {
226 return nil
227 }
228
229 return x.typ
230 }
231
232
233
234 func (check *Checker) initVars(lhs []*Var, origRHS []ast.Expr, returnPos token.Pos) {
235 rhs, commaOk := check.exprList(origRHS, len(lhs) == 2 && !returnPos.IsValid())
236
237 if len(lhs) != len(rhs) {
238
239 for _, obj := range lhs {
240 if obj.typ == nil {
241 obj.typ = Typ[Invalid]
242 }
243 }
244
245 for _, x := range rhs {
246 if x.mode == invalid {
247 return
248 }
249 }
250 if returnPos.IsValid() {
251 check.errorf(atPos(returnPos), _WrongResultCount, "wrong number of return values (want %d, got %d)", len(lhs), len(rhs))
252 return
253 }
254 check.errorf(rhs[0], _WrongAssignCount, "cannot initialize %d variables with %d values", len(lhs), len(rhs))
255 return
256 }
257
258 context := "assignment"
259 if returnPos.IsValid() {
260 context = "return statement"
261 }
262
263 if commaOk {
264 var a [2]Type
265 for i := range a {
266 a[i] = check.initVar(lhs[i], rhs[i], context)
267 }
268 check.recordCommaOkTypes(origRHS[0], a)
269 return
270 }
271
272 for i, lhs := range lhs {
273 check.initVar(lhs, rhs[i], context)
274 }
275 }
276
277 func (check *Checker) assignVars(lhs, origRHS []ast.Expr) {
278 rhs, commaOk := check.exprList(origRHS, len(lhs) == 2)
279
280 if len(lhs) != len(rhs) {
281 check.useLHS(lhs...)
282
283 for _, x := range rhs {
284 if x.mode == invalid {
285 return
286 }
287 }
288 check.errorf(rhs[0], _WrongAssignCount, "cannot assign %d values to %d variables", len(rhs), len(lhs))
289 return
290 }
291
292 if commaOk {
293 var a [2]Type
294 for i := range a {
295 a[i] = check.assignVar(lhs[i], rhs[i])
296 }
297 check.recordCommaOkTypes(origRHS[0], a)
298 return
299 }
300
301 for i, lhs := range lhs {
302 check.assignVar(lhs, rhs[i])
303 }
304 }
305
306 func (check *Checker) shortVarDecl(pos positioner, lhs, rhs []ast.Expr) {
307 top := len(check.delayed)
308 scope := check.scope
309
310
311 seen := make(map[string]bool, len(lhs))
312 lhsVars := make([]*Var, len(lhs))
313 newVars := make([]*Var, 0, len(lhs))
314 hasErr := false
315 for i, lhs := range lhs {
316 ident, _ := lhs.(*ast.Ident)
317 if ident == nil {
318 check.useLHS(lhs)
319
320 check.errorf(lhs, _BadDecl, "non-name %s on left side of :=", lhs)
321 hasErr = true
322 continue
323 }
324
325 name := ident.Name
326 if name != "_" {
327 if seen[name] {
328 check.errorf(lhs, _RepeatedDecl, "%s repeated on left side of :=", lhs)
329 hasErr = true
330 continue
331 }
332 seen[name] = true
333 }
334
335
336
337
338
339 if alt := scope.Lookup(name); alt != nil {
340 check.recordUse(ident, alt)
341
342 if obj, _ := alt.(*Var); obj != nil {
343 lhsVars[i] = obj
344 } else {
345 check.errorf(lhs, _UnassignableOperand, "cannot assign to %s", lhs)
346 hasErr = true
347 }
348 continue
349 }
350
351
352 obj := NewVar(ident.Pos(), check.pkg, name, nil)
353 lhsVars[i] = obj
354 if name != "_" {
355 newVars = append(newVars, obj)
356 }
357 check.recordDef(ident, obj)
358 }
359
360
361 for i, obj := range lhsVars {
362 if obj == nil {
363 lhsVars[i] = NewVar(lhs[i].Pos(), check.pkg, "_", nil)
364 }
365 }
366
367 check.initVars(lhsVars, rhs, token.NoPos)
368
369
370 check.processDelayed(top)
371
372 if len(newVars) == 0 && !hasErr {
373 check.softErrorf(pos, _NoNewVar, "no new variables on left side of :=")
374 return
375 }
376
377
378
379
380
381
382 scopePos := rhs[len(rhs)-1].End()
383 for _, obj := range newVars {
384 check.declare(scope, nil, obj, scopePos)
385 }
386 }
387
View as plain text