github.com/bir3/gocompiler@v0.3.205/src/go/types/stmt.go (about) 1 // Copyright 2012 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 typechecking of statements. 6 7 package types 8 9 import ( 10 "github.com/bir3/gocompiler/src/go/ast" 11 "github.com/bir3/gocompiler/src/go/constant" 12 "github.com/bir3/gocompiler/src/go/token" 13 . "github.com/bir3/gocompiler/src/internal/types/errors" 14 "sort" 15 ) 16 17 func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body *ast.BlockStmt, iota constant.Value) { 18 if check.conf.IgnoreFuncBodies { 19 panic("function body not ignored") 20 } 21 22 if trace { 23 check.trace(body.Pos(), "-- %s: %s", name, sig) 24 } 25 26 // set function scope extent 27 sig.scope.pos = body.Pos() 28 sig.scope.end = body.End() 29 30 // save/restore current environment and set up function environment 31 // (and use 0 indentation at function start) 32 defer func(env environment, indent int) { 33 check.environment = env 34 check.indent = indent 35 }(check.environment, check.indent) 36 check.environment = environment{ 37 decl: decl, 38 scope: sig.scope, 39 iota: iota, 40 sig: sig, 41 } 42 check.indent = 0 43 44 check.stmtList(0, body.List) 45 46 if check.hasLabel { 47 check.labels(body) 48 } 49 50 if sig.results.Len() > 0 && !check.isTerminating(body, "") { 51 check.error(atPos(body.Rbrace), MissingReturn, "missing return") 52 } 53 54 // spec: "Implementation restriction: A compiler may make it illegal to 55 // declare a variable inside a function body if the variable is never used." 56 check.usage(sig.scope) 57 } 58 59 func (check *Checker) usage(scope *Scope) { 60 var unused []*Var 61 for name, elem := range scope.elems { 62 elem = resolve(name, elem) 63 if v, _ := elem.(*Var); v != nil && !v.used { 64 unused = append(unused, v) 65 } 66 } 67 sort.Slice(unused, func(i, j int) bool { 68 return unused[i].pos < unused[j].pos 69 }) 70 for _, v := range unused { 71 check.softErrorf(v, UnusedVar, "%s declared and not used", v.name) 72 } 73 74 for _, scope := range scope.children { 75 // Don't go inside function literal scopes a second time; 76 // they are handled explicitly by funcBody. 77 if !scope.isFunc { 78 check.usage(scope) 79 } 80 } 81 } 82 83 // stmtContext is a bitset describing which 84 // control-flow statements are permissible, 85 // and provides additional context information 86 // for better error messages. 87 type stmtContext uint 88 89 const ( 90 // permissible control-flow statements 91 breakOk stmtContext = 1 << iota 92 continueOk 93 fallthroughOk 94 95 // additional context information 96 finalSwitchCase 97 inTypeSwitch 98 ) 99 100 func (check *Checker) simpleStmt(s ast.Stmt) { 101 if s != nil { 102 check.stmt(0, s) 103 } 104 } 105 106 func trimTrailingEmptyStmts(list []ast.Stmt) []ast.Stmt { 107 for i := len(list); i > 0; i-- { 108 if _, ok := list[i-1].(*ast.EmptyStmt); !ok { 109 return list[:i] 110 } 111 } 112 return nil 113 } 114 115 func (check *Checker) stmtList(ctxt stmtContext, list []ast.Stmt) { 116 ok := ctxt&fallthroughOk != 0 117 inner := ctxt &^ fallthroughOk 118 list = trimTrailingEmptyStmts(list) // trailing empty statements are "invisible" to fallthrough analysis 119 for i, s := range list { 120 inner := inner 121 if ok && i+1 == len(list) { 122 inner |= fallthroughOk 123 } 124 check.stmt(inner, s) 125 } 126 } 127 128 func (check *Checker) multipleDefaults(list []ast.Stmt) { 129 var first ast.Stmt 130 for _, s := range list { 131 var d ast.Stmt 132 switch c := s.(type) { 133 case *ast.CaseClause: 134 if len(c.List) == 0 { 135 d = s 136 } 137 case *ast.CommClause: 138 if c.Comm == nil { 139 d = s 140 } 141 default: 142 check.error(s, InvalidSyntaxTree, "case/communication clause expected") 143 } 144 if d != nil { 145 if first != nil { 146 check.errorf(d, DuplicateDefault, "multiple defaults (first at %s)", check.fset.Position(first.Pos())) 147 } else { 148 first = d 149 } 150 } 151 } 152 } 153 154 func (check *Checker) openScope(node ast.Node, comment string) { 155 scope := NewScope(check.scope, node.Pos(), node.End(), comment) 156 check.recordScope(node, scope) 157 check.scope = scope 158 } 159 160 func (check *Checker) closeScope() { 161 check.scope = check.scope.Parent() 162 } 163 164 func assignOp(op token.Token) token.Token { 165 // token_test.go verifies the token ordering this function relies on 166 if token.ADD_ASSIGN <= op && op <= token.AND_NOT_ASSIGN { 167 return op + (token.ADD - token.ADD_ASSIGN) 168 } 169 return token.ILLEGAL 170 } 171 172 func (check *Checker) suspendedCall(keyword string, call *ast.CallExpr) { 173 var x operand 174 var msg string 175 var code Code 176 switch check.rawExpr(&x, call, nil, false) { 177 case conversion: 178 msg = "requires function call, not conversion" 179 code = InvalidDefer 180 if keyword == "go" { 181 code = InvalidGo 182 } 183 case expression: 184 msg = "discards result of" 185 code = UnusedResults 186 case statement: 187 return 188 default: 189 unreachable() 190 } 191 check.errorf(&x, code, "%s %s %s", keyword, msg, &x) 192 } 193 194 // goVal returns the Go value for val, or nil. 195 func goVal(val constant.Value) any { 196 // val should exist, but be conservative and check 197 if val == nil { 198 return nil 199 } 200 // Match implementation restriction of other compilers. 201 // gc only checks duplicates for integer, floating-point 202 // and string values, so only create Go values for these 203 // types. 204 switch val.Kind() { 205 case constant.Int: 206 if x, ok := constant.Int64Val(val); ok { 207 return x 208 } 209 if x, ok := constant.Uint64Val(val); ok { 210 return x 211 } 212 case constant.Float: 213 if x, ok := constant.Float64Val(val); ok { 214 return x 215 } 216 case constant.String: 217 return constant.StringVal(val) 218 } 219 return nil 220 } 221 222 // A valueMap maps a case value (of a basic Go type) to a list of positions 223 // where the same case value appeared, together with the corresponding case 224 // types. 225 // Since two case values may have the same "underlying" value but different 226 // types we need to also check the value's types (e.g., byte(1) vs myByte(1)) 227 // when the switch expression is of interface type. 228 type ( 229 valueMap map[any][]valueType // underlying Go value -> valueType 230 valueType struct { 231 pos token.Pos 232 typ Type 233 } 234 ) 235 236 func (check *Checker) caseValues(x *operand, values []ast.Expr, seen valueMap) { 237 L: 238 for _, e := range values { 239 var v operand 240 check.expr(&v, e) 241 if x.mode == invalid || v.mode == invalid { 242 continue L 243 } 244 check.convertUntyped(&v, x.typ) 245 if v.mode == invalid { 246 continue L 247 } 248 // Order matters: By comparing v against x, error positions are at the case values. 249 res := v // keep original v unchanged 250 check.comparison(&res, x, token.EQL, true) 251 if res.mode == invalid { 252 continue L 253 } 254 if v.mode != constant_ { 255 continue L // we're done 256 } 257 // look for duplicate values 258 if val := goVal(v.val); val != nil { 259 // look for duplicate types for a given value 260 // (quadratic algorithm, but these lists tend to be very short) 261 for _, vt := range seen[val] { 262 if Identical(v.typ, vt.typ) { 263 check.errorf(&v, DuplicateCase, "duplicate case %s in expression switch", &v) 264 check.error(atPos(vt.pos), DuplicateCase, "\tprevious case") // secondary error, \t indented 265 continue L 266 } 267 } 268 seen[val] = append(seen[val], valueType{v.Pos(), v.typ}) 269 } 270 } 271 } 272 273 // isNil reports whether the expression e denotes the predeclared value nil. 274 func (check *Checker) isNil(e ast.Expr) bool { 275 // The only way to express the nil value is by literally writing nil (possibly in parentheses). 276 if name, _ := unparen(e).(*ast.Ident); name != nil { 277 _, ok := check.lookup(name.Name).(*Nil) 278 return ok 279 } 280 return false 281 } 282 283 // If the type switch expression is invalid, x is nil. 284 func (check *Checker) caseTypes(x *operand, types []ast.Expr, seen map[Type]ast.Expr) (T Type) { 285 var dummy operand 286 L: 287 for _, e := range types { 288 // The spec allows the value nil instead of a type. 289 if check.isNil(e) { 290 T = nil 291 check.expr(&dummy, e) // run e through expr so we get the usual Info recordings 292 } else { 293 T = check.varType(e) 294 if T == Typ[Invalid] { 295 continue L 296 } 297 } 298 // look for duplicate types 299 // (quadratic algorithm, but type switches tend to be reasonably small) 300 for t, other := range seen { 301 if T == nil && t == nil || T != nil && t != nil && Identical(T, t) { 302 // talk about "case" rather than "type" because of nil case 303 Ts := "nil" 304 if T != nil { 305 Ts = TypeString(T, check.qualifier) 306 } 307 check.errorf(e, DuplicateCase, "duplicate case %s in type switch", Ts) 308 check.error(other, DuplicateCase, "\tprevious case") // secondary error, \t indented 309 continue L 310 } 311 } 312 seen[T] = e 313 if x != nil && T != nil { 314 check.typeAssertion(e, x, T, true) 315 } 316 } 317 return 318 } 319 320 // TODO(gri) Once we are certain that typeHash is correct in all situations, use this version of caseTypes instead. 321 // (Currently it may be possible that different types have identical names and import paths due to ImporterFrom.) 322 // 323 // func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []ast.Expr, seen map[string]ast.Expr) (T Type) { 324 // var dummy operand 325 // L: 326 // for _, e := range types { 327 // // The spec allows the value nil instead of a type. 328 // var hash string 329 // if check.isNil(e) { 330 // check.expr(&dummy, e) // run e through expr so we get the usual Info recordings 331 // T = nil 332 // hash = "<nil>" // avoid collision with a type named nil 333 // } else { 334 // T = check.varType(e) 335 // if T == Typ[Invalid] { 336 // continue L 337 // } 338 // hash = typeHash(T, nil) 339 // } 340 // // look for duplicate types 341 // if other := seen[hash]; other != nil { 342 // // talk about "case" rather than "type" because of nil case 343 // Ts := "nil" 344 // if T != nil { 345 // Ts = TypeString(T, check.qualifier) 346 // } 347 // var err error_ 348 // err.code = DuplicateCase 349 // err.errorf(e, "duplicate case %s in type switch", Ts) 350 // err.errorf(other, "previous case") 351 // check.report(&err) 352 // continue L 353 // } 354 // seen[hash] = e 355 // if T != nil { 356 // check.typeAssertion(e.Pos(), x, xtyp, T) 357 // } 358 // } 359 // return 360 // } 361 362 // stmt typechecks statement s. 363 func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { 364 // statements must end with the same top scope as they started with 365 if debug { 366 defer func(scope *Scope) { 367 // don't check if code is panicking 368 if p := recover(); p != nil { 369 panic(p) 370 } 371 assert(scope == check.scope) 372 }(check.scope) 373 } 374 375 // process collected function literals before scope changes 376 defer check.processDelayed(len(check.delayed)) 377 378 // reset context for statements of inner blocks 379 inner := ctxt &^ (fallthroughOk | finalSwitchCase | inTypeSwitch) 380 381 switch s := s.(type) { 382 case *ast.BadStmt, *ast.EmptyStmt: 383 // ignore 384 385 case *ast.DeclStmt: 386 check.declStmt(s.Decl) 387 388 case *ast.LabeledStmt: 389 check.hasLabel = true 390 check.stmt(ctxt, s.Stmt) 391 392 case *ast.ExprStmt: 393 // spec: "With the exception of specific built-in functions, 394 // function and method calls and receive operations can appear 395 // in statement context. Such statements may be parenthesized." 396 var x operand 397 kind := check.rawExpr(&x, s.X, nil, false) 398 var msg string 399 var code Code 400 switch x.mode { 401 default: 402 if kind == statement { 403 return 404 } 405 msg = "is not used" 406 code = UnusedExpr 407 case builtin: 408 msg = "must be called" 409 code = UncalledBuiltin 410 case typexpr: 411 msg = "is not an expression" 412 code = NotAnExpr 413 } 414 check.errorf(&x, code, "%s %s", &x, msg) 415 416 case *ast.SendStmt: 417 var ch, val operand 418 check.expr(&ch, s.Chan) 419 check.expr(&val, s.Value) 420 if ch.mode == invalid || val.mode == invalid { 421 return 422 } 423 u := coreType(ch.typ) 424 if u == nil { 425 check.errorf(inNode(s, s.Arrow), InvalidSend, invalidOp+"cannot send to %s: no core type", &ch) 426 return 427 } 428 uch, _ := u.(*Chan) 429 if uch == nil { 430 check.errorf(inNode(s, s.Arrow), InvalidSend, invalidOp+"cannot send to non-channel %s", &ch) 431 return 432 } 433 if uch.dir == RecvOnly { 434 check.errorf(inNode(s, s.Arrow), InvalidSend, invalidOp+"cannot send to receive-only channel %s", &ch) 435 return 436 } 437 check.assignment(&val, uch.elem, "send") 438 439 case *ast.IncDecStmt: 440 var op token.Token 441 switch s.Tok { 442 case token.INC: 443 op = token.ADD 444 case token.DEC: 445 op = token.SUB 446 default: 447 check.errorf(inNode(s, s.TokPos), InvalidSyntaxTree, "unknown inc/dec operation %s", s.Tok) 448 return 449 } 450 451 var x operand 452 check.expr(&x, s.X) 453 if x.mode == invalid { 454 return 455 } 456 if !allNumeric(x.typ) { 457 check.errorf(s.X, NonNumericIncDec, invalidOp+"%s%s (non-numeric type %s)", s.X, s.Tok, x.typ) 458 return 459 } 460 461 Y := &ast.BasicLit{ValuePos: s.X.Pos(), Kind: token.INT, Value: "1"} // use x's position 462 check.binary(&x, nil, s.X, Y, op, s.TokPos) 463 if x.mode == invalid { 464 return 465 } 466 check.assignVar(s.X, &x) 467 468 case *ast.AssignStmt: 469 switch s.Tok { 470 case token.ASSIGN, token.DEFINE: 471 if len(s.Lhs) == 0 { 472 check.error(s, InvalidSyntaxTree, "missing lhs in assignment") 473 return 474 } 475 if s.Tok == token.DEFINE { 476 check.shortVarDecl(inNode(s, s.TokPos), s.Lhs, s.Rhs) 477 } else { 478 // regular assignment 479 check.assignVars(s.Lhs, s.Rhs) 480 } 481 482 default: 483 // assignment operations 484 if len(s.Lhs) != 1 || len(s.Rhs) != 1 { 485 check.errorf(inNode(s, s.TokPos), MultiValAssignOp, "assignment operation %s requires single-valued expressions", s.Tok) 486 return 487 } 488 op := assignOp(s.Tok) 489 if op == token.ILLEGAL { 490 check.errorf(atPos(s.TokPos), InvalidSyntaxTree, "unknown assignment operation %s", s.Tok) 491 return 492 } 493 var x operand 494 check.binary(&x, nil, s.Lhs[0], s.Rhs[0], op, s.TokPos) 495 if x.mode == invalid { 496 return 497 } 498 check.assignVar(s.Lhs[0], &x) 499 } 500 501 case *ast.GoStmt: 502 check.suspendedCall("go", s.Call) 503 504 case *ast.DeferStmt: 505 check.suspendedCall("defer", s.Call) 506 507 case *ast.ReturnStmt: 508 res := check.sig.results 509 // Return with implicit results allowed for function with named results. 510 // (If one is named, all are named.) 511 if len(s.Results) == 0 && res.Len() > 0 && res.vars[0].name != "" { 512 // spec: "Implementation restriction: A compiler may disallow an empty expression 513 // list in a "return" statement if a different entity (constant, type, or variable) 514 // with the same name as a result parameter is in scope at the place of the return." 515 for _, obj := range res.vars { 516 if alt := check.lookup(obj.name); alt != nil && alt != obj { 517 check.errorf(s, OutOfScopeResult, "result parameter %s not in scope at return", obj.name) 518 check.errorf(alt, OutOfScopeResult, "\tinner declaration of %s", obj) 519 // ok to continue 520 } 521 } 522 } else { 523 var lhs []*Var 524 if res.Len() > 0 { 525 lhs = res.vars 526 } 527 check.initVars(lhs, s.Results, s) 528 } 529 530 case *ast.BranchStmt: 531 if s.Label != nil { 532 check.hasLabel = true 533 return // checked in 2nd pass (check.labels) 534 } 535 switch s.Tok { 536 case token.BREAK: 537 if ctxt&breakOk == 0 { 538 check.error(s, MisplacedBreak, "break not in for, switch, or select statement") 539 } 540 case token.CONTINUE: 541 if ctxt&continueOk == 0 { 542 check.error(s, MisplacedContinue, "continue not in for statement") 543 } 544 case token.FALLTHROUGH: 545 if ctxt&fallthroughOk == 0 { 546 var msg string 547 switch { 548 case ctxt&finalSwitchCase != 0: 549 msg = "cannot fallthrough final case in switch" 550 case ctxt&inTypeSwitch != 0: 551 msg = "cannot fallthrough in type switch" 552 default: 553 msg = "fallthrough statement out of place" 554 } 555 check.error(s, MisplacedFallthrough, msg) 556 } 557 default: 558 check.errorf(s, InvalidSyntaxTree, "branch statement: %s", s.Tok) 559 } 560 561 case *ast.BlockStmt: 562 check.openScope(s, "block") 563 defer check.closeScope() 564 565 check.stmtList(inner, s.List) 566 567 case *ast.IfStmt: 568 check.openScope(s, "if") 569 defer check.closeScope() 570 571 check.simpleStmt(s.Init) 572 var x operand 573 check.expr(&x, s.Cond) 574 if x.mode != invalid && !allBoolean(x.typ) { 575 check.error(s.Cond, InvalidCond, "non-boolean condition in if statement") 576 } 577 check.stmt(inner, s.Body) 578 // The parser produces a correct AST but if it was modified 579 // elsewhere the else branch may be invalid. Check again. 580 switch s.Else.(type) { 581 case nil, *ast.BadStmt: 582 // valid or error already reported 583 case *ast.IfStmt, *ast.BlockStmt: 584 check.stmt(inner, s.Else) 585 default: 586 check.error(s.Else, InvalidSyntaxTree, "invalid else branch in if statement") 587 } 588 589 case *ast.SwitchStmt: 590 inner |= breakOk 591 check.openScope(s, "switch") 592 defer check.closeScope() 593 594 check.simpleStmt(s.Init) 595 var x operand 596 if s.Tag != nil { 597 check.expr(&x, s.Tag) 598 // By checking assignment of x to an invisible temporary 599 // (as a compiler would), we get all the relevant checks. 600 check.assignment(&x, nil, "switch expression") 601 if x.mode != invalid && !Comparable(x.typ) && !hasNil(x.typ) { 602 check.errorf(&x, InvalidExprSwitch, "cannot switch on %s (%s is not comparable)", &x, x.typ) 603 x.mode = invalid 604 } 605 } else { 606 // spec: "A missing switch expression is 607 // equivalent to the boolean value true." 608 x.mode = constant_ 609 x.typ = Typ[Bool] 610 x.val = constant.MakeBool(true) 611 x.expr = &ast.Ident{NamePos: s.Body.Lbrace, Name: "true"} 612 } 613 614 check.multipleDefaults(s.Body.List) 615 616 seen := make(valueMap) // map of seen case values to positions and types 617 for i, c := range s.Body.List { 618 clause, _ := c.(*ast.CaseClause) 619 if clause == nil { 620 check.error(c, InvalidSyntaxTree, "incorrect expression switch case") 621 continue 622 } 623 check.caseValues(&x, clause.List, seen) 624 check.openScope(clause, "case") 625 inner := inner 626 if i+1 < len(s.Body.List) { 627 inner |= fallthroughOk 628 } else { 629 inner |= finalSwitchCase 630 } 631 check.stmtList(inner, clause.Body) 632 check.closeScope() 633 } 634 635 case *ast.TypeSwitchStmt: 636 inner |= breakOk | inTypeSwitch 637 check.openScope(s, "type switch") 638 defer check.closeScope() 639 640 check.simpleStmt(s.Init) 641 642 // A type switch guard must be of the form: 643 // 644 // TypeSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "type" ")" . 645 // 646 // The parser is checking syntactic correctness; 647 // remaining syntactic errors are considered AST errors here. 648 // TODO(gri) better factoring of error handling (invalid ASTs) 649 // 650 var lhs *ast.Ident // lhs identifier or nil 651 var rhs ast.Expr 652 switch guard := s.Assign.(type) { 653 case *ast.ExprStmt: 654 rhs = guard.X 655 case *ast.AssignStmt: 656 if len(guard.Lhs) != 1 || guard.Tok != token.DEFINE || len(guard.Rhs) != 1 { 657 check.error(s, InvalidSyntaxTree, "incorrect form of type switch guard") 658 return 659 } 660 661 lhs, _ = guard.Lhs[0].(*ast.Ident) 662 if lhs == nil { 663 check.error(s, InvalidSyntaxTree, "incorrect form of type switch guard") 664 return 665 } 666 667 if lhs.Name == "_" { 668 // _ := x.(type) is an invalid short variable declaration 669 check.softErrorf(lhs, NoNewVar, "no new variable on left side of :=") 670 lhs = nil // avoid declared and not used error below 671 } else { 672 check.recordDef(lhs, nil) // lhs variable is implicitly declared in each cause clause 673 } 674 675 rhs = guard.Rhs[0] 676 677 default: 678 check.error(s, InvalidSyntaxTree, "incorrect form of type switch guard") 679 return 680 } 681 682 // rhs must be of the form: expr.(type) and expr must be an ordinary interface 683 expr, _ := rhs.(*ast.TypeAssertExpr) 684 if expr == nil || expr.Type != nil { 685 check.error(s, InvalidSyntaxTree, "incorrect form of type switch guard") 686 return 687 } 688 var x operand 689 check.expr(&x, expr.X) 690 if x.mode == invalid { 691 return 692 } 693 // TODO(gri) we may want to permit type switches on type parameter values at some point 694 var sx *operand // switch expression against which cases are compared against; nil if invalid 695 if isTypeParam(x.typ) { 696 check.errorf(&x, InvalidTypeSwitch, "cannot use type switch on type parameter value %s", &x) 697 } else { 698 if _, ok := under(x.typ).(*Interface); ok { 699 sx = &x 700 } else { 701 check.errorf(&x, InvalidTypeSwitch, "%s is not an interface", &x) 702 } 703 } 704 705 check.multipleDefaults(s.Body.List) 706 707 var lhsVars []*Var // list of implicitly declared lhs variables 708 seen := make(map[Type]ast.Expr) // map of seen types to positions 709 for _, s := range s.Body.List { 710 clause, _ := s.(*ast.CaseClause) 711 if clause == nil { 712 check.error(s, InvalidSyntaxTree, "incorrect type switch case") 713 continue 714 } 715 // Check each type in this type switch case. 716 T := check.caseTypes(sx, clause.List, seen) 717 check.openScope(clause, "case") 718 // If lhs exists, declare a corresponding variable in the case-local scope. 719 if lhs != nil { 720 // spec: "The TypeSwitchGuard may include a short variable declaration. 721 // When that form is used, the variable is declared at the beginning of 722 // the implicit block in each clause. In clauses with a case listing 723 // exactly one type, the variable has that type; otherwise, the variable 724 // has the type of the expression in the TypeSwitchGuard." 725 if len(clause.List) != 1 || T == nil { 726 T = x.typ 727 } 728 obj := NewVar(lhs.Pos(), check.pkg, lhs.Name, T) 729 scopePos := clause.Pos() + token.Pos(len("default")) // for default clause (len(List) == 0) 730 if n := len(clause.List); n > 0 { 731 scopePos = clause.List[n-1].End() 732 } 733 check.declare(check.scope, nil, obj, scopePos) 734 check.recordImplicit(clause, obj) 735 // For the "declared and not used" error, all lhs variables act as 736 // one; i.e., if any one of them is 'used', all of them are 'used'. 737 // Collect them for later analysis. 738 lhsVars = append(lhsVars, obj) 739 } 740 check.stmtList(inner, clause.Body) 741 check.closeScope() 742 } 743 744 // If lhs exists, we must have at least one lhs variable that was used. 745 if lhs != nil { 746 var used bool 747 for _, v := range lhsVars { 748 if v.used { 749 used = true 750 } 751 v.used = true // avoid usage error when checking entire function 752 } 753 if !used { 754 check.softErrorf(lhs, UnusedVar, "%s declared and not used", lhs.Name) 755 } 756 } 757 758 case *ast.SelectStmt: 759 inner |= breakOk 760 761 check.multipleDefaults(s.Body.List) 762 763 for _, s := range s.Body.List { 764 clause, _ := s.(*ast.CommClause) 765 if clause == nil { 766 continue // error reported before 767 } 768 769 // clause.Comm must be a SendStmt, RecvStmt, or default case 770 valid := false 771 var rhs ast.Expr // rhs of RecvStmt, or nil 772 switch s := clause.Comm.(type) { 773 case nil, *ast.SendStmt: 774 valid = true 775 case *ast.AssignStmt: 776 if len(s.Rhs) == 1 { 777 rhs = s.Rhs[0] 778 } 779 case *ast.ExprStmt: 780 rhs = s.X 781 } 782 783 // if present, rhs must be a receive operation 784 if rhs != nil { 785 if x, _ := unparen(rhs).(*ast.UnaryExpr); x != nil && x.Op == token.ARROW { 786 valid = true 787 } 788 } 789 790 if !valid { 791 check.error(clause.Comm, InvalidSelectCase, "select case must be send or receive (possibly with assignment)") 792 continue 793 } 794 795 check.openScope(s, "case") 796 if clause.Comm != nil { 797 check.stmt(inner, clause.Comm) 798 } 799 check.stmtList(inner, clause.Body) 800 check.closeScope() 801 } 802 803 case *ast.ForStmt: 804 inner |= breakOk | continueOk 805 check.openScope(s, "for") 806 defer check.closeScope() 807 808 check.simpleStmt(s.Init) 809 if s.Cond != nil { 810 var x operand 811 check.expr(&x, s.Cond) 812 if x.mode != invalid && !allBoolean(x.typ) { 813 check.error(s.Cond, InvalidCond, "non-boolean condition in for statement") 814 } 815 } 816 check.simpleStmt(s.Post) 817 // spec: "The init statement may be a short variable 818 // declaration, but the post statement must not." 819 if s, _ := s.Post.(*ast.AssignStmt); s != nil && s.Tok == token.DEFINE { 820 check.softErrorf(s, InvalidPostDecl, "cannot declare in post statement") 821 // Don't call useLHS here because we want to use the lhs in 822 // this erroneous statement so that we don't get errors about 823 // these lhs variables being declared and not used. 824 check.use(s.Lhs...) // avoid follow-up errors 825 } 826 check.stmt(inner, s.Body) 827 828 case *ast.RangeStmt: 829 inner |= breakOk | continueOk 830 831 // check expression to iterate over 832 var x operand 833 check.expr(&x, s.X) 834 835 // determine key/value types 836 var key, val Type 837 if x.mode != invalid { 838 // Ranging over a type parameter is permitted if it has a core type. 839 var cause string 840 u := coreType(x.typ) 841 switch t := u.(type) { 842 case nil: 843 cause = check.sprintf("%s has no core type", x.typ) 844 case *Chan: 845 if s.Value != nil { 846 check.softErrorf(s.Value, InvalidIterVar, "range over %s permits only one iteration variable", &x) 847 // ok to continue 848 } 849 if t.dir == SendOnly { 850 cause = "receive from send-only channel" 851 } 852 } 853 key, val = rangeKeyVal(u) 854 if key == nil || cause != "" { 855 if cause == "" { 856 check.softErrorf(&x, InvalidRangeExpr, "cannot range over %s", &x) 857 } else { 858 check.softErrorf(&x, InvalidRangeExpr, "cannot range over %s (%s)", &x, cause) 859 } 860 // ok to continue 861 } 862 } 863 864 // Open the for-statement block scope now, after the range clause. 865 // Iteration variables declared with := need to go in this scope (was issue #51437). 866 check.openScope(s, "range") 867 defer check.closeScope() 868 869 // check assignment to/declaration of iteration variables 870 // (irregular assignment, cannot easily map to existing assignment checks) 871 872 // lhs expressions and initialization value (rhs) types 873 lhs := [2]ast.Expr{s.Key, s.Value} 874 rhs := [2]Type{key, val} // key, val may be nil 875 876 if s.Tok == token.DEFINE { 877 // short variable declaration 878 var vars []*Var 879 for i, lhs := range lhs { 880 if lhs == nil { 881 continue 882 } 883 884 // determine lhs variable 885 var obj *Var 886 if ident, _ := lhs.(*ast.Ident); ident != nil { 887 // declare new variable 888 name := ident.Name 889 obj = NewVar(ident.Pos(), check.pkg, name, nil) 890 check.recordDef(ident, obj) 891 // _ variables don't count as new variables 892 if name != "_" { 893 vars = append(vars, obj) 894 } 895 } else { 896 check.errorf(lhs, InvalidSyntaxTree, "cannot declare %s", lhs) 897 obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable 898 } 899 900 // initialize lhs variable 901 if typ := rhs[i]; typ != nil { 902 x.mode = value 903 x.expr = lhs // we don't have a better rhs expression to use here 904 x.typ = typ 905 check.initVar(obj, &x, "range clause") 906 } else { 907 obj.typ = Typ[Invalid] 908 obj.used = true // don't complain about unused variable 909 } 910 } 911 912 // declare variables 913 if len(vars) > 0 { 914 scopePos := s.Body.Pos() 915 for _, obj := range vars { 916 check.declare(check.scope, nil /* recordDef already called */, obj, scopePos) 917 } 918 } else { 919 check.error(inNode(s, s.TokPos), NoNewVar, "no new variables on left side of :=") 920 } 921 } else { 922 // ordinary assignment 923 for i, lhs := range lhs { 924 if lhs == nil { 925 continue 926 } 927 if typ := rhs[i]; typ != nil { 928 x.mode = value 929 x.expr = lhs // we don't have a better rhs expression to use here 930 x.typ = typ 931 check.assignVar(lhs, &x) 932 } 933 } 934 } 935 936 check.stmt(inner, s.Body) 937 938 default: 939 check.error(s, InvalidSyntaxTree, "invalid statement") 940 } 941 } 942 943 // rangeKeyVal returns the key and value type produced by a range clause 944 // over an expression of type typ. If the range clause is not permitted 945 // the results are nil. 946 func rangeKeyVal(typ Type) (key, val Type) { 947 switch typ := arrayPtrDeref(typ).(type) { 948 case *Basic: 949 if isString(typ) { 950 return Typ[Int], universeRune // use 'rune' name 951 } 952 case *Array: 953 return Typ[Int], typ.elem 954 case *Slice: 955 return Typ[Int], typ.elem 956 case *Map: 957 return typ.key, typ.elem 958 case *Chan: 959 return typ.elem, Typ[Invalid] 960 } 961 return 962 }