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