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.
8 "cmd/compile/internal/base"
9 "cmd/compile/internal/ir"
10 "cmd/compile/internal/types"
12 "internal/types/errors"
15 func RangeExprType(t *types.Type) *types.Type {
16 if t.IsPtr() && t.Elem().IsArray() {
22 func typecheckrangeExpr(n *ir.RangeStmt) {
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)
38 lhs, rhs := []ir.Node{n.X}, []ir.Node{n.Y}
40 n.X, n.Y = lhs[0], rhs[0]
42 // TODO(mdempsky): This seems out of place.
44 types.CheckSize(n.X.Type()) // ensure width is calculated for backend
48 func tcAssignList(n *ir.AssignListStmt) {
49 if base.EnableTrace && base.Flag.LowerT {
50 defer tracePrint("tcAssignList", n)(nil)
53 assign(n, n.Lhs, n.Rhs)
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).
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))
70 if lhs[i].Typecheck() == 0 {
71 lhs[i] = AssignExpr(lhs[i])
76 assignType := func(i int, typ *types.Type) {
79 checkassignto(typ, lhs[i])
85 rhs[0] = typecheck(rhs[0], ctxExpr|ctxMultiOK)
86 if rtyp := rhs[0].Type(); rtyp != nil && rtyp.IsFuncArgStruct() {
95 for len(lhs) == 2 && cr == 1 {
96 stmt := stmt.(*ir.AssignListStmt)
101 stmt.SetOp(ir.OAS2MAPR)
103 stmt.SetOp(ir.OAS2RECV)
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)
116 assignType(0, r.Type())
117 assignType(1, types.UntypedBool)
122 if r, ok := rhs[0].(*ir.CallExpr); ok && len(rhs) == 1 {
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))
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)))
138 stmt := stmt.(*ir.AssignListStmt)
139 stmt.SetOp(ir.OAS2FUNC)
140 r := rhs[0].(*ir.CallExpr)
146 result := rtyp.Field(i).Type
147 assignType(i, result)
149 if lhs[i].Type() == nil || result == nil {
151 } else if lhs[i] != ir.BlankNode && !types.Identical(lhs[i].Type(), result) {
155 if mismatched && !failed {
156 RewriteMultiValueCall(stmt, r)
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")
169 func plural(n int) string {
176 // tcCheckNil typechecks an OCHECKNIL node.
177 func tcCheckNil(n *ir.UnaryExpr) ir.Node {
179 if !n.X.Type().IsPtrShaped() {
180 base.FatalfAt(n.Pos(), "%L is not pointer shaped", n.X)
185 // tcFor typechecks an OFOR node.
186 func tcFor(n *ir.ForStmt) ir.Node {
188 n.Cond = Expr(n.Cond)
189 n.Cond = DefaultLit(n.Cond, nil)
192 if t != nil && !t.IsBoolean() {
193 base.Errorf("non-bool %L used as for condition", n.Cond)
196 n.Post = Stmt(n.Post)
201 // tcGoDefer typechecks an OGO/ODEFER statement.
203 // Really, this means normalizing the statement to always use a simple
204 // function call with no arguments and no results. For example, it
212 // defer func() { f(x1, y1) }()
213 func tcGoDefer(n *ir.GoDeferStmt) {
217 init.Append(ir.TakeInit(call)...)
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
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)
229 // argps collects the list of operands within the call expression
230 // that must be evaluated at the go/defer statement.
233 var visit func(argp *ir.Node)
234 visit = func(argp *ir.Node) {
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
244 case ir.OLITERAL, ir.ONIL, ir.OMETHEXPR:
247 arg := arg.(*ir.Name)
248 if arg.Class == ir.PFUNC {
249 return // reference to global function
252 arg := arg.(*ir.AddrExpr)
253 if arg.X.Op() == ir.OLINKSYMOFFSET {
254 return // address of global symbol
258 arg := arg.(*ir.ConvExpr)
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.
264 // TODO(mdempsky): Limit to static callees with
265 // //go:uintptr{escapes,keepalive}?
266 if arg.Type().IsUintptr() && arg.X.Type().IsUnsafePtr() {
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) {
279 case *ir.StructKeyExpr:
288 argps = append(argps, argp)
291 visitList := func(list []ir.Node) {
292 for i := range list {
299 base.Fatalf("unexpected call op: %v", call.Op())
302 call := call.(*ir.CallExpr)
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
313 call := call.(*ir.CallExpr)
314 argps = append(argps, &call.X.(*ir.SelectorExpr).X) // must be first for OCHECKNIL; see below
317 case ir.OAPPEND, ir.ODELETE, ir.OPRINT, ir.OPRINTN, ir.ORECOVERFP:
318 call := call.(*ir.CallExpr)
323 call := call.(*ir.BinaryExpr)
328 case ir.OCLEAR, ir.OCLOSE, ir.OPANIC:
329 call := call.(*ir.UnaryExpr)
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.
341 as := ir.NewAssignListStmt(callPos, ir.OAS2, make([]ir.Node, len(argps)), make([]ir.Node, len(argps)))
342 for i, argp := range argps {
346 if ir.HasUniquePos(arg) {
351 tmp := TempAt(pos, ir.CurFunc, arg.Type())
352 init.Append(Stmt(ir.NewDecl(pos, ir.ODCL, tmp)))
357 // Rewrite original expression to use/capture tmp.
358 *argp = ir.NewClosureVar(pos, wrapperFn, tmp)
360 init.Append(Stmt(as))
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 {
366 init.Append(Stmt(ir.NewUnaryExpr(stmtPos, ir.OCHECKNIL, ir.NewUnaryExpr(iface.Pos(), ir.OITAB, iface))))
370 // Move call into the wrapper function, now that it's safe to
372 wrapperFn.Body = []ir.Node{call}
374 // Finally, rewrite the go/defer statement to call the wrapper.
375 n.Call = Call(call.Pos(), wrapperFn.OClosure, nil, false)
378 // tcIf typechecks an OIF node.
379 func tcIf(n *ir.IfStmt) ir.Node {
381 n.Cond = Expr(n.Cond)
382 n.Cond = DefaultLit(n.Cond, nil)
385 if t != nil && !t.IsBoolean() {
386 base.Errorf("non-bool %L used as if condition", n.Cond)
395 func tcRange(n *ir.RangeStmt) {
398 // delicate little dance. see tcAssignList
400 if !ir.DeclaredBy(n.Key, n) {
401 n.Key = AssignExpr(n.Key)
406 if !ir.DeclaredBy(n.Value, n) {
407 n.Value = AssignExpr(n.Value)
412 // second half of dance
414 if n.Key != nil && n.Key.Typecheck() == 0 {
415 n.Key = AssignExpr(n.Key)
417 if n.Value != nil && n.Value.Typecheck() == 0 {
418 n.Value = AssignExpr(n.Value)
424 // tcReturn typechecks an ORETURN node.
425 func tcReturn(n *ir.ReturnStmt) ir.Node {
427 if ir.CurFunc == nil {
428 base.Errorf("return outside function")
433 if ir.HasNamedResults(ir.CurFunc) && len(n.Results) == 0 {
436 typecheckaste(ir.ORETURN, nil, false, ir.CurFunc.Type().Results(), n.Results, func() string { return "return argument" })
441 func tcSelect(sel *ir.SelectStmt) {
442 var def *ir.CommClause
443 lno := ir.SetPos(sel)
445 for _, ncase := range sel.Cases {
446 if ncase.Comm == nil {
449 base.ErrorfAt(ncase.Pos(), errors.DuplicateDefault, "multiple defaults in select (first at %v)", ir.Line(def))
454 n := Stmt(ncase.Comm)
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})
459 selrecv.SetTypecheck(1)
460 selrecv.SetInit(n.Init())
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.
473 base.ErrorfAt(pos, errors.InvalidSelectCase, "select case must be receive, send or assign recv")
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)
486 if n.Y.Op() != ir.ORECV {
487 base.ErrorfAt(n.Pos(), errors.InvalidSelectCase, "select assignment must have receive on right hand side")
490 oselrecv2(n.X, n.Y, n.Def)
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")
498 n.SetOp(ir.OSELRECV2)
501 // convert <-c into _, _ = <-c
502 n := n.(*ir.UnaryExpr)
503 oselrecv2(ir.BlankNode, n, false)
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)
526 base.Errorf("invalid operation: %v (send to non-chan type %v)", n, t)
530 if !t.ChanDir().CanSend() {
531 base.Errorf("invalid operation: %v (send to receive-only type %v)", n, t)
535 n.Value = AssignConv(n.Value, t.Elem(), "send")
536 if n.Value.Type() == nil {
542 // tcSwitch typechecks a switch statement.
543 func tcSwitch(n *ir.SwitchStmt) {
545 if n.Tag != nil && n.Tag.Op() == ir.OTYPESW {
552 func tcSwitchExpr(n *ir.SwitchStmt) {
553 t := types.Types[types.TBOOL]
556 n.Tag = DefaultLit(n.Tag, nil)
565 case t.Kind() == types.TFUNC:
570 case !types.IsComparable(t):
572 base.ErrorfAt(n.Pos(), errors.InvalidExprSwitch, "cannot switch on %L (struct containing %v cannot be compared)", n.Tag, types.IncomparableField(t).Type)
574 base.ErrorfAt(n.Pos(), errors.InvalidExprSwitch, "cannot switch on %L", n.Tag)
581 for _, ncase := range n.Cases {
583 if len(ls) == 0 { // default:
585 base.ErrorfAt(ncase.Pos(), errors.DuplicateDefault, "multiple defaults in switch (first at %v)", ir.Line(defCase))
594 ls[i] = DefaultLit(ls[i], t)
596 if t == nil || n1.Type() == nil {
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)
605 op1, _ := Assignop(n1.Type(), t)
606 op2, _ := Assignop(t, n1.Type())
607 if op1 == ir.OXXX && op2 == ir.OXXX {
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)
611 base.ErrorfAt(ncase.Pos(), errors.MismatchedTypes, "invalid case %v in switch (mismatched types %v and bool)", n1, n1.Type())
621 func tcSwitchType(n *ir.SwitchStmt) {
622 guard := n.Tag.(*ir.TypeSwitchGuard)
623 guard.X = Expr(guard.X)
625 if t != nil && !t.IsInterface() {
626 base.ErrorfAt(n.Pos(), errors.InvalidTypeSwitch, "cannot type switch on non-interface value %L", guard.X)
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())
637 var defCase, nilCase ir.Node
639 for _, ncase := range n.Cases {
641 if len(ls) == 0 { // default:
643 base.ErrorfAt(ncase.Pos(), errors.DuplicateDefault, "multiple defaults in switch (first at %v)", ir.Line(defCase))
650 ls[i] = typecheck(ls[i], ctxExpr|ctxType)
652 if t == nil || n1.Type() == nil {
656 if ir.IsNil(n1) { // case nil:
658 base.ErrorfAt(ncase.Pos(), errors.DuplicateCase, "multiple nil cases in type switch (first at %v)", ir.Line(nilCase))
664 if n1.Op() == ir.ODYNAMICTYPE {
667 if n1.Op() != ir.OTYPE {
668 base.ErrorfAt(ncase.Pos(), errors.NotAType, "%L is not a type", n1)
671 if !n1.Type().IsInterface() {
672 why := ImplementsExplain(n1.Type(), t)
674 base.ErrorfAt(ncase.Pos(), errors.ImpossibleAssert, "impossible type switch case: %L cannot have dynamic type %v (%s)", guard.X, n1.Type(), why)
679 ts.add(ncase.Pos(), n1.Type())
682 if ncase.Var != nil {
683 // Assign the clause variable's type.
686 if ls[0].Op() == ir.OTYPE || ls[0].Op() == ir.ODYNAMICTYPE {
688 } else if !ir.IsNil(ls[0]) {
689 // Invalid single-type case;
690 // mark variable as broken.
698 nvar = AssignExpr(nvar).(*ir.Name)
700 // Clause variable is broken; prevent typechecking.
710 type typeSet struct {
711 m map[string]src.XPos
714 func (s *typeSet) add(pos src.XPos, typ *types.Type) {
716 s.m = make(map[string]src.XPos)
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))