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