Source file 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  )
    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  	// delicate little dance.  see tcAssignList
    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  // type check assignment.
    89  // if this assignment is the definition of a var on the left side,
    90  // fill in the var's type.
    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  	// TODO(mdempsky): This seems out of place.
   106  	if !ir.IsBlank(n.X) {
   107  		types.CheckSize(n.X.Type()) // ensure width is calculated for backend
   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  	// delicate little dance.
   121  	// the definition of lhs may refer to this assignment
   122  	// as its definition, in which case it will call tcAssign.
   123  	// in that case, do not call typecheck back, or it will cycle.
   124  	// if the variable has a type (ntype) then typechecking
   125  	// will not look at defn, so it is okay (and desirable,
   126  	// so that the conversion below happens).
   127  
   128  	checkLHS := func(i int, typ *types.Type) {
   129  		lhs[i] = Resolve(lhs[i])
   130  		if base.Flag.G != 0 || base.Debug.Unified != 0 {
   131  			// New logic added in CL 403837 for Go 1.19, which only has -G=3 and unified IR.
   132  			if n := lhs[i]; typ != nil && ir.DeclaredBy(n, stmt) && n.Type() == nil {
   133  				base.Assertf(typ.Kind() == types.TNIL, "unexpected untyped nil")
   134  				n.SetType(defaultType(typ))
   135  			}
   136  		} else {
   137  			// Original logic from Go 1.18, which is still needed for -G=0.
   138  			if n := lhs[i]; typ != nil && ir.DeclaredBy(n, stmt) && n.Name().Ntype == nil {
   139  				if typ.Kind() != types.TNIL {
   140  					n.SetType(defaultType(typ))
   141  				} else {
   142  					base.Errorf("use of untyped nil")
   143  				}
   144  			}
   145  		}
   146  
   147  		if lhs[i].Typecheck() == 0 {
   148  			lhs[i] = AssignExpr(lhs[i])
   149  		}
   150  		checkassign(stmt, lhs[i])
   151  	}
   152  
   153  	assignType := func(i int, typ *types.Type) {
   154  		checkLHS(i, typ)
   155  		if typ != nil {
   156  			checkassignto(typ, lhs[i])
   157  		}
   158  	}
   159  
   160  	cr := len(rhs)
   161  	if len(rhs) == 1 {
   162  		rhs[0] = typecheck(rhs[0], ctxExpr|ctxMultiOK)
   163  		if rtyp := rhs[0].Type(); rtyp != nil && rtyp.IsFuncArgStruct() {
   164  			cr = rtyp.NumFields()
   165  		}
   166  	} else {
   167  		Exprs(rhs)
   168  	}
   169  
   170  	// x, ok = y
   171  assignOK:
   172  	for len(lhs) == 2 && cr == 1 {
   173  		stmt := stmt.(*ir.AssignListStmt)
   174  		r := rhs[0]
   175  
   176  		switch r.Op() {
   177  		case ir.OINDEXMAP:
   178  			stmt.SetOp(ir.OAS2MAPR)
   179  		case ir.ORECV:
   180  			stmt.SetOp(ir.OAS2RECV)
   181  		case ir.ODOTTYPE:
   182  			r := r.(*ir.TypeAssertExpr)
   183  			stmt.SetOp(ir.OAS2DOTTYPE)
   184  			r.SetOp(ir.ODOTTYPE2)
   185  		case ir.ODYNAMICDOTTYPE:
   186  			r := r.(*ir.DynamicTypeAssertExpr)
   187  			stmt.SetOp(ir.OAS2DOTTYPE)
   188  			r.SetOp(ir.ODYNAMICDOTTYPE2)
   189  		default:
   190  			break assignOK
   191  		}
   192  
   193  		assignType(0, r.Type())
   194  		assignType(1, types.UntypedBool)
   195  		return
   196  	}
   197  
   198  	if len(lhs) != cr {
   199  		if r, ok := rhs[0].(*ir.CallExpr); ok && len(rhs) == 1 {
   200  			if r.Type() != nil {
   201  				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))
   202  			}
   203  		} else {
   204  			base.ErrorfAt(stmt.Pos(), "assignment mismatch: %d variable%s but %v value%s", len(lhs), plural(len(lhs)), len(rhs), plural(len(rhs)))
   205  		}
   206  
   207  		for i := range lhs {
   208  			checkLHS(i, nil)
   209  		}
   210  		return
   211  	}
   212  
   213  	// x,y,z = f()
   214  	if cr > len(rhs) {
   215  		stmt := stmt.(*ir.AssignListStmt)
   216  		stmt.SetOp(ir.OAS2FUNC)
   217  		r := rhs[0].(*ir.CallExpr)
   218  		rtyp := r.Type()
   219  
   220  		mismatched := false
   221  		failed := false
   222  		for i := range lhs {
   223  			result := rtyp.Field(i).Type
   224  			assignType(i, result)
   225  
   226  			if lhs[i].Type() == nil || result == nil {
   227  				failed = true
   228  			} else if lhs[i] != ir.BlankNode && !types.Identical(lhs[i].Type(), result) {
   229  				mismatched = true
   230  			}
   231  		}
   232  		if mismatched && !failed {
   233  			RewriteMultiValueCall(stmt, r)
   234  		}
   235  		return
   236  	}
   237  
   238  	for i, r := range rhs {
   239  		checkLHS(i, r.Type())
   240  		if lhs[i].Type() != nil {
   241  			rhs[i] = AssignConv(r, lhs[i].Type(), "assignment")
   242  		}
   243  	}
   244  }
   245  
   246  func plural(n int) string {
   247  	if n == 1 {
   248  		return ""
   249  	}
   250  	return "s"
   251  }
   252  
   253  // tcCheckNil typechecks an OCHECKNIL node.
   254  func tcCheckNil(n *ir.UnaryExpr) ir.Node {
   255  	n.X = Expr(n.X)
   256  	if !n.X.Type().IsPtrShaped() {
   257  		base.FatalfAt(n.Pos(), "%L is not pointer shaped", n.X)
   258  	}
   259  	return n
   260  }
   261  
   262  // tcFor typechecks an OFOR node.
   263  func tcFor(n *ir.ForStmt) ir.Node {
   264  	Stmts(n.Init())
   265  	n.Cond = Expr(n.Cond)
   266  	n.Cond = DefaultLit(n.Cond, nil)
   267  	if n.Cond != nil {
   268  		t := n.Cond.Type()
   269  		if t != nil && !t.IsBoolean() {
   270  			base.Errorf("non-bool %L used as for condition", n.Cond)
   271  		}
   272  	}
   273  	n.Post = Stmt(n.Post)
   274  	if n.Op() == ir.OFORUNTIL {
   275  		Stmts(n.Late)
   276  	}
   277  	Stmts(n.Body)
   278  	return n
   279  }
   280  
   281  func tcGoDefer(n *ir.GoDeferStmt) {
   282  	what := "defer"
   283  	if n.Op() == ir.OGO {
   284  		what = "go"
   285  	}
   286  
   287  	switch n.Call.Op() {
   288  	// ok
   289  	case ir.OCALLINTER,
   290  		ir.OCALLMETH,
   291  		ir.OCALLFUNC,
   292  		ir.OCLOSE,
   293  		ir.OCOPY,
   294  		ir.ODELETE,
   295  		ir.OPANIC,
   296  		ir.OPRINT,
   297  		ir.OPRINTN,
   298  		ir.ORECOVER:
   299  		return
   300  
   301  	case ir.OAPPEND,
   302  		ir.OCAP,
   303  		ir.OCOMPLEX,
   304  		ir.OIMAG,
   305  		ir.OLEN,
   306  		ir.OMAKE,
   307  		ir.OMAKESLICE,
   308  		ir.OMAKECHAN,
   309  		ir.OMAKEMAP,
   310  		ir.ONEW,
   311  		ir.OREAL,
   312  		ir.OLITERAL: // conversion or unsafe.Alignof, Offsetof, Sizeof
   313  		if orig := ir.Orig(n.Call); orig.Op() == ir.OCONV {
   314  			break
   315  		}
   316  		base.ErrorfAt(n.Pos(), "%s discards result of %v", what, n.Call)
   317  		return
   318  	}
   319  
   320  	// type is broken or missing, most likely a method call on a broken type
   321  	// we will warn about the broken type elsewhere. no need to emit a potentially confusing error
   322  	if n.Call.Type() == nil || n.Call.Type().Broke() {
   323  		return
   324  	}
   325  
   326  	if !n.Diag() {
   327  		// The syntax made sure it was a call, so this must be
   328  		// a conversion.
   329  		n.SetDiag(true)
   330  		base.ErrorfAt(n.Pos(), "%s requires function call, not conversion", what)
   331  	}
   332  }
   333  
   334  // tcIf typechecks an OIF node.
   335  func tcIf(n *ir.IfStmt) ir.Node {
   336  	Stmts(n.Init())
   337  	n.Cond = Expr(n.Cond)
   338  	n.Cond = DefaultLit(n.Cond, nil)
   339  	if n.Cond != nil {
   340  		t := n.Cond.Type()
   341  		if t != nil && !t.IsBoolean() {
   342  			base.Errorf("non-bool %L used as if condition", n.Cond)
   343  		}
   344  	}
   345  	Stmts(n.Body)
   346  	Stmts(n.Else)
   347  	return n
   348  }
   349  
   350  // range
   351  func tcRange(n *ir.RangeStmt) {
   352  	// Typechecking order is important here:
   353  	// 0. first typecheck range expression (slice/map/chan),
   354  	//	it is evaluated only once and so logically it is not part of the loop.
   355  	// 1. typecheck produced values,
   356  	//	this part can declare new vars and so it must be typechecked before body,
   357  	//	because body can contain a closure that captures the vars.
   358  	// 2. decldepth++ to denote loop body.
   359  	// 3. typecheck body.
   360  	// 4. decldepth--.
   361  	typecheckrangeExpr(n)
   362  
   363  	// second half of dance, the first half being typecheckrangeExpr
   364  	n.SetTypecheck(1)
   365  	if n.Key != nil && n.Key.Typecheck() == 0 {
   366  		n.Key = AssignExpr(n.Key)
   367  	}
   368  	if n.Value != nil && n.Value.Typecheck() == 0 {
   369  		n.Value = AssignExpr(n.Value)
   370  	}
   371  
   372  	Stmts(n.Body)
   373  }
   374  
   375  // tcReturn typechecks an ORETURN node.
   376  func tcReturn(n *ir.ReturnStmt) ir.Node {
   377  	typecheckargs(n)
   378  	if ir.CurFunc == nil {
   379  		base.Errorf("return outside function")
   380  		n.SetType(nil)
   381  		return n
   382  	}
   383  
   384  	if ir.HasNamedResults(ir.CurFunc) && len(n.Results) == 0 {
   385  		return n
   386  	}
   387  	typecheckaste(ir.ORETURN, nil, false, ir.CurFunc.Type().Results(), n.Results, func() string { return "return argument" })
   388  	return n
   389  }
   390  
   391  // select
   392  func tcSelect(sel *ir.SelectStmt) {
   393  	var def *ir.CommClause
   394  	lno := ir.SetPos(sel)
   395  	Stmts(sel.Init())
   396  	for _, ncase := range sel.Cases {
   397  		if ncase.Comm == nil {
   398  			// default
   399  			if def != nil {
   400  				base.ErrorfAt(ncase.Pos(), "multiple defaults in select (first at %v)", ir.Line(def))
   401  			} else {
   402  				def = ncase
   403  			}
   404  		} else {
   405  			n := Stmt(ncase.Comm)
   406  			ncase.Comm = n
   407  			oselrecv2 := func(dst, recv ir.Node, def bool) {
   408  				selrecv := ir.NewAssignListStmt(n.Pos(), ir.OSELRECV2, []ir.Node{dst, ir.BlankNode}, []ir.Node{recv})
   409  				selrecv.Def = def
   410  				selrecv.SetTypecheck(1)
   411  				selrecv.SetInit(n.Init())
   412  				ncase.Comm = selrecv
   413  			}
   414  			switch n.Op() {
   415  			default:
   416  				pos := n.Pos()
   417  				if n.Op() == ir.ONAME {
   418  					// We don't have the right position for ONAME nodes (see #15459 and
   419  					// others). Using ncase.Pos for now as it will provide the correct
   420  					// line number (assuming the expression follows the "case" keyword
   421  					// on the same line). This matches the approach before 1.10.
   422  					pos = ncase.Pos()
   423  				}
   424  				base.ErrorfAt(pos, "select case must be receive, send or assign recv")
   425  
   426  			case ir.OAS:
   427  				// convert x = <-c into x, _ = <-c
   428  				// remove implicit conversions; the eventual assignment
   429  				// will reintroduce them.
   430  				n := n.(*ir.AssignStmt)
   431  				if r := n.Y; r.Op() == ir.OCONVNOP || r.Op() == ir.OCONVIFACE {
   432  					r := r.(*ir.ConvExpr)
   433  					if r.Implicit() {
   434  						n.Y = r.X
   435  					}
   436  				}
   437  				if n.Y.Op() != ir.ORECV {
   438  					base.ErrorfAt(n.Pos(), "select assignment must have receive on right hand side")
   439  					break
   440  				}
   441  				oselrecv2(n.X, n.Y, n.Def)
   442  
   443  			case ir.OAS2RECV:
   444  				n := n.(*ir.AssignListStmt)
   445  				if n.Rhs[0].Op() != ir.ORECV {
   446  					base.ErrorfAt(n.Pos(), "select assignment must have receive on right hand side")
   447  					break
   448  				}
   449  				n.SetOp(ir.OSELRECV2)
   450  
   451  			case ir.ORECV:
   452  				// convert <-c into _, _ = <-c
   453  				n := n.(*ir.UnaryExpr)
   454  				oselrecv2(ir.BlankNode, n, false)
   455  
   456  			case ir.OSEND:
   457  				break
   458  			}
   459  		}
   460  
   461  		Stmts(ncase.Body)
   462  	}
   463  
   464  	base.Pos = lno
   465  }
   466  
   467  // tcSend typechecks an OSEND node.
   468  func tcSend(n *ir.SendStmt) ir.Node {
   469  	n.Chan = Expr(n.Chan)
   470  	n.Value = Expr(n.Value)
   471  	n.Chan = DefaultLit(n.Chan, nil)
   472  	t := n.Chan.Type()
   473  	if t == nil {
   474  		return n
   475  	}
   476  	if !t.IsChan() {
   477  		base.Errorf("invalid operation: %v (send to non-chan type %v)", n, t)
   478  		return n
   479  	}
   480  
   481  	if !t.ChanDir().CanSend() {
   482  		base.Errorf("invalid operation: %v (send to receive-only type %v)", n, t)
   483  		return n
   484  	}
   485  
   486  	n.Value = AssignConv(n.Value, t.Elem(), "send")
   487  	if n.Value.Type() == nil {
   488  		return n
   489  	}
   490  	return n
   491  }
   492  
   493  // tcSwitch typechecks a switch statement.
   494  func tcSwitch(n *ir.SwitchStmt) {
   495  	Stmts(n.Init())
   496  	if n.Tag != nil && n.Tag.Op() == ir.OTYPESW {
   497  		tcSwitchType(n)
   498  	} else {
   499  		tcSwitchExpr(n)
   500  	}
   501  }
   502  
   503  func tcSwitchExpr(n *ir.SwitchStmt) {
   504  	t := types.Types[types.TBOOL]
   505  	if n.Tag != nil {
   506  		n.Tag = Expr(n.Tag)
   507  		n.Tag = DefaultLit(n.Tag, nil)
   508  		t = n.Tag.Type()
   509  	}
   510  
   511  	var nilonly string
   512  	if t != nil {
   513  		switch {
   514  		case t.IsMap():
   515  			nilonly = "map"
   516  		case t.Kind() == types.TFUNC:
   517  			nilonly = "func"
   518  		case t.IsSlice():
   519  			nilonly = "slice"
   520  
   521  		case !types.IsComparable(t):
   522  			if t.IsStruct() {
   523  				base.ErrorfAt(n.Pos(), "cannot switch on %L (struct containing %v cannot be compared)", n.Tag, types.IncomparableField(t).Type)
   524  			} else {
   525  				base.ErrorfAt(n.Pos(), "cannot switch on %L", n.Tag)
   526  			}
   527  			t = nil
   528  		}
   529  	}
   530  
   531  	var defCase ir.Node
   532  	var cs constSet
   533  	for _, ncase := range n.Cases {
   534  		ls := ncase.List
   535  		if len(ls) == 0 { // default:
   536  			if defCase != nil {
   537  				base.ErrorfAt(ncase.Pos(), "multiple defaults in switch (first at %v)", ir.Line(defCase))
   538  			} else {
   539  				defCase = ncase
   540  			}
   541  		}
   542  
   543  		for i := range ls {
   544  			ir.SetPos(ncase)
   545  			ls[i] = Expr(ls[i])
   546  			ls[i] = DefaultLit(ls[i], t)
   547  			n1 := ls[i]
   548  			if t == nil || n1.Type() == nil {
   549  				continue
   550  			}
   551  
   552  			if nilonly != "" && !ir.IsNil(n1) {
   553  				base.ErrorfAt(ncase.Pos(), "invalid case %v in switch (can only compare %s %v to nil)", n1, nilonly, n.Tag)
   554  			} else if t.IsInterface() && !n1.Type().IsInterface() && !types.IsComparable(n1.Type()) {
   555  				base.ErrorfAt(ncase.Pos(), "invalid case %L in switch (incomparable type)", n1)
   556  			} else {
   557  				op1, _ := Assignop(n1.Type(), t)
   558  				op2, _ := Assignop(t, n1.Type())
   559  				if op1 == ir.OXXX && op2 == ir.OXXX {
   560  					if n.Tag != nil {
   561  						base.ErrorfAt(ncase.Pos(), "invalid case %v in switch on %v (mismatched types %v and %v)", n1, n.Tag, n1.Type(), t)
   562  					} else {
   563  						base.ErrorfAt(ncase.Pos(), "invalid case %v in switch (mismatched types %v and bool)", n1, n1.Type())
   564  					}
   565  				}
   566  			}
   567  
   568  			// Don't check for duplicate bools. Although the spec allows it,
   569  			// (1) the compiler hasn't checked it in the past, so compatibility mandates it, and
   570  			// (2) it would disallow useful things like
   571  			//       case GOARCH == "arm" && GOARM == "5":
   572  			//       case GOARCH == "arm":
   573  			//     which would both evaluate to false for non-ARM compiles.
   574  			if !n1.Type().IsBoolean() {
   575  				cs.add(ncase.Pos(), n1, "case", "switch")
   576  			}
   577  		}
   578  
   579  		Stmts(ncase.Body)
   580  	}
   581  }
   582  
   583  func tcSwitchType(n *ir.SwitchStmt) {
   584  	guard := n.Tag.(*ir.TypeSwitchGuard)
   585  	guard.X = Expr(guard.X)
   586  	t := guard.X.Type()
   587  	if t != nil && !t.IsInterface() {
   588  		base.ErrorfAt(n.Pos(), "cannot type switch on non-interface value %L", guard.X)
   589  		t = nil
   590  	}
   591  
   592  	// We don't actually declare the type switch's guarded
   593  	// declaration itself. So if there are no cases, we won't
   594  	// notice that it went unused.
   595  	if v := guard.Tag; v != nil && !ir.IsBlank(v) && len(n.Cases) == 0 {
   596  		base.ErrorfAt(v.Pos(), "%v declared but not used", v.Sym())
   597  	}
   598  
   599  	var defCase, nilCase ir.Node
   600  	var ts typeSet
   601  	for _, ncase := range n.Cases {
   602  		ls := ncase.List
   603  		if len(ls) == 0 { // default:
   604  			if defCase != nil {
   605  				base.ErrorfAt(ncase.Pos(), "multiple defaults in switch (first at %v)", ir.Line(defCase))
   606  			} else {
   607  				defCase = ncase
   608  			}
   609  		}
   610  
   611  		for i := range ls {
   612  			ls[i] = typecheck(ls[i], ctxExpr|ctxType)
   613  			n1 := ls[i]
   614  			if t == nil || n1.Type() == nil {
   615  				continue
   616  			}
   617  
   618  			var missing, have *types.Field
   619  			var ptr int
   620  			if ir.IsNil(n1) { // case nil:
   621  				if nilCase != nil {
   622  					base.ErrorfAt(ncase.Pos(), "multiple nil cases in type switch (first at %v)", ir.Line(nilCase))
   623  				} else {
   624  					nilCase = ncase
   625  				}
   626  				continue
   627  			}
   628  			if n1.Op() != ir.OTYPE {
   629  				base.ErrorfAt(ncase.Pos(), "%L is not a type", n1)
   630  				continue
   631  			}
   632  			if !n1.Type().IsInterface() && !implements(n1.Type(), t, &missing, &have, &ptr) && !missing.Broke() {
   633  				if have != nil && !have.Broke() {
   634  					base.ErrorfAt(ncase.Pos(), "impossible type switch case: %L cannot have dynamic type %v"+
   635  						" (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)
   636  				} else if ptr != 0 {
   637  					base.ErrorfAt(ncase.Pos(), "impossible type switch case: %L cannot have dynamic type %v"+
   638  						" (%v method has pointer receiver)", guard.X, n1.Type(), missing.Sym)
   639  				} else {
   640  					base.ErrorfAt(ncase.Pos(), "impossible type switch case: %L cannot have dynamic type %v"+
   641  						" (missing %v method)", guard.X, n1.Type(), missing.Sym)
   642  				}
   643  				continue
   644  			}
   645  
   646  			ts.add(ncase.Pos(), n1.Type())
   647  		}
   648  
   649  		if ncase.Var != nil {
   650  			// Assign the clause variable's type.
   651  			vt := t
   652  			if len(ls) == 1 {
   653  				if ls[0].Op() == ir.OTYPE {
   654  					vt = ls[0].Type()
   655  				} else if !ir.IsNil(ls[0]) {
   656  					// Invalid single-type case;
   657  					// mark variable as broken.
   658  					vt = nil
   659  				}
   660  			}
   661  
   662  			nvar := ncase.Var
   663  			nvar.SetType(vt)
   664  			if vt != nil {
   665  				nvar = AssignExpr(nvar).(*ir.Name)
   666  			} else {
   667  				// Clause variable is broken; prevent typechecking.
   668  				nvar.SetTypecheck(1)
   669  				nvar.SetWalkdef(1)
   670  			}
   671  			ncase.Var = nvar
   672  		}
   673  
   674  		Stmts(ncase.Body)
   675  	}
   676  }
   677  
   678  type typeSet struct {
   679  	m map[string]src.XPos
   680  }
   681  
   682  func (s *typeSet) add(pos src.XPos, typ *types.Type) {
   683  	if s.m == nil {
   684  		s.m = make(map[string]src.XPos)
   685  	}
   686  
   687  	ls := typ.LinkString()
   688  	if prev, ok := s.m[ls]; ok {
   689  		base.ErrorfAt(pos, "duplicate case %v in type switch\n\tprevious case at %s", typ, base.FmtPos(prev))
   690  		return
   691  	}
   692  	s.m[ls] = pos
   693  }
   694  

View as plain text