]> Cypherpunks.ru repositories - gostls13.git/blob - src/go/types/assignments.go
[dev.typeparams] merge master (2f0da6d) into dev.typeparams
[gostls13.git] / src / go / types / assignments.go
1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // This file implements initialization and assignment checks.
6
7 package types
8
9 import (
10         "go/ast"
11         "go/token"
12 )
13
14 // assignment reports whether x can be assigned to a variable of type T,
15 // if necessary by attempting to convert untyped values to the appropriate
16 // type. context describes the context in which the assignment takes place.
17 // Use T == nil to indicate assignment to an untyped blank identifier.
18 // x.mode is set to invalid if the assignment failed.
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 // error reported before
25         case constant_, variable, mapindex, value, commaok, commaerr:
26                 // ok
27         default:
28                 // we may get here because of other problems (issue #39634, crash 12)
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                 // spec: "If an untyped constant is assigned to a variable of interface
36                 // type or the blank identifier, the constant is first converted to type
37                 // bool, rune, int, float64, complex128 or string respectively, depending
38                 // on whether the value is a boolean, rune, integer, floating-point,
39                 // complex, or string constant."
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         // A generic (non-instantiated) function value cannot be assigned to a variable.
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         // spec: "If a left-hand side is the blank identifier, any typed or
79         // non-constant value except for the predeclared identifier nil may
80         // be assigned to it."
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         // rhs must be a constant
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         // If the lhs doesn't have a type yet, use the type of x.
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         // If the lhs doesn't have a type yet, use the type of x.
136         if lhs.typ == nil {
137                 typ := x.typ
138                 if isUntyped(typ) {
139                         // convert untyped types to default types
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         // Determine if the lhs is a (possibly parenthesized) identifier.
165         ident, _ := unparen(lhs).(*ast.Ident)
166
167         // Don't evaluate lhs if it is the blank identifier.
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         // If the lhs is an identifier denoting a variable v, this assignment
178         // is not a 'use' of v. Remember current value of v.used and restore
179         // after evaluating the lhs via check.expr.
180         var v *Var
181         var v_used bool
182         if ident != nil {
183                 if obj := check.lookup(ident.Name); obj != nil {
184                         // It's ok to mark non-local variables, but ignore variables
185                         // from other packages to avoid potential race conditions with
186                         // dot-imported variables.
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 // restore v.used
198         }
199
200         if z.mode == invalid || z.typ == Typ[Invalid] {
201                 return nil
202         }
203
204         // spec: "Each left-hand side operand must be addressable, a map index
205         // expression, or the blank identifier. Operands may be parenthesized."
206         switch z.mode {
207         case invalid:
208                 return nil
209         case variable, mapindex:
210                 // ok
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 // If returnPos is valid, initVars is called to type-check the assignment of
233 // return expressions, and returnPos is the position of the return statement.
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                 // invalidate lhs
239                 for _, obj := range lhs {
240                         if obj.typ == nil {
241                                 obj.typ = Typ[Invalid]
242                         }
243                 }
244                 // don't report an error if we already reported one
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                 // don't report an error if we already reported one
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         // collect lhs variables
311         var newVars []*Var
312         var lhsVars = make([]*Var, len(lhs))
313         for i, lhs := range lhs {
314                 var obj *Var
315                 if ident, _ := lhs.(*ast.Ident); ident != nil {
316                         // Use the correct obj if the ident is redeclared. The
317                         // variable's scope starts after the declaration; so we
318                         // must use Scope.Lookup here and call Scope.Insert
319                         // (via check.declare) later.
320                         name := ident.Name
321                         if alt := scope.Lookup(name); alt != nil {
322                                 // redeclared object must be a variable
323                                 if alt, _ := alt.(*Var); alt != nil {
324                                         obj = alt
325                                 } else {
326                                         check.errorf(lhs, _UnassignableOperand, "cannot assign to %s", lhs)
327                                 }
328                                 check.recordUse(ident, alt)
329                         } else {
330                                 // declare new variable, possibly a blank (_) variable
331                                 obj = NewVar(ident.Pos(), check.pkg, name, nil)
332                                 if name != "_" {
333                                         newVars = append(newVars, obj)
334                                 }
335                                 check.recordDef(ident, obj)
336                         }
337                 } else {
338                         check.useLHS(lhs)
339                         check.invalidAST(lhs, "cannot declare %s", lhs)
340                 }
341                 if obj == nil {
342                         obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable
343                 }
344                 lhsVars[i] = obj
345         }
346
347         check.initVars(lhsVars, rhs, token.NoPos)
348
349         // process function literals in rhs expressions before scope changes
350         check.processDelayed(top)
351
352         // declare new variables
353         if len(newVars) > 0 {
354                 // spec: "The scope of a constant or variable identifier declared inside
355                 // a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
356                 // for short variable declarations) and ends at the end of the innermost
357                 // containing block."
358                 scopePos := rhs[len(rhs)-1].End()
359                 for _, obj := range newVars {
360                         check.declare(scope, nil, obj, scopePos) // recordObject already called
361                 }
362         } else {
363                 check.softErrorf(pos, _NoNewVar, "no new variables on left side of :=")
364         }
365 }