]> Cypherpunks.ru repositories - gostls13.git/blob - src/go/types/assignments.go
[dev.typeparams] merge dev.regabi (618e3c1) 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                 lhs.used = true
133                 return nil
134         }
135
136         // If the lhs doesn't have a type yet, use the type of x.
137         if lhs.typ == nil {
138                 typ := x.typ
139                 if isUntyped(typ) {
140                         // convert untyped types to default types
141                         if typ == Typ[UntypedNil] {
142                                 check.errorf(x, _UntypedNil, "use of untyped nil in %s", context)
143                                 lhs.typ = Typ[Invalid]
144                                 return nil
145                         }
146                         typ = Default(typ)
147                 }
148                 lhs.typ = typ
149         }
150
151         check.assignment(x, lhs.typ, context)
152         if x.mode == invalid {
153                 return nil
154         }
155
156         return x.typ
157 }
158
159 func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type {
160         if x.mode == invalid || x.typ == Typ[Invalid] {
161                 check.useLHS(lhs)
162                 return nil
163         }
164
165         // Determine if the lhs is a (possibly parenthesized) identifier.
166         ident, _ := unparen(lhs).(*ast.Ident)
167
168         // Don't evaluate lhs if it is the blank identifier.
169         if ident != nil && ident.Name == "_" {
170                 check.recordDef(ident, nil)
171                 check.assignment(x, nil, "assignment to _ identifier")
172                 if x.mode == invalid {
173                         return nil
174                 }
175                 return x.typ
176         }
177
178         // If the lhs is an identifier denoting a variable v, this assignment
179         // is not a 'use' of v. Remember current value of v.used and restore
180         // after evaluating the lhs via check.expr.
181         var v *Var
182         var v_used bool
183         if ident != nil {
184                 if obj := check.lookup(ident.Name); obj != nil {
185                         // It's ok to mark non-local variables, but ignore variables
186                         // from other packages to avoid potential race conditions with
187                         // dot-imported variables.
188                         if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {
189                                 v = w
190                                 v_used = v.used
191                         }
192                 }
193         }
194
195         var z operand
196         check.expr(&z, lhs)
197         if v != nil {
198                 v.used = v_used // restore v.used
199         }
200
201         if z.mode == invalid || z.typ == Typ[Invalid] {
202                 return nil
203         }
204
205         // spec: "Each left-hand side operand must be addressable, a map index
206         // expression, or the blank identifier. Operands may be parenthesized."
207         switch z.mode {
208         case invalid:
209                 return nil
210         case variable, mapindex:
211                 // ok
212         default:
213                 if sel, ok := z.expr.(*ast.SelectorExpr); ok {
214                         var op operand
215                         check.expr(&op, sel.X)
216                         if op.mode == mapindex {
217                                 check.errorf(&z, _UnaddressableFieldAssign, "cannot assign to struct field %s in map", ExprString(z.expr))
218                                 return nil
219                         }
220                 }
221                 check.errorf(&z, _UnassignableOperand, "cannot assign to %s", &z)
222                 return nil
223         }
224
225         check.assignment(x, z.typ, "assignment")
226         if x.mode == invalid {
227                 return nil
228         }
229
230         return x.typ
231 }
232
233 // If returnPos is valid, initVars is called to type-check the assignment of
234 // return expressions, and returnPos is the position of the return statement.
235 func (check *Checker) initVars(lhs []*Var, origRHS []ast.Expr, returnPos token.Pos) {
236         rhs, commaOk := check.exprList(origRHS, len(lhs) == 2 && !returnPos.IsValid())
237
238         if len(lhs) != len(rhs) {
239                 // invalidate lhs
240                 for _, obj := range lhs {
241                         if obj.typ == nil {
242                                 obj.typ = Typ[Invalid]
243                         }
244                 }
245                 // don't report an error if we already reported one
246                 for _, x := range rhs {
247                         if x.mode == invalid {
248                                 return
249                         }
250                 }
251                 if returnPos.IsValid() {
252                         check.errorf(atPos(returnPos), _WrongResultCount, "wrong number of return values (want %d, got %d)", len(lhs), len(rhs))
253                         return
254                 }
255                 check.errorf(rhs[0], _WrongAssignCount, "cannot initialize %d variables with %d values", len(lhs), len(rhs))
256                 return
257         }
258
259         context := "assignment"
260         if returnPos.IsValid() {
261                 context = "return statement"
262         }
263
264         if commaOk {
265                 var a [2]Type
266                 for i := range a {
267                         a[i] = check.initVar(lhs[i], rhs[i], context)
268                 }
269                 check.recordCommaOkTypes(origRHS[0], a)
270                 return
271         }
272
273         for i, lhs := range lhs {
274                 check.initVar(lhs, rhs[i], context)
275         }
276 }
277
278 func (check *Checker) assignVars(lhs, origRHS []ast.Expr) {
279         rhs, commaOk := check.exprList(origRHS, len(lhs) == 2)
280
281         if len(lhs) != len(rhs) {
282                 check.useLHS(lhs...)
283                 // don't report an error if we already reported one
284                 for _, x := range rhs {
285                         if x.mode == invalid {
286                                 return
287                         }
288                 }
289                 check.errorf(rhs[0], _WrongAssignCount, "cannot assign %d values to %d variables", len(rhs), len(lhs))
290                 return
291         }
292
293         if commaOk {
294                 var a [2]Type
295                 for i := range a {
296                         a[i] = check.assignVar(lhs[i], rhs[i])
297                 }
298                 check.recordCommaOkTypes(origRHS[0], a)
299                 return
300         }
301
302         for i, lhs := range lhs {
303                 check.assignVar(lhs, rhs[i])
304         }
305 }
306
307 func (check *Checker) shortVarDecl(pos positioner, lhs, rhs []ast.Expr) {
308         top := len(check.delayed)
309         scope := check.scope
310
311         // collect lhs variables
312         var newVars []*Var
313         var lhsVars = make([]*Var, len(lhs))
314         for i, lhs := range lhs {
315                 var obj *Var
316                 if ident, _ := lhs.(*ast.Ident); ident != nil {
317                         // Use the correct obj if the ident is redeclared. The
318                         // variable's scope starts after the declaration; so we
319                         // must use Scope.Lookup here and call Scope.Insert
320                         // (via check.declare) later.
321                         name := ident.Name
322                         if alt := scope.Lookup(name); alt != nil {
323                                 // redeclared object must be a variable
324                                 if alt, _ := alt.(*Var); alt != nil {
325                                         obj = alt
326                                 } else {
327                                         check.errorf(lhs, _UnassignableOperand, "cannot assign to %s", lhs)
328                                 }
329                                 check.recordUse(ident, alt)
330                         } else {
331                                 // declare new variable, possibly a blank (_) variable
332                                 obj = NewVar(ident.Pos(), check.pkg, name, nil)
333                                 if name != "_" {
334                                         newVars = append(newVars, obj)
335                                 }
336                                 check.recordDef(ident, obj)
337                         }
338                 } else {
339                         check.useLHS(lhs)
340                         check.invalidAST(lhs, "cannot declare %s", lhs)
341                 }
342                 if obj == nil {
343                         obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable
344                 }
345                 lhsVars[i] = obj
346         }
347
348         check.initVars(lhsVars, rhs, token.NoPos)
349
350         // process function literals in rhs expressions before scope changes
351         check.processDelayed(top)
352
353         // declare new variables
354         if len(newVars) > 0 {
355                 // spec: "The scope of a constant or variable identifier declared inside
356                 // a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
357                 // for short variable declarations) and ends at the end of the innermost
358                 // containing block."
359                 scopePos := rhs[len(rhs)-1].End()
360                 for _, obj := range newVars {
361                         check.declare(scope, nil, obj, scopePos) // recordObject already called
362                 }
363         } else {
364                 check.softErrorf(pos, _NoNewVar, "no new variables on left side of :=")
365         }
366 }