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.
5 // This file implements typechecking of statements.
10 "cmd/compile/internal/syntax"
13 . "internal/types/errors"
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")
23 check.trace(body.Pos(), "-- %s: %s", name, sig)
26 // set function scope extent
27 sig.scope.pos = body.Pos()
28 sig.scope.end = syntax.EndPos(body)
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
35 }(check.environment, check.indent)
36 check.environment = environment{
44 check.stmtList(0, body.List)
46 if check.hasLabel && !check.conf.IgnoreBranchErrors {
50 if sig.results.Len() > 0 && !check.isTerminating(body, "") {
51 check.error(body.Rbrace, MissingReturn, "missing return")
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)
59 func (check *Checker) usage(scope *Scope) {
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)
67 sort.Slice(unused, func(i, j int) bool {
68 return cmpPos(unused[i].pos, unused[j].pos) < 0
70 for _, v := range unused {
71 check.softErrorf(v.pos, UnusedVar, "%s declared and not used", v.name)
74 for _, scope := range scope.children {
75 // Don't go inside function literal scopes a second time;
76 // they are handled explicitly by funcBody.
83 // stmtContext is a bitset describing which
84 // control-flow statements are permissible,
85 // and provides additional context information
86 // for better error messages.
90 // permissible control-flow statements
91 breakOk stmtContext = 1 << iota
95 // additional context information
100 func (check *Checker) simpleStmt(s syntax.Stmt) {
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 {
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 {
121 if ok && i+1 == len(list) {
122 inner |= fallthroughOk
128 func (check *Checker) multipleSwitchDefaults(list []*syntax.CaseClause) {
129 var first *syntax.CaseClause
130 for _, c := range list {
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)
142 func (check *Checker) multipleSelectDefaults(list []*syntax.CommClause) {
143 var first *syntax.CommClause
144 for _, c := range list {
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)
156 func (check *Checker) openScope(node syntax.Node, comment string) {
157 check.openScopeUntil(node, syntax.EndPos(node), comment)
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)
166 func (check *Checker) closeScope() {
167 check.scope = check.scope.Parent()
170 func (check *Checker) suspendedCall(keyword string, call syntax.Expr) {
176 if _, ok := call.(*syntax.CallExpr); !ok {
177 check.errorf(call, code, "expression in %s must be function call", keyword)
184 switch check.rawExpr(nil, &x, call, nil, false) {
186 msg = "requires function call, not conversion"
188 msg = "discards result of"
195 check.errorf(&x, code, "%s %s %s", keyword, msg, &x)
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
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
210 if x, ok := constant.Int64Val(val); ok {
213 if x, ok := constant.Uint64Val(val); ok {
217 if x, ok := constant.Float64Val(val); ok {
220 case constant.String:
221 return constant.StringVal(val)
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
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.
233 valueMap map[interface{}][]valueType // underlying Go value -> valueType
240 func (check *Checker) caseValues(x *operand, values []syntax.Expr, seen valueMap) {
242 for _, e := range values {
244 check.expr(nil, &v, e)
245 if x.mode == invalid || v.mode == invalid {
248 check.convertUntyped(&v, x.typ)
249 if v.mode == invalid {
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 {
258 if v.mode != constant_ {
259 continue L // we're done
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) {
268 err.code = DuplicateCase
269 err.errorf(&v, "duplicate case %s in expression switch", &v)
270 err.errorf(vt.pos, "previous case")
275 seen[val] = append(seen[val], valueType{v.Pos(), v.typ})
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)
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) {
294 for _, e := range types {
295 // The spec allows the value nil instead of a type.
298 check.expr(nil, &dummy, e) // run e through expr so we get the usual Info recordings
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
312 Ts = TypeString(T, check.qualifier)
315 err.code = DuplicateCase
316 err.errorf(e, "duplicate case %s in type switch", Ts)
317 err.errorf(other, "previous case")
323 if x != nil && T != nil {
324 check.typeAssertion(e, x, T, true)
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.)
333 // func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []syntax.Expr, seen map[string]syntax.Expr) (T Type) {
336 // for _, e := range types {
337 // // The spec allows the value nil instead of a type.
339 // if check.isNil(e) {
340 // check.expr(nil, &dummy, e) // run e through expr so we get the usual Info recordings
342 // hash = "<nil>" // avoid collision with a type named nil
344 // T = check.varType(e)
348 // hash = typeHash(T, nil)
350 // // look for duplicate types
351 // if other := seen[hash]; other != nil {
352 // // talk about "case" rather than "type" because of nil case
355 // Ts = TypeString(T, check.qualifier)
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)
366 // check.typeAssertion(e, x, xtyp, T, true)
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
376 defer func(scope *Scope) {
377 // don't check if code is panicking
378 if p := recover(); p != nil {
381 assert(scope == check.scope)
385 // process collected function literals before scope changes
386 defer check.processDelayed(len(check.delayed))
388 // reset context for statements of inner blocks
389 inner := ctxt &^ (fallthroughOk | finalSwitchCase | inTypeSwitch)
391 switch s := s.(type) {
392 case *syntax.EmptyStmt:
395 case *syntax.DeclStmt:
396 check.declStmt(s.DeclList)
398 case *syntax.LabeledStmt:
399 check.hasLabel = true
400 check.stmt(ctxt, s.Stmt)
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."
407 kind := check.rawExpr(nil, &x, s.X, nil, false)
412 if kind == statement {
418 msg = "must be called"
419 code = UncalledBuiltin
421 msg = "is not an expression"
424 check.errorf(&x, code, "%s %s", &x, msg)
426 case *syntax.SendStmt:
428 check.expr(nil, &ch, s.Chan)
429 check.expr(nil, &val, s.Value)
430 if ch.mode == invalid || val.mode == invalid {
433 u := coreType(ch.typ)
435 check.errorf(s, InvalidSend, invalidOp+"cannot send to %s: no core type", &ch)
440 check.errorf(s, InvalidSend, invalidOp+"cannot send to non-channel %s", &ch)
443 if uch.dir == RecvOnly {
444 check.errorf(s, InvalidSend, invalidOp+"cannot send to receive-only channel %s", &ch)
447 check.assignment(&val, uch.elem, "send")
449 case *syntax.AssignStmt:
452 // (no need to call unpackExpr as s.Lhs must be single-valued)
454 check.expr(nil, &x, s.Lhs)
455 if x.mode == invalid {
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)
462 check.assignVar(s.Lhs, nil, &x)
466 lhs := syntax.UnpackListExpr(s.Lhs)
467 rhs := syntax.UnpackListExpr(s.Rhs)
470 check.assignVars(lhs, rhs)
473 check.shortVarDecl(s.Pos(), lhs, rhs)
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)
484 check.binary(&x, nil, lhs[0], rhs[0], s.Op)
485 check.assignVar(lhs[0], nil, &x)
487 case *syntax.CallStmt:
489 if s.Tok == syntax.Defer {
492 check.suspendedCall(kind, s.Call)
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 {
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)
518 check.initVars(lhs, results, s)
521 case *syntax.BranchStmt:
523 check.hasLabel = true
524 break // checked in 2nd pass (check.labels)
526 if check.conf.IgnoreBranchErrors {
531 if ctxt&breakOk == 0 {
532 check.error(s, MisplacedBreak, "break not in for, switch, or select statement")
534 case syntax.Continue:
535 if ctxt&continueOk == 0 {
536 check.error(s, MisplacedContinue, "continue not in for statement")
538 case syntax.Fallthrough:
539 if ctxt&fallthroughOk == 0 {
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"
547 msg = "fallthrough statement out of place"
549 check.error(s, MisplacedFallthrough, msg)
552 // goto's must have labels, should have been caught above
555 check.errorf(s, InvalidSyntaxTree, "branch statement: %s", s.Tok)
558 case *syntax.BlockStmt:
559 check.openScope(s, "block")
560 defer check.closeScope()
562 check.stmtList(inner, s.List)
565 check.openScope(s, "if")
566 defer check.closeScope()
568 check.simpleStmt(s.Init)
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")
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) {
579 // valid or error already reported
580 case *syntax.IfStmt, *syntax.BlockStmt:
581 check.stmt(inner, s.Else)
583 check.error(s.Else, InvalidSyntaxTree, "invalid else branch in if statement")
586 case *syntax.SwitchStmt:
588 check.openScope(s, "switch")
589 defer check.closeScope()
591 check.simpleStmt(s.Init)
593 if g, _ := s.Tag.(*syntax.TypeSwitchGuard); g != nil {
594 check.typeSwitchStmt(inner|inTypeSwitch, s, g)
596 check.switchStmt(inner, s)
599 case *syntax.SelectStmt:
602 check.multipleSelectDefaults(s.Body)
604 for i, clause := range s.Body {
606 continue // error reported before
609 // clause.Comm must be a SendStmt, RecvStmt, or default case
611 var rhs syntax.Expr // rhs of RecvStmt, or nil
612 switch s := clause.Comm.(type) {
613 case nil, *syntax.SendStmt:
615 case *syntax.AssignStmt:
616 if _, ok := s.Rhs.(*syntax.ListExpr); !ok {
619 case *syntax.ExprStmt:
623 // if present, rhs must be a receive operation
625 if x, _ := syntax.Unparen(rhs).(*syntax.Operation); x != nil && x.Y == nil && x.Op == syntax.Recv {
631 check.error(clause.Comm, InvalidSelectCase, "select case must be send or receive (possibly with assignment)")
635 if i+1 < len(s.Body) {
636 end = s.Body[i+1].Pos()
638 check.openScopeUntil(clause, end, "case")
639 if clause.Comm != nil {
640 check.stmt(inner, clause.Comm)
642 check.stmtList(inner, clause.Body)
646 case *syntax.ForStmt:
647 inner |= breakOk | continueOk
649 if rclause, _ := s.Init.(*syntax.RangeClause); rclause != nil {
650 check.rangeStmt(inner, s, rclause)
654 check.openScope(s, "for")
655 defer check.closeScope()
657 check.simpleStmt(s.Init)
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")
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
672 check.stmt(inner, s.Body)
675 check.error(s, InvalidSyntaxTree, "invalid statement")
679 func (check *Checker) switchStmt(inner stmtContext, s *syntax.SwitchStmt) {
680 // init statement already handled
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)
693 // spec: "A missing switch expression is
694 // equivalent to the boolean value true."
697 x.val = constant.MakeBool(true)
698 // TODO(gri) should have a better position here
701 pos = s.Body[0].Pos()
703 x.expr = syntax.NewName(pos, "true")
706 check.multipleSwitchDefaults(s.Body)
708 seen := make(valueMap) // map of seen case values to positions and types
709 for i, clause := range s.Body {
711 check.error(clause, InvalidSyntaxTree, "incorrect expression switch case")
716 if i+1 < len(s.Body) {
717 end = s.Body[i+1].Pos()
718 inner |= fallthroughOk
720 inner |= finalSwitchCase
722 check.caseValues(&x, syntax.UnpackListExpr(clause.Cases), seen)
723 check.openScopeUntil(clause, end, "case")
724 check.stmtList(inner, clause.Body)
729 func (check *Checker) typeSwitchStmt(inner stmtContext, s *syntax.SwitchStmt, guard *syntax.TypeSwitchGuard) {
730 // init statement already handled
732 // A type switch guard must be of the form:
734 // TypeSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "type" ")" .
735 // \__lhs__/ \___rhs___/
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
745 check.recordDef(lhs, nil) // lhs variable is implicitly declared in each cause clause
751 check.expr(nil, &x, guard.X)
752 if x.mode == invalid {
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)
761 if _, ok := under(x.typ).(*Interface); ok {
764 check.errorf(&x, InvalidTypeSwitch, "%s is not an interface", &x)
768 check.multipleSwitchDefaults(s.Body)
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 {
774 check.error(s, InvalidSyntaxTree, "incorrect type switch case")
778 if i+1 < len(s.Body) {
779 end = s.Body[i+1].Pos()
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.
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 {
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])
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)
809 check.stmtList(inner, clause.Body)
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.)
819 for _, v := range lhsVars {
823 v.used = true // avoid usage error when checking entire function
826 check.softErrorf(lhs, UnusedVar, "%s declared and not used", lhs.Value)
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")
843 // len(p.ElemList) >= 2
845 sValue = p.ElemList[1]
846 if len(p.ElemList) > 2 {
847 // delay error reporting until we know more
848 sExtra = p.ElemList[2]
852 rangeVar := rclause.X
855 // Do not use rclause anymore.
858 // Everything from here on is shared between cmd/compile/internal/types2 and go/types.
860 // check expression to iterate over
862 check.expr(nil, &x, rangeVar)
864 // determine key/value types
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)
870 case !ok && cause != "":
871 check.softErrorf(&x, InvalidRangeExpr, "cannot range over %s: %s", &x, cause)
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)
879 check.softErrorf(sExtra, InvalidIterVar, "range clause permits at most two iteration variables")
880 case isFunc && ((k == nil) != (sKey == nil) || (v == nil) != (sValue == nil)):
884 count = "no iteration variables"
886 count = "one iteration variable"
888 count = "two iteration variables"
890 check.softErrorf(&x, InvalidIterVar, "range over %s must have %s", &x, count)
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()
900 // check assignment to/declaration of iteration variables
901 // (irregular assignment, cannot easily map to existing assignment checks)
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
908 // short variable declaration
910 for i, lhs := range lhs {
915 // determine lhs variable
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
924 vars = append(vars, obj)
927 check.errorf(lhs, InvalidSyntaxTree, "cannot declare %s", lhs)
928 obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable
931 // initialize lhs variable
932 if typ := rhs[i]; typ != nil {
934 x.expr = lhs // we don't have a better rhs expression to use here
936 check.initVar(obj, &x, "range clause")
938 obj.typ = Typ[Invalid]
939 obj.used = true // don't complain about unused variable
945 scopePos := s.Body.Pos()
946 for _, obj := range vars {
947 check.declare(check.scope, nil /* recordDef already called */, obj, scopePos)
950 check.error(noNewVarPos, NoNewVar, "no new variables on left side of :=")
953 // ordinary assignment
954 for i, lhs := range lhs {
958 if typ := rhs[i]; typ != nil {
960 x.expr = lhs // we don't have a better rhs expression to use here
962 check.assignVar(lhs, nil, &x)
967 check.stmt(inner, s.Body)
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)
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
984 toSig := func(t Type) *Signature {
985 sig, _ := coreType(t).(*Signature)
990 switch typ := arrayPtrDeref(coreType(typ)).(type) {
992 return bad("no core type")
995 return Typ[Int], universeRune, "", false, true // use 'rune' name
998 return orig, nil, "", false, true
1001 return Typ[Int], typ.elem, "", false, true
1003 return Typ[Int], typ.elem, "", false, true
1005 return typ.key, typ.elem, "", false, true
1007 if typ.dir == SendOnly {
1008 return bad("receive from send-only channel")
1010 return typ.elem, nil, "", false, true
1012 if !buildcfg.Experiment.Range {
1015 assert(typ.Recv() == nil)
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")
1024 cb := toSig(typ.Params().At(0).Type())
1025 assert(cb.Recv() == nil)
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")
1032 if cb.Params().Len() >= 1 {
1033 key = cb.Params().At(0).Type()
1035 if cb.Params().Len() >= 2 {
1036 val = cb.Params().At(1).Type()
1038 return key, val, "", true, true