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.
5 // This file implements initialization and assignment checks.
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) {
24 return // error reported before
25 case constant_, variable, mapindex, value, commaok, commaerr:
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)
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)
46 target = Default(x.typ)
48 newType, val, code := check.implicitTypeAndValue(x, target)
50 msg := check.sprintf("cannot use %s as %s value in %s", x, target, context)
54 case _NumericOverflow:
57 code = _IncompatibleAssign
59 check.error(x, code, msg)
65 check.updateExprVal(x.expr, val)
69 check.updateExprType(x.expr, newType, false)
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)
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."
86 if ok, code := x.assignableTo(check, T, &reason); !ok {
88 check.errorf(x, code, "cannot use %s as %s value in %s: %s", x, T, context, reason)
90 check.errorf(x, code, "cannot use %s as %s value in %s", x, T, context)
96 func (check *Checker) initConst(lhs *Const, x *operand) {
97 if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
99 lhs.typ = Typ[Invalid]
104 // rhs must be a constant
105 if x.mode != constant_ {
106 check.errorf(x, _InvalidConstInit, "%s is not constant", x)
108 lhs.typ = Typ[Invalid]
112 assert(isConstType(x.typ))
114 // If the lhs doesn't have a type yet, use the type of x.
119 check.assignment(x, lhs.typ, "constant declaration")
120 if x.mode == invalid {
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] {
130 lhs.typ = Typ[Invalid]
136 // If the lhs doesn't have a type yet, use the type of x.
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]
151 check.assignment(x, lhs.typ, context)
152 if x.mode == invalid {
159 func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type {
160 if x.mode == invalid || x.typ == Typ[Invalid] {
165 // Determine if the lhs is a (possibly parenthesized) identifier.
166 ident, _ := unparen(lhs).(*ast.Ident)
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 {
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.
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 {
198 v.used = v_used // restore v.used
201 if z.mode == invalid || z.typ == Typ[Invalid] {
205 // spec: "Each left-hand side operand must be addressable, a map index
206 // expression, or the blank identifier. Operands may be parenthesized."
210 case variable, mapindex:
213 if sel, ok := z.expr.(*ast.SelectorExpr); ok {
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))
221 check.errorf(&z, _UnassignableOperand, "cannot assign to %s", &z)
225 check.assignment(x, z.typ, "assignment")
226 if x.mode == invalid {
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())
238 if len(lhs) != len(rhs) {
240 for _, obj := range lhs {
242 obj.typ = Typ[Invalid]
245 // don't report an error if we already reported one
246 for _, x := range rhs {
247 if x.mode == invalid {
251 if returnPos.IsValid() {
252 check.errorf(atPos(returnPos), _WrongResultCount, "wrong number of return values (want %d, got %d)", len(lhs), len(rhs))
255 check.errorf(rhs[0], _WrongAssignCount, "cannot initialize %d variables with %d values", len(lhs), len(rhs))
259 context := "assignment"
260 if returnPos.IsValid() {
261 context = "return statement"
267 a[i] = check.initVar(lhs[i], rhs[i], context)
269 check.recordCommaOkTypes(origRHS[0], a)
273 for i, lhs := range lhs {
274 check.initVar(lhs, rhs[i], context)
278 func (check *Checker) assignVars(lhs, origRHS []ast.Expr) {
279 rhs, commaOk := check.exprList(origRHS, len(lhs) == 2)
281 if len(lhs) != len(rhs) {
283 // don't report an error if we already reported one
284 for _, x := range rhs {
285 if x.mode == invalid {
289 check.errorf(rhs[0], _WrongAssignCount, "cannot assign %d values to %d variables", len(rhs), len(lhs))
296 a[i] = check.assignVar(lhs[i], rhs[i])
298 check.recordCommaOkTypes(origRHS[0], a)
302 for i, lhs := range lhs {
303 check.assignVar(lhs, rhs[i])
307 func (check *Checker) shortVarDecl(pos positioner, lhs, rhs []ast.Expr) {
308 top := len(check.delayed)
311 // collect lhs variables
313 var lhsVars = make([]*Var, len(lhs))
314 for i, lhs := range lhs {
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.
322 if alt := scope.Lookup(name); alt != nil {
323 // redeclared object must be a variable
324 if alt, _ := alt.(*Var); alt != nil {
327 check.errorf(lhs, _UnassignableOperand, "cannot assign to %s", lhs)
329 check.recordUse(ident, alt)
331 // declare new variable, possibly a blank (_) variable
332 obj = NewVar(ident.Pos(), check.pkg, name, nil)
334 newVars = append(newVars, obj)
336 check.recordDef(ident, obj)
340 check.invalidAST(lhs, "cannot declare %s", lhs)
343 obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable
348 check.initVars(lhsVars, rhs, token.NoPos)
350 // process function literals in rhs expressions before scope changes
351 check.processDelayed(top)
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
364 check.softErrorf(pos, _NoNewVar, "no new variables on left side of :=")