1
2
3
4
5
6
7 package types2
8
9 import (
10 "cmd/compile/internal/syntax"
11 "go/constant"
12 . "internal/types/errors"
13 "slices"
14 )
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 version: check.version,
36 iota: iota,
37 sig: sig,
38 }
39 check.indent = 0
40
41 check.stmtList(0, body.List)
42
43 if check.hasLabel && !check.conf.IgnoreBranchErrors {
44 check.labels(body)
45 }
46
47 if sig.results.Len() > 0 && !check.isTerminating(body, "") {
48 check.error(body.Rbrace, MissingReturn, "missing return")
49 }
50
51
52
53 check.usage(sig.scope)
54 }
55
56 func (check *Checker) usage(scope *Scope) {
57 needUse := func(kind VarKind) bool {
58 return !(kind == RecvVar || kind == ParamVar || kind == ResultVar)
59 }
60 var unused []*Var
61 for name, elem := range scope.elems {
62 elem = resolve(name, elem)
63 if v, _ := elem.(*Var); v != nil && needUse(v.kind) && !check.usedVars[v] {
64 unused = append(unused, v)
65 }
66 }
67 slices.SortFunc(unused, func(a, b *Var) int {
68 return cmpPos(a.pos, b.pos)
69 })
70 for _, v := range unused {
71 check.softErrorf(v.pos, UnusedVar, "declared and not used: %s", v.name)
72 }
73
74 for _, scope := range scope.children {
75
76
77 if !scope.isFunc {
78 check.usage(scope)
79 }
80 }
81 }
82
83
84
85
86
87 type stmtContext uint
88
89 const (
90
91 breakOk stmtContext = 1 << iota
92 continueOk
93 fallthroughOk
94
95
96 finalSwitchCase
97 inTypeSwitch
98 )
99
100 func (check *Checker) simpleStmt(s syntax.Stmt) {
101 if s != nil {
102 check.stmt(0, s)
103 }
104 }
105
106 func trimTrailingEmptyStmts(list []syntax.Stmt) []syntax.Stmt {
107 for i := len(list); i > 0; i-- {
108 if _, ok := list[i-1].(*syntax.EmptyStmt); !ok {
109 return list[:i]
110 }
111 }
112 return nil
113 }
114
115 func (check *Checker) stmtList(ctxt stmtContext, list []syntax.Stmt) {
116 ok := ctxt&fallthroughOk != 0
117 inner := ctxt &^ fallthroughOk
118 list = trimTrailingEmptyStmts(list)
119 for i, s := range list {
120 inner := inner
121 if ok && i+1 == len(list) {
122 inner |= fallthroughOk
123 }
124 check.stmt(inner, s)
125 }
126 }
127
128 func (check *Checker) multipleSwitchDefaults(list []*syntax.CaseClause) {
129 var first *syntax.CaseClause
130 for _, c := range list {
131 if c.Cases == nil {
132 if first != nil {
133 check.errorf(c, DuplicateDefault, "multiple defaults (first at %s)", first.Pos())
134
135 } else {
136 first = c
137 }
138 }
139 }
140 }
141
142 func (check *Checker) multipleSelectDefaults(list []*syntax.CommClause) {
143 var first *syntax.CommClause
144 for _, c := range list {
145 if c.Comm == nil {
146 if first != nil {
147 check.errorf(c, DuplicateDefault, "multiple defaults (first at %s)", first.Pos())
148
149 } else {
150 first = c
151 }
152 }
153 }
154 }
155
156 func (check *Checker) openScope(node syntax.Node, comment string) {
157 scope := NewScope(check.scope, node.Pos(), syntax.EndPos(node), 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, 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) any {
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[any][]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.isValid() || !v.isValid() {
242 continue L
243 }
244 check.convertUntyped(&v, x.typ())
245 if !v.isValid() {
246 continue L
247 }
248
249 res := v
250 check.comparison(&res, x, syntax.Eql, true)
251 if !res.isValid() {
252 continue L
253 }
254 if v.mode() != constant_ {
255 continue L
256 }
257
258 if val := goVal(v.val); val != nil {
259
260
261 for _, vt := range seen[val] {
262 if Identical(v.typ(), vt.typ) {
263 err := check.newError(DuplicateCase)
264 err.addf(&v, "duplicate case %s in expression switch", &v)
265 err.addf(vt.pos, "previous case")
266 err.report()
267 continue L
268 }
269 }
270 seen[val] = append(seen[val], valueType{v.Pos(), v.typ()})
271 }
272 }
273 }
274
275
276 func (check *Checker) isNil(e syntax.Expr) bool {
277
278 if name, _ := syntax.Unparen(e).(*syntax.Name); name != nil {
279 _, ok := check.lookup(name.Value).(*Nil)
280 return ok
281 }
282 return false
283 }
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306 func (check *Checker) caseTypes(x *operand, types []syntax.Expr, seen map[Type]syntax.Expr) Type {
307 var T Type
308 var dummy operand
309 L:
310 for _, e := range types {
311
312 if check.isNil(e) {
313 T = nil
314 check.expr(nil, &dummy, e)
315 } else {
316 T = check.varType(e)
317 if !isValid(T) {
318 continue L
319 }
320 }
321
322
323 for t, other := range seen {
324 if T == nil && t == nil || T != nil && t != nil && Identical(T, t) {
325
326 Ts := "nil"
327 if T != nil {
328 Ts = TypeString(T, check.qualifier)
329 }
330 err := check.newError(DuplicateCase)
331 err.addf(e, "duplicate case %s in type switch", Ts)
332 err.addf(other, "previous case")
333 err.report()
334 continue L
335 }
336 }
337 seen[T] = e
338 if x != nil && T != nil {
339 check.typeAssertion(e, x, T, true)
340 }
341 }
342
343
344
345 if len(types) != 1 || T == nil {
346 T = Typ[Invalid]
347 if x != nil {
348 T = x.typ()
349 }
350 }
351
352 assert(T != nil)
353 return T
354 }
355
356
357
358 func (check *Checker) caseTypes_currently_unused(x *operand, xtyp *Interface, types []syntax.Expr, seen map[string]syntax.Expr) Type {
359 var T Type
360 var dummy operand
361 L:
362 for _, e := range types {
363
364 var hash string
365 if check.isNil(e) {
366 check.expr(nil, &dummy, e)
367 T = nil
368 hash = "<nil>"
369 } else {
370 T = check.varType(e)
371 if !isValid(T) {
372 continue L
373 }
374 panic("enable typeHash(T, nil)")
375
376 }
377
378 if other := seen[hash]; other != nil {
379
380 Ts := "nil"
381 if T != nil {
382 Ts = TypeString(T, check.qualifier)
383 }
384 err := check.newError(DuplicateCase)
385 err.addf(e, "duplicate case %s in type switch", Ts)
386 err.addf(other, "previous case")
387 err.report()
388 continue L
389 }
390 seen[hash] = e
391 if T != nil {
392 check.typeAssertion(e, x, T, true)
393 }
394 }
395
396
397
398 if len(types) != 1 || T == nil {
399 T = Typ[Invalid]
400 if x != nil {
401 T = x.typ()
402 }
403 }
404
405 assert(T != nil)
406 return T
407 }
408
409
410 func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
411
412 if debug {
413 defer func(scope *Scope) {
414
415 if p := recover(); p != nil {
416 panic(p)
417 }
418 assert(scope == check.scope)
419 }(check.scope)
420 }
421
422
423 defer check.processDelayed(len(check.delayed))
424
425
426 inner := ctxt &^ (fallthroughOk | finalSwitchCase | inTypeSwitch)
427
428 switch s := s.(type) {
429 case *syntax.EmptyStmt:
430
431
432 case *syntax.DeclStmt:
433 check.declStmt(s.DeclList)
434
435 case *syntax.LabeledStmt:
436 check.hasLabel = true
437 check.stmt(ctxt, s.Stmt)
438
439 case *syntax.ExprStmt:
440
441
442
443 var x operand
444 kind := check.rawExpr(nil, &x, s.X, false)
445 var msg string
446 var code Code
447 switch x.mode() {
448 default:
449 if kind == statement {
450 return
451 }
452 msg = "is not used"
453 code = UnusedExpr
454 case builtin:
455 msg = "must be called"
456 code = UncalledBuiltin
457 case typexpr:
458 msg = "is not an expression"
459 code = NotAnExpr
460 }
461 check.errorf(&x, code, "%s %s", &x, msg)
462
463 case *syntax.SendStmt:
464 var ch, val operand
465 check.expr(nil, &ch, s.Chan)
466 if ch.isValid() {
467
468
469 T := check.chanElem(s, &ch, false)
470 check.genericExpr(newTarget(T, "channel send"), &val, s.Value)
471 if T != nil {
472 check.assignment(&val, T, "send")
473 }
474 } else {
475
476 check.genericExpr(nil, &val, s.Value)
477 }
478
479 case *syntax.AssignStmt:
480 if s.Rhs == nil {
481
482
483 var x operand
484 check.expr(nil, &x, s.Lhs)
485 if !x.isValid() {
486 return
487 }
488 if !allNumeric(x.typ()) {
489 check.errorf(s.Lhs, NonNumericIncDec, invalidOp+"%s%s%s (non-numeric type %s)", s.Lhs, s.Op, s.Op, x.typ())
490 return
491 }
492 check.assignVar(s.Lhs, nil, &x, "assignment")
493 return
494 }
495
496 lhs := syntax.UnpackListExpr(s.Lhs)
497 rhs := syntax.UnpackListExpr(s.Rhs)
498 switch s.Op {
499 case 0:
500 check.assignVars(lhs, rhs)
501 return
502 case syntax.Def:
503 check.shortVarDecl(s.Pos(), lhs, rhs)
504 return
505 }
506
507
508 if len(lhs) != 1 || len(rhs) != 1 {
509 check.errorf(s, MultiValAssignOp, "assignment operation %s requires single-valued expressions", s.Op)
510 return
511 }
512
513 var x operand
514 check.binary(&x, nil, lhs[0], rhs[0], s.Op)
515 check.assignVar(lhs[0], nil, &x, "assignment")
516
517 case *syntax.CallStmt:
518 kind := "go"
519 if s.Tok == syntax.Defer {
520 kind = "defer"
521 }
522 check.suspendedCall(kind, s.Call)
523
524 case *syntax.ReturnStmt:
525 res := check.sig.results
526
527
528 results := syntax.UnpackListExpr(s.Results)
529 if len(results) == 0 && res.Len() > 0 && res.vars[0].name != "" {
530
531
532
533 for _, obj := range res.vars {
534 if alt := check.lookup(obj.name); alt != nil && alt != obj {
535 err := check.newError(OutOfScopeResult)
536 err.addf(s, "result parameter %s not in scope at return", obj.name)
537 err.addf(alt, "inner declaration of %s", obj)
538 err.report()
539
540 }
541 }
542 } else {
543 var lhs []*Var
544 if res.Len() > 0 {
545 lhs = res.vars
546 }
547 check.initVars(lhs, results, s)
548 }
549
550 case *syntax.BranchStmt:
551 if s.Label != nil {
552 check.hasLabel = true
553 break
554 }
555 if check.conf.IgnoreBranchErrors {
556 break
557 }
558 switch s.Tok {
559 case syntax.Break:
560 if ctxt&breakOk == 0 {
561 check.error(s, MisplacedBreak, "break not in for, switch, or select statement")
562 }
563 case syntax.Continue:
564 if ctxt&continueOk == 0 {
565 check.error(s, MisplacedContinue, "continue not in for statement")
566 }
567 case syntax.Fallthrough:
568 if ctxt&fallthroughOk == 0 {
569 var msg string
570 switch {
571 case ctxt&finalSwitchCase != 0:
572 msg = "cannot fallthrough final case in switch"
573 case ctxt&inTypeSwitch != 0:
574 msg = "cannot fallthrough in type switch"
575 default:
576 msg = "fallthrough statement out of place"
577 }
578 check.error(s, MisplacedFallthrough, msg)
579 }
580 case syntax.Goto:
581
582 fallthrough
583 default:
584 check.errorf(s, InvalidSyntaxTree, "branch statement: %s", s.Tok)
585 }
586
587 case *syntax.BlockStmt:
588 check.openScope(s, "block")
589 defer check.closeScope()
590
591 check.stmtList(inner, s.List)
592
593 case *syntax.IfStmt:
594 check.openScope(s, "if")
595 defer check.closeScope()
596
597 check.simpleStmt(s.Init)
598 var x operand
599 check.expr(nil, &x, s.Cond)
600 if x.isValid() && !allBoolean(x.typ()) {
601 check.error(s.Cond, InvalidCond, "non-boolean condition in if statement")
602 }
603 check.stmt(inner, s.Then)
604
605
606 switch s.Else.(type) {
607 case nil:
608
609 case *syntax.IfStmt, *syntax.BlockStmt:
610 check.stmt(inner, s.Else)
611 default:
612 check.error(s.Else, InvalidSyntaxTree, "invalid else branch in if statement")
613 }
614
615 case *syntax.SwitchStmt:
616 inner |= breakOk
617 check.openScope(s, "switch")
618 defer check.closeScope()
619
620 check.simpleStmt(s.Init)
621
622 if g, _ := s.Tag.(*syntax.TypeSwitchGuard); g != nil {
623 check.typeSwitchStmt(inner|inTypeSwitch, s, g)
624 } else {
625 check.switchStmt(inner, s)
626 }
627
628 case *syntax.SelectStmt:
629 inner |= breakOk
630
631 check.multipleSelectDefaults(s.Body)
632
633 for _, clause := range s.Body {
634 if clause == nil {
635 continue
636 }
637
638
639 valid := false
640 var rhs syntax.Expr
641 switch s := clause.Comm.(type) {
642 case nil, *syntax.SendStmt:
643 valid = true
644 case *syntax.AssignStmt:
645 if _, ok := s.Rhs.(*syntax.ListExpr); !ok {
646 rhs = s.Rhs
647 }
648 case *syntax.ExprStmt:
649 rhs = s.X
650 }
651
652
653 if rhs != nil {
654 if x, _ := syntax.Unparen(rhs).(*syntax.Operation); x != nil && x.Y == nil && x.Op == syntax.Recv {
655 valid = true
656 }
657 }
658
659 if !valid {
660 check.error(clause.Comm, InvalidSelectCase, "select case must be send or receive (possibly with assignment)")
661 continue
662 }
663 check.openScope(clause, "case")
664 if clause.Comm != nil {
665 check.stmt(inner, clause.Comm)
666 }
667 check.stmtList(inner, clause.Body)
668 check.closeScope()
669 }
670
671 case *syntax.ForStmt:
672 inner |= breakOk | continueOk
673
674 if rclause, _ := s.Init.(*syntax.RangeClause); rclause != nil {
675
676 sKey := rclause.Lhs
677 var sValue, sExtra syntax.Expr
678 if p, _ := sKey.(*syntax.ListExpr); p != nil {
679 if len(p.ElemList) < 2 {
680 check.error(s, InvalidSyntaxTree, "invalid lhs in range clause")
681 return
682 }
683
684 sKey = p.ElemList[0]
685 sValue = p.ElemList[1]
686 if len(p.ElemList) > 2 {
687
688 sExtra = p.ElemList[2]
689 }
690 }
691 check.rangeStmt(inner, s, s, sKey, sValue, sExtra, rclause.X, rclause.Def)
692 break
693 }
694
695 check.openScope(s, "for")
696 defer check.closeScope()
697
698 check.simpleStmt(s.Init)
699 if s.Cond != nil {
700 var x operand
701 check.expr(nil, &x, s.Cond)
702 if x.isValid() && !allBoolean(x.typ()) {
703 check.error(s.Cond, InvalidCond, "non-boolean condition in for statement")
704 }
705 }
706 check.simpleStmt(s.Post)
707
708
709 if s, _ := s.Post.(*syntax.AssignStmt); s != nil && s.Op == syntax.Def {
710
711 check.use(s.Lhs)
712 }
713 check.stmt(inner, s.Body)
714
715 default:
716 check.error(s, InvalidSyntaxTree, "invalid statement")
717 }
718 }
719
720 func (check *Checker) switchStmt(inner stmtContext, s *syntax.SwitchStmt) {
721
722
723 var x operand
724 if s.Tag != nil {
725 check.expr(nil, &x, s.Tag)
726
727
728 check.assignment(&x, nil, "switch expression")
729 if x.isValid() && !Comparable(x.typ()) && !hasNil(x.typ()) {
730 check.errorf(&x, InvalidExprSwitch, "cannot switch on %s (%s is not comparable)", &x, x.typ())
731 x.invalidate()
732 }
733 } else {
734
735
736 x.mode_ = constant_
737 x.typ_ = Typ[Bool]
738 x.val = constant.MakeBool(true)
739
740 pos := s.Rbrace
741 if len(s.Body) > 0 {
742 pos = s.Body[0].Pos()
743 }
744 x.expr = syntax.NewName(pos, "true")
745 }
746
747 check.multipleSwitchDefaults(s.Body)
748
749 seen := make(valueMap)
750 for i, clause := range s.Body {
751 if clause == nil {
752 check.error(clause, InvalidSyntaxTree, "incorrect expression switch case")
753 continue
754 }
755 inner := inner
756 if i+1 < len(s.Body) {
757 inner |= fallthroughOk
758 } else {
759 inner |= finalSwitchCase
760 }
761 check.caseValues(&x, syntax.UnpackListExpr(clause.Cases), seen)
762 check.openScope(clause, "case")
763 check.stmtList(inner, clause.Body)
764 check.closeScope()
765 }
766 }
767
768 func (check *Checker) typeSwitchStmt(inner stmtContext, s *syntax.SwitchStmt, guard *syntax.TypeSwitchGuard) {
769
770
771
772
773
774
775
776
777 lhs := guard.Lhs
778 if lhs != nil {
779 if lhs.Value == "_" {
780
781 check.softErrorf(lhs, NoNewVar, "no new variable on left side of :=")
782 lhs = nil
783 } else {
784 check.recordDef(lhs, nil)
785 }
786 }
787
788
789 var sx *operand
790 {
791 var x operand
792 check.expr(nil, &x, guard.X)
793 if x.isValid() {
794 if isTypeParam(x.typ()) {
795 check.errorf(&x, InvalidTypeSwitch, "cannot use type switch on type parameter value %s", &x)
796 } else if IsInterface(x.typ()) {
797 sx = &x
798 } else {
799 check.errorf(&x, InvalidTypeSwitch, "%s is not an interface", &x)
800 }
801 }
802 }
803
804 check.multipleSwitchDefaults(s.Body)
805
806 var lhsVars []*Var
807 seen := make(map[Type]syntax.Expr)
808 for _, clause := range s.Body {
809 if clause == nil {
810 check.error(s, InvalidSyntaxTree, "incorrect type switch case")
811 continue
812 }
813
814 cases := syntax.UnpackListExpr(clause.Cases)
815 T := check.caseTypes(sx, cases, seen)
816 check.openScope(clause, "case")
817
818 if lhs != nil {
819 obj := newVar(LocalVar, lhs.Pos(), check.pkg, lhs.Value, T)
820 check.declare(check.scope, nil, obj, clause.Colon)
821 check.recordImplicit(clause, obj)
822
823
824
825 lhsVars = append(lhsVars, obj)
826 }
827 check.stmtList(inner, clause.Body)
828 check.closeScope()
829 }
830
831
832
833
834
835 if lhs != nil {
836 var used bool
837 for _, v := range lhsVars {
838 if check.usedVars[v] {
839 used = true
840 }
841 check.usedVars[v] = true
842 }
843 if !used {
844 check.softErrorf(lhs, UnusedVar, "%s declared and not used", lhs.Value)
845 }
846 }
847 }
848
View as plain text