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, "%s declared and not used", 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 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 var err error_
264 err.code = DuplicateCase
265 err.errorf(&v, "duplicate case %s in expression switch", &v)
266 err.errorf(vt.pos, "previous case")
267 check.report(&err)
268 continue L
269 }
270 }
271 seen[val] = append(seen[val], valueType{v.Pos(), v.typ})
272 }
273 }
274 }
275
276
277 func (check *Checker) isNil(e syntax.Expr) bool {
278
279 if name, _ := syntax.Unparen(e).(*syntax.Name); name != nil {
280 _, ok := check.lookup(name.Value).(*Nil)
281 return ok
282 }
283 return false
284 }
285
286
287 func (check *Checker) caseTypes(x *operand, types []syntax.Expr, seen map[Type]syntax.Expr) (T Type) {
288 var dummy operand
289 L:
290 for _, e := range types {
291
292 if check.isNil(e) {
293 T = nil
294 check.expr(nil, &dummy, e)
295 } else {
296 T = check.varType(e)
297 if !isValid(T) {
298 continue L
299 }
300 }
301
302
303 for t, other := range seen {
304 if T == nil && t == nil || T != nil && t != nil && Identical(T, t) {
305
306 Ts := "nil"
307 if T != nil {
308 Ts = TypeString(T, check.qualifier)
309 }
310 var err error_
311 err.code = DuplicateCase
312 err.errorf(e, "duplicate case %s in type switch", Ts)
313 err.errorf(other, "previous case")
314 check.report(&err)
315 continue L
316 }
317 }
318 seen[T] = e
319 if x != nil && T != nil {
320 check.typeAssertion(e, x, T, true)
321 }
322 }
323 return
324 }
325
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 func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
370
371 if debug {
372 defer func(scope *Scope) {
373
374 if p := recover(); p != nil {
375 panic(p)
376 }
377 assert(scope == check.scope)
378 }(check.scope)
379 }
380
381
382 defer check.processDelayed(len(check.delayed))
383
384
385 inner := ctxt &^ (fallthroughOk | finalSwitchCase | inTypeSwitch)
386
387 switch s := s.(type) {
388 case *syntax.EmptyStmt:
389
390
391 case *syntax.DeclStmt:
392 check.declStmt(s.DeclList)
393
394 case *syntax.LabeledStmt:
395 check.hasLabel = true
396 check.stmt(ctxt, s.Stmt)
397
398 case *syntax.ExprStmt:
399
400
401
402 var x operand
403 kind := check.rawExpr(nil, &x, s.X, nil, false)
404 var msg string
405 var code Code
406 switch x.mode {
407 default:
408 if kind == statement {
409 return
410 }
411 msg = "is not used"
412 code = UnusedExpr
413 case builtin:
414 msg = "must be called"
415 code = UncalledBuiltin
416 case typexpr:
417 msg = "is not an expression"
418 code = NotAnExpr
419 }
420 check.errorf(&x, code, "%s %s", &x, msg)
421
422 case *syntax.SendStmt:
423 var ch, val operand
424 check.expr(nil, &ch, s.Chan)
425 check.expr(nil, &val, s.Value)
426 if ch.mode == invalid || val.mode == invalid {
427 return
428 }
429 u := coreType(ch.typ)
430 if u == nil {
431 check.errorf(s, InvalidSend, invalidOp+"cannot send to %s: no core type", &ch)
432 return
433 }
434 uch, _ := u.(*Chan)
435 if uch == nil {
436 check.errorf(s, InvalidSend, invalidOp+"cannot send to non-channel %s", &ch)
437 return
438 }
439 if uch.dir == RecvOnly {
440 check.errorf(s, InvalidSend, invalidOp+"cannot send to receive-only channel %s", &ch)
441 return
442 }
443 check.assignment(&val, uch.elem, "send")
444
445 case *syntax.AssignStmt:
446 if s.Rhs == nil {
447
448
449 var x operand
450 check.expr(nil, &x, s.Lhs)
451 if x.mode == invalid {
452 return
453 }
454 if !allNumeric(x.typ) {
455 check.errorf(s.Lhs, NonNumericIncDec, invalidOp+"%s%s%s (non-numeric type %s)", s.Lhs, s.Op, s.Op, x.typ)
456 return
457 }
458 check.assignVar(s.Lhs, nil, &x, "assignment")
459 return
460 }
461
462 lhs := syntax.UnpackListExpr(s.Lhs)
463 rhs := syntax.UnpackListExpr(s.Rhs)
464 switch s.Op {
465 case 0:
466 check.assignVars(lhs, rhs)
467 return
468 case syntax.Def:
469 check.shortVarDecl(s.Pos(), lhs, rhs)
470 return
471 }
472
473
474 if len(lhs) != 1 || len(rhs) != 1 {
475 check.errorf(s, MultiValAssignOp, "assignment operation %s requires single-valued expressions", s.Op)
476 return
477 }
478
479 var x operand
480 check.binary(&x, nil, lhs[0], rhs[0], s.Op)
481 check.assignVar(lhs[0], nil, &x, "assignment")
482
483 case *syntax.CallStmt:
484 kind := "go"
485 if s.Tok == syntax.Defer {
486 kind = "defer"
487 }
488 check.suspendedCall(kind, s.Call)
489
490 case *syntax.ReturnStmt:
491 res := check.sig.results
492
493
494 results := syntax.UnpackListExpr(s.Results)
495 if len(results) == 0 && res.Len() > 0 && res.vars[0].name != "" {
496
497
498
499 for _, obj := range res.vars {
500 if alt := check.lookup(obj.name); alt != nil && alt != obj {
501 var err error_
502 err.code = OutOfScopeResult
503 err.errorf(s, "result parameter %s not in scope at return", obj.name)
504 err.errorf(alt, "inner declaration of %s", obj)
505 check.report(&err)
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 x operand
747 check.expr(nil, &x, guard.X)
748 if x.mode == invalid {
749 return
750 }
751
752
753 var sx *operand
754 if isTypeParam(x.typ) {
755 check.errorf(&x, InvalidTypeSwitch, "cannot use type switch on type parameter value %s", &x)
756 } else {
757 if _, ok := under(x.typ).(*Interface); ok {
758 sx = &x
759 } else {
760 check.errorf(&x, InvalidTypeSwitch, "%s is not an interface", &x)
761 }
762 }
763
764 check.multipleSwitchDefaults(s.Body)
765
766 var lhsVars []*Var
767 seen := make(map[Type]syntax.Expr)
768 for i, clause := range s.Body {
769 if clause == nil {
770 check.error(s, InvalidSyntaxTree, "incorrect type switch case")
771 continue
772 }
773 end := s.Rbrace
774 if i+1 < len(s.Body) {
775 end = s.Body[i+1].Pos()
776 }
777
778 cases := syntax.UnpackListExpr(clause.Cases)
779 T := check.caseTypes(sx, cases, seen)
780 check.openScopeUntil(clause, end, "case")
781
782 if lhs != nil {
783
784
785
786
787
788 if len(cases) != 1 || T == nil {
789 T = x.typ
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, isFunc, ok := rangeKeyVal(x.typ, func(v goVersion) bool {
865 return check.allowVersion(check.pkg, 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 case isFunc && ((k == nil) != (sKey == nil) || (v == nil) != (sValue == nil)):
879 var count string
880 switch {
881 case k == nil:
882 count = "no iteration variables"
883 case v == nil:
884 count = "one iteration variable"
885 default:
886 count = "two iteration variables"
887 }
888 check.softErrorf(&x, InvalidIterVar, "range over %s must have %s", &x, count)
889 }
890 key, val = k, v
891 }
892
893
894
895 check.openScope(s, "range")
896 defer check.closeScope()
897
898
899
900
901
902 lhs := [2]Expr{sKey, sValue}
903 rhs := [2]Type{key, val}
904
905 constIntRange := x.mode == constant_ && isInteger(x.typ)
906
907 if isDef {
908
909 var vars []*Var
910 for i, lhs := range lhs {
911 if lhs == nil {
912 continue
913 }
914
915
916 var obj *Var
917 if ident, _ := lhs.(*identType); ident != nil {
918
919 name := identName(ident)
920 obj = NewVar(ident.Pos(), check.pkg, name, nil)
921 check.recordDef(ident, obj)
922
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)
929 }
930
931
932 if constIntRange {
933 check.initVar(obj, &x, "range clause")
934 } else if typ := rhs[i]; typ != nil {
935 x.mode = value
936 x.expr = lhs
937 x.typ = typ
938 check.initVar(obj, &x, "assignment")
939 } else {
940 obj.typ = Typ[Invalid]
941 obj.used = true
942 }
943 }
944
945
946 if len(vars) > 0 {
947 scopePos := s.Body.Pos()
948 for _, obj := range vars {
949 check.declare(check.scope, nil , obj, scopePos)
950 }
951 } else {
952 check.error(noNewVarPos, NoNewVar, "no new variables on left side of :=")
953 }
954 } else if sKey != nil {
955
956 for i, lhs := range lhs {
957 if lhs == nil {
958 continue
959 }
960
961 if constIntRange {
962 check.assignVar(lhs, nil, &x, "range clause")
963 } else if typ := rhs[i]; typ != nil {
964 x.mode = value
965 x.expr = lhs
966 x.typ = typ
967 check.assignVar(lhs, nil, &x, "assignment")
968 }
969 }
970 } else if constIntRange {
971
972
973
974
975
976 check.assignment(&x, nil, "range clause")
977 }
978
979 check.stmt(inner, s.Body)
980 }
981
982
983
984 func RangeKeyVal(typ Type) (Type, Type) {
985 key, val, _, _, _ := rangeKeyVal(typ, nil)
986 return key, val
987 }
988
989
990
991
992
993
994 func rangeKeyVal(typ Type, allowVersion func(goVersion) bool) (key, val Type, cause string, isFunc, ok bool) {
995 bad := func(cause string) (Type, Type, string, bool, bool) {
996 return Typ[Invalid], Typ[Invalid], cause, false, false
997 }
998 toSig := func(t Type) *Signature {
999 sig, _ := coreType(t).(*Signature)
1000 return sig
1001 }
1002
1003 orig := typ
1004 switch typ := arrayPtrDeref(coreType(typ)).(type) {
1005 case nil:
1006 return bad("no core type")
1007 case *Basic:
1008 if isString(typ) {
1009 return Typ[Int], universeRune, "", false, true
1010 }
1011 if isInteger(typ) {
1012 if allowVersion != nil && !allowVersion(go1_22) {
1013 return bad("requires go1.22 or later")
1014 }
1015 return orig, nil, "", false, true
1016 }
1017 case *Array:
1018 return Typ[Int], typ.elem, "", false, true
1019 case *Slice:
1020 return Typ[Int], typ.elem, "", false, true
1021 case *Map:
1022 return typ.key, typ.elem, "", false, true
1023 case *Chan:
1024 if typ.dir == SendOnly {
1025 return bad("receive from send-only channel")
1026 }
1027 return typ.elem, nil, "", false, true
1028 case *Signature:
1029
1030 if !buildcfg.Experiment.RangeFunc {
1031 break
1032 }
1033 assert(typ.Recv() == nil)
1034 switch {
1035 case typ.Params().Len() != 1:
1036 return bad("func must be func(yield func(...) bool): wrong argument count")
1037 case toSig(typ.Params().At(0).Type()) == nil:
1038 return bad("func must be func(yield func(...) bool): argument is not func")
1039 case typ.Results().Len() != 0:
1040 return bad("func must be func(yield func(...) bool): unexpected results")
1041 }
1042 cb := toSig(typ.Params().At(0).Type())
1043 assert(cb.Recv() == nil)
1044 switch {
1045 case cb.Params().Len() > 2:
1046 return bad("func must be func(yield func(...) bool): yield func has too many parameters")
1047 case cb.Results().Len() != 1 || !isBoolean(cb.Results().At(0).Type()):
1048 return bad("func must be func(yield func(...) bool): yield func does not return bool")
1049 }
1050 if cb.Params().Len() >= 1 {
1051 key = cb.Params().At(0).Type()
1052 }
1053 if cb.Params().Len() >= 2 {
1054 val = cb.Params().At(1).Type()
1055 }
1056 return key, val, "", true, true
1057 }
1058 return
1059 }
1060
View as plain text