1
2
3
4
5 package typecheck
6
7 import (
8 "cmd/compile/internal/base"
9 "cmd/compile/internal/ir"
10 "cmd/compile/internal/types"
11 "cmd/internal/src"
12 "internal/types/errors"
13 )
14
15 func RangeExprType(t *types.Type) *types.Type {
16 if t.IsPtr() && t.Elem().IsArray() {
17 return t.Elem()
18 }
19 return t
20 }
21
22
23
24
25 func tcAssign(n *ir.AssignStmt) {
26 if base.EnableTrace && base.Flag.LowerT {
27 defer tracePrint("tcAssign", n)(nil)
28 }
29
30 if n.Y == nil {
31 n.X = AssignExpr(n.X)
32 return
33 }
34
35 lhs, rhs := []ir.Node{n.X}, []ir.Node{n.Y}
36 assign(n, lhs, rhs)
37 n.X, n.Y = lhs[0], rhs[0]
38
39
40 if !ir.IsBlank(n.X) {
41 types.CheckSize(n.X.Type())
42 }
43 }
44
45 func tcAssignList(n *ir.AssignListStmt) {
46 if base.EnableTrace && base.Flag.LowerT {
47 defer tracePrint("tcAssignList", n)(nil)
48 }
49
50 assign(n, n.Lhs, n.Rhs)
51 }
52
53 func assign(stmt ir.Node, lhs, rhs []ir.Node) {
54
55
56
57
58
59
60
61
62 checkLHS := func(i int, typ *types.Type) {
63 if n := lhs[i]; typ != nil && ir.DeclaredBy(n, stmt) && n.Type() == nil {
64 base.Assertf(typ.Kind() == types.TNIL, "unexpected untyped nil")
65 n.SetType(defaultType(typ))
66 }
67 if lhs[i].Typecheck() == 0 {
68 lhs[i] = AssignExpr(lhs[i])
69 }
70 checkassign(lhs[i])
71 }
72
73 assignType := func(i int, typ *types.Type) {
74 checkLHS(i, typ)
75 if typ != nil {
76 checkassignto(typ, lhs[i])
77 }
78 }
79
80 cr := len(rhs)
81 if len(rhs) == 1 {
82 rhs[0] = typecheck(rhs[0], ctxExpr|ctxMultiOK)
83 if rtyp := rhs[0].Type(); rtyp != nil && rtyp.IsFuncArgStruct() {
84 cr = rtyp.NumFields()
85 }
86 } else {
87 Exprs(rhs)
88 }
89
90
91 assignOK:
92 for len(lhs) == 2 && cr == 1 {
93 stmt := stmt.(*ir.AssignListStmt)
94 r := rhs[0]
95
96 switch r.Op() {
97 case ir.OINDEXMAP:
98 stmt.SetOp(ir.OAS2MAPR)
99 case ir.ORECV:
100 stmt.SetOp(ir.OAS2RECV)
101 case ir.ODOTTYPE:
102 r := r.(*ir.TypeAssertExpr)
103 stmt.SetOp(ir.OAS2DOTTYPE)
104 r.SetOp(ir.ODOTTYPE2)
105 case ir.ODYNAMICDOTTYPE:
106 r := r.(*ir.DynamicTypeAssertExpr)
107 stmt.SetOp(ir.OAS2DOTTYPE)
108 r.SetOp(ir.ODYNAMICDOTTYPE2)
109 default:
110 break assignOK
111 }
112
113 assignType(0, r.Type())
114 assignType(1, types.UntypedBool)
115 return
116 }
117
118 if len(lhs) != cr {
119 if r, ok := rhs[0].(*ir.CallExpr); ok && len(rhs) == 1 {
120 if r.Type() != nil {
121 base.ErrorfAt(stmt.Pos(), errors.WrongAssignCount, "assignment mismatch: %d variable%s but %v returns %d value%s", len(lhs), plural(len(lhs)), r.Fun, cr, plural(cr))
122 }
123 } else {
124 base.ErrorfAt(stmt.Pos(), errors.WrongAssignCount, "assignment mismatch: %d variable%s but %v value%s", len(lhs), plural(len(lhs)), len(rhs), plural(len(rhs)))
125 }
126
127 for i := range lhs {
128 checkLHS(i, nil)
129 }
130 return
131 }
132
133
134 if cr > len(rhs) {
135 stmt := stmt.(*ir.AssignListStmt)
136 stmt.SetOp(ir.OAS2FUNC)
137 r := rhs[0].(*ir.CallExpr)
138 rtyp := r.Type()
139
140 mismatched := false
141 failed := false
142 for i := range lhs {
143 result := rtyp.Field(i).Type
144 assignType(i, result)
145
146 if lhs[i].Type() == nil || result == nil {
147 failed = true
148 } else if lhs[i] != ir.BlankNode && !types.Identical(lhs[i].Type(), result) {
149 mismatched = true
150 }
151 }
152 if mismatched && !failed {
153 RewriteMultiValueCall(stmt, r)
154 }
155 return
156 }
157
158 for i, r := range rhs {
159 checkLHS(i, r.Type())
160 if lhs[i].Type() != nil {
161 rhs[i] = AssignConv(r, lhs[i].Type(), "assignment")
162 }
163 }
164 }
165
166 func plural(n int) string {
167 if n == 1 {
168 return ""
169 }
170 return "s"
171 }
172
173
174 func tcCheckNil(n *ir.UnaryExpr) ir.Node {
175 n.X = Expr(n.X)
176 if !n.X.Type().IsPtrShaped() {
177 base.FatalfAt(n.Pos(), "%L is not pointer shaped", n.X)
178 }
179 return n
180 }
181
182
183 func tcFor(n *ir.ForStmt) ir.Node {
184 Stmts(n.Init())
185 n.Cond = Expr(n.Cond)
186 n.Cond = DefaultLit(n.Cond, nil)
187 if n.Cond != nil {
188 t := n.Cond.Type()
189 if t != nil && !t.IsBoolean() {
190 base.Errorf("non-bool %L used as for condition", n.Cond)
191 }
192 }
193 n.Post = Stmt(n.Post)
194 Stmts(n.Body)
195 return n
196 }
197
198
199 func tcGoDefer(n *ir.GoDeferStmt) {
200 call := normalizeGoDeferCall(n.Pos(), n.Op(), n.Call, n.PtrInit())
201 call.GoDefer = true
202 n.Call = call
203 }
204
205
206
207
208
209
210
211
212
213
214
215
216
217 func normalizeGoDeferCall(pos src.XPos, op ir.Op, call ir.Node, init *ir.Nodes) *ir.CallExpr {
218 init.Append(ir.TakeInit(call)...)
219
220 if call, ok := call.(*ir.CallExpr); ok && call.Op() == ir.OCALLFUNC {
221 if sig := call.Fun.Type(); sig.NumParams()+sig.NumResults() == 0 {
222 return call
223 }
224 }
225
226
227 wrapperFn := ir.NewClosureFunc(pos, pos, op, types.NewSignature(nil, nil, nil), ir.CurFunc, Target)
228 wrapperFn.DeclareParams(true)
229 wrapperFn.SetWrapper(true)
230
231
232
233 var argps []*ir.Node
234
235 var visit func(argp *ir.Node)
236 visit = func(argp *ir.Node) {
237 arg := *argp
238 if arg == nil {
239 return
240 }
241
242
243
244
245 switch arg.Op() {
246 case ir.OLITERAL, ir.ONIL, ir.OMETHEXPR, ir.ONEW:
247 return
248 case ir.ONAME:
249 arg := arg.(*ir.Name)
250 if arg.Class == ir.PFUNC {
251 return
252 }
253 case ir.OADDR:
254 arg := arg.(*ir.AddrExpr)
255 if arg.X.Op() == ir.OLINKSYMOFFSET {
256 return
257 }
258
259 case ir.OCONVNOP:
260 arg := arg.(*ir.ConvExpr)
261
262
263
264
265
266
267
268 if arg.Type().IsUintptr() && arg.X.Type().IsUnsafePtr() {
269 visit(&arg.X)
270 return
271 }
272
273 case ir.OARRAYLIT, ir.OSLICELIT, ir.OSTRUCTLIT:
274
275
276 list := arg.(*ir.CompLitExpr).List
277 for i, el := range list {
278 switch el := el.(type) {
279 case *ir.KeyExpr:
280 visit(&el.Value)
281 case *ir.StructKeyExpr:
282 visit(&el.Value)
283 default:
284 visit(&list[i])
285 }
286 }
287 return
288 }
289
290 argps = append(argps, argp)
291 }
292
293 visitList := func(list []ir.Node) {
294 for i := range list {
295 visit(&list[i])
296 }
297 }
298
299 switch call.Op() {
300 default:
301 base.Fatalf("unexpected call op: %v", call.Op())
302
303 case ir.OCALLFUNC:
304 call := call.(*ir.CallExpr)
305
306
307 if wrapped := ir.StaticCalleeName(call.Fun); wrapped != nil {
308 wrapperFn.WrappedFunc = wrapped.Func
309 }
310
311 visit(&call.Fun)
312 visitList(call.Args)
313
314 case ir.OCALLINTER:
315 call := call.(*ir.CallExpr)
316 argps = append(argps, &call.Fun.(*ir.SelectorExpr).X)
317 visitList(call.Args)
318
319 case ir.OAPPEND, ir.ODELETE, ir.OPRINT, ir.OPRINTLN, ir.ORECOVER:
320 call := call.(*ir.CallExpr)
321 visitList(call.Args)
322 visit(&call.RType)
323
324 case ir.OCOPY:
325 call := call.(*ir.BinaryExpr)
326 visit(&call.X)
327 visit(&call.Y)
328 visit(&call.RType)
329
330 case ir.OCLEAR, ir.OCLOSE, ir.OPANIC:
331 call := call.(*ir.UnaryExpr)
332 visit(&call.X)
333 }
334
335 if len(argps) != 0 {
336
337
338
339
340 stmtPos := base.Pos
341 callPos := base.Pos
342
343 as := ir.NewAssignListStmt(callPos, ir.OAS2, make([]ir.Node, len(argps)), make([]ir.Node, len(argps)))
344 for i, argp := range argps {
345 arg := *argp
346
347 pos := callPos
348 if ir.HasUniquePos(arg) {
349 pos = arg.Pos()
350 }
351
352
353 tmp := TempAt(pos, ir.CurFunc, arg.Type())
354 init.Append(Stmt(ir.NewDecl(pos, ir.ODCL, tmp)))
355 tmp.Defn = as
356 as.Lhs[i] = tmp
357 as.Rhs[i] = arg
358
359
360 *argp = ir.NewClosureVar(pos, wrapperFn, tmp)
361 }
362 init.Append(Stmt(as))
363
364
365
366 if call.Op() == ir.OCALLINTER {
367 iface := as.Lhs[0]
368 init.Append(Stmt(ir.NewUnaryExpr(stmtPos, ir.OCHECKNIL, ir.NewUnaryExpr(iface.Pos(), ir.OITAB, iface))))
369 }
370 }
371
372
373
374 wrapperFn.Body = []ir.Node{call}
375
376
377 return Call(call.Pos(), wrapperFn.OClosure, nil, false).(*ir.CallExpr)
378 }
379
380
381 func tcIf(n *ir.IfStmt) ir.Node {
382 Stmts(n.Init())
383 n.Cond = Expr(n.Cond)
384 n.Cond = DefaultLit(n.Cond, nil)
385 if n.Cond != nil {
386 t := n.Cond.Type()
387 if t != nil && !t.IsBoolean() {
388 base.Errorf("non-bool %L used as if condition", n.Cond)
389 }
390 }
391 Stmts(n.Body)
392 Stmts(n.Else)
393 return n
394 }
395
396
397 func tcRange(n *ir.RangeStmt) {
398 n.X = Expr(n.X)
399
400
401 if n.Key != nil {
402 if !ir.DeclaredBy(n.Key, n) {
403 n.Key = AssignExpr(n.Key)
404 }
405 checkassign(n.Key)
406 }
407 if n.Value != nil {
408 if !ir.DeclaredBy(n.Value, n) {
409 n.Value = AssignExpr(n.Value)
410 }
411 checkassign(n.Value)
412 }
413
414
415 n.SetTypecheck(1)
416 if n.Key != nil && n.Key.Typecheck() == 0 {
417 n.Key = AssignExpr(n.Key)
418 }
419 if n.Value != nil && n.Value.Typecheck() == 0 {
420 n.Value = AssignExpr(n.Value)
421 }
422
423 Stmts(n.Body)
424 }
425
426
427 func tcReturn(n *ir.ReturnStmt) ir.Node {
428 if ir.CurFunc == nil {
429 base.FatalfAt(n.Pos(), "return outside function")
430 }
431
432 typecheckargs(n)
433 if len(n.Results) != 0 {
434 typecheckaste(ir.ORETURN, nil, false, ir.CurFunc.Type().Results(), n.Results, func() string { return "return argument" })
435 }
436 return n
437 }
438
439
440 func tcSelect(sel *ir.SelectStmt) {
441 var def *ir.CommClause
442 lno := ir.SetPos(sel)
443 Stmts(sel.Init())
444 for _, ncase := range sel.Cases {
445 if ncase.Comm == nil {
446
447 if def != nil {
448 base.ErrorfAt(ncase.Pos(), errors.DuplicateDefault, "multiple defaults in select (first at %v)", ir.Line(def))
449 } else {
450 def = ncase
451 }
452 } else {
453 n := Stmt(ncase.Comm)
454 ncase.Comm = n
455 oselrecv2 := func(dst, recv ir.Node, def bool) {
456 selrecv := ir.NewAssignListStmt(n.Pos(), ir.OSELRECV2, []ir.Node{dst, ir.BlankNode}, []ir.Node{recv})
457 selrecv.Def = def
458 selrecv.SetTypecheck(1)
459 selrecv.SetInit(n.Init())
460 ncase.Comm = selrecv
461 }
462 switch n.Op() {
463 default:
464 pos := n.Pos()
465 if n.Op() == ir.ONAME {
466
467
468
469
470 pos = ncase.Pos()
471 }
472 base.ErrorfAt(pos, errors.InvalidSelectCase, "select case must be receive, send or assign recv")
473
474 case ir.OAS:
475
476
477
478 n := n.(*ir.AssignStmt)
479 if r := n.Y; r.Op() == ir.OCONVNOP || r.Op() == ir.OCONVIFACE {
480 r := r.(*ir.ConvExpr)
481 if r.Implicit() {
482 n.Y = r.X
483 }
484 }
485 if n.Y.Op() != ir.ORECV {
486 base.ErrorfAt(n.Pos(), errors.InvalidSelectCase, "select assignment must have receive on right hand side")
487 break
488 }
489 oselrecv2(n.X, n.Y, n.Def)
490
491 case ir.OAS2RECV:
492 n := n.(*ir.AssignListStmt)
493 if n.Rhs[0].Op() != ir.ORECV {
494 base.ErrorfAt(n.Pos(), errors.InvalidSelectCase, "select assignment must have receive on right hand side")
495 break
496 }
497 n.SetOp(ir.OSELRECV2)
498
499 case ir.ORECV:
500
501 n := n.(*ir.UnaryExpr)
502 oselrecv2(ir.BlankNode, n, false)
503
504 case ir.OSEND:
505 break
506 }
507 }
508
509 Stmts(ncase.Body)
510 }
511
512 base.Pos = lno
513 }
514
515
516 func tcSend(n *ir.SendStmt) ir.Node {
517 n.Chan = Expr(n.Chan)
518 n.Value = Expr(n.Value)
519 n.Chan = DefaultLit(n.Chan, nil)
520 t := n.Chan.Type()
521 if t == nil {
522 return n
523 }
524 if !t.IsChan() {
525 base.Errorf("invalid operation: %v (send to non-chan type %v)", n, t)
526 return n
527 }
528
529 if !t.ChanDir().CanSend() {
530 base.Errorf("invalid operation: %v (send to receive-only type %v)", n, t)
531 return n
532 }
533
534 n.Value = AssignConv(n.Value, t.Elem(), "send")
535 if n.Value.Type() == nil {
536 return n
537 }
538 return n
539 }
540
541
542 func tcSwitch(n *ir.SwitchStmt) {
543 Stmts(n.Init())
544 if n.Tag != nil && n.Tag.Op() == ir.OTYPESW {
545 tcSwitchType(n)
546 } else {
547 tcSwitchExpr(n)
548 }
549 }
550
551 func tcSwitchExpr(n *ir.SwitchStmt) {
552 t := types.Types[types.TBOOL]
553 if n.Tag != nil {
554 n.Tag = Expr(n.Tag)
555 n.Tag = DefaultLit(n.Tag, nil)
556 t = n.Tag.Type()
557 }
558
559 var nilonly string
560 if t != nil {
561 switch {
562 case t.IsMap():
563 nilonly = "map"
564 case t.Kind() == types.TFUNC:
565 nilonly = "func"
566 case t.IsSlice():
567 nilonly = "slice"
568
569 case !types.IsComparable(t):
570 if t.IsStruct() {
571 base.ErrorfAt(n.Pos(), errors.InvalidExprSwitch, "cannot switch on %L (struct containing %v cannot be compared)", n.Tag, types.IncomparableField(t).Type)
572 } else {
573 base.ErrorfAt(n.Pos(), errors.InvalidExprSwitch, "cannot switch on %L", n.Tag)
574 }
575 t = nil
576 }
577 }
578
579 var defCase ir.Node
580 for _, ncase := range n.Cases {
581 ls := ncase.List
582 if len(ls) == 0 {
583 if defCase != nil {
584 base.ErrorfAt(ncase.Pos(), errors.DuplicateDefault, "multiple defaults in switch (first at %v)", ir.Line(defCase))
585 } else {
586 defCase = ncase
587 }
588 }
589
590 for i := range ls {
591 ir.SetPos(ncase)
592 ls[i] = Expr(ls[i])
593 ls[i] = DefaultLit(ls[i], t)
594 n1 := ls[i]
595 if t == nil || n1.Type() == nil {
596 continue
597 }
598
599 if nilonly != "" && !ir.IsNil(n1) {
600 base.ErrorfAt(ncase.Pos(), errors.MismatchedTypes, "invalid case %v in switch (can only compare %s %v to nil)", n1, nilonly, n.Tag)
601 } else if t.IsInterface() && !n1.Type().IsInterface() && !types.IsComparable(n1.Type()) {
602 base.ErrorfAt(ncase.Pos(), errors.UndefinedOp, "invalid case %L in switch (incomparable type)", n1)
603 } else {
604 op1, _ := assignOp(n1.Type(), t)
605 op2, _ := assignOp(t, n1.Type())
606 if op1 == ir.OXXX && op2 == ir.OXXX {
607 if n.Tag != nil {
608 base.ErrorfAt(ncase.Pos(), errors.MismatchedTypes, "invalid case %v in switch on %v (mismatched types %v and %v)", n1, n.Tag, n1.Type(), t)
609 } else {
610 base.ErrorfAt(ncase.Pos(), errors.MismatchedTypes, "invalid case %v in switch (mismatched types %v and bool)", n1, n1.Type())
611 }
612 }
613 }
614 }
615
616 Stmts(ncase.Body)
617 }
618 }
619
620 func tcSwitchType(n *ir.SwitchStmt) {
621 guard := n.Tag.(*ir.TypeSwitchGuard)
622 guard.X = Expr(guard.X)
623 t := guard.X.Type()
624 if t != nil && !t.IsInterface() {
625 base.ErrorfAt(n.Pos(), errors.InvalidTypeSwitch, "cannot type switch on non-interface value %L", guard.X)
626 t = nil
627 }
628
629
630
631
632 if v := guard.Tag; v != nil && !ir.IsBlank(v) && len(n.Cases) == 0 {
633 base.ErrorfAt(v.Pos(), errors.UnusedVar, "%v declared but not used", v.Sym())
634 }
635
636 var defCase, nilCase ir.Node
637 var ts typeSet
638 for _, ncase := range n.Cases {
639 ls := ncase.List
640 if len(ls) == 0 {
641 if defCase != nil {
642 base.ErrorfAt(ncase.Pos(), errors.DuplicateDefault, "multiple defaults in switch (first at %v)", ir.Line(defCase))
643 } else {
644 defCase = ncase
645 }
646 }
647
648 for i := range ls {
649 ls[i] = typecheck(ls[i], ctxExpr|ctxType)
650 n1 := ls[i]
651 if t == nil || n1.Type() == nil {
652 continue
653 }
654
655 if ir.IsNil(n1) {
656 if nilCase != nil {
657 base.ErrorfAt(ncase.Pos(), errors.DuplicateCase, "multiple nil cases in type switch (first at %v)", ir.Line(nilCase))
658 } else {
659 nilCase = ncase
660 }
661 continue
662 }
663 if n1.Op() == ir.ODYNAMICTYPE {
664 continue
665 }
666 if n1.Op() != ir.OTYPE {
667 base.ErrorfAt(ncase.Pos(), errors.NotAType, "%L is not a type", n1)
668 continue
669 }
670 if !n1.Type().IsInterface() {
671 why := ImplementsExplain(n1.Type(), t)
672 if why != "" {
673 base.ErrorfAt(ncase.Pos(), errors.ImpossibleAssert, "impossible type switch case: %L cannot have dynamic type %v (%s)", guard.X, n1.Type(), why)
674 }
675 continue
676 }
677
678 ts.add(ncase.Pos(), n1.Type())
679 }
680
681 if ncase.Var != nil {
682
683 vt := t
684 if len(ls) == 1 {
685 if ls[0].Op() == ir.OTYPE || ls[0].Op() == ir.ODYNAMICTYPE {
686 vt = ls[0].Type()
687 } else if !ir.IsNil(ls[0]) {
688
689
690 vt = nil
691 }
692 }
693
694 nvar := ncase.Var
695 nvar.SetType(vt)
696 if vt != nil {
697 nvar = AssignExpr(nvar).(*ir.Name)
698 } else {
699
700 nvar.SetTypecheck(1)
701 }
702 ncase.Var = nvar
703 }
704
705 Stmts(ncase.Body)
706 }
707 }
708
709 type typeSet struct {
710 m map[string]src.XPos
711 }
712
713 func (s *typeSet) add(pos src.XPos, typ *types.Type) {
714 if s.m == nil {
715 s.m = make(map[string]src.XPos)
716 }
717
718 ls := typ.LinkString()
719 if prev, ok := s.m[ls]; ok {
720 base.ErrorfAt(pos, errors.DuplicateCase, "duplicate case %v in type switch\n\tprevious case at %s", typ, base.FmtPos(prev))
721 return
722 }
723 s.m[ls] = pos
724 }
725
View as plain text