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, 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
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, nil, 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 check.expr(nil, &val, s.Value)
467 if ch.mode == invalid || val.mode == invalid {
468 return
469 }
470 if elem := check.chanElem(s, &ch, false); elem != nil {
471 check.assignment(&val, elem, "send")
472 }
473
474 case *syntax.AssignStmt:
475 if s.Rhs == nil {
476
477
478 var x operand
479 check.expr(nil, &x, s.Lhs)
480 if x.mode == invalid {
481 return
482 }
483 if !allNumeric(x.typ) {
484 check.errorf(s.Lhs, NonNumericIncDec, invalidOp+"%s%s%s (non-numeric type %s)", s.Lhs, s.Op, s.Op, x.typ)
485 return
486 }
487 check.assignVar(s.Lhs, nil, &x, "assignment")
488 return
489 }
490
491 lhs := syntax.UnpackListExpr(s.Lhs)
492 rhs := syntax.UnpackListExpr(s.Rhs)
493 switch s.Op {
494 case 0:
495 check.assignVars(lhs, rhs)
496 return
497 case syntax.Def:
498 check.shortVarDecl(s.Pos(), lhs, rhs)
499 return
500 }
501
502
503 if len(lhs) != 1 || len(rhs) != 1 {
504 check.errorf(s, MultiValAssignOp, "assignment operation %s requires single-valued expressions", s.Op)
505 return
506 }
507
508 var x operand
509 check.binary(&x, nil, lhs[0], rhs[0], s.Op)
510 check.assignVar(lhs[0], nil, &x, "assignment")
511
512 case *syntax.CallStmt:
513 kind := "go"
514 if s.Tok == syntax.Defer {
515 kind = "defer"
516 }
517 check.suspendedCall(kind, s.Call)
518
519 case *syntax.ReturnStmt:
520 res := check.sig.results
521
522
523 results := syntax.UnpackListExpr(s.Results)
524 if len(results) == 0 && res.Len() > 0 && res.vars[0].name != "" {
525
526
527
528 for _, obj := range res.vars {
529 if alt := check.lookup(obj.name); alt != nil && alt != obj {
530 err := check.newError(OutOfScopeResult)
531 err.addf(s, "result parameter %s not in scope at return", obj.name)
532 err.addf(alt, "inner declaration of %s", obj)
533 err.report()
534
535 }
536 }
537 } else {
538 var lhs []*Var
539 if res.Len() > 0 {
540 lhs = res.vars
541 }
542 check.initVars(lhs, results, s)
543 }
544
545 case *syntax.BranchStmt:
546 if s.Label != nil {
547 check.hasLabel = true
548 break
549 }
550 if check.conf.IgnoreBranchErrors {
551 break
552 }
553 switch s.Tok {
554 case syntax.Break:
555 if ctxt&breakOk == 0 {
556 check.error(s, MisplacedBreak, "break not in for, switch, or select statement")
557 }
558 case syntax.Continue:
559 if ctxt&continueOk == 0 {
560 check.error(s, MisplacedContinue, "continue not in for statement")
561 }
562 case syntax.Fallthrough:
563 if ctxt&fallthroughOk == 0 {
564 var msg string
565 switch {
566 case ctxt&finalSwitchCase != 0:
567 msg = "cannot fallthrough final case in switch"
568 case ctxt&inTypeSwitch != 0:
569 msg = "cannot fallthrough in type switch"
570 default:
571 msg = "fallthrough statement out of place"
572 }
573 check.error(s, MisplacedFallthrough, msg)
574 }
575 case syntax.Goto:
576
577 fallthrough
578 default:
579 check.errorf(s, InvalidSyntaxTree, "branch statement: %s", s.Tok)
580 }
581
582 case *syntax.BlockStmt:
583 check.openScope(s, "block")
584 defer check.closeScope()
585
586 check.stmtList(inner, s.List)
587
588 case *syntax.IfStmt:
589 check.openScope(s, "if")
590 defer check.closeScope()
591
592 check.simpleStmt(s.Init)
593 var x operand
594 check.expr(nil, &x, s.Cond)
595 if x.mode != invalid && !allBoolean(x.typ) {
596 check.error(s.Cond, InvalidCond, "non-boolean condition in if statement")
597 }
598 check.stmt(inner, s.Then)
599
600
601 switch s.Else.(type) {
602 case nil:
603
604 case *syntax.IfStmt, *syntax.BlockStmt:
605 check.stmt(inner, s.Else)
606 default:
607 check.error(s.Else, InvalidSyntaxTree, "invalid else branch in if statement")
608 }
609
610 case *syntax.SwitchStmt:
611 inner |= breakOk
612 check.openScope(s, "switch")
613 defer check.closeScope()
614
615 check.simpleStmt(s.Init)
616
617 if g, _ := s.Tag.(*syntax.TypeSwitchGuard); g != nil {
618 check.typeSwitchStmt(inner|inTypeSwitch, s, g)
619 } else {
620 check.switchStmt(inner, s)
621 }
622
623 case *syntax.SelectStmt:
624 inner |= breakOk
625
626 check.multipleSelectDefaults(s.Body)
627
628 for _, clause := range s.Body {
629 if clause == nil {
630 continue
631 }
632
633
634 valid := false
635 var rhs syntax.Expr
636 switch s := clause.Comm.(type) {
637 case nil, *syntax.SendStmt:
638 valid = true
639 case *syntax.AssignStmt:
640 if _, ok := s.Rhs.(*syntax.ListExpr); !ok {
641 rhs = s.Rhs
642 }
643 case *syntax.ExprStmt:
644 rhs = s.X
645 }
646
647
648 if rhs != nil {
649 if x, _ := syntax.Unparen(rhs).(*syntax.Operation); x != nil && x.Y == nil && x.Op == syntax.Recv {
650 valid = true
651 }
652 }
653
654 if !valid {
655 check.error(clause.Comm, InvalidSelectCase, "select case must be send or receive (possibly with assignment)")
656 continue
657 }
658 check.openScope(clause, "case")
659 if clause.Comm != nil {
660 check.stmt(inner, clause.Comm)
661 }
662 check.stmtList(inner, clause.Body)
663 check.closeScope()
664 }
665
666 case *syntax.ForStmt:
667 inner |= breakOk | continueOk
668
669 if rclause, _ := s.Init.(*syntax.RangeClause); rclause != nil {
670
671 sKey := rclause.Lhs
672 var sValue, sExtra syntax.Expr
673 if p, _ := sKey.(*syntax.ListExpr); p != nil {
674 if len(p.ElemList) < 2 {
675 check.error(s, InvalidSyntaxTree, "invalid lhs in range clause")
676 return
677 }
678
679 sKey = p.ElemList[0]
680 sValue = p.ElemList[1]
681 if len(p.ElemList) > 2 {
682
683 sExtra = p.ElemList[2]
684 }
685 }
686 check.rangeStmt(inner, s, s, sKey, sValue, sExtra, rclause.X, rclause.Def)
687 break
688 }
689
690 check.openScope(s, "for")
691 defer check.closeScope()
692
693 check.simpleStmt(s.Init)
694 if s.Cond != nil {
695 var x operand
696 check.expr(nil, &x, s.Cond)
697 if x.mode != invalid && !allBoolean(x.typ) {
698 check.error(s.Cond, InvalidCond, "non-boolean condition in for statement")
699 }
700 }
701 check.simpleStmt(s.Post)
702
703
704 if s, _ := s.Post.(*syntax.AssignStmt); s != nil && s.Op == syntax.Def {
705
706 check.use(s.Lhs)
707 }
708 check.stmt(inner, s.Body)
709
710 default:
711 check.error(s, InvalidSyntaxTree, "invalid statement")
712 }
713 }
714
715 func (check *Checker) switchStmt(inner stmtContext, s *syntax.SwitchStmt) {
716
717
718 var x operand
719 if s.Tag != nil {
720 check.expr(nil, &x, s.Tag)
721
722
723 check.assignment(&x, nil, "switch expression")
724 if x.mode != invalid && !Comparable(x.typ) && !hasNil(x.typ) {
725 check.errorf(&x, InvalidExprSwitch, "cannot switch on %s (%s is not comparable)", &x, x.typ)
726 x.mode = invalid
727 }
728 } else {
729
730
731 x.mode = constant_
732 x.typ = Typ[Bool]
733 x.val = constant.MakeBool(true)
734
735 pos := s.Rbrace
736 if len(s.Body) > 0 {
737 pos = s.Body[0].Pos()
738 }
739 x.expr = syntax.NewName(pos, "true")
740 }
741
742 check.multipleSwitchDefaults(s.Body)
743
744 seen := make(valueMap)
745 for i, clause := range s.Body {
746 if clause == nil {
747 check.error(clause, InvalidSyntaxTree, "incorrect expression switch case")
748 continue
749 }
750 inner := inner
751 if i+1 < len(s.Body) {
752 inner |= fallthroughOk
753 } else {
754 inner |= finalSwitchCase
755 }
756 check.caseValues(&x, syntax.UnpackListExpr(clause.Cases), seen)
757 check.openScope(clause, "case")
758 check.stmtList(inner, clause.Body)
759 check.closeScope()
760 }
761 }
762
763 func (check *Checker) typeSwitchStmt(inner stmtContext, s *syntax.SwitchStmt, guard *syntax.TypeSwitchGuard) {
764
765
766
767
768
769
770
771
772 lhs := guard.Lhs
773 if lhs != nil {
774 if lhs.Value == "_" {
775
776 check.softErrorf(lhs, NoNewVar, "no new variable on left side of :=")
777 lhs = nil
778 } else {
779 check.recordDef(lhs, nil)
780 }
781 }
782
783
784 var sx *operand
785 {
786 var x operand
787 check.expr(nil, &x, guard.X)
788 if x.mode != invalid {
789 if isTypeParam(x.typ) {
790 check.errorf(&x, InvalidTypeSwitch, "cannot use type switch on type parameter value %s", &x)
791 } else if IsInterface(x.typ) {
792 sx = &x
793 } else {
794 check.errorf(&x, InvalidTypeSwitch, "%s is not an interface", &x)
795 }
796 }
797 }
798
799 check.multipleSwitchDefaults(s.Body)
800
801 var lhsVars []*Var
802 seen := make(map[Type]syntax.Expr)
803 for _, clause := range s.Body {
804 if clause == nil {
805 check.error(s, InvalidSyntaxTree, "incorrect type switch case")
806 continue
807 }
808
809 cases := syntax.UnpackListExpr(clause.Cases)
810 T := check.caseTypes(sx, cases, seen)
811 check.openScope(clause, "case")
812
813 if lhs != nil {
814 obj := newVar(LocalVar, lhs.Pos(), check.pkg, lhs.Value, T)
815 check.declare(check.scope, nil, obj, clause.Colon)
816 check.recordImplicit(clause, obj)
817
818
819
820 lhsVars = append(lhsVars, obj)
821 }
822 check.stmtList(inner, clause.Body)
823 check.closeScope()
824 }
825
826
827
828
829
830 if lhs != nil {
831 var used bool
832 for _, v := range lhsVars {
833 if check.usedVars[v] {
834 used = true
835 }
836 check.usedVars[v] = true
837 }
838 if !used {
839 check.softErrorf(lhs, UnusedVar, "%s declared and not used", lhs.Value)
840 }
841 }
842 }
843
View as plain text