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 rangeOverInt := 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 assert(obj.typ == nil)
931
932
933 typ := rhs[i]
934 if typ == nil {
935 obj.typ = Typ[Invalid]
936 obj.used = true
937 continue
938 }
939
940 if rangeOverInt {
941 assert(i == 0)
942 check.initVar(obj, &x, "range clause")
943 } else {
944 var y operand
945 y.mode = value
946 y.expr = lhs
947 y.typ = typ
948 check.initVar(obj, &y, "assignment")
949 }
950 assert(obj.typ != nil)
951 }
952
953
954 if len(vars) > 0 {
955 scopePos := s.Body.Pos()
956 for _, obj := range vars {
957 check.declare(check.scope, nil , obj, scopePos)
958 }
959 } else {
960 check.error(noNewVarPos, NoNewVar, "no new variables on left side of :=")
961 }
962 } else if sKey != nil {
963
964 for i, lhs := range lhs {
965 if lhs == nil {
966 continue
967 }
968
969
970 typ := rhs[i]
971 if typ == nil {
972 continue
973 }
974
975 if rangeOverInt {
976 assert(i == 0)
977 check.assignVar(lhs, nil, &x, "range clause")
978
979
980
981 if x.mode != invalid && !isInteger(x.typ) {
982 check.softErrorf(lhs, InvalidRangeExpr, "cannot use iteration variable of type %s", x.typ)
983 }
984 } else {
985 var y operand
986 y.mode = value
987 y.expr = lhs
988 y.typ = typ
989 check.assignVar(lhs, nil, &y, "assignment")
990 }
991 }
992 } else if rangeOverInt {
993
994
995
996
997
998
999 check.assignment(&x, nil, "range clause")
1000 }
1001
1002 check.stmt(inner, s.Body)
1003 }
1004
1005
1006
1007 func RangeKeyVal(typ Type) (Type, Type) {
1008 key, val, _, _, _ := rangeKeyVal(typ, nil)
1009 return key, val
1010 }
1011
1012
1013
1014
1015
1016
1017 func rangeKeyVal(typ Type, allowVersion func(goVersion) bool) (key, val Type, cause string, isFunc, ok bool) {
1018 bad := func(cause string) (Type, Type, string, bool, bool) {
1019 return Typ[Invalid], Typ[Invalid], cause, false, false
1020 }
1021 toSig := func(t Type) *Signature {
1022 sig, _ := coreType(t).(*Signature)
1023 return sig
1024 }
1025
1026 orig := typ
1027 switch typ := arrayPtrDeref(coreType(typ)).(type) {
1028 case nil:
1029 return bad("no core type")
1030 case *Basic:
1031 if isString(typ) {
1032 return Typ[Int], universeRune, "", false, true
1033 }
1034 if isInteger(typ) {
1035 if allowVersion != nil && !allowVersion(go1_22) {
1036 return bad("requires go1.22 or later")
1037 }
1038 return orig, nil, "", false, true
1039 }
1040 case *Array:
1041 return Typ[Int], typ.elem, "", false, true
1042 case *Slice:
1043 return Typ[Int], typ.elem, "", false, true
1044 case *Map:
1045 return typ.key, typ.elem, "", false, true
1046 case *Chan:
1047 if typ.dir == SendOnly {
1048 return bad("receive from send-only channel")
1049 }
1050 return typ.elem, nil, "", false, true
1051 case *Signature:
1052
1053 if !buildcfg.Experiment.RangeFunc {
1054 break
1055 }
1056 assert(typ.Recv() == nil)
1057 switch {
1058 case typ.Params().Len() != 1:
1059 return bad("func must be func(yield func(...) bool): wrong argument count")
1060 case toSig(typ.Params().At(0).Type()) == nil:
1061 return bad("func must be func(yield func(...) bool): argument is not func")
1062 case typ.Results().Len() != 0:
1063 return bad("func must be func(yield func(...) bool): unexpected results")
1064 }
1065 cb := toSig(typ.Params().At(0).Type())
1066 assert(cb.Recv() == nil)
1067 switch {
1068 case cb.Params().Len() > 2:
1069 return bad("func must be func(yield func(...) bool): yield func has too many parameters")
1070 case cb.Results().Len() != 1 || !isBoolean(cb.Results().At(0).Type()):
1071 return bad("func must be func(yield func(...) bool): yield func does not return bool")
1072 }
1073 if cb.Params().Len() >= 1 {
1074 key = cb.Params().At(0).Type()
1075 }
1076 if cb.Params().Len() >= 2 {
1077 val = cb.Params().At(1).Type()
1078 }
1079 return key, val, "", true, true
1080 }
1081 return
1082 }
1083
View as plain text