Source file
src/go/types/stmt.go
1
2
3
4
5
6
7 package types
8
9 import (
10 "go/ast"
11 "go/constant"
12 "go/token"
13 "internal/buildcfg"
14 . "internal/types/errors"
15 "sort"
16 )
17
18 func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body *ast.BlockStmt, iota constant.Value) {
19 if check.conf.IgnoreFuncBodies {
20 panic("function body not ignored")
21 }
22
23 if check.conf._Trace {
24 check.trace(body.Pos(), "-- %s: %s", name, sig)
25 }
26
27
28
29 defer func(env environment, indent int) {
30 check.environment = env
31 check.indent = indent
32 }(check.environment, check.indent)
33 check.environment = environment{
34 decl: decl,
35 scope: sig.scope,
36 iota: iota,
37 sig: sig,
38 }
39 check.indent = 0
40
41 check.stmtList(0, body.List)
42
43 if check.hasLabel {
44 check.labels(body)
45 }
46
47 if sig.results.Len() > 0 && !check.isTerminating(body, "") {
48 check.error(atPos(body.Rbrace), MissingReturn, "missing return")
49 }
50
51
52
53 check.usage(sig.scope)
54 }
55
56 func (check *Checker) usage(scope *Scope) {
57 var unused []*Var
58 for name, elem := range scope.elems {
59 elem = resolve(name, elem)
60 if v, _ := elem.(*Var); v != nil && !v.used {
61 unused = append(unused, v)
62 }
63 }
64 sort.Slice(unused, func(i, j int) bool {
65 return cmpPos(unused[i].pos, unused[j].pos) < 0
66 })
67 for _, v := range unused {
68 check.softErrorf(v, UnusedVar, "%s declared and not used", quote(v.name))
69 }
70
71 for _, scope := range scope.children {
72
73
74 if !scope.isFunc {
75 check.usage(scope)
76 }
77 }
78 }
79
80
81
82
83
84 type stmtContext uint
85
86 const (
87
88 breakOk stmtContext = 1 << iota
89 continueOk
90 fallthroughOk
91
92
93 finalSwitchCase
94 inTypeSwitch
95 )
96
97 func (check *Checker) simpleStmt(s ast.Stmt) {
98 if s != nil {
99 check.stmt(0, s)
100 }
101 }
102
103 func trimTrailingEmptyStmts(list []ast.Stmt) []ast.Stmt {
104 for i := len(list); i > 0; i-- {
105 if _, ok := list[i-1].(*ast.EmptyStmt); !ok {
106 return list[:i]
107 }
108 }
109 return nil
110 }
111
112 func (check *Checker) stmtList(ctxt stmtContext, list []ast.Stmt) {
113 ok := ctxt&fallthroughOk != 0
114 inner := ctxt &^ fallthroughOk
115 list = trimTrailingEmptyStmts(list)
116 for i, s := range list {
117 inner := inner
118 if ok && i+1 == len(list) {
119 inner |= fallthroughOk
120 }
121 check.stmt(inner, s)
122 }
123 }
124
125 func (check *Checker) multipleDefaults(list []ast.Stmt) {
126 var first ast.Stmt
127 for _, s := range list {
128 var d ast.Stmt
129 switch c := s.(type) {
130 case *ast.CaseClause:
131 if len(c.List) == 0 {
132 d = s
133 }
134 case *ast.CommClause:
135 if c.Comm == nil {
136 d = s
137 }
138 default:
139 check.error(s, InvalidSyntaxTree, "case/communication clause expected")
140 }
141 if d != nil {
142 if first != nil {
143 check.errorf(d, DuplicateDefault, "multiple defaults (first at %s)", check.fset.Position(first.Pos()))
144 } else {
145 first = d
146 }
147 }
148 }
149 }
150
151 func (check *Checker) openScope(node ast.Node, comment string) {
152 scope := NewScope(check.scope, node.Pos(), node.End(), comment)
153 check.recordScope(node, scope)
154 check.scope = scope
155 }
156
157 func (check *Checker) closeScope() {
158 check.scope = check.scope.Parent()
159 }
160
161 func assignOp(op token.Token) token.Token {
162
163 if token.ADD_ASSIGN <= op && op <= token.AND_NOT_ASSIGN {
164 return op + (token.ADD - token.ADD_ASSIGN)
165 }
166 return token.ILLEGAL
167 }
168
169 func (check *Checker) suspendedCall(keyword string, call *ast.CallExpr) {
170 var x operand
171 var msg string
172 var code Code
173 switch check.rawExpr(nil, &x, call, nil, false) {
174 case conversion:
175 msg = "requires function call, not conversion"
176 code = InvalidDefer
177 if keyword == "go" {
178 code = InvalidGo
179 }
180 case expression:
181 msg = "discards result of"
182 code = UnusedResults
183 case statement:
184 return
185 default:
186 panic("unreachable")
187 }
188 check.errorf(&x, code, "%s %s %s", keyword, msg, &x)
189 }
190
191
192 func goVal(val constant.Value) any {
193
194 if val == nil {
195 return nil
196 }
197
198
199
200
201 switch val.Kind() {
202 case constant.Int:
203 if x, ok := constant.Int64Val(val); ok {
204 return x
205 }
206 if x, ok := constant.Uint64Val(val); ok {
207 return x
208 }
209 case constant.Float:
210 if x, ok := constant.Float64Val(val); ok {
211 return x
212 }
213 case constant.String:
214 return constant.StringVal(val)
215 }
216 return nil
217 }
218
219
220
221
222
223
224
225 type (
226 valueMap map[any][]valueType
227 valueType struct {
228 pos token.Pos
229 typ Type
230 }
231 )
232
233 func (check *Checker) caseValues(x *operand, values []ast.Expr, seen valueMap) {
234 L:
235 for _, e := range values {
236 var v operand
237 check.expr(nil, &v, e)
238 if x.mode == invalid || v.mode == invalid {
239 continue L
240 }
241 check.convertUntyped(&v, x.typ)
242 if v.mode == invalid {
243 continue L
244 }
245
246 res := v
247 check.comparison(&res, x, token.EQL, true)
248 if res.mode == invalid {
249 continue L
250 }
251 if v.mode != constant_ {
252 continue L
253 }
254
255 if val := goVal(v.val); val != nil {
256
257
258 for _, vt := range seen[val] {
259 if Identical(v.typ, vt.typ) {
260 err := check.newError(DuplicateCase)
261 err.addf(&v, "duplicate case %s in expression switch", &v)
262 err.addf(atPos(vt.pos), "previous case")
263 err.report()
264 continue L
265 }
266 }
267 seen[val] = append(seen[val], valueType{v.Pos(), v.typ})
268 }
269 }
270 }
271
272
273 func (check *Checker) isNil(e ast.Expr) bool {
274
275 if name, _ := ast.Unparen(e).(*ast.Ident); name != nil {
276 _, ok := check.lookup(name.Name).(*Nil)
277 return ok
278 }
279 return false
280 }
281
282
283 func (check *Checker) caseTypes(x *operand, types []ast.Expr, seen map[Type]ast.Expr) (T Type) {
284 var dummy operand
285 L:
286 for _, e := range types {
287
288 if check.isNil(e) {
289 T = nil
290 check.expr(nil, &dummy, e)
291 } else {
292 T = check.varType(e)
293 if !isValid(T) {
294 continue L
295 }
296 }
297
298
299 for t, other := range seen {
300 if T == nil && t == nil || T != nil && t != nil && Identical(T, t) {
301
302 Ts := "nil"
303 if T != nil {
304 Ts = TypeString(T, check.qualifier)
305 }
306 err := check.newError(DuplicateCase)
307 err.addf(e, "duplicate case %s in type switch", Ts)
308 err.addf(other, "previous case")
309 err.report()
310 continue L
311 }
312 }
313 seen[T] = e
314 if x != nil && T != nil {
315 check.typeAssertion(e, x, T, true)
316 }
317 }
318 return
319 }
320
321
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 func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
364
365 if debug {
366 defer func(scope *Scope) {
367
368 if p := recover(); p != nil {
369 panic(p)
370 }
371 assert(scope == check.scope)
372 }(check.scope)
373 }
374
375
376 defer check.processDelayed(len(check.delayed))
377
378
379 inner := ctxt &^ (fallthroughOk | finalSwitchCase | inTypeSwitch)
380
381 switch s := s.(type) {
382 case *ast.BadStmt, *ast.EmptyStmt:
383
384
385 case *ast.DeclStmt:
386 check.declStmt(s.Decl)
387
388 case *ast.LabeledStmt:
389 check.hasLabel = true
390 check.stmt(ctxt, s.Stmt)
391
392 case *ast.ExprStmt:
393
394
395
396 var x operand
397 kind := check.rawExpr(nil, &x, s.X, nil, false)
398 var msg string
399 var code Code
400 switch x.mode {
401 default:
402 if kind == statement {
403 return
404 }
405 msg = "is not used"
406 code = UnusedExpr
407 case builtin:
408 msg = "must be called"
409 code = UncalledBuiltin
410 case typexpr:
411 msg = "is not an expression"
412 code = NotAnExpr
413 }
414 check.errorf(&x, code, "%s %s", &x, msg)
415
416 case *ast.SendStmt:
417 var ch, val operand
418 check.expr(nil, &ch, s.Chan)
419 check.expr(nil, &val, s.Value)
420 if ch.mode == invalid || val.mode == invalid {
421 return
422 }
423 u := coreType(ch.typ)
424 if u == nil {
425 check.errorf(inNode(s, s.Arrow), InvalidSend, invalidOp+"cannot send to %s: no core type", &ch)
426 return
427 }
428 uch, _ := u.(*Chan)
429 if uch == nil {
430 check.errorf(inNode(s, s.Arrow), InvalidSend, invalidOp+"cannot send to non-channel %s", &ch)
431 return
432 }
433 if uch.dir == RecvOnly {
434 check.errorf(inNode(s, s.Arrow), InvalidSend, invalidOp+"cannot send to receive-only channel %s", &ch)
435 return
436 }
437 check.assignment(&val, uch.elem, "send")
438
439 case *ast.IncDecStmt:
440 var op token.Token
441 switch s.Tok {
442 case token.INC:
443 op = token.ADD
444 case token.DEC:
445 op = token.SUB
446 default:
447 check.errorf(inNode(s, s.TokPos), InvalidSyntaxTree, "unknown inc/dec operation %s", s.Tok)
448 return
449 }
450
451 var x operand
452 check.expr(nil, &x, s.X)
453 if x.mode == invalid {
454 return
455 }
456 if !allNumeric(x.typ) {
457 check.errorf(s.X, NonNumericIncDec, invalidOp+"%s%s (non-numeric type %s)", s.X, s.Tok, x.typ)
458 return
459 }
460
461 Y := &ast.BasicLit{ValuePos: s.X.Pos(), Kind: token.INT, Value: "1"}
462 check.binary(&x, nil, s.X, Y, op, s.TokPos)
463 if x.mode == invalid {
464 return
465 }
466 check.assignVar(s.X, nil, &x, "assignment")
467
468 case *ast.AssignStmt:
469 switch s.Tok {
470 case token.ASSIGN, token.DEFINE:
471 if len(s.Lhs) == 0 {
472 check.error(s, InvalidSyntaxTree, "missing lhs in assignment")
473 return
474 }
475 if s.Tok == token.DEFINE {
476 check.shortVarDecl(inNode(s, s.TokPos), s.Lhs, s.Rhs)
477 } else {
478
479 check.assignVars(s.Lhs, s.Rhs)
480 }
481
482 default:
483
484 if len(s.Lhs) != 1 || len(s.Rhs) != 1 {
485 check.errorf(inNode(s, s.TokPos), MultiValAssignOp, "assignment operation %s requires single-valued expressions", s.Tok)
486 return
487 }
488 op := assignOp(s.Tok)
489 if op == token.ILLEGAL {
490 check.errorf(atPos(s.TokPos), InvalidSyntaxTree, "unknown assignment operation %s", s.Tok)
491 return
492 }
493 var x operand
494 check.binary(&x, nil, s.Lhs[0], s.Rhs[0], op, s.TokPos)
495 if x.mode == invalid {
496 return
497 }
498 check.assignVar(s.Lhs[0], nil, &x, "assignment")
499 }
500
501 case *ast.GoStmt:
502 check.suspendedCall("go", s.Call)
503
504 case *ast.DeferStmt:
505 check.suspendedCall("defer", s.Call)
506
507 case *ast.ReturnStmt:
508 res := check.sig.results
509
510
511 if len(s.Results) == 0 && res.Len() > 0 && res.vars[0].name != "" {
512
513
514
515 for _, obj := range res.vars {
516 if alt := check.lookup(obj.name); alt != nil && alt != obj {
517 err := check.newError(OutOfScopeResult)
518 err.addf(s, "result parameter %s not in scope at return", quote(obj.name))
519 err.addf(alt, "inner declaration of %s", obj)
520 err.report()
521
522 }
523 }
524 } else {
525 var lhs []*Var
526 if res.Len() > 0 {
527 lhs = res.vars
528 }
529 check.initVars(lhs, s.Results, s)
530 }
531
532 case *ast.BranchStmt:
533 if s.Label != nil {
534 check.hasLabel = true
535 return
536 }
537 switch s.Tok {
538 case token.BREAK:
539 if ctxt&breakOk == 0 {
540 check.error(s, MisplacedBreak, "break not in for, switch, or select statement")
541 }
542 case token.CONTINUE:
543 if ctxt&continueOk == 0 {
544 check.error(s, MisplacedContinue, "continue not in for statement")
545 }
546 case token.FALLTHROUGH:
547 if ctxt&fallthroughOk == 0 {
548 var msg string
549 switch {
550 case ctxt&finalSwitchCase != 0:
551 msg = "cannot fallthrough final case in switch"
552 case ctxt&inTypeSwitch != 0:
553 msg = "cannot fallthrough in type switch"
554 default:
555 msg = "fallthrough statement out of place"
556 }
557 check.error(s, MisplacedFallthrough, msg)
558 }
559 default:
560 check.errorf(s, InvalidSyntaxTree, "branch statement: %s", s.Tok)
561 }
562
563 case *ast.BlockStmt:
564 check.openScope(s, "block")
565 defer check.closeScope()
566
567 check.stmtList(inner, s.List)
568
569 case *ast.IfStmt:
570 check.openScope(s, "if")
571 defer check.closeScope()
572
573 check.simpleStmt(s.Init)
574 var x operand
575 check.expr(nil, &x, s.Cond)
576 if x.mode != invalid && !allBoolean(x.typ) {
577 check.error(s.Cond, InvalidCond, "non-boolean condition in if statement")
578 }
579 check.stmt(inner, s.Body)
580
581
582 switch s.Else.(type) {
583 case nil, *ast.BadStmt:
584
585 case *ast.IfStmt, *ast.BlockStmt:
586 check.stmt(inner, s.Else)
587 default:
588 check.error(s.Else, InvalidSyntaxTree, "invalid else branch in if statement")
589 }
590
591 case *ast.SwitchStmt:
592 inner |= breakOk
593 check.openScope(s, "switch")
594 defer check.closeScope()
595
596 check.simpleStmt(s.Init)
597 var x operand
598 if s.Tag != nil {
599 check.expr(nil, &x, s.Tag)
600
601
602 check.assignment(&x, nil, "switch expression")
603 if x.mode != invalid && !Comparable(x.typ) && !hasNil(x.typ) {
604 check.errorf(&x, InvalidExprSwitch, "cannot switch on %s (%s is not comparable)", &x, x.typ)
605 x.mode = invalid
606 }
607 } else {
608
609
610 x.mode = constant_
611 x.typ = Typ[Bool]
612 x.val = constant.MakeBool(true)
613 x.expr = &ast.Ident{NamePos: s.Body.Lbrace, Name: "true"}
614 }
615
616 check.multipleDefaults(s.Body.List)
617
618 seen := make(valueMap)
619 for i, c := range s.Body.List {
620 clause, _ := c.(*ast.CaseClause)
621 if clause == nil {
622 check.error(c, InvalidSyntaxTree, "incorrect expression switch case")
623 continue
624 }
625 check.caseValues(&x, clause.List, seen)
626 check.openScope(clause, "case")
627 inner := inner
628 if i+1 < len(s.Body.List) {
629 inner |= fallthroughOk
630 } else {
631 inner |= finalSwitchCase
632 }
633 check.stmtList(inner, clause.Body)
634 check.closeScope()
635 }
636
637 case *ast.TypeSwitchStmt:
638 inner |= breakOk | inTypeSwitch
639 check.openScope(s, "type switch")
640 defer check.closeScope()
641
642 check.simpleStmt(s.Init)
643
644
645
646
647
648
649
650
651
652 var lhs *ast.Ident
653 var rhs ast.Expr
654 switch guard := s.Assign.(type) {
655 case *ast.ExprStmt:
656 rhs = guard.X
657 case *ast.AssignStmt:
658 if len(guard.Lhs) != 1 || guard.Tok != token.DEFINE || len(guard.Rhs) != 1 {
659 check.error(s, InvalidSyntaxTree, "incorrect form of type switch guard")
660 return
661 }
662
663 lhs, _ = guard.Lhs[0].(*ast.Ident)
664 if lhs == nil {
665 check.error(s, InvalidSyntaxTree, "incorrect form of type switch guard")
666 return
667 }
668
669 if lhs.Name == "_" {
670
671 check.softErrorf(lhs, NoNewVar, "no new variable on left side of :=")
672 lhs = nil
673 } else {
674 check.recordDef(lhs, nil)
675 }
676
677 rhs = guard.Rhs[0]
678
679 default:
680 check.error(s, InvalidSyntaxTree, "incorrect form of type switch guard")
681 return
682 }
683
684
685 expr, _ := rhs.(*ast.TypeAssertExpr)
686 if expr == nil || expr.Type != nil {
687 check.error(s, InvalidSyntaxTree, "incorrect form of type switch guard")
688 return
689 }
690 var x operand
691 check.expr(nil, &x, expr.X)
692 if x.mode == invalid {
693 return
694 }
695
696 var sx *operand
697 if isTypeParam(x.typ) {
698 check.errorf(&x, InvalidTypeSwitch, "cannot use type switch on type parameter value %s", &x)
699 } else {
700 if _, ok := under(x.typ).(*Interface); ok {
701 sx = &x
702 } else {
703 check.errorf(&x, InvalidTypeSwitch, "%s is not an interface", &x)
704 }
705 }
706
707 check.multipleDefaults(s.Body.List)
708
709 var lhsVars []*Var
710 seen := make(map[Type]ast.Expr)
711 for _, s := range s.Body.List {
712 clause, _ := s.(*ast.CaseClause)
713 if clause == nil {
714 check.error(s, InvalidSyntaxTree, "incorrect type switch case")
715 continue
716 }
717
718 T := check.caseTypes(sx, clause.List, seen)
719 check.openScope(clause, "case")
720
721 if lhs != nil {
722
723
724
725
726
727 if len(clause.List) != 1 || T == nil {
728 T = x.typ
729 }
730 obj := NewVar(lhs.Pos(), check.pkg, lhs.Name, T)
731 scopePos := clause.Pos() + token.Pos(len("default"))
732 if n := len(clause.List); n > 0 {
733 scopePos = clause.List[n-1].End()
734 }
735 check.declare(check.scope, nil, obj, scopePos)
736 check.recordImplicit(clause, obj)
737
738
739
740 lhsVars = append(lhsVars, obj)
741 }
742 check.stmtList(inner, clause.Body)
743 check.closeScope()
744 }
745
746
747 if lhs != nil {
748 var used bool
749 for _, v := range lhsVars {
750 if v.used {
751 used = true
752 }
753 v.used = true
754 }
755 if !used {
756 check.softErrorf(lhs, UnusedVar, "%s declared and not used", lhs.Name)
757 }
758 }
759
760 case *ast.SelectStmt:
761 inner |= breakOk
762
763 check.multipleDefaults(s.Body.List)
764
765 for _, s := range s.Body.List {
766 clause, _ := s.(*ast.CommClause)
767 if clause == nil {
768 continue
769 }
770
771
772 valid := false
773 var rhs ast.Expr
774 switch s := clause.Comm.(type) {
775 case nil, *ast.SendStmt:
776 valid = true
777 case *ast.AssignStmt:
778 if len(s.Rhs) == 1 {
779 rhs = s.Rhs[0]
780 }
781 case *ast.ExprStmt:
782 rhs = s.X
783 }
784
785
786 if rhs != nil {
787 if x, _ := ast.Unparen(rhs).(*ast.UnaryExpr); x != nil && x.Op == token.ARROW {
788 valid = true
789 }
790 }
791
792 if !valid {
793 check.error(clause.Comm, InvalidSelectCase, "select case must be send or receive (possibly with assignment)")
794 continue
795 }
796
797 check.openScope(s, "case")
798 if clause.Comm != nil {
799 check.stmt(inner, clause.Comm)
800 }
801 check.stmtList(inner, clause.Body)
802 check.closeScope()
803 }
804
805 case *ast.ForStmt:
806 inner |= breakOk | continueOk
807 check.openScope(s, "for")
808 defer check.closeScope()
809
810 check.simpleStmt(s.Init)
811 if s.Cond != nil {
812 var x operand
813 check.expr(nil, &x, s.Cond)
814 if x.mode != invalid && !allBoolean(x.typ) {
815 check.error(s.Cond, InvalidCond, "non-boolean condition in for statement")
816 }
817 }
818 check.simpleStmt(s.Post)
819
820
821 if s, _ := s.Post.(*ast.AssignStmt); s != nil && s.Tok == token.DEFINE {
822 check.softErrorf(s, InvalidPostDecl, "cannot declare in post statement")
823
824
825
826 check.use(s.Lhs...)
827 }
828 check.stmt(inner, s.Body)
829
830 case *ast.RangeStmt:
831 inner |= breakOk | continueOk
832 check.rangeStmt(inner, s)
833
834 default:
835 check.error(s, InvalidSyntaxTree, "invalid statement")
836 }
837 }
838
839 func (check *Checker) rangeStmt(inner stmtContext, s *ast.RangeStmt) {
840
841 type Expr = ast.Expr
842 type identType = ast.Ident
843 identName := func(n *identType) string { return n.Name }
844 sKey, sValue := s.Key, s.Value
845 var sExtra ast.Expr = nil
846 isDef := s.Tok == token.DEFINE
847 rangeVar := s.X
848 noNewVarPos := inNode(s, s.TokPos)
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 constIntRange := x.mode == constant_ && 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
937 if constIntRange {
938 check.initVar(obj, &x, "range clause")
939 } else {
940 x.mode = value
941 x.expr = lhs
942 x.typ = typ
943 check.initVar(obj, &x, "assignment")
944 }
945 assert(obj.typ != nil)
946 }
947
948
949 if len(vars) > 0 {
950 scopePos := s.Body.Pos()
951 for _, obj := range vars {
952 check.declare(check.scope, nil , obj, scopePos)
953 }
954 } else {
955 check.error(noNewVarPos, NoNewVar, "no new variables on left side of :=")
956 }
957 } else if sKey != nil {
958
959 for i, lhs := range lhs {
960 if lhs == nil {
961 continue
962 }
963
964
965 typ := rhs[i]
966 if typ == nil {
967 continue
968 }
969
970 if constIntRange {
971 check.assignVar(lhs, nil, &x, "range clause")
972 } else {
973 x.mode = value
974 x.expr = lhs
975 x.typ = typ
976 check.assignVar(lhs, nil, &x, "assignment")
977 }
978 }
979 } else if constIntRange {
980
981
982
983
984
985 check.assignment(&x, nil, "range clause")
986 }
987
988 check.stmt(inner, s.Body)
989 }
990
991
992
993
994
995
996 func rangeKeyVal(typ Type, allowVersion func(goVersion) bool) (key, val Type, cause string, isFunc, ok bool) {
997 bad := func(cause string) (Type, Type, string, bool, bool) {
998 return Typ[Invalid], Typ[Invalid], cause, false, false
999 }
1000 toSig := func(t Type) *Signature {
1001 sig, _ := coreType(t).(*Signature)
1002 return sig
1003 }
1004
1005 orig := typ
1006 switch typ := arrayPtrDeref(coreType(typ)).(type) {
1007 case nil:
1008 return bad("no core type")
1009 case *Basic:
1010 if isString(typ) {
1011 return Typ[Int], universeRune, "", false, true
1012 }
1013 if isInteger(typ) {
1014 if allowVersion != nil && !allowVersion(go1_22) {
1015 return bad("requires go1.22 or later")
1016 }
1017 return orig, nil, "", false, true
1018 }
1019 case *Array:
1020 return Typ[Int], typ.elem, "", false, true
1021 case *Slice:
1022 return Typ[Int], typ.elem, "", false, true
1023 case *Map:
1024 return typ.key, typ.elem, "", false, true
1025 case *Chan:
1026 if typ.dir == SendOnly {
1027 return bad("receive from send-only channel")
1028 }
1029 return typ.elem, nil, "", false, true
1030 case *Signature:
1031 if !buildcfg.Experiment.RangeFunc && allowVersion != nil && !allowVersion(go1_23) {
1032 return bad("requires go1.23 or later")
1033 }
1034 assert(typ.Recv() == nil)
1035 switch {
1036 case typ.Params().Len() != 1:
1037 return bad("func must be func(yield func(...) bool): wrong argument count")
1038 case toSig(typ.Params().At(0).Type()) == nil:
1039 return bad("func must be func(yield func(...) bool): argument is not func")
1040 case typ.Results().Len() != 0:
1041 return bad("func must be func(yield func(...) bool): unexpected results")
1042 }
1043 cb := toSig(typ.Params().At(0).Type())
1044 assert(cb.Recv() == nil)
1045 switch {
1046 case cb.Params().Len() > 2:
1047 return bad("func must be func(yield func(...) bool): yield func has too many parameters")
1048 case cb.Results().Len() != 1 || !isBoolean(cb.Results().At(0).Type()):
1049 return bad("func must be func(yield func(...) bool): yield func does not return bool")
1050 }
1051 if cb.Params().Len() >= 1 {
1052 key = cb.Params().At(0).Type()
1053 }
1054 if cb.Params().Len() >= 2 {
1055 val = cb.Params().At(1).Type()
1056 }
1057 return key, val, "", true, true
1058 }
1059 return
1060 }
1061
View as plain text