]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/compile/internal/typecheck/stmt.go
b902fd9a583de1474c12d91692331bf75fa47938
[gostls13.git] / src / cmd / compile / internal / typecheck / stmt.go
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
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 func typecheckrangeExpr(n *ir.RangeStmt) {
23 }
24
25 // type check assignment.
26 // if this assignment is the definition of a var on the left side,
27 // fill in the var's type.
28 func tcAssign(n *ir.AssignStmt) {
29         if base.EnableTrace && base.Flag.LowerT {
30                 defer tracePrint("tcAssign", n)(nil)
31         }
32
33         if n.Y == nil {
34                 n.X = AssignExpr(n.X)
35                 return
36         }
37
38         lhs, rhs := []ir.Node{n.X}, []ir.Node{n.Y}
39         assign(n, lhs, rhs)
40         n.X, n.Y = lhs[0], rhs[0]
41
42         // TODO(mdempsky): This seems out of place.
43         if !ir.IsBlank(n.X) {
44                 types.CheckSize(n.X.Type()) // ensure width is calculated for backend
45         }
46 }
47
48 func tcAssignList(n *ir.AssignListStmt) {
49         if base.EnableTrace && base.Flag.LowerT {
50                 defer tracePrint("tcAssignList", n)(nil)
51         }
52
53         assign(n, n.Lhs, n.Rhs)
54 }
55
56 func assign(stmt ir.Node, lhs, rhs []ir.Node) {
57         // delicate little dance.
58         // the definition of lhs may refer to this assignment
59         // as its definition, in which case it will call tcAssign.
60         // in that case, do not call typecheck back, or it will cycle.
61         // if the variable has a type (ntype) then typechecking
62         // will not look at defn, so it is okay (and desirable,
63         // so that the conversion below happens).
64
65         checkLHS := func(i int, typ *types.Type) {
66                 if n := lhs[i]; typ != nil && ir.DeclaredBy(n, stmt) && n.Type() == nil {
67                         base.Assertf(typ.Kind() == types.TNIL, "unexpected untyped nil")
68                         n.SetType(defaultType(typ))
69                 }
70                 if lhs[i].Typecheck() == 0 {
71                         lhs[i] = AssignExpr(lhs[i])
72                 }
73                 checkassign(lhs[i])
74         }
75
76         assignType := func(i int, typ *types.Type) {
77                 checkLHS(i, typ)
78                 if typ != nil {
79                         checkassignto(typ, lhs[i])
80                 }
81         }
82
83         cr := len(rhs)
84         if len(rhs) == 1 {
85                 rhs[0] = typecheck(rhs[0], ctxExpr|ctxMultiOK)
86                 if rtyp := rhs[0].Type(); rtyp != nil && rtyp.IsFuncArgStruct() {
87                         cr = rtyp.NumFields()
88                 }
89         } else {
90                 Exprs(rhs)
91         }
92
93         // x, ok = y
94 assignOK:
95         for len(lhs) == 2 && cr == 1 {
96                 stmt := stmt.(*ir.AssignListStmt)
97                 r := rhs[0]
98
99                 switch r.Op() {
100                 case ir.OINDEXMAP:
101                         stmt.SetOp(ir.OAS2MAPR)
102                 case ir.ORECV:
103                         stmt.SetOp(ir.OAS2RECV)
104                 case ir.ODOTTYPE:
105                         r := r.(*ir.TypeAssertExpr)
106                         stmt.SetOp(ir.OAS2DOTTYPE)
107                         r.SetOp(ir.ODOTTYPE2)
108                 case ir.ODYNAMICDOTTYPE:
109                         r := r.(*ir.DynamicTypeAssertExpr)
110                         stmt.SetOp(ir.OAS2DOTTYPE)
111                         r.SetOp(ir.ODYNAMICDOTTYPE2)
112                 default:
113                         break assignOK
114                 }
115
116                 assignType(0, r.Type())
117                 assignType(1, types.UntypedBool)
118                 return
119         }
120
121         if len(lhs) != cr {
122                 if r, ok := rhs[0].(*ir.CallExpr); ok && len(rhs) == 1 {
123                         if r.Type() != nil {
124                                 base.ErrorfAt(stmt.Pos(), errors.WrongAssignCount, "assignment mismatch: %d variable%s but %v returns %d value%s", len(lhs), plural(len(lhs)), r.X, cr, plural(cr))
125                         }
126                 } else {
127                         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)))
128                 }
129
130                 for i := range lhs {
131                         checkLHS(i, nil)
132                 }
133                 return
134         }
135
136         // x,y,z = f()
137         if cr > len(rhs) {
138                 stmt := stmt.(*ir.AssignListStmt)
139                 stmt.SetOp(ir.OAS2FUNC)
140                 r := rhs[0].(*ir.CallExpr)
141                 rtyp := r.Type()
142
143                 mismatched := false
144                 failed := false
145                 for i := range lhs {
146                         result := rtyp.Field(i).Type
147                         assignType(i, result)
148
149                         if lhs[i].Type() == nil || result == nil {
150                                 failed = true
151                         } else if lhs[i] != ir.BlankNode && !types.Identical(lhs[i].Type(), result) {
152                                 mismatched = true
153                         }
154                 }
155                 if mismatched && !failed {
156                         RewriteMultiValueCall(stmt, r)
157                 }
158                 return
159         }
160
161         for i, r := range rhs {
162                 checkLHS(i, r.Type())
163                 if lhs[i].Type() != nil {
164                         rhs[i] = AssignConv(r, lhs[i].Type(), "assignment")
165                 }
166         }
167 }
168
169 func plural(n int) string {
170         if n == 1 {
171                 return ""
172         }
173         return "s"
174 }
175
176 // tcCheckNil typechecks an OCHECKNIL node.
177 func tcCheckNil(n *ir.UnaryExpr) ir.Node {
178         n.X = Expr(n.X)
179         if !n.X.Type().IsPtrShaped() {
180                 base.FatalfAt(n.Pos(), "%L is not pointer shaped", n.X)
181         }
182         return n
183 }
184
185 // tcFor typechecks an OFOR node.
186 func tcFor(n *ir.ForStmt) ir.Node {
187         Stmts(n.Init())
188         n.Cond = Expr(n.Cond)
189         n.Cond = DefaultLit(n.Cond, nil)
190         if n.Cond != nil {
191                 t := n.Cond.Type()
192                 if t != nil && !t.IsBoolean() {
193                         base.Errorf("non-bool %L used as for condition", n.Cond)
194                 }
195         }
196         n.Post = Stmt(n.Post)
197         Stmts(n.Body)
198         return n
199 }
200
201 func tcGoDefer(n *ir.GoDeferStmt) {
202         what := "defer"
203         if n.Op() == ir.OGO {
204                 what = "go"
205         }
206
207         switch n.Call.Op() {
208         // ok
209         case ir.OCALLINTER,
210                 ir.OCALLMETH,
211                 ir.OCALLFUNC,
212                 ir.OCLEAR,
213                 ir.OCLOSE,
214                 ir.OCOPY,
215                 ir.ODELETE,
216                 ir.OMAX,
217                 ir.OMIN,
218                 ir.OPANIC,
219                 ir.OPRINT,
220                 ir.OPRINTN,
221                 ir.ORECOVER,
222                 ir.ORECOVERFP:
223                 return
224
225         case ir.OAPPEND,
226                 ir.OCAP,
227                 ir.OCOMPLEX,
228                 ir.OIMAG,
229                 ir.OLEN,
230                 ir.OMAKE,
231                 ir.OMAKESLICE,
232                 ir.OMAKECHAN,
233                 ir.OMAKEMAP,
234                 ir.ONEW,
235                 ir.OREAL,
236                 ir.OLITERAL: // conversion or unsafe.Alignof, Offsetof, Sizeof
237                 if orig := ir.Orig(n.Call); orig.Op() == ir.OCONV {
238                         break
239                 }
240                 base.ErrorfAt(n.Pos(), errors.UnusedResults, "%s discards result of %v", what, n.Call)
241                 return
242         }
243
244         // type is broken or missing, most likely a method call on a broken type
245         // we will warn about the broken type elsewhere. no need to emit a potentially confusing error
246         if n.Call.Type() == nil {
247                 return
248         }
249
250         // The syntax made sure it was a call, so this must be
251         // a conversion.
252         base.FatalfAt(n.Pos(), "%s requires function call, not conversion", what)
253 }
254
255 // tcIf typechecks an OIF node.
256 func tcIf(n *ir.IfStmt) ir.Node {
257         Stmts(n.Init())
258         n.Cond = Expr(n.Cond)
259         n.Cond = DefaultLit(n.Cond, nil)
260         if n.Cond != nil {
261                 t := n.Cond.Type()
262                 if t != nil && !t.IsBoolean() {
263                         base.Errorf("non-bool %L used as if condition", n.Cond)
264                 }
265         }
266         Stmts(n.Body)
267         Stmts(n.Else)
268         return n
269 }
270
271 // range
272 func tcRange(n *ir.RangeStmt) {
273         n.X = Expr(n.X)
274
275         // delicate little dance.  see tcAssignList
276         if n.Key != nil {
277                 if !ir.DeclaredBy(n.Key, n) {
278                         n.Key = AssignExpr(n.Key)
279                 }
280                 checkassign(n.Key)
281         }
282         if n.Value != nil {
283                 if !ir.DeclaredBy(n.Value, n) {
284                         n.Value = AssignExpr(n.Value)
285                 }
286                 checkassign(n.Value)
287         }
288
289         // second half of dance
290         n.SetTypecheck(1)
291         if n.Key != nil && n.Key.Typecheck() == 0 {
292                 n.Key = AssignExpr(n.Key)
293         }
294         if n.Value != nil && n.Value.Typecheck() == 0 {
295                 n.Value = AssignExpr(n.Value)
296         }
297
298         Stmts(n.Body)
299 }
300
301 // tcReturn typechecks an ORETURN node.
302 func tcReturn(n *ir.ReturnStmt) ir.Node {
303         typecheckargs(n)
304         if ir.CurFunc == nil {
305                 base.Errorf("return outside function")
306                 n.SetType(nil)
307                 return n
308         }
309
310         if ir.HasNamedResults(ir.CurFunc) && len(n.Results) == 0 {
311                 return n
312         }
313         typecheckaste(ir.ORETURN, nil, false, ir.CurFunc.Type().Results(), n.Results, func() string { return "return argument" })
314         return n
315 }
316
317 // select
318 func tcSelect(sel *ir.SelectStmt) {
319         var def *ir.CommClause
320         lno := ir.SetPos(sel)
321         Stmts(sel.Init())
322         for _, ncase := range sel.Cases {
323                 if ncase.Comm == nil {
324                         // default
325                         if def != nil {
326                                 base.ErrorfAt(ncase.Pos(), errors.DuplicateDefault, "multiple defaults in select (first at %v)", ir.Line(def))
327                         } else {
328                                 def = ncase
329                         }
330                 } else {
331                         n := Stmt(ncase.Comm)
332                         ncase.Comm = n
333                         oselrecv2 := func(dst, recv ir.Node, def bool) {
334                                 selrecv := ir.NewAssignListStmt(n.Pos(), ir.OSELRECV2, []ir.Node{dst, ir.BlankNode}, []ir.Node{recv})
335                                 selrecv.Def = def
336                                 selrecv.SetTypecheck(1)
337                                 selrecv.SetInit(n.Init())
338                                 ncase.Comm = selrecv
339                         }
340                         switch n.Op() {
341                         default:
342                                 pos := n.Pos()
343                                 if n.Op() == ir.ONAME {
344                                         // We don't have the right position for ONAME nodes (see #15459 and
345                                         // others). Using ncase.Pos for now as it will provide the correct
346                                         // line number (assuming the expression follows the "case" keyword
347                                         // on the same line). This matches the approach before 1.10.
348                                         pos = ncase.Pos()
349                                 }
350                                 base.ErrorfAt(pos, errors.InvalidSelectCase, "select case must be receive, send or assign recv")
351
352                         case ir.OAS:
353                                 // convert x = <-c into x, _ = <-c
354                                 // remove implicit conversions; the eventual assignment
355                                 // will reintroduce them.
356                                 n := n.(*ir.AssignStmt)
357                                 if r := n.Y; r.Op() == ir.OCONVNOP || r.Op() == ir.OCONVIFACE {
358                                         r := r.(*ir.ConvExpr)
359                                         if r.Implicit() {
360                                                 n.Y = r.X
361                                         }
362                                 }
363                                 if n.Y.Op() != ir.ORECV {
364                                         base.ErrorfAt(n.Pos(), errors.InvalidSelectCase, "select assignment must have receive on right hand side")
365                                         break
366                                 }
367                                 oselrecv2(n.X, n.Y, n.Def)
368
369                         case ir.OAS2RECV:
370                                 n := n.(*ir.AssignListStmt)
371                                 if n.Rhs[0].Op() != ir.ORECV {
372                                         base.ErrorfAt(n.Pos(), errors.InvalidSelectCase, "select assignment must have receive on right hand side")
373                                         break
374                                 }
375                                 n.SetOp(ir.OSELRECV2)
376
377                         case ir.ORECV:
378                                 // convert <-c into _, _ = <-c
379                                 n := n.(*ir.UnaryExpr)
380                                 oselrecv2(ir.BlankNode, n, false)
381
382                         case ir.OSEND:
383                                 break
384                         }
385                 }
386
387                 Stmts(ncase.Body)
388         }
389
390         base.Pos = lno
391 }
392
393 // tcSend typechecks an OSEND node.
394 func tcSend(n *ir.SendStmt) ir.Node {
395         n.Chan = Expr(n.Chan)
396         n.Value = Expr(n.Value)
397         n.Chan = DefaultLit(n.Chan, nil)
398         t := n.Chan.Type()
399         if t == nil {
400                 return n
401         }
402         if !t.IsChan() {
403                 base.Errorf("invalid operation: %v (send to non-chan type %v)", n, t)
404                 return n
405         }
406
407         if !t.ChanDir().CanSend() {
408                 base.Errorf("invalid operation: %v (send to receive-only type %v)", n, t)
409                 return n
410         }
411
412         n.Value = AssignConv(n.Value, t.Elem(), "send")
413         if n.Value.Type() == nil {
414                 return n
415         }
416         return n
417 }
418
419 // tcSwitch typechecks a switch statement.
420 func tcSwitch(n *ir.SwitchStmt) {
421         Stmts(n.Init())
422         if n.Tag != nil && n.Tag.Op() == ir.OTYPESW {
423                 tcSwitchType(n)
424         } else {
425                 tcSwitchExpr(n)
426         }
427 }
428
429 func tcSwitchExpr(n *ir.SwitchStmt) {
430         t := types.Types[types.TBOOL]
431         if n.Tag != nil {
432                 n.Tag = Expr(n.Tag)
433                 n.Tag = DefaultLit(n.Tag, nil)
434                 t = n.Tag.Type()
435         }
436
437         var nilonly string
438         if t != nil {
439                 switch {
440                 case t.IsMap():
441                         nilonly = "map"
442                 case t.Kind() == types.TFUNC:
443                         nilonly = "func"
444                 case t.IsSlice():
445                         nilonly = "slice"
446
447                 case !types.IsComparable(t):
448                         if t.IsStruct() {
449                                 base.ErrorfAt(n.Pos(), errors.InvalidExprSwitch, "cannot switch on %L (struct containing %v cannot be compared)", n.Tag, types.IncomparableField(t).Type)
450                         } else {
451                                 base.ErrorfAt(n.Pos(), errors.InvalidExprSwitch, "cannot switch on %L", n.Tag)
452                         }
453                         t = nil
454                 }
455         }
456
457         var defCase ir.Node
458         for _, ncase := range n.Cases {
459                 ls := ncase.List
460                 if len(ls) == 0 { // default:
461                         if defCase != nil {
462                                 base.ErrorfAt(ncase.Pos(), errors.DuplicateDefault, "multiple defaults in switch (first at %v)", ir.Line(defCase))
463                         } else {
464                                 defCase = ncase
465                         }
466                 }
467
468                 for i := range ls {
469                         ir.SetPos(ncase)
470                         ls[i] = Expr(ls[i])
471                         ls[i] = DefaultLit(ls[i], t)
472                         n1 := ls[i]
473                         if t == nil || n1.Type() == nil {
474                                 continue
475                         }
476
477                         if nilonly != "" && !ir.IsNil(n1) {
478                                 base.ErrorfAt(ncase.Pos(), errors.MismatchedTypes, "invalid case %v in switch (can only compare %s %v to nil)", n1, nilonly, n.Tag)
479                         } else if t.IsInterface() && !n1.Type().IsInterface() && !types.IsComparable(n1.Type()) {
480                                 base.ErrorfAt(ncase.Pos(), errors.UndefinedOp, "invalid case %L in switch (incomparable type)", n1)
481                         } else {
482                                 op1, _ := Assignop(n1.Type(), t)
483                                 op2, _ := Assignop(t, n1.Type())
484                                 if op1 == ir.OXXX && op2 == ir.OXXX {
485                                         if n.Tag != nil {
486                                                 base.ErrorfAt(ncase.Pos(), errors.MismatchedTypes, "invalid case %v in switch on %v (mismatched types %v and %v)", n1, n.Tag, n1.Type(), t)
487                                         } else {
488                                                 base.ErrorfAt(ncase.Pos(), errors.MismatchedTypes, "invalid case %v in switch (mismatched types %v and bool)", n1, n1.Type())
489                                         }
490                                 }
491                         }
492                 }
493
494                 Stmts(ncase.Body)
495         }
496 }
497
498 func tcSwitchType(n *ir.SwitchStmt) {
499         guard := n.Tag.(*ir.TypeSwitchGuard)
500         guard.X = Expr(guard.X)
501         t := guard.X.Type()
502         if t != nil && !t.IsInterface() {
503                 base.ErrorfAt(n.Pos(), errors.InvalidTypeSwitch, "cannot type switch on non-interface value %L", guard.X)
504                 t = nil
505         }
506
507         // We don't actually declare the type switch's guarded
508         // declaration itself. So if there are no cases, we won't
509         // notice that it went unused.
510         if v := guard.Tag; v != nil && !ir.IsBlank(v) && len(n.Cases) == 0 {
511                 base.ErrorfAt(v.Pos(), errors.UnusedVar, "%v declared but not used", v.Sym())
512         }
513
514         var defCase, nilCase ir.Node
515         var ts typeSet
516         for _, ncase := range n.Cases {
517                 ls := ncase.List
518                 if len(ls) == 0 { // default:
519                         if defCase != nil {
520                                 base.ErrorfAt(ncase.Pos(), errors.DuplicateDefault, "multiple defaults in switch (first at %v)", ir.Line(defCase))
521                         } else {
522                                 defCase = ncase
523                         }
524                 }
525
526                 for i := range ls {
527                         ls[i] = typecheck(ls[i], ctxExpr|ctxType)
528                         n1 := ls[i]
529                         if t == nil || n1.Type() == nil {
530                                 continue
531                         }
532
533                         if ir.IsNil(n1) { // case nil:
534                                 if nilCase != nil {
535                                         base.ErrorfAt(ncase.Pos(), errors.DuplicateCase, "multiple nil cases in type switch (first at %v)", ir.Line(nilCase))
536                                 } else {
537                                         nilCase = ncase
538                                 }
539                                 continue
540                         }
541                         if n1.Op() == ir.ODYNAMICTYPE {
542                                 continue
543                         }
544                         if n1.Op() != ir.OTYPE {
545                                 base.ErrorfAt(ncase.Pos(), errors.NotAType, "%L is not a type", n1)
546                                 continue
547                         }
548                         if !n1.Type().IsInterface() {
549                                 why := ImplementsExplain(n1.Type(), t)
550                                 if why != "" {
551                                         base.ErrorfAt(ncase.Pos(), errors.ImpossibleAssert, "impossible type switch case: %L cannot have dynamic type %v (%s)", guard.X, n1.Type(), why)
552                                 }
553                                 continue
554                         }
555
556                         ts.add(ncase.Pos(), n1.Type())
557                 }
558
559                 if ncase.Var != nil {
560                         // Assign the clause variable's type.
561                         vt := t
562                         if len(ls) == 1 {
563                                 if ls[0].Op() == ir.OTYPE || ls[0].Op() == ir.ODYNAMICTYPE {
564                                         vt = ls[0].Type()
565                                 } else if !ir.IsNil(ls[0]) {
566                                         // Invalid single-type case;
567                                         // mark variable as broken.
568                                         vt = nil
569                                 }
570                         }
571
572                         nvar := ncase.Var
573                         nvar.SetType(vt)
574                         if vt != nil {
575                                 nvar = AssignExpr(nvar).(*ir.Name)
576                         } else {
577                                 // Clause variable is broken; prevent typechecking.
578                                 nvar.SetTypecheck(1)
579                         }
580                         ncase.Var = nvar
581                 }
582
583                 Stmts(ncase.Body)
584         }
585 }
586
587 type typeSet struct {
588         m map[string]src.XPos
589 }
590
591 func (s *typeSet) add(pos src.XPos, typ *types.Type) {
592         if s.m == nil {
593                 s.m = make(map[string]src.XPos)
594         }
595
596         ls := typ.LinkString()
597         if prev, ok := s.m[ls]; ok {
598                 base.ErrorfAt(pos, errors.DuplicateCase, "duplicate case %v in type switch\n\tprevious case at %s", typ, base.FmtPos(prev))
599                 return
600         }
601         s.m[ls] = pos
602 }