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