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 "fmt" 11 "go/ast" 12 "strings" 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 // we may get here because of other problems (issue #39634, crash 12) 30 check.errorf(x, 0, "cannot assign %s to %s in %s", x, T, context) 31 return 32 } 33 34 if isUntyped(x.typ) { 35 target := T 36 // spec: "If an untyped constant is assigned to a variable of interface 37 // type or the blank identifier, the constant is first converted to type 38 // bool, rune, int, float64, complex128 or string respectively, depending 39 // on whether the value is a boolean, rune, integer, floating-point, 40 // complex, or string constant." 41 if T == nil || IsInterface(T) && !isTypeParam(T) { 42 if T == nil && x.typ == Typ[UntypedNil] { 43 check.errorf(x, _UntypedNil, "use of untyped nil in %s", context) 44 x.mode = invalid 45 return 46 } 47 target = Default(x.typ) 48 } 49 newType, val, code := check.implicitTypeAndValue(x, target) 50 if code != 0 { 51 msg := check.sprintf("cannot use %s as %s value in %s", x, target, context) 52 switch code { 53 case _TruncatedFloat: 54 msg += " (truncated)" 55 case _NumericOverflow: 56 msg += " (overflows)" 57 default: 58 code = _IncompatibleAssign 59 } 60 check.error(x, code, msg) 61 x.mode = invalid 62 return 63 } 64 if val != nil { 65 x.val = val 66 check.updateExprVal(x.expr, val) 67 } 68 if newType != x.typ { 69 x.typ = newType 70 check.updateExprType(x.expr, newType, false) 71 } 72 } 73 74 // A generic (non-instantiated) function value cannot be assigned to a variable. 75 if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 { 76 check.errorf(x, _WrongTypeArgCount, "cannot use generic function %s without instantiation in %s", x, context) 77 } 78 79 // spec: "If a left-hand side is the blank identifier, any typed or 80 // non-constant value except for the predeclared identifier nil may 81 // be assigned to it." 82 if T == nil { 83 return 84 } 85 86 reason := "" 87 if ok, code := x.assignableTo(check, T, &reason); !ok { 88 if compilerErrorMessages { 89 if reason != "" { 90 check.errorf(x, code, "cannot use %s as type %s in %s:\n\t%s", x, T, context, reason) 91 } else { 92 check.errorf(x, code, "cannot use %s as type %s in %s", x, T, context) 93 } 94 } else { 95 if reason != "" { 96 check.errorf(x, code, "cannot use %s as %s value in %s: %s", x, T, context, reason) 97 } else { 98 check.errorf(x, code, "cannot use %s as %s value in %s", x, T, context) 99 } 100 } 101 x.mode = invalid 102 } 103} 104 105func (check *Checker) initConst(lhs *Const, x *operand) { 106 if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] { 107 if lhs.typ == nil { 108 lhs.typ = Typ[Invalid] 109 } 110 return 111 } 112 113 // rhs must be a constant 114 if x.mode != constant_ { 115 check.errorf(x, _InvalidConstInit, "%s is not constant", x) 116 if lhs.typ == nil { 117 lhs.typ = Typ[Invalid] 118 } 119 return 120 } 121 assert(isConstType(x.typ)) 122 123 // If the lhs doesn't have a type yet, use the type of x. 124 if lhs.typ == nil { 125 lhs.typ = x.typ 126 } 127 128 check.assignment(x, lhs.typ, "constant declaration") 129 if x.mode == invalid { 130 return 131 } 132 133 lhs.val = x.val 134} 135 136func (check *Checker) initVar(lhs *Var, x *operand, context string) Type { 137 if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] { 138 if lhs.typ == nil { 139 lhs.typ = Typ[Invalid] 140 } 141 return nil 142 } 143 144 // If the lhs doesn't have a type yet, use the type of x. 145 if lhs.typ == nil { 146 typ := x.typ 147 if isUntyped(typ) { 148 // convert untyped types to default types 149 if typ == Typ[UntypedNil] { 150 check.errorf(x, _UntypedNil, "use of untyped nil in %s", context) 151 lhs.typ = Typ[Invalid] 152 return nil 153 } 154 typ = Default(typ) 155 } 156 lhs.typ = typ 157 } 158 159 check.assignment(x, lhs.typ, context) 160 if x.mode == invalid { 161 return nil 162 } 163 164 return x.typ 165} 166 167func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type { 168 if x.mode == invalid || x.typ == Typ[Invalid] { 169 check.useLHS(lhs) 170 return nil 171 } 172 173 // Determine if the lhs is a (possibly parenthesized) identifier. 174 ident, _ := unparen(lhs).(*ast.Ident) 175 176 // Don't evaluate lhs if it is the blank identifier. 177 if ident != nil && ident.Name == "_" { 178 check.recordDef(ident, nil) 179 check.assignment(x, nil, "assignment to _ identifier") 180 if x.mode == invalid { 181 return nil 182 } 183 return x.typ 184 } 185 186 // If the lhs is an identifier denoting a variable v, this assignment 187 // is not a 'use' of v. Remember current value of v.used and restore 188 // after evaluating the lhs via check.expr. 189 var v *Var 190 var v_used bool 191 if ident != nil { 192 if obj := check.lookup(ident.Name); obj != nil { 193 // It's ok to mark non-local variables, but ignore variables 194 // from other packages to avoid potential race conditions with 195 // dot-imported variables. 196 if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg { 197 v = w 198 v_used = v.used 199 } 200 } 201 } 202 203 var z operand 204 check.expr(&z, lhs) 205 if v != nil { 206 v.used = v_used // restore v.used 207 } 208 209 if z.mode == invalid || z.typ == Typ[Invalid] { 210 return nil 211 } 212 213 // spec: "Each left-hand side operand must be addressable, a map index 214 // expression, or the blank identifier. Operands may be parenthesized." 215 switch z.mode { 216 case invalid: 217 return nil 218 case variable, mapindex: 219 // ok 220 default: 221 if sel, ok := z.expr.(*ast.SelectorExpr); ok { 222 var op operand 223 check.expr(&op, sel.X) 224 if op.mode == mapindex { 225 check.errorf(&z, _UnaddressableFieldAssign, "cannot assign to struct field %s in map", ExprString(z.expr)) 226 return nil 227 } 228 } 229 check.errorf(&z, _UnassignableOperand, "cannot assign to %s", &z) 230 return nil 231 } 232 233 check.assignment(x, z.typ, "assignment") 234 if x.mode == invalid { 235 return nil 236 } 237 238 return x.typ 239} 240 241// operandTypes returns the list of types for the given operands. 242func operandTypes(list []*operand) (res []Type) { 243 for _, x := range list { 244 res = append(res, x.typ) 245 } 246 return res 247} 248 249// varTypes returns the list of types for the given variables. 250func varTypes(list []*Var) (res []Type) { 251 for _, x := range list { 252 res = append(res, x.typ) 253 } 254 return res 255} 256 257// typesSummary returns a string of the form "(t1, t2, ...)" where the 258// ti's are user-friendly string representations for the given types. 259// If variadic is set and the last type is a slice, its string is of 260// the form "...E" where E is the slice's element type. 261func (check *Checker) typesSummary(list []Type, variadic bool) string { 262 var res []string 263 for i, t := range list { 264 var s string 265 switch { 266 case t == nil: 267 fallthrough // should not happend but be cautious 268 case t == Typ[Invalid]: 269 s = "<T>" 270 case isUntyped(t): 271 if isNumeric(t) { 272 // Do not imply a specific type requirement: 273 // "have number, want float64" is better than 274 // "have untyped int, want float64" or 275 // "have int, want float64". 276 s = "number" 277 } else { 278 // If we don't have a number, omit the "untyped" qualifier 279 // for compactness. 280 s = strings.Replace(t.(*Basic).name, "untyped ", "", -1) 281 } 282 case variadic && i == len(list)-1: 283 s = check.sprintf("...%s", t.(*Slice).elem) 284 } 285 if s == "" { 286 s = check.sprintf("%s", t) 287 } 288 res = append(res, s) 289 } 290 return "(" + strings.Join(res, ", ") + ")" 291} 292 293func (check *Checker) assignError(rhs []ast.Expr, nvars, nvals int) { 294 measure := func(x int, unit string) string { 295 s := fmt.Sprintf("%d %s", x, unit) 296 if x != 1 { 297 s += "s" 298 } 299 return s 300 } 301 302 vars := measure(nvars, "variable") 303 vals := measure(nvals, "value") 304 rhs0 := rhs[0] 305 306 if len(rhs) == 1 { 307 if call, _ := unparen(rhs0).(*ast.CallExpr); call != nil { 308 check.errorf(rhs0, _WrongAssignCount, "assignment mismatch: %s but %s returns %s", vars, call.Fun, vals) 309 return 310 } 311 } 312 check.errorf(rhs0, _WrongAssignCount, "assignment mismatch: %s but %s", vars, vals) 313} 314 315// If returnStmt != nil, initVars is called to type-check the assignment 316// of return expressions, and returnStmt is the the return statement. 317func (check *Checker) initVars(lhs []*Var, origRHS []ast.Expr, returnStmt ast.Stmt) { 318 rhs, commaOk := check.exprList(origRHS, len(lhs) == 2 && returnStmt == nil) 319 320 if len(lhs) != len(rhs) { 321 // invalidate lhs 322 for _, obj := range lhs { 323 obj.used = true // avoid declared but not used errors 324 if obj.typ == nil { 325 obj.typ = Typ[Invalid] 326 } 327 } 328 // don't report an error if we already reported one 329 for _, x := range rhs { 330 if x.mode == invalid { 331 return 332 } 333 } 334 if returnStmt != nil { 335 var at positioner = returnStmt 336 qualifier := "not enough" 337 if len(rhs) > len(lhs) { 338 at = rhs[len(lhs)].expr // report at first extra value 339 qualifier = "too many" 340 } else if len(rhs) > 0 { 341 at = rhs[len(rhs)-1].expr // report at last value 342 } 343 check.errorf(at, _WrongResultCount, "%s return values\n\thave %s\n\twant %s", 344 qualifier, 345 check.typesSummary(operandTypes(rhs), false), 346 check.typesSummary(varTypes(lhs), false), 347 ) 348 return 349 } 350 if compilerErrorMessages { 351 check.assignError(origRHS, len(lhs), len(rhs)) 352 } else { 353 check.errorf(rhs[0], _WrongAssignCount, "cannot initialize %d variables with %d values", len(lhs), len(rhs)) 354 } 355 return 356 } 357 358 context := "assignment" 359 if returnStmt != nil { 360 context = "return statement" 361 } 362 363 if commaOk { 364 var a [2]Type 365 for i := range a { 366 a[i] = check.initVar(lhs[i], rhs[i], context) 367 } 368 check.recordCommaOkTypes(origRHS[0], a) 369 return 370 } 371 372 for i, lhs := range lhs { 373 check.initVar(lhs, rhs[i], context) 374 } 375} 376 377func (check *Checker) assignVars(lhs, origRHS []ast.Expr) { 378 rhs, commaOk := check.exprList(origRHS, len(lhs) == 2) 379 380 if len(lhs) != len(rhs) { 381 check.useLHS(lhs...) 382 // don't report an error if we already reported one 383 for _, x := range rhs { 384 if x.mode == invalid { 385 return 386 } 387 } 388 if compilerErrorMessages { 389 check.assignError(origRHS, len(lhs), len(rhs)) 390 } else { 391 check.errorf(rhs[0], _WrongAssignCount, "cannot assign %d values to %d variables", len(rhs), len(lhs)) 392 } 393 return 394 } 395 396 if commaOk { 397 var a [2]Type 398 for i := range a { 399 a[i] = check.assignVar(lhs[i], rhs[i]) 400 } 401 check.recordCommaOkTypes(origRHS[0], a) 402 return 403 } 404 405 for i, lhs := range lhs { 406 check.assignVar(lhs, rhs[i]) 407 } 408} 409 410func (check *Checker) shortVarDecl(pos positioner, lhs, rhs []ast.Expr) { 411 top := len(check.delayed) 412 scope := check.scope 413 414 // collect lhs variables 415 seen := make(map[string]bool, len(lhs)) 416 lhsVars := make([]*Var, len(lhs)) 417 newVars := make([]*Var, 0, len(lhs)) 418 hasErr := false 419 for i, lhs := range lhs { 420 ident, _ := lhs.(*ast.Ident) 421 if ident == nil { 422 check.useLHS(lhs) 423 // TODO(rFindley) this is redundant with a parser error. Consider omitting? 424 check.errorf(lhs, _BadDecl, "non-name %s on left side of :=", lhs) 425 hasErr = true 426 continue 427 } 428 429 name := ident.Name 430 if name != "_" { 431 if seen[name] { 432 check.errorf(lhs, _RepeatedDecl, "%s repeated on left side of :=", lhs) 433 hasErr = true 434 continue 435 } 436 seen[name] = true 437 } 438 439 // Use the correct obj if the ident is redeclared. The 440 // variable's scope starts after the declaration; so we 441 // must use Scope.Lookup here and call Scope.Insert 442 // (via check.declare) later. 443 if alt := scope.Lookup(name); alt != nil { 444 check.recordUse(ident, alt) 445 // redeclared object must be a variable 446 if obj, _ := alt.(*Var); obj != nil { 447 lhsVars[i] = obj 448 } else { 449 check.errorf(lhs, _UnassignableOperand, "cannot assign to %s", lhs) 450 hasErr = true 451 } 452 continue 453 } 454 455 // declare new variable 456 obj := NewVar(ident.Pos(), check.pkg, name, nil) 457 lhsVars[i] = obj 458 if name != "_" { 459 newVars = append(newVars, obj) 460 } 461 check.recordDef(ident, obj) 462 } 463 464 // create dummy variables where the lhs is invalid 465 for i, obj := range lhsVars { 466 if obj == nil { 467 lhsVars[i] = NewVar(lhs[i].Pos(), check.pkg, "_", nil) 468 } 469 } 470 471 check.initVars(lhsVars, rhs, nil) 472 473 // process function literals in rhs expressions before scope changes 474 check.processDelayed(top) 475 476 if len(newVars) == 0 && !hasErr { 477 check.softErrorf(pos, _NoNewVar, "no new variables on left side of :=") 478 return 479 } 480 481 // declare new variables 482 // spec: "The scope of a constant or variable identifier declared inside 483 // a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl 484 // for short variable declarations) and ends at the end of the innermost 485 // containing block." 486 scopePos := rhs[len(rhs)-1].End() 487 for _, obj := range newVars { 488 check.declare(scope, nil, obj, scopePos) // id = nil: recordDef already called 489 } 490} 491