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