github.com/bir3/gocompiler@v0.9.2202/src/go/types/assignments.go (about) 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 "fmt" 11 "github.com/bir3/gocompiler/src/go/ast" 12 . "github.com/bir3/gocompiler/src/internal/types/errors" 13 "strings" 14 ) 15 16 // assignment reports whether x can be assigned to a variable of type T, 17 // if necessary by attempting to convert untyped values to the appropriate 18 // type. context describes the context in which the assignment takes place. 19 // Use T == nil to indicate assignment to an untyped blank identifier. 20 // If the assignment check fails, x.mode is set to invalid. 21 func (check *Checker) assignment(x *operand, T Type, context string) { 22 check.singleValue(x) 23 24 switch x.mode { 25 case invalid: 26 return // error reported before 27 case constant_, variable, mapindex, value, commaok, commaerr: 28 // ok 29 default: 30 // we may get here because of other problems (go.dev/issue/39634, crash 12) 31 // TODO(gri) do we need a new "generic" error code here? 32 check.errorf(x, IncompatibleAssign, "cannot assign %s to %s in %s", x, T, context) 33 x.mode = invalid 34 return 35 } 36 37 if isUntyped(x.typ) { 38 target := T 39 // spec: "If an untyped constant is assigned to a variable of interface 40 // type or the blank identifier, the constant is first converted to type 41 // bool, rune, int, float64, complex128 or string respectively, depending 42 // on whether the value is a boolean, rune, integer, floating-point, 43 // complex, or string constant." 44 if T == nil || isNonTypeParamInterface(T) { 45 if T == nil && x.typ == Typ[UntypedNil] { 46 check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context) 47 x.mode = invalid 48 return 49 } 50 target = Default(x.typ) 51 } 52 newType, val, code := check.implicitTypeAndValue(x, target) 53 if code != 0 { 54 msg := check.sprintf("cannot use %s as %s value in %s", x, target, context) 55 switch code { 56 case TruncatedFloat: 57 msg += " (truncated)" 58 case NumericOverflow: 59 msg += " (overflows)" 60 default: 61 code = IncompatibleAssign 62 } 63 check.error(x, code, msg) 64 x.mode = invalid 65 return 66 } 67 if val != nil { 68 x.val = val 69 check.updateExprVal(x.expr, val) 70 } 71 if newType != x.typ { 72 x.typ = newType 73 check.updateExprType(x.expr, newType, false) 74 } 75 } 76 // x.typ is typed 77 78 // A generic (non-instantiated) function value cannot be assigned to a variable. 79 if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 { 80 check.errorf(x, WrongTypeArgCount, "cannot use generic function %s without instantiation in %s", x, context) 81 x.mode = invalid 82 return 83 } 84 85 // spec: "If a left-hand side is the blank identifier, any typed or 86 // non-constant value except for the predeclared identifier nil may 87 // be assigned to it." 88 if T == nil { 89 return 90 } 91 92 cause := "" 93 if ok, code := x.assignableTo(check, T, &cause); !ok { 94 if cause != "" { 95 check.errorf(x, code, "cannot use %s as %s value in %s: %s", x, T, context, cause) 96 } else { 97 check.errorf(x, code, "cannot use %s as %s value in %s", x, T, context) 98 } 99 x.mode = invalid 100 } 101 } 102 103 func (check *Checker) initConst(lhs *Const, x *operand) { 104 if x.mode == invalid || !isValid(x.typ) || !isValid(lhs.typ) { 105 if lhs.typ == nil { 106 lhs.typ = Typ[Invalid] 107 } 108 return 109 } 110 111 // rhs must be a constant 112 if x.mode != constant_ { 113 check.errorf(x, InvalidConstInit, "%s is not constant", x) 114 if lhs.typ == nil { 115 lhs.typ = Typ[Invalid] 116 } 117 return 118 } 119 assert(isConstType(x.typ)) 120 121 // If the lhs doesn't have a type yet, use the type of x. 122 if lhs.typ == nil { 123 lhs.typ = x.typ 124 } 125 126 check.assignment(x, lhs.typ, "constant declaration") 127 if x.mode == invalid { 128 return 129 } 130 131 lhs.val = x.val 132 } 133 134 // initVar checks the initialization lhs = x in a variable declaration. 135 // If lhs doesn't have a type yet, it is given the type of x, 136 // or Typ[Invalid] in case of an error. 137 // If the initialization check fails, x.mode is set to invalid. 138 func (check *Checker) initVar(lhs *Var, x *operand, context string) { 139 if x.mode == invalid || !isValid(x.typ) || !isValid(lhs.typ) { 140 if lhs.typ == nil { 141 lhs.typ = Typ[Invalid] 142 } 143 x.mode = invalid 144 return 145 } 146 147 // If lhs doesn't have a type yet, use the type of x. 148 if lhs.typ == nil { 149 typ := x.typ 150 if isUntyped(typ) { 151 // convert untyped types to default types 152 if typ == Typ[UntypedNil] { 153 check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context) 154 lhs.typ = Typ[Invalid] 155 x.mode = invalid 156 return 157 } 158 typ = Default(typ) 159 } 160 lhs.typ = typ 161 } 162 163 check.assignment(x, lhs.typ, context) 164 } 165 166 // lhsVar checks a lhs variable in an assignment and returns its type. 167 // lhsVar takes care of not counting a lhs identifier as a "use" of 168 // that identifier. The result is nil if it is the blank identifier, 169 // and Typ[Invalid] if it is an invalid lhs expression. 170 func (check *Checker) lhsVar(lhs ast.Expr) Type { 171 // Determine if the lhs is a (possibly parenthesized) identifier. 172 ident, _ := unparen(lhs).(*ast.Ident) 173 174 // Don't evaluate lhs if it is the blank identifier. 175 if ident != nil && ident.Name == "_" { 176 check.recordDef(ident, nil) 177 return nil 178 } 179 180 // If the lhs is an identifier denoting a variable v, this reference 181 // is not a 'use' of v. Remember current value of v.used and restore 182 // after evaluating the lhs via check.expr. 183 var v *Var 184 var v_used bool 185 if ident != nil { 186 if obj := check.lookup(ident.Name); obj != nil { 187 // It's ok to mark non-local variables, but ignore variables 188 // from other packages to avoid potential race conditions with 189 // dot-imported variables. 190 if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg { 191 v = w 192 v_used = v.used 193 } 194 } 195 } 196 197 var x operand 198 check.expr(nil, &x, lhs) 199 200 if v != nil { 201 v.used = v_used // restore v.used 202 } 203 204 if x.mode == invalid || !isValid(x.typ) { 205 return Typ[Invalid] 206 } 207 208 // spec: "Each left-hand side operand must be addressable, a map index 209 // expression, or the blank identifier. Operands may be parenthesized." 210 switch x.mode { 211 case invalid: 212 return Typ[Invalid] 213 case variable, mapindex: 214 // ok 215 default: 216 if sel, ok := x.expr.(*ast.SelectorExpr); ok { 217 var op operand 218 check.expr(nil, &op, sel.X) 219 if op.mode == mapindex { 220 check.errorf(&x, UnaddressableFieldAssign, "cannot assign to struct field %s in map", ExprString(x.expr)) 221 return Typ[Invalid] 222 } 223 } 224 check.errorf(&x, UnassignableOperand, "cannot assign to %s (neither addressable nor a map index expression)", x.expr) 225 return Typ[Invalid] 226 } 227 228 return x.typ 229 } 230 231 // assignVar checks the assignment lhs = rhs (if x == nil), or lhs = x (if x != nil). 232 // If x != nil, it must be the evaluation of rhs (and rhs will be ignored). 233 // If the assignment check fails and x != nil, x.mode is set to invalid. 234 func (check *Checker) assignVar(lhs, rhs ast.Expr, x *operand, context string) { 235 T := check.lhsVar(lhs) // nil if lhs is _ 236 if !isValid(T) { 237 if x != nil { 238 x.mode = invalid 239 } else { 240 check.use(rhs) 241 } 242 return 243 } 244 245 if x == nil { 246 var target *target 247 // avoid calling ExprString if not needed 248 if T != nil { 249 if _, ok := under(T).(*Signature); ok { 250 target = newTarget(T, ExprString(lhs)) 251 } 252 } 253 x = new(operand) 254 check.expr(target, x, rhs) 255 } 256 257 if T == nil && context == "assignment" { 258 context = "assignment to _ identifier" 259 } 260 check.assignment(x, T, context) 261 } 262 263 // operandTypes returns the list of types for the given operands. 264 func operandTypes(list []*operand) (res []Type) { 265 for _, x := range list { 266 res = append(res, x.typ) 267 } 268 return res 269 } 270 271 // varTypes returns the list of types for the given variables. 272 func varTypes(list []*Var) (res []Type) { 273 for _, x := range list { 274 res = append(res, x.typ) 275 } 276 return res 277 } 278 279 // typesSummary returns a string of the form "(t1, t2, ...)" where the 280 // ti's are user-friendly string representations for the given types. 281 // If variadic is set and the last type is a slice, its string is of 282 // the form "...E" where E is the slice's element type. 283 func (check *Checker) typesSummary(list []Type, variadic bool) string { 284 var res []string 285 for i, t := range list { 286 var s string 287 switch { 288 case t == nil: 289 fallthrough // should not happen but be cautious 290 case !isValid(t): 291 s = "unknown type" 292 case isUntyped(t): 293 if isNumeric(t) { 294 // Do not imply a specific type requirement: 295 // "have number, want float64" is better than 296 // "have untyped int, want float64" or 297 // "have int, want float64". 298 s = "number" 299 } else { 300 // If we don't have a number, omit the "untyped" qualifier 301 // for compactness. 302 s = strings.Replace(t.(*Basic).name, "untyped ", "", -1) 303 } 304 case variadic && i == len(list)-1: 305 s = check.sprintf("...%s", t.(*Slice).elem) 306 } 307 if s == "" { 308 s = check.sprintf("%s", t) 309 } 310 res = append(res, s) 311 } 312 return "(" + strings.Join(res, ", ") + ")" 313 } 314 315 func measure(x int, unit string) string { 316 if x != 1 { 317 unit += "s" 318 } 319 return fmt.Sprintf("%d %s", x, unit) 320 } 321 322 func (check *Checker) assignError(rhs []ast.Expr, l, r int) { 323 vars := measure(l, "variable") 324 vals := measure(r, "value") 325 rhs0 := rhs[0] 326 327 if len(rhs) == 1 { 328 if call, _ := unparen(rhs0).(*ast.CallExpr); call != nil { 329 check.errorf(rhs0, WrongAssignCount, "assignment mismatch: %s but %s returns %s", vars, call.Fun, vals) 330 return 331 } 332 } 333 check.errorf(rhs0, WrongAssignCount, "assignment mismatch: %s but %s", vars, vals) 334 } 335 336 func (check *Checker) returnError(at positioner, lhs []*Var, rhs []*operand) { 337 l, r := len(lhs), len(rhs) 338 qualifier := "not enough" 339 if r > l { 340 at = rhs[l] // report at first extra value 341 qualifier = "too many" 342 } else if r > 0 { 343 at = rhs[r-1] // report at last value 344 } 345 var err error_ 346 err.code = WrongResultCount 347 err.errorf(at.Pos(), "%s return values", qualifier) 348 err.errorf(nopos, "have %s", check.typesSummary(operandTypes(rhs), false)) 349 err.errorf(nopos, "want %s", check.typesSummary(varTypes(lhs), false)) 350 check.report(&err) 351 } 352 353 // initVars type-checks assignments of initialization expressions orig_rhs 354 // to variables lhs. 355 // If returnStmt is non-nil, initVars type-checks the implicit assignment 356 // of result expressions orig_rhs to function result parameters lhs. 357 func (check *Checker) initVars(lhs []*Var, orig_rhs []ast.Expr, returnStmt ast.Stmt) { 358 context := "assignment" 359 if returnStmt != nil { 360 context = "return statement" 361 } 362 363 l, r := len(lhs), len(orig_rhs) 364 365 // If l == 1 and the rhs is a single call, for a better 366 // error message don't handle it as n:n mapping below. 367 isCall := false 368 if r == 1 { 369 _, isCall = unparen(orig_rhs[0]).(*ast.CallExpr) 370 } 371 372 // If we have a n:n mapping from lhs variable to rhs expression, 373 // each value can be assigned to its corresponding variable. 374 if l == r && !isCall { 375 var x operand 376 for i, lhs := range lhs { 377 desc := lhs.name 378 if returnStmt != nil && desc == "" { 379 desc = "result variable" 380 } 381 check.expr(newTarget(lhs.typ, desc), &x, orig_rhs[i]) 382 check.initVar(lhs, &x, context) 383 } 384 return 385 } 386 387 // If we don't have an n:n mapping, the rhs must be a single expression 388 // resulting in 2 or more values; otherwise we have an assignment mismatch. 389 if r != 1 { 390 // Only report a mismatch error if there are no other errors on the rhs. 391 if check.use(orig_rhs...) { 392 if returnStmt != nil { 393 rhs := check.exprList(orig_rhs) 394 check.returnError(returnStmt, lhs, rhs) 395 } else { 396 check.assignError(orig_rhs, l, r) 397 } 398 } 399 // ensure that LHS variables have a type 400 for _, v := range lhs { 401 if v.typ == nil { 402 v.typ = Typ[Invalid] 403 } 404 } 405 return 406 } 407 408 rhs, commaOk := check.multiExpr(orig_rhs[0], l == 2 && returnStmt == nil) 409 r = len(rhs) 410 if l == r { 411 for i, lhs := range lhs { 412 check.initVar(lhs, rhs[i], context) 413 } 414 // Only record comma-ok expression if both initializations succeeded 415 // (go.dev/issue/59371). 416 if commaOk && rhs[0].mode != invalid && rhs[1].mode != invalid { 417 check.recordCommaOkTypes(orig_rhs[0], rhs) 418 } 419 return 420 } 421 422 // In all other cases we have an assignment mismatch. 423 // Only report a mismatch error if there are no other errors on the rhs. 424 if rhs[0].mode != invalid { 425 if returnStmt != nil { 426 check.returnError(returnStmt, lhs, rhs) 427 } else { 428 check.assignError(orig_rhs, l, r) 429 } 430 } 431 // ensure that LHS variables have a type 432 for _, v := range lhs { 433 if v.typ == nil { 434 v.typ = Typ[Invalid] 435 } 436 } 437 // orig_rhs[0] was already evaluated 438 } 439 440 // assignVars type-checks assignments of expressions orig_rhs to variables lhs. 441 func (check *Checker) assignVars(lhs, orig_rhs []ast.Expr) { 442 l, r := len(lhs), len(orig_rhs) 443 444 // If l == 1 and the rhs is a single call, for a better 445 // error message don't handle it as n:n mapping below. 446 isCall := false 447 if r == 1 { 448 _, isCall = unparen(orig_rhs[0]).(*ast.CallExpr) 449 } 450 451 // If we have a n:n mapping from lhs variable to rhs expression, 452 // each value can be assigned to its corresponding variable. 453 if l == r && !isCall { 454 for i, lhs := range lhs { 455 check.assignVar(lhs, orig_rhs[i], nil, "assignment") 456 } 457 return 458 } 459 460 // If we don't have an n:n mapping, the rhs must be a single expression 461 // resulting in 2 or more values; otherwise we have an assignment mismatch. 462 if r != 1 { 463 // Only report a mismatch error if there are no other errors on the lhs or rhs. 464 okLHS := check.useLHS(lhs...) 465 okRHS := check.use(orig_rhs...) 466 if okLHS && okRHS { 467 check.assignError(orig_rhs, l, r) 468 } 469 return 470 } 471 472 rhs, commaOk := check.multiExpr(orig_rhs[0], l == 2) 473 r = len(rhs) 474 if l == r { 475 for i, lhs := range lhs { 476 check.assignVar(lhs, nil, rhs[i], "assignment") 477 } 478 // Only record comma-ok expression if both assignments succeeded 479 // (go.dev/issue/59371). 480 if commaOk && rhs[0].mode != invalid && rhs[1].mode != invalid { 481 check.recordCommaOkTypes(orig_rhs[0], rhs) 482 } 483 return 484 } 485 486 // In all other cases we have an assignment mismatch. 487 // Only report a mismatch error if there are no other errors on the rhs. 488 if rhs[0].mode != invalid { 489 check.assignError(orig_rhs, l, r) 490 } 491 check.useLHS(lhs...) 492 // orig_rhs[0] was already evaluated 493 } 494 495 func (check *Checker) shortVarDecl(pos positioner, lhs, rhs []ast.Expr) { 496 top := len(check.delayed) 497 scope := check.scope 498 499 // collect lhs variables 500 seen := make(map[string]bool, len(lhs)) 501 lhsVars := make([]*Var, len(lhs)) 502 newVars := make([]*Var, 0, len(lhs)) 503 hasErr := false 504 for i, lhs := range lhs { 505 ident, _ := lhs.(*ast.Ident) 506 if ident == nil { 507 check.useLHS(lhs) 508 // TODO(rFindley) this is redundant with a parser error. Consider omitting? 509 check.errorf(lhs, BadDecl, "non-name %s on left side of :=", lhs) 510 hasErr = true 511 continue 512 } 513 514 name := ident.Name 515 if name != "_" { 516 if seen[name] { 517 check.errorf(lhs, RepeatedDecl, "%s repeated on left side of :=", lhs) 518 hasErr = true 519 continue 520 } 521 seen[name] = true 522 } 523 524 // Use the correct obj if the ident is redeclared. The 525 // variable's scope starts after the declaration; so we 526 // must use Scope.Lookup here and call Scope.Insert 527 // (via check.declare) later. 528 if alt := scope.Lookup(name); alt != nil { 529 check.recordUse(ident, alt) 530 // redeclared object must be a variable 531 if obj, _ := alt.(*Var); obj != nil { 532 lhsVars[i] = obj 533 } else { 534 check.errorf(lhs, UnassignableOperand, "cannot assign to %s", lhs) 535 hasErr = true 536 } 537 continue 538 } 539 540 // declare new variable 541 obj := NewVar(ident.Pos(), check.pkg, name, nil) 542 lhsVars[i] = obj 543 if name != "_" { 544 newVars = append(newVars, obj) 545 } 546 check.recordDef(ident, obj) 547 } 548 549 // create dummy variables where the lhs is invalid 550 for i, obj := range lhsVars { 551 if obj == nil { 552 lhsVars[i] = NewVar(lhs[i].Pos(), check.pkg, "_", nil) 553 } 554 } 555 556 check.initVars(lhsVars, rhs, nil) 557 558 // process function literals in rhs expressions before scope changes 559 check.processDelayed(top) 560 561 if len(newVars) == 0 && !hasErr { 562 check.softErrorf(pos, NoNewVar, "no new variables on left side of :=") 563 return 564 } 565 566 // declare new variables 567 // spec: "The scope of a constant or variable identifier declared inside 568 // a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl 569 // for short variable declarations) and ends at the end of the innermost 570 // containing block." 571 scopePos := rhs[len(rhs)-1].End() 572 for _, obj := range newVars { 573 check.declare(scope, nil, obj, scopePos) // id = nil: recordDef already called 574 } 575 }