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