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", quote(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 func (check *Checker) caseTypes(x *operand, types []syntax.Expr, seen map[Type]syntax.Expr) (T Type) {
287 var dummy operand
288 L:
289 for _, e := range types {
290
291 if check.isNil(e) {
292 T = nil
293 check.expr(nil, &dummy, e)
294 } else {
295 T = check.varType(e)
296 if !isValid(T) {
297 continue L
298 }
299 }
300
301
302 for t, other := range seen {
303 if T == nil && t == nil || T != nil && t != nil && Identical(T, t) {
304
305 Ts := "nil"
306 if T != nil {
307 Ts = TypeString(T, check.qualifier)
308 }
309 err := check.newError(DuplicateCase)
310 err.addf(e, "duplicate case %s in type switch", Ts)
311 err.addf(other, "previous case")
312 err.report()
313 continue L
314 }
315 }
316 seen[T] = e
317 if x != nil && T != nil {
318 check.typeAssertion(e, x, T, true)
319 }
320 }
321 return
322 }
323
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 func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
367
368 if debug {
369 defer func(scope *Scope) {
370
371 if p := recover(); p != nil {
372 panic(p)
373 }
374 assert(scope == check.scope)
375 }(check.scope)
376 }
377
378
379 defer check.processDelayed(len(check.delayed))
380
381
382 inner := ctxt &^ (fallthroughOk | finalSwitchCase | inTypeSwitch)
383
384 switch s := s.(type) {
385 case *syntax.EmptyStmt:
386
387
388 case *syntax.DeclStmt:
389 check.declStmt(s.DeclList)
390
391 case *syntax.LabeledStmt:
392 check.hasLabel = true
393 check.stmt(ctxt, s.Stmt)
394
395 case *syntax.ExprStmt:
396
397
398
399 var x operand
400 kind := check.rawExpr(nil, &x, s.X, nil, false)
401 var msg string
402 var code Code
403 switch x.mode {
404 default:
405 if kind == statement {
406 return
407 }
408 msg = "is not used"
409 code = UnusedExpr
410 case builtin:
411 msg = "must be called"
412 code = UncalledBuiltin
413 case typexpr:
414 msg = "is not an expression"
415 code = NotAnExpr
416 }
417 check.errorf(&x, code, "%s %s", &x, msg)
418
419 case *syntax.SendStmt:
420 var ch, val operand
421 check.expr(nil, &ch, s.Chan)
422 check.expr(nil, &val, s.Value)
423 if ch.mode == invalid || val.mode == invalid {
424 return
425 }
426 u := coreType(ch.typ)
427 if u == nil {
428 check.errorf(s, InvalidSend, invalidOp+"cannot send to %s: no core type", &ch)
429 return
430 }
431 uch, _ := u.(*Chan)
432 if uch == nil {
433 check.errorf(s, InvalidSend, invalidOp+"cannot send to non-channel %s", &ch)
434 return
435 }
436 if uch.dir == RecvOnly {
437 check.errorf(s, InvalidSend, invalidOp+"cannot send to receive-only channel %s", &ch)
438 return
439 }
440 check.assignment(&val, uch.elem, "send")
441
442 case *syntax.AssignStmt:
443 if s.Rhs == nil {
444
445
446 var x operand
447 check.expr(nil, &x, s.Lhs)
448 if x.mode == invalid {
449 return
450 }
451 if !allNumeric(x.typ) {
452 check.errorf(s.Lhs, NonNumericIncDec, invalidOp+"%s%s%s (non-numeric type %s)", s.Lhs, s.Op, s.Op, x.typ)
453 return
454 }
455 check.assignVar(s.Lhs, nil, &x, "assignment")
456 return
457 }
458
459 lhs := syntax.UnpackListExpr(s.Lhs)
460 rhs := syntax.UnpackListExpr(s.Rhs)
461 switch s.Op {
462 case 0:
463 check.assignVars(lhs, rhs)
464 return
465 case syntax.Def:
466 check.shortVarDecl(s.Pos(), lhs, rhs)
467 return
468 }
469
470
471 if len(lhs) != 1 || len(rhs) != 1 {
472 check.errorf(s, MultiValAssignOp, "assignment operation %s requires single-valued expressions", s.Op)
473 return
474 }
475
476 var x operand
477 check.binary(&x, nil, lhs[0], rhs[0], s.Op)
478 check.assignVar(lhs[0], nil, &x, "assignment")
479
480 case *syntax.CallStmt:
481 kind := "go"
482 if s.Tok == syntax.Defer {
483 kind = "defer"
484 }
485 check.suspendedCall(kind, s.Call)
486
487 case *syntax.ReturnStmt:
488 res := check.sig.results
489
490
491 results := syntax.UnpackListExpr(s.Results)
492 if len(results) == 0 && res.Len() > 0 && res.vars[0].name != "" {
493
494
495
496 for _, obj := range res.vars {
497 if alt := check.lookup(obj.name); alt != nil && alt != obj {
498 err := check.newError(OutOfScopeResult)
499 err.addf(s, "result parameter %s not in scope at return", quote(obj.name))
500 err.addf(alt, "inner declaration of %s", obj)
501 err.report()
502
503 }
504 }
505 } else {
506 var lhs []*Var
507 if res.Len() > 0 {
508 lhs = res.vars
509 }
510 check.initVars(lhs, results, s)
511 }
512
513 case *syntax.BranchStmt:
514 if s.Label != nil {
515 check.hasLabel = true
516 break
517 }
518 if check.conf.IgnoreBranchErrors {
519 break
520 }
521 switch s.Tok {
522 case syntax.Break:
523 if ctxt&breakOk == 0 {
524 check.error(s, MisplacedBreak, "break not in for, switch, or select statement")
525 }
526 case syntax.Continue:
527 if ctxt&continueOk == 0 {
528 check.error(s, MisplacedContinue, "continue not in for statement")
529 }
530 case syntax.Fallthrough:
531 if ctxt&fallthroughOk == 0 {
532 var msg string
533 switch {
534 case ctxt&finalSwitchCase != 0:
535 msg = "cannot fallthrough final case in switch"
536 case ctxt&inTypeSwitch != 0:
537 msg = "cannot fallthrough in type switch"
538 default:
539 msg = "fallthrough statement out of place"
540 }
541 check.error(s, MisplacedFallthrough, msg)
542 }
543 case syntax.Goto:
544
545 fallthrough
546 default:
547 check.errorf(s, InvalidSyntaxTree, "branch statement: %s", s.Tok)
548 }
549
550 case *syntax.BlockStmt:
551 check.openScope(s, "block")
552 defer check.closeScope()
553
554 check.stmtList(inner, s.List)
555
556 case *syntax.IfStmt:
557 check.openScope(s, "if")
558 defer check.closeScope()
559
560 check.simpleStmt(s.Init)
561 var x operand
562 check.expr(nil, &x, s.Cond)
563 if x.mode != invalid && !allBoolean(x.typ) {
564 check.error(s.Cond, InvalidCond, "non-boolean condition in if statement")
565 }
566 check.stmt(inner, s.Then)
567
568
569 switch s.Else.(type) {
570 case nil:
571
572 case *syntax.IfStmt, *syntax.BlockStmt:
573 check.stmt(inner, s.Else)
574 default:
575 check.error(s.Else, InvalidSyntaxTree, "invalid else branch in if statement")
576 }
577
578 case *syntax.SwitchStmt:
579 inner |= breakOk
580 check.openScope(s, "switch")
581 defer check.closeScope()
582
583 check.simpleStmt(s.Init)
584
585 if g, _ := s.Tag.(*syntax.TypeSwitchGuard); g != nil {
586 check.typeSwitchStmt(inner|inTypeSwitch, s, g)
587 } else {
588 check.switchStmt(inner, s)
589 }
590
591 case *syntax.SelectStmt:
592 inner |= breakOk
593
594 check.multipleSelectDefaults(s.Body)
595
596 for i, clause := range s.Body {
597 if clause == nil {
598 continue
599 }
600
601
602 valid := false
603 var rhs syntax.Expr
604 switch s := clause.Comm.(type) {
605 case nil, *syntax.SendStmt:
606 valid = true
607 case *syntax.AssignStmt:
608 if _, ok := s.Rhs.(*syntax.ListExpr); !ok {
609 rhs = s.Rhs
610 }
611 case *syntax.ExprStmt:
612 rhs = s.X
613 }
614
615
616 if rhs != nil {
617 if x, _ := syntax.Unparen(rhs).(*syntax.Operation); x != nil && x.Y == nil && x.Op == syntax.Recv {
618 valid = true
619 }
620 }
621
622 if !valid {
623 check.error(clause.Comm, InvalidSelectCase, "select case must be send or receive (possibly with assignment)")
624 continue
625 }
626 end := s.Rbrace
627 if i+1 < len(s.Body) {
628 end = s.Body[i+1].Pos()
629 }
630 check.openScopeUntil(clause, end, "case")
631 if clause.Comm != nil {
632 check.stmt(inner, clause.Comm)
633 }
634 check.stmtList(inner, clause.Body)
635 check.closeScope()
636 }
637
638 case *syntax.ForStmt:
639 inner |= breakOk | continueOk
640
641 if rclause, _ := s.Init.(*syntax.RangeClause); rclause != nil {
642 check.rangeStmt(inner, s, rclause)
643 break
644 }
645
646 check.openScope(s, "for")
647 defer check.closeScope()
648
649 check.simpleStmt(s.Init)
650 if s.Cond != nil {
651 var x operand
652 check.expr(nil, &x, s.Cond)
653 if x.mode != invalid && !allBoolean(x.typ) {
654 check.error(s.Cond, InvalidCond, "non-boolean condition in for statement")
655 }
656 }
657 check.simpleStmt(s.Post)
658
659
660 if s, _ := s.Post.(*syntax.AssignStmt); s != nil && s.Op == syntax.Def {
661
662 check.use(s.Lhs)
663 }
664 check.stmt(inner, s.Body)
665
666 default:
667 check.error(s, InvalidSyntaxTree, "invalid statement")
668 }
669 }
670
671 func (check *Checker) switchStmt(inner stmtContext, s *syntax.SwitchStmt) {
672
673
674 var x operand
675 if s.Tag != nil {
676 check.expr(nil, &x, s.Tag)
677
678
679 check.assignment(&x, nil, "switch expression")
680 if x.mode != invalid && !Comparable(x.typ) && !hasNil(x.typ) {
681 check.errorf(&x, InvalidExprSwitch, "cannot switch on %s (%s is not comparable)", &x, x.typ)
682 x.mode = invalid
683 }
684 } else {
685
686
687 x.mode = constant_
688 x.typ = Typ[Bool]
689 x.val = constant.MakeBool(true)
690
691 pos := s.Rbrace
692 if len(s.Body) > 0 {
693 pos = s.Body[0].Pos()
694 }
695 x.expr = syntax.NewName(pos, "true")
696 }
697
698 check.multipleSwitchDefaults(s.Body)
699
700 seen := make(valueMap)
701 for i, clause := range s.Body {
702 if clause == nil {
703 check.error(clause, InvalidSyntaxTree, "incorrect expression switch case")
704 continue
705 }
706 end := s.Rbrace
707 inner := inner
708 if i+1 < len(s.Body) {
709 end = s.Body[i+1].Pos()
710 inner |= fallthroughOk
711 } else {
712 inner |= finalSwitchCase
713 }
714 check.caseValues(&x, syntax.UnpackListExpr(clause.Cases), seen)
715 check.openScopeUntil(clause, end, "case")
716 check.stmtList(inner, clause.Body)
717 check.closeScope()
718 }
719 }
720
721 func (check *Checker) typeSwitchStmt(inner stmtContext, s *syntax.SwitchStmt, guard *syntax.TypeSwitchGuard) {
722
723
724
725
726
727
728
729
730 lhs := guard.Lhs
731 if lhs != nil {
732 if lhs.Value == "_" {
733
734 check.softErrorf(lhs, NoNewVar, "no new variable on left side of :=")
735 lhs = nil
736 } else {
737 check.recordDef(lhs, nil)
738 }
739 }
740
741
742 var x operand
743 check.expr(nil, &x, guard.X)
744 if x.mode == invalid {
745 return
746 }
747
748
749 var sx *operand
750 if isTypeParam(x.typ) {
751 check.errorf(&x, InvalidTypeSwitch, "cannot use type switch on type parameter value %s", &x)
752 } else {
753 if _, ok := under(x.typ).(*Interface); ok {
754 sx = &x
755 } else {
756 check.errorf(&x, InvalidTypeSwitch, "%s is not an interface", &x)
757 }
758 }
759
760 check.multipleSwitchDefaults(s.Body)
761
762 var lhsVars []*Var
763 seen := make(map[Type]syntax.Expr)
764 for i, clause := range s.Body {
765 if clause == nil {
766 check.error(s, InvalidSyntaxTree, "incorrect type switch case")
767 continue
768 }
769 end := s.Rbrace
770 if i+1 < len(s.Body) {
771 end = s.Body[i+1].Pos()
772 }
773
774 cases := syntax.UnpackListExpr(clause.Cases)
775 T := check.caseTypes(sx, cases, seen)
776 check.openScopeUntil(clause, end, "case")
777
778 if lhs != nil {
779
780
781
782
783
784 if len(cases) != 1 || T == nil {
785 T = x.typ
786 }
787 obj := NewVar(lhs.Pos(), check.pkg, lhs.Value, T)
788
789
790 scopePos := clause.Pos()
791 if n := len(cases); n > 0 {
792 scopePos = syntax.EndPos(cases[n-1])
793 }
794 check.declare(check.scope, nil, obj, scopePos)
795 check.recordImplicit(clause, obj)
796
797
798
799 lhsVars = append(lhsVars, obj)
800 }
801 check.stmtList(inner, clause.Body)
802 check.closeScope()
803 }
804
805
806
807
808
809 if lhs != nil {
810 var used bool
811 for _, v := range lhsVars {
812 if v.used {
813 used = true
814 }
815 v.used = true
816 }
817 if !used {
818 check.softErrorf(lhs, UnusedVar, "%s declared and not used", lhs.Value)
819 }
820 }
821 }
822
823 func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *syntax.RangeClause) {
824
825 type Expr = syntax.Expr
826 type identType = syntax.Name
827 identName := func(n *identType) string { return n.Value }
828 sKey := rclause.Lhs
829 var sValue, sExtra syntax.Expr
830 if p, _ := sKey.(*syntax.ListExpr); p != nil {
831 if len(p.ElemList) < 2 {
832 check.error(s, InvalidSyntaxTree, "invalid lhs in range clause")
833 return
834 }
835
836 sKey = p.ElemList[0]
837 sValue = p.ElemList[1]
838 if len(p.ElemList) > 2 {
839
840 sExtra = p.ElemList[2]
841 }
842 }
843 isDef := rclause.Def
844 rangeVar := rclause.X
845 noNewVarPos := s
846
847
848 rclause = nil
849
850
851
852
853 var x operand
854 check.expr(nil, &x, rangeVar)
855
856
857 var key, val Type
858 if x.mode != invalid {
859
860 k, v, cause, isFunc, ok := rangeKeyVal(x.typ, func(v goVersion) bool {
861 return check.allowVersion(x.expr, v)
862 })
863 switch {
864 case !ok && cause != "":
865 check.softErrorf(&x, InvalidRangeExpr, "cannot range over %s: %s", &x, cause)
866 case !ok:
867 check.softErrorf(&x, InvalidRangeExpr, "cannot range over %s", &x)
868 case k == nil && sKey != nil:
869 check.softErrorf(sKey, InvalidIterVar, "range over %s permits no iteration variables", &x)
870 case v == nil && sValue != nil:
871 check.softErrorf(sValue, InvalidIterVar, "range over %s permits only one iteration variable", &x)
872 case sExtra != nil:
873 check.softErrorf(sExtra, InvalidIterVar, "range clause permits at most two iteration variables")
874 case isFunc && ((k == nil) != (sKey == nil) || (v == nil) != (sValue == nil)):
875 var count string
876 switch {
877 case k == nil:
878 count = "no iteration variables"
879 case v == nil:
880 count = "one iteration variable"
881 default:
882 count = "two iteration variables"
883 }
884 check.softErrorf(&x, InvalidIterVar, "range over %s must have %s", &x, count)
885 }
886 key, val = k, v
887 }
888
889
890
891 check.openScope(s, "range")
892 defer check.closeScope()
893
894
895
896
897
898 lhs := [2]Expr{sKey, sValue}
899 rhs := [2]Type{key, val}
900
901 rangeOverInt := isInteger(x.typ)
902
903 if isDef {
904
905 var vars []*Var
906 for i, lhs := range lhs {
907 if lhs == nil {
908 continue
909 }
910
911
912 var obj *Var
913 if ident, _ := lhs.(*identType); ident != nil {
914
915 name := identName(ident)
916 obj = NewVar(ident.Pos(), check.pkg, name, nil)
917 check.recordDef(ident, obj)
918
919 if name != "_" {
920 vars = append(vars, obj)
921 }
922 } else {
923 check.errorf(lhs, InvalidSyntaxTree, "cannot declare %s", lhs)
924 obj = NewVar(lhs.Pos(), check.pkg, "_", nil)
925 }
926 assert(obj.typ == nil)
927
928
929 typ := rhs[i]
930 if typ == nil {
931 obj.typ = Typ[Invalid]
932 obj.used = true
933 continue
934 }
935
936 if rangeOverInt {
937 assert(i == 0)
938 check.initVar(obj, &x, "range clause")
939 } else {
940 var y operand
941 y.mode = value
942 y.expr = lhs
943 y.typ = typ
944 check.initVar(obj, &y, "assignment")
945 }
946 assert(obj.typ != nil)
947 }
948
949
950 if len(vars) > 0 {
951 scopePos := s.Body.Pos()
952 for _, obj := range vars {
953 check.declare(check.scope, nil , obj, scopePos)
954 }
955 } else {
956 check.error(noNewVarPos, NoNewVar, "no new variables on left side of :=")
957 }
958 } else if sKey != nil {
959
960 for i, lhs := range lhs {
961 if lhs == nil {
962 continue
963 }
964
965
966 typ := rhs[i]
967 if typ == nil {
968 continue
969 }
970
971 if rangeOverInt {
972 assert(i == 0)
973 check.assignVar(lhs, nil, &x, "range clause")
974
975
976
977 if x.mode != invalid && !isInteger(x.typ) {
978 check.softErrorf(lhs, InvalidRangeExpr, "cannot use iteration variable of type %s", x.typ)
979 }
980 } else {
981 var y operand
982 y.mode = value
983 y.expr = lhs
984 y.typ = typ
985 check.assignVar(lhs, nil, &y, "assignment")
986 }
987 }
988 } else if rangeOverInt {
989
990
991
992
993
994
995 check.assignment(&x, nil, "range clause")
996 }
997
998 check.stmt(inner, s.Body)
999 }
1000
1001
1002
1003 func RangeKeyVal(typ Type) (Type, Type) {
1004 key, val, _, _, _ := rangeKeyVal(typ, nil)
1005 return key, val
1006 }
1007
1008
1009
1010
1011
1012
1013 func rangeKeyVal(typ Type, allowVersion func(goVersion) bool) (key, val Type, cause string, isFunc, ok bool) {
1014 bad := func(cause string) (Type, Type, string, bool, bool) {
1015 return Typ[Invalid], Typ[Invalid], cause, false, false
1016 }
1017 toSig := func(t Type) *Signature {
1018 sig, _ := coreType(t).(*Signature)
1019 return sig
1020 }
1021
1022 orig := typ
1023 switch typ := arrayPtrDeref(coreType(typ)).(type) {
1024 case nil:
1025 return bad("no core type")
1026 case *Basic:
1027 if isString(typ) {
1028 return Typ[Int], universeRune, "", false, true
1029 }
1030 if isInteger(typ) {
1031 if allowVersion != nil && !allowVersion(go1_22) {
1032 return bad("requires go1.22 or later")
1033 }
1034 return orig, nil, "", false, true
1035 }
1036 case *Array:
1037 return Typ[Int], typ.elem, "", false, true
1038 case *Slice:
1039 return Typ[Int], typ.elem, "", false, true
1040 case *Map:
1041 return typ.key, typ.elem, "", false, true
1042 case *Chan:
1043 if typ.dir == SendOnly {
1044 return bad("receive from send-only channel")
1045 }
1046 return typ.elem, nil, "", false, true
1047 case *Signature:
1048 if !buildcfg.Experiment.RangeFunc && allowVersion != nil && !allowVersion(go1_23) {
1049 return bad("requires go1.23 or later")
1050 }
1051 assert(typ.Recv() == nil)
1052 switch {
1053 case typ.Params().Len() != 1:
1054 return bad("func must be func(yield func(...) bool): wrong argument count")
1055 case toSig(typ.Params().At(0).Type()) == nil:
1056 return bad("func must be func(yield func(...) bool): argument is not func")
1057 case typ.Results().Len() != 0:
1058 return bad("func must be func(yield func(...) bool): unexpected results")
1059 }
1060 cb := toSig(typ.Params().At(0).Type())
1061 assert(cb.Recv() == nil)
1062 switch {
1063 case cb.Params().Len() > 2:
1064 return bad("func must be func(yield func(...) bool): yield func has too many parameters")
1065 case cb.Results().Len() != 1 || !isBoolean(cb.Results().At(0).Type()):
1066 return bad("func must be func(yield func(...) bool): yield func does not return bool")
1067 }
1068 if cb.Params().Len() >= 1 {
1069 key = cb.Params().At(0).Type()
1070 }
1071 if cb.Params().Len() >= 2 {
1072 val = cb.Params().At(1).Type()
1073 }
1074 return key, val, "", true, true
1075 }
1076 return
1077 }
1078
View as plain text