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 7package types 8 9import ( 10 "errors" 11 "go/ast" 12 "go/token" 13) 14 15// assignment reports whether x can be assigned to a variable of type T, 16// if necessary by attempting to convert untyped values to the appropriate 17// type. context describes the context in which the assignment takes place. 18// Use T == nil to indicate assignment to an untyped blank identifier. 19// x.mode is set to invalid if the assignment failed. 20func (check *Checker) assignment(x *operand, T Type, context string) { 21 check.singleValue(x) 22 23 switch x.mode { 24 case invalid: 25 return // error reported before 26 case constant_, variable, mapindex, value, commaok, commaerr: 27 // ok 28 default: 29 unreachable() 30 } 31 32 if isUntyped(x.typ) { 33 target := T 34 // spec: "If an untyped constant is assigned to a variable of interface 35 // type or the blank identifier, the constant is first converted to type 36 // bool, rune, int, float64, complex128 or string respectively, depending 37 // on whether the value is a boolean, rune, integer, floating-point, 38 // complex, or string constant." 39 if T == nil || IsInterface(T) { 40 if T == nil && x.typ == Typ[UntypedNil] { 41 check.errorf(x, _UntypedNil, "use of untyped nil in %s", context) 42 x.mode = invalid 43 return 44 } 45 target = Default(x.typ) 46 } 47 if err := check.canConvertUntyped(x, target); err != nil { 48 msg := check.sprintf("cannot use %s as %s value in %s", x, target, context) 49 code := _IncompatibleAssign 50 var ierr Error 51 if errors.As(err, &ierr) { 52 // Preserve these inner errors, as they are informative. 53 switch ierr.go116code { 54 case _TruncatedFloat: 55 msg += " (truncated)" 56 code = ierr.go116code 57 case _NumericOverflow: 58 msg += " (overflows)" 59 code = ierr.go116code 60 } 61 } 62 check.error(x, code, msg) 63 x.mode = invalid 64 return 65 } 66 } 67 // x.typ is typed 68 69 // spec: "If a left-hand side is the blank identifier, any typed or 70 // non-constant value except for the predeclared identifier nil may 71 // be assigned to it." 72 if T == nil { 73 return 74 } 75 76 reason := "" 77 if ok, code := x.assignableTo(check, T, &reason); !ok { 78 if reason != "" { 79 check.errorf(x, code, "cannot use %s as %s value in %s: %s", x, T, context, reason) 80 } else { 81 check.errorf(x, code, "cannot use %s as %s value in %s", x, T, context) 82 } 83 x.mode = invalid 84 } 85} 86 87func (check *Checker) initConst(lhs *Const, x *operand) { 88 if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] { 89 if lhs.typ == nil { 90 lhs.typ = Typ[Invalid] 91 } 92 return 93 } 94 95 // rhs must be a constant 96 if x.mode != constant_ { 97 check.errorf(x, _InvalidConstInit, "%s is not constant", x) 98 if lhs.typ == nil { 99 lhs.typ = Typ[Invalid] 100 } 101 return 102 } 103 assert(isConstType(x.typ)) 104 105 // If the lhs doesn't have a type yet, use the type of x. 106 if lhs.typ == nil { 107 lhs.typ = x.typ 108 } 109 110 check.assignment(x, lhs.typ, "constant declaration") 111 if x.mode == invalid { 112 return 113 } 114 115 lhs.val = x.val 116} 117 118func (check *Checker) initVar(lhs *Var, x *operand, context string) Type { 119 if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] { 120 if lhs.typ == nil { 121 lhs.typ = Typ[Invalid] 122 } 123 return nil 124 } 125 126 // If the lhs doesn't have a type yet, use the type of x. 127 if lhs.typ == nil { 128 typ := x.typ 129 if isUntyped(typ) { 130 // convert untyped types to default types 131 if typ == Typ[UntypedNil] { 132 check.errorf(x, _UntypedNil, "use of untyped nil in %s", context) 133 lhs.typ = Typ[Invalid] 134 return nil 135 } 136 typ = Default(typ) 137 } 138 lhs.typ = typ 139 } 140 141 check.assignment(x, lhs.typ, context) 142 if x.mode == invalid { 143 return nil 144 } 145 146 return x.typ 147} 148 149func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type { 150 if x.mode == invalid || x.typ == Typ[Invalid] { 151 return nil 152 } 153 154 // Determine if the lhs is a (possibly parenthesized) identifier. 155 ident, _ := unparen(lhs).(*ast.Ident) 156 157 // Don't evaluate lhs if it is the blank identifier. 158 if ident != nil && ident.Name == "_" { 159 check.recordDef(ident, nil) 160 check.assignment(x, nil, "assignment to _ identifier") 161 if x.mode == invalid { 162 return nil 163 } 164 return x.typ 165 } 166 167 // If the lhs is an identifier denoting a variable v, this assignment 168 // is not a 'use' of v. Remember current value of v.used and restore 169 // after evaluating the lhs via check.expr. 170 var v *Var 171 var v_used bool 172 if ident != nil { 173 if obj := check.lookup(ident.Name); obj != nil { 174 // It's ok to mark non-local variables, but ignore variables 175 // from other packages to avoid potential race conditions with 176 // dot-imported variables. 177 if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg { 178 v = w 179 v_used = v.used 180 } 181 } 182 } 183 184 var z operand 185 check.expr(&z, lhs) 186 if v != nil { 187 v.used = v_used // restore v.used 188 } 189 190 if z.mode == invalid || z.typ == Typ[Invalid] { 191 return nil 192 } 193 194 // spec: "Each left-hand side operand must be addressable, a map index 195 // expression, or the blank identifier. Operands may be parenthesized." 196 switch z.mode { 197 case invalid: 198 return nil 199 case variable, mapindex: 200 // ok 201 default: 202 if sel, ok := z.expr.(*ast.SelectorExpr); ok { 203 var op operand 204 check.expr(&op, sel.X) 205 if op.mode == mapindex { 206 check.errorf(&z, _UnaddressableFieldAssign, "cannot assign to struct field %s in map", ExprString(z.expr)) 207 return nil 208 } 209 } 210 check.errorf(&z, _UnassignableOperand, "cannot assign to %s", &z) 211 return nil 212 } 213 214 check.assignment(x, z.typ, "assignment") 215 if x.mode == invalid { 216 return nil 217 } 218 219 return x.typ 220} 221 222// If returnPos is valid, initVars is called to type-check the assignment of 223// return expressions, and returnPos is the position of the return statement. 224func (check *Checker) initVars(lhs []*Var, rhs []ast.Expr, returnPos token.Pos) { 225 l := len(lhs) 226 get, r, commaOk := unpack(func(x *operand, i int) { check.multiExpr(x, rhs[i]) }, len(rhs), l == 2 && !returnPos.IsValid()) 227 if get == nil || l != r { 228 // invalidate lhs and use rhs 229 for _, obj := range lhs { 230 if obj.typ == nil { 231 obj.typ = Typ[Invalid] 232 } 233 } 234 if get == nil { 235 return // error reported by unpack 236 } 237 check.useGetter(get, r) 238 if returnPos.IsValid() { 239 check.errorf(atPos(returnPos), _WrongResultCount, "wrong number of return values (want %d, got %d)", l, r) 240 return 241 } 242 check.errorf(rhs[0], _WrongAssignCount, "cannot initialize %d variables with %d values", l, r) 243 return 244 } 245 246 context := "assignment" 247 if returnPos.IsValid() { 248 context = "return statement" 249 } 250 251 var x operand 252 if commaOk { 253 var a [2]Type 254 for i := range a { 255 get(&x, i) 256 a[i] = check.initVar(lhs[i], &x, context) 257 } 258 check.recordCommaOkTypes(rhs[0], a) 259 return 260 } 261 262 for i, lhs := range lhs { 263 get(&x, i) 264 check.initVar(lhs, &x, context) 265 } 266} 267 268func (check *Checker) assignVars(lhs, rhs []ast.Expr) { 269 l := len(lhs) 270 get, r, commaOk := unpack(func(x *operand, i int) { check.multiExpr(x, rhs[i]) }, len(rhs), l == 2) 271 if get == nil { 272 check.useLHS(lhs...) 273 return // error reported by unpack 274 } 275 if l != r { 276 check.useGetter(get, r) 277 check.errorf(rhs[0], _WrongAssignCount, "cannot assign %d values to %d variables", r, l) 278 return 279 } 280 281 var x operand 282 if commaOk { 283 var a [2]Type 284 for i := range a { 285 get(&x, i) 286 a[i] = check.assignVar(lhs[i], &x) 287 } 288 check.recordCommaOkTypes(rhs[0], a) 289 return 290 } 291 292 for i, lhs := range lhs { 293 get(&x, i) 294 check.assignVar(lhs, &x) 295 } 296} 297 298func (check *Checker) shortVarDecl(pos positioner, lhs, rhs []ast.Expr) { 299 top := len(check.delayed) 300 scope := check.scope 301 302 // collect lhs variables 303 var newVars []*Var 304 var lhsVars = make([]*Var, len(lhs)) 305 for i, lhs := range lhs { 306 var obj *Var 307 if ident, _ := lhs.(*ast.Ident); ident != nil { 308 // Use the correct obj if the ident is redeclared. The 309 // variable's scope starts after the declaration; so we 310 // must use Scope.Lookup here and call Scope.Insert 311 // (via check.declare) later. 312 name := ident.Name 313 if alt := scope.Lookup(name); alt != nil { 314 // redeclared object must be a variable 315 if alt, _ := alt.(*Var); alt != nil { 316 obj = alt 317 } else { 318 check.errorf(lhs, _UnassignableOperand, "cannot assign to %s", lhs) 319 } 320 check.recordUse(ident, alt) 321 } else { 322 // declare new variable, possibly a blank (_) variable 323 obj = NewVar(ident.Pos(), check.pkg, name, nil) 324 if name != "_" { 325 newVars = append(newVars, obj) 326 } 327 check.recordDef(ident, obj) 328 } 329 } else { 330 check.useLHS(lhs) 331 check.invalidAST(lhs, "cannot declare %s", lhs) 332 } 333 if obj == nil { 334 obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable 335 } 336 lhsVars[i] = obj 337 } 338 339 check.initVars(lhsVars, rhs, token.NoPos) 340 341 // process function literals in rhs expressions before scope changes 342 check.processDelayed(top) 343 344 // declare new variables 345 if len(newVars) > 0 { 346 // spec: "The scope of a constant or variable identifier declared inside 347 // a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl 348 // for short variable declarations) and ends at the end of the innermost 349 // containing block." 350 scopePos := rhs[len(rhs)-1].End() 351 for _, obj := range newVars { 352 check.declare(scope, nil, obj, scopePos) // recordObject already called 353 } 354 } else { 355 check.softErrorf(pos, _NoNewVar, "no new variables on left side of :=") 356 } 357} 358