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