1
2
3
4
5
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
27
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
51
52 check.usage(sig.scope)
53 }
54
55 func (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
72
73 if !scope.isFunc {
74 check.usage(scope)
75 }
76 }
77 }
78
79
80
81
82
83 type stmtContext uint
84
85 const (
86
87 breakOk stmtContext = 1 << iota
88 continueOk
89 fallthroughOk
90
91
92 finalSwitchCase
93 inTypeSwitch
94 )
95
96 func (check *Checker) simpleStmt(s syntax.Stmt) {
97 if s != nil {
98 check.stmt(0, s)
99 }
100 }
101
102 func 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
111 func (check *Checker) stmtList(ctxt stmtContext, list []syntax.Stmt) {
112 ok := ctxt&fallthroughOk != 0
113 inner := ctxt &^ fallthroughOk
114 list = trimTrailingEmptyStmts(list)
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
124 func (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
131 } else {
132 first = c
133 }
134 }
135 }
136 }
137
138 func (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
145 } else {
146 first = c
147 }
148 }
149 }
150 }
151
152 func (check *Checker) openScope(node syntax.Node, comment string) {
153 check.openScopeUntil(node, syntax.EndPos(node), comment)
154 }
155
156 func (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
162 func (check *Checker) closeScope() {
163 check.scope = check.scope.Parent()
164 }
165
166 func (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
195 func goVal(val constant.Value) interface{} {
196
197 if val == nil {
198 return nil
199 }
200
201
202
203
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
223
224
225
226
227
228 type (
229 valueMap map[interface{}][]valueType
230 valueType struct {
231 pos syntax.Pos
232 typ Type
233 }
234 )
235
236 func (check *Checker) caseValues(x *operand, values []syntax.Expr, seen valueMap) {
237 L:
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
249 res := v
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
256 }
257
258 if val := goVal(v.val); val != nil {
259
260
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
276 func (check *Checker) isNil(e syntax.Expr) bool {
277
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
286
287
288
289
290 func (check *Checker) caseTypes(x *operand, types []syntax.Expr, seen map[Type]syntax.Expr) (T Type) {
291 var dummy operand
292 L:
293 for _, e := range types {
294
295 if check.isNil(e) {
296 T = nil
297 check.expr(nil, &dummy, e)
298 } else {
299 T = check.varType(e)
300 if !isValid(T) {
301 continue L
302 }
303 }
304
305
306 for t, other := range seen {
307 if T == nil && t == nil || T != nil && t != nil && Identical(T, t) {
308
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
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370 func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
371
372 if debug {
373 defer func(scope *Scope) {
374
375 if p := recover(); p != nil {
376 panic(p)
377 }
378 assert(scope == check.scope)
379 }(check.scope)
380 }
381
382
383 defer check.processDelayed(len(check.delayed))
384
385
386 inner := ctxt &^ (fallthroughOk | finalSwitchCase | inTypeSwitch)
387
388 switch s := s.(type) {
389 case *syntax.EmptyStmt:
390
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
401
402
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
449
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
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
494
495 results := syntax.UnpackListExpr(s.Results)
496 if len(results) == 0 && res.Len() > 0 && res.vars[0].name != "" {
497
498
499
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
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
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
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
572
573 switch s.Else.(type) {
574 case nil:
575
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
603 }
604
605
606 valid := false
607 var rhs syntax.Expr
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
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
663
664 if s, _ := s.Post.(*syntax.AssignStmt); s != nil && s.Op == syntax.Def {
665
666 check.use(s.Lhs)
667 }
668 check.stmt(inner, s.Body)
669
670 default:
671 check.error(s, InvalidSyntaxTree, "invalid statement")
672 }
673 }
674
675 func (check *Checker) switchStmt(inner stmtContext, s *syntax.SwitchStmt) {
676
677
678 var x operand
679 if s.Tag != nil {
680 check.expr(nil, &x, s.Tag)
681
682
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
690
691 x.mode = constant_
692 x.typ = Typ[Bool]
693 x.val = constant.MakeBool(true)
694
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)
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
725 func (check *Checker) typeSwitchStmt(inner stmtContext, s *syntax.SwitchStmt, guard *syntax.TypeSwitchGuard) {
726
727
728
729
730
731
732
733
734 lhs := guard.Lhs
735 if lhs != nil {
736 if lhs.Value == "_" {
737
738 check.softErrorf(lhs, NoNewVar, "no new variable on left side of :=")
739 lhs = nil
740 } else {
741 check.recordDef(lhs, nil)
742 }
743 }
744
745
746 var sx *operand
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
764 seen := make(map[Type]syntax.Expr)
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
775 cases := syntax.UnpackListExpr(clause.Cases)
776 T := check.caseTypes(sx, cases, seen)
777 check.openScopeUntil(clause, end, "case")
778
779 if lhs != nil {
780
781
782
783
784
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
793
794 scopePos := clause.Pos()
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
801
802
803 lhsVars = append(lhsVars, obj)
804 }
805 check.stmtList(inner, clause.Body)
806 check.closeScope()
807 }
808
809
810
811
812
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
820 }
821 if !used {
822 check.softErrorf(lhs, UnusedVar, "%s declared and not used", lhs.Value)
823 }
824 }
825 }
826
827 func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *syntax.RangeClause) {
828
829 type Expr = syntax.Expr
830 type identType = syntax.Name
831 identName := func(n *identType) string { return n.Value }
832 sKey := rclause.Lhs
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
840 sKey = p.ElemList[0]
841 sValue = p.ElemList[1]
842 if len(p.ElemList) > 2 {
843
844 sExtra = p.ElemList[2]
845 }
846 }
847 isDef := rclause.Def
848 rangeVar := rclause.X
849 noNewVarPos := s
850
851
852 rclause = nil
853
854
855
856
857 var x operand
858 check.expr(nil, &x, rangeVar)
859
860
861 var key, val Type
862 if x.mode != invalid {
863
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
883
884 check.openScope(s, "range")
885 defer check.closeScope()
886
887
888
889
890
891 lhs := [2]Expr{sKey, sValue}
892 rhs := [2]Type{key, val}
893
894 rangeOverInt := isInteger(x.typ)
895
896 if isDef {
897
898 var vars []*Var
899 for i, lhs := range lhs {
900 if lhs == nil {
901 continue
902 }
903
904
905 var obj *Var
906 if ident, _ := lhs.(*identType); ident != nil {
907
908 name := identName(ident)
909 obj = NewVar(ident.Pos(), check.pkg, name, nil)
910 check.recordDef(ident, obj)
911
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)
918 }
919 assert(obj.typ == nil)
920
921
922 typ := rhs[i]
923 if typ == nil || typ == Typ[Invalid] {
924
925 obj.typ = Typ[Invalid]
926 obj.used = true
927 continue
928 }
929
930 if rangeOverInt {
931 assert(i == 0)
932 check.initVar(obj, &x, "range clause")
933 } else {
934 var y operand
935 y.mode = value
936 y.expr = lhs
937 y.typ = typ
938 check.initVar(obj, &y, "assignment")
939 }
940 assert(obj.typ != nil)
941 }
942
943
944 if len(vars) > 0 {
945 scopePos := s.Body.Pos()
946 for _, obj := range vars {
947 check.declare(check.scope, nil , obj, scopePos)
948 }
949 } else {
950 check.error(noNewVarPos, NoNewVar, "no new variables on left side of :=")
951 }
952 } else if sKey != nil {
953
954 for i, lhs := range lhs {
955 if lhs == nil {
956 continue
957 }
958
959
960 typ := rhs[i]
961 if typ == nil || typ == Typ[Invalid] {
962 continue
963 }
964
965 if rangeOverInt {
966 assert(i == 0)
967 check.assignVar(lhs, nil, &x, "range clause")
968
969
970
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
978 y.typ = typ
979 check.assignVar(lhs, nil, &y, "assignment")
980 }
981 }
982 } else if rangeOverInt {
983
984
985
986
987
988
989 check.assignment(&x, nil, "range clause")
990 }
991
992 check.stmt(inner, s.Body)
993 }
994
995
996
997 func RangeKeyVal(typ Type) (Type, Type) {
998 key, val, _, _ := rangeKeyVal(typ, nil)
999 return key, val
1000 }
1001
1002
1003
1004
1005
1006
1007 func 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
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
View as plain text