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