]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/compile/internal/typecheck/stmt.go
4c21f045afaea45fca681b2bfac3b530e13ef682
[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 // tcGoDefer typechecks an OGO/ODEFER statement.
202 //
203 // Really, this means normalizing the statement to always use a simple
204 // function call with no arguments and no results. For example, it
205 // rewrites:
206 //
207 //      defer f(x, y)
208 //
209 // into:
210 //
211 //      x1, y1 := x, y
212 //      defer func() { f(x1, y1) }()
213 func tcGoDefer(n *ir.GoDeferStmt) {
214         call := n.Call
215
216         init := n.PtrInit()
217         init.Append(ir.TakeInit(call)...)
218
219         if call, ok := n.Call.(*ir.CallExpr); ok && call.Op() == ir.OCALLFUNC {
220                 if sig := call.X.Type(); sig.NumParams()+sig.NumResults() == 0 {
221                         return // already in normal form
222                 }
223         }
224
225         // Create a new wrapper function without parameters or results.
226         wrapperFn := ir.NewClosureFunc(n.Pos(), n.Pos(), n.Op(), types.NewSignature(nil, nil, nil), ir.CurFunc, Target)
227         wrapperFn.SetWrapper(true)
228
229         // argps collects the list of operands within the call expression
230         // that must be evaluated at the go/defer statement.
231         var argps []*ir.Node
232
233         var visit func(argp *ir.Node)
234         visit = func(argp *ir.Node) {
235                 arg := *argp
236                 if arg == nil {
237                         return
238                 }
239
240                 // Recognize a few common expressions that can be evaluated within
241                 // the wrapper, so we don't need to allocate space for them within
242                 // the closure.
243                 switch arg.Op() {
244                 case ir.OLITERAL, ir.ONIL, ir.OMETHEXPR:
245                         return
246                 case ir.ONAME:
247                         arg := arg.(*ir.Name)
248                         if arg.Class == ir.PFUNC {
249                                 return // reference to global function
250                         }
251                 case ir.OADDR:
252                         arg := arg.(*ir.AddrExpr)
253                         if arg.X.Op() == ir.OLINKSYMOFFSET {
254                                 return // address of global symbol
255                         }
256
257                 case ir.OCONVNOP:
258                         arg := arg.(*ir.ConvExpr)
259
260                         // For unsafe.Pointer->uintptr conversion arguments, save the
261                         // unsafe.Pointer argument. This is necessary to handle cases
262                         // like fixedbugs/issue24491a.go correctly.
263                         //
264                         // TODO(mdempsky): Limit to static callees with
265                         // //go:uintptr{escapes,keepalive}?
266                         if arg.Type().IsUintptr() && arg.X.Type().IsUnsafePtr() {
267                                 visit(&arg.X)
268                                 return
269                         }
270
271                 case ir.OARRAYLIT, ir.OSLICELIT, ir.OSTRUCTLIT:
272                         // TODO(mdempsky): For very large slices, it may be preferable
273                         // to construct them at the go/defer statement instead.
274                         list := arg.(*ir.CompLitExpr).List
275                         for i, el := range list {
276                                 switch el := el.(type) {
277                                 case *ir.KeyExpr:
278                                         visit(&el.Value)
279                                 case *ir.StructKeyExpr:
280                                         visit(&el.Value)
281                                 default:
282                                         visit(&list[i])
283                                 }
284                         }
285                         return
286                 }
287
288                 argps = append(argps, argp)
289         }
290
291         visitList := func(list []ir.Node) {
292                 for i := range list {
293                         visit(&list[i])
294                 }
295         }
296
297         switch call.Op() {
298         default:
299                 base.Fatalf("unexpected call op: %v", call.Op())
300
301         case ir.OCALLFUNC:
302                 call := call.(*ir.CallExpr)
303
304                 // If the callee is a named function, link to the original callee.
305                 if wrapped := ir.StaticCalleeName(call.X); wrapped != nil {
306                         wrapperFn.WrappedFunc = wrapped.Func
307                 }
308
309                 visit(&call.X)
310                 visitList(call.Args)
311
312         case ir.OCALLINTER:
313                 call := call.(*ir.CallExpr)
314                 argps = append(argps, &call.X.(*ir.SelectorExpr).X) // must be first for OCHECKNIL; see below
315                 visitList(call.Args)
316
317         case ir.OAPPEND, ir.ODELETE, ir.OPRINT, ir.OPRINTN, ir.ORECOVERFP:
318                 call := call.(*ir.CallExpr)
319                 visitList(call.Args)
320                 visit(&call.RType)
321
322         case ir.OCOPY:
323                 call := call.(*ir.BinaryExpr)
324                 visit(&call.X)
325                 visit(&call.Y)
326                 visit(&call.RType)
327
328         case ir.OCLEAR, ir.OCLOSE, ir.OPANIC:
329                 call := call.(*ir.UnaryExpr)
330                 visit(&call.X)
331         }
332
333         if len(argps) != 0 {
334                 // Found one or more operands that need to be evaluated upfront
335                 // and spilled to temporary variables, which can be captured by
336                 // the wrapper function.
337
338                 stmtPos := base.Pos
339                 callPos := base.Pos
340
341                 as := ir.NewAssignListStmt(callPos, ir.OAS2, make([]ir.Node, len(argps)), make([]ir.Node, len(argps)))
342                 for i, argp := range argps {
343                         arg := *argp
344
345                         pos := callPos
346                         if ir.HasUniquePos(arg) {
347                                 pos = arg.Pos()
348                         }
349
350                         // tmp := arg
351                         tmp := TempAt(pos, ir.CurFunc, arg.Type())
352                         init.Append(Stmt(ir.NewDecl(pos, ir.ODCL, tmp)))
353                         tmp.Defn = as
354                         as.Lhs[i] = tmp
355                         as.Rhs[i] = arg
356
357                         // Rewrite original expression to use/capture tmp.
358                         *argp = ir.NewClosureVar(pos, wrapperFn, tmp)
359                 }
360                 init.Append(Stmt(as))
361
362                 // For "go/defer iface.M()", if iface is nil, we need to panic at
363                 // the point of the go/defer statement.
364                 if call.Op() == ir.OCALLINTER {
365                         iface := as.Lhs[0]
366                         init.Append(Stmt(ir.NewUnaryExpr(stmtPos, ir.OCHECKNIL, ir.NewUnaryExpr(iface.Pos(), ir.OITAB, iface))))
367                 }
368         }
369
370         // Move call into the wrapper function, now that it's safe to
371         // evaluate there.
372         wrapperFn.Body = []ir.Node{call}
373
374         // Finally, rewrite the go/defer statement to call the wrapper.
375         n.Call = Call(call.Pos(), wrapperFn.OClosure, nil, false)
376 }
377
378 // tcIf typechecks an OIF node.
379 func tcIf(n *ir.IfStmt) ir.Node {
380         Stmts(n.Init())
381         n.Cond = Expr(n.Cond)
382         n.Cond = DefaultLit(n.Cond, nil)
383         if n.Cond != nil {
384                 t := n.Cond.Type()
385                 if t != nil && !t.IsBoolean() {
386                         base.Errorf("non-bool %L used as if condition", n.Cond)
387                 }
388         }
389         Stmts(n.Body)
390         Stmts(n.Else)
391         return n
392 }
393
394 // range
395 func tcRange(n *ir.RangeStmt) {
396         n.X = Expr(n.X)
397
398         // delicate little dance.  see tcAssignList
399         if n.Key != nil {
400                 if !ir.DeclaredBy(n.Key, n) {
401                         n.Key = AssignExpr(n.Key)
402                 }
403                 checkassign(n.Key)
404         }
405         if n.Value != nil {
406                 if !ir.DeclaredBy(n.Value, n) {
407                         n.Value = AssignExpr(n.Value)
408                 }
409                 checkassign(n.Value)
410         }
411
412         // second half of dance
413         n.SetTypecheck(1)
414         if n.Key != nil && n.Key.Typecheck() == 0 {
415                 n.Key = AssignExpr(n.Key)
416         }
417         if n.Value != nil && n.Value.Typecheck() == 0 {
418                 n.Value = AssignExpr(n.Value)
419         }
420
421         Stmts(n.Body)
422 }
423
424 // tcReturn typechecks an ORETURN node.
425 func tcReturn(n *ir.ReturnStmt) ir.Node {
426         typecheckargs(n)
427         if ir.CurFunc == nil {
428                 base.Errorf("return outside function")
429                 n.SetType(nil)
430                 return n
431         }
432
433         if ir.HasNamedResults(ir.CurFunc) && len(n.Results) == 0 {
434                 return n
435         }
436         typecheckaste(ir.ORETURN, nil, false, ir.CurFunc.Type().Results(), n.Results, func() string { return "return argument" })
437         return n
438 }
439
440 // select
441 func tcSelect(sel *ir.SelectStmt) {
442         var def *ir.CommClause
443         lno := ir.SetPos(sel)
444         Stmts(sel.Init())
445         for _, ncase := range sel.Cases {
446                 if ncase.Comm == nil {
447                         // default
448                         if def != nil {
449                                 base.ErrorfAt(ncase.Pos(), errors.DuplicateDefault, "multiple defaults in select (first at %v)", ir.Line(def))
450                         } else {
451                                 def = ncase
452                         }
453                 } else {
454                         n := Stmt(ncase.Comm)
455                         ncase.Comm = n
456                         oselrecv2 := func(dst, recv ir.Node, def bool) {
457                                 selrecv := ir.NewAssignListStmt(n.Pos(), ir.OSELRECV2, []ir.Node{dst, ir.BlankNode}, []ir.Node{recv})
458                                 selrecv.Def = def
459                                 selrecv.SetTypecheck(1)
460                                 selrecv.SetInit(n.Init())
461                                 ncase.Comm = selrecv
462                         }
463                         switch n.Op() {
464                         default:
465                                 pos := n.Pos()
466                                 if n.Op() == ir.ONAME {
467                                         // We don't have the right position for ONAME nodes (see #15459 and
468                                         // others). Using ncase.Pos for now as it will provide the correct
469                                         // line number (assuming the expression follows the "case" keyword
470                                         // on the same line). This matches the approach before 1.10.
471                                         pos = ncase.Pos()
472                                 }
473                                 base.ErrorfAt(pos, errors.InvalidSelectCase, "select case must be receive, send or assign recv")
474
475                         case ir.OAS:
476                                 // convert x = <-c into x, _ = <-c
477                                 // remove implicit conversions; the eventual assignment
478                                 // will reintroduce them.
479                                 n := n.(*ir.AssignStmt)
480                                 if r := n.Y; r.Op() == ir.OCONVNOP || r.Op() == ir.OCONVIFACE {
481                                         r := r.(*ir.ConvExpr)
482                                         if r.Implicit() {
483                                                 n.Y = r.X
484                                         }
485                                 }
486                                 if n.Y.Op() != ir.ORECV {
487                                         base.ErrorfAt(n.Pos(), errors.InvalidSelectCase, "select assignment must have receive on right hand side")
488                                         break
489                                 }
490                                 oselrecv2(n.X, n.Y, n.Def)
491
492                         case ir.OAS2RECV:
493                                 n := n.(*ir.AssignListStmt)
494                                 if n.Rhs[0].Op() != ir.ORECV {
495                                         base.ErrorfAt(n.Pos(), errors.InvalidSelectCase, "select assignment must have receive on right hand side")
496                                         break
497                                 }
498                                 n.SetOp(ir.OSELRECV2)
499
500                         case ir.ORECV:
501                                 // convert <-c into _, _ = <-c
502                                 n := n.(*ir.UnaryExpr)
503                                 oselrecv2(ir.BlankNode, n, false)
504
505                         case ir.OSEND:
506                                 break
507                         }
508                 }
509
510                 Stmts(ncase.Body)
511         }
512
513         base.Pos = lno
514 }
515
516 // tcSend typechecks an OSEND node.
517 func tcSend(n *ir.SendStmt) ir.Node {
518         n.Chan = Expr(n.Chan)
519         n.Value = Expr(n.Value)
520         n.Chan = DefaultLit(n.Chan, nil)
521         t := n.Chan.Type()
522         if t == nil {
523                 return n
524         }
525         if !t.IsChan() {
526                 base.Errorf("invalid operation: %v (send to non-chan type %v)", n, t)
527                 return n
528         }
529
530         if !t.ChanDir().CanSend() {
531                 base.Errorf("invalid operation: %v (send to receive-only type %v)", n, t)
532                 return n
533         }
534
535         n.Value = AssignConv(n.Value, t.Elem(), "send")
536         if n.Value.Type() == nil {
537                 return n
538         }
539         return n
540 }
541
542 // tcSwitch typechecks a switch statement.
543 func tcSwitch(n *ir.SwitchStmt) {
544         Stmts(n.Init())
545         if n.Tag != nil && n.Tag.Op() == ir.OTYPESW {
546                 tcSwitchType(n)
547         } else {
548                 tcSwitchExpr(n)
549         }
550 }
551
552 func tcSwitchExpr(n *ir.SwitchStmt) {
553         t := types.Types[types.TBOOL]
554         if n.Tag != nil {
555                 n.Tag = Expr(n.Tag)
556                 n.Tag = DefaultLit(n.Tag, nil)
557                 t = n.Tag.Type()
558         }
559
560         var nilonly string
561         if t != nil {
562                 switch {
563                 case t.IsMap():
564                         nilonly = "map"
565                 case t.Kind() == types.TFUNC:
566                         nilonly = "func"
567                 case t.IsSlice():
568                         nilonly = "slice"
569
570                 case !types.IsComparable(t):
571                         if t.IsStruct() {
572                                 base.ErrorfAt(n.Pos(), errors.InvalidExprSwitch, "cannot switch on %L (struct containing %v cannot be compared)", n.Tag, types.IncomparableField(t).Type)
573                         } else {
574                                 base.ErrorfAt(n.Pos(), errors.InvalidExprSwitch, "cannot switch on %L", n.Tag)
575                         }
576                         t = nil
577                 }
578         }
579
580         var defCase ir.Node
581         for _, ncase := range n.Cases {
582                 ls := ncase.List
583                 if len(ls) == 0 { // default:
584                         if defCase != nil {
585                                 base.ErrorfAt(ncase.Pos(), errors.DuplicateDefault, "multiple defaults in switch (first at %v)", ir.Line(defCase))
586                         } else {
587                                 defCase = ncase
588                         }
589                 }
590
591                 for i := range ls {
592                         ir.SetPos(ncase)
593                         ls[i] = Expr(ls[i])
594                         ls[i] = DefaultLit(ls[i], t)
595                         n1 := ls[i]
596                         if t == nil || n1.Type() == nil {
597                                 continue
598                         }
599
600                         if nilonly != "" && !ir.IsNil(n1) {
601                                 base.ErrorfAt(ncase.Pos(), errors.MismatchedTypes, "invalid case %v in switch (can only compare %s %v to nil)", n1, nilonly, n.Tag)
602                         } else if t.IsInterface() && !n1.Type().IsInterface() && !types.IsComparable(n1.Type()) {
603                                 base.ErrorfAt(ncase.Pos(), errors.UndefinedOp, "invalid case %L in switch (incomparable type)", n1)
604                         } else {
605                                 op1, _ := Assignop(n1.Type(), t)
606                                 op2, _ := Assignop(t, n1.Type())
607                                 if op1 == ir.OXXX && op2 == ir.OXXX {
608                                         if n.Tag != nil {
609                                                 base.ErrorfAt(ncase.Pos(), errors.MismatchedTypes, "invalid case %v in switch on %v (mismatched types %v and %v)", n1, n.Tag, n1.Type(), t)
610                                         } else {
611                                                 base.ErrorfAt(ncase.Pos(), errors.MismatchedTypes, "invalid case %v in switch (mismatched types %v and bool)", n1, n1.Type())
612                                         }
613                                 }
614                         }
615                 }
616
617                 Stmts(ncase.Body)
618         }
619 }
620
621 func tcSwitchType(n *ir.SwitchStmt) {
622         guard := n.Tag.(*ir.TypeSwitchGuard)
623         guard.X = Expr(guard.X)
624         t := guard.X.Type()
625         if t != nil && !t.IsInterface() {
626                 base.ErrorfAt(n.Pos(), errors.InvalidTypeSwitch, "cannot type switch on non-interface value %L", guard.X)
627                 t = nil
628         }
629
630         // We don't actually declare the type switch's guarded
631         // declaration itself. So if there are no cases, we won't
632         // notice that it went unused.
633         if v := guard.Tag; v != nil && !ir.IsBlank(v) && len(n.Cases) == 0 {
634                 base.ErrorfAt(v.Pos(), errors.UnusedVar, "%v declared but not used", v.Sym())
635         }
636
637         var defCase, nilCase ir.Node
638         var ts typeSet
639         for _, ncase := range n.Cases {
640                 ls := ncase.List
641                 if len(ls) == 0 { // default:
642                         if defCase != nil {
643                                 base.ErrorfAt(ncase.Pos(), errors.DuplicateDefault, "multiple defaults in switch (first at %v)", ir.Line(defCase))
644                         } else {
645                                 defCase = ncase
646                         }
647                 }
648
649                 for i := range ls {
650                         ls[i] = typecheck(ls[i], ctxExpr|ctxType)
651                         n1 := ls[i]
652                         if t == nil || n1.Type() == nil {
653                                 continue
654                         }
655
656                         if ir.IsNil(n1) { // case nil:
657                                 if nilCase != nil {
658                                         base.ErrorfAt(ncase.Pos(), errors.DuplicateCase, "multiple nil cases in type switch (first at %v)", ir.Line(nilCase))
659                                 } else {
660                                         nilCase = ncase
661                                 }
662                                 continue
663                         }
664                         if n1.Op() == ir.ODYNAMICTYPE {
665                                 continue
666                         }
667                         if n1.Op() != ir.OTYPE {
668                                 base.ErrorfAt(ncase.Pos(), errors.NotAType, "%L is not a type", n1)
669                                 continue
670                         }
671                         if !n1.Type().IsInterface() {
672                                 why := ImplementsExplain(n1.Type(), t)
673                                 if why != "" {
674                                         base.ErrorfAt(ncase.Pos(), errors.ImpossibleAssert, "impossible type switch case: %L cannot have dynamic type %v (%s)", guard.X, n1.Type(), why)
675                                 }
676                                 continue
677                         }
678
679                         ts.add(ncase.Pos(), n1.Type())
680                 }
681
682                 if ncase.Var != nil {
683                         // Assign the clause variable's type.
684                         vt := t
685                         if len(ls) == 1 {
686                                 if ls[0].Op() == ir.OTYPE || ls[0].Op() == ir.ODYNAMICTYPE {
687                                         vt = ls[0].Type()
688                                 } else if !ir.IsNil(ls[0]) {
689                                         // Invalid single-type case;
690                                         // mark variable as broken.
691                                         vt = nil
692                                 }
693                         }
694
695                         nvar := ncase.Var
696                         nvar.SetType(vt)
697                         if vt != nil {
698                                 nvar = AssignExpr(nvar).(*ir.Name)
699                         } else {
700                                 // Clause variable is broken; prevent typechecking.
701                                 nvar.SetTypecheck(1)
702                         }
703                         ncase.Var = nvar
704                 }
705
706                 Stmts(ncase.Body)
707         }
708 }
709
710 type typeSet struct {
711         m map[string]src.XPos
712 }
713
714 func (s *typeSet) add(pos src.XPos, typ *types.Type) {
715         if s.m == nil {
716                 s.m = make(map[string]src.XPos)
717         }
718
719         ls := typ.LinkString()
720         if prev, ok := s.m[ls]; ok {
721                 base.ErrorfAt(pos, errors.DuplicateCase, "duplicate case %v in type switch\n\tprevious case at %s", typ, base.FmtPos(prev))
722                 return
723         }
724         s.m[ls] = pos
725 }