github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/cmd/compile/internal/gc/swt.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 gc
     6  
     7  import (
     8  	"cmd/compile/internal/types"
     9  	"fmt"
    10  	"sort"
    11  )
    12  
    13  const (
    14  	// expression switch
    15  	switchKindExpr  = iota // switch a {...} or switch 5 {...}
    16  	switchKindTrue         // switch true {...} or switch {...}
    17  	switchKindFalse        // switch false {...}
    18  )
    19  
    20  const (
    21  	binarySearchMin = 4 // minimum number of cases for binary search
    22  	integerRangeMin = 2 // minimum size of integer ranges
    23  )
    24  
    25  // An exprSwitch walks an expression switch.
    26  type exprSwitch struct {
    27  	exprname *Node // node for the expression being switched on
    28  	kind     int   // kind of switch statement (switchKind*)
    29  }
    30  
    31  // A typeSwitch walks a type switch.
    32  type typeSwitch struct {
    33  	hashname *Node // node for the hash of the type of the variable being switched on
    34  	facename *Node // node for the concrete type of the variable being switched on
    35  	okname   *Node // boolean node used for comma-ok type assertions
    36  }
    37  
    38  // A caseClause is a single case clause in a switch statement.
    39  type caseClause struct {
    40  	node    *Node  // points at case statement
    41  	ordinal int    // position in switch
    42  	hash    uint32 // hash of a type switch
    43  	// isconst indicates whether this case clause is a constant,
    44  	// for the purposes of the switch code generation.
    45  	// For expression switches, that's generally literals (case 5:, not case x:).
    46  	// For type switches, that's concrete types (case time.Time:), not interfaces (case io.Reader:).
    47  	isconst bool
    48  }
    49  
    50  // caseClauses are all the case clauses in a switch statement.
    51  type caseClauses struct {
    52  	list   []caseClause // general cases
    53  	defjmp *Node        // OGOTO for default case or OBREAK if no default case present
    54  	niljmp *Node        // OGOTO for nil type case in a type switch
    55  }
    56  
    57  // typecheckswitch typechecks a switch statement.
    58  func typecheckswitch(n *Node) {
    59  	typecheckslice(n.Ninit.Slice(), ctxStmt)
    60  
    61  	var nilonly string
    62  	var top int
    63  	var t *types.Type
    64  
    65  	if n.Left != nil && n.Left.Op == OTYPESW {
    66  		// type switch
    67  		top = Etype
    68  		n.Left.Right = typecheck(n.Left.Right, ctxExpr)
    69  		t = n.Left.Right.Type
    70  		if t != nil && !t.IsInterface() {
    71  			yyerrorl(n.Pos, "cannot type switch on non-interface value %L", n.Left.Right)
    72  		}
    73  		if v := n.Left.Left; v != nil && !v.isBlank() && n.List.Len() == 0 {
    74  			// We don't actually declare the type switch's guarded
    75  			// declaration itself. So if there are no cases, we
    76  			// won't notice that it went unused.
    77  			yyerrorl(v.Pos, "%v declared and not used", v.Sym)
    78  		}
    79  	} else {
    80  		// expression switch
    81  		top = ctxExpr
    82  		if n.Left != nil {
    83  			n.Left = typecheck(n.Left, ctxExpr)
    84  			n.Left = defaultlit(n.Left, nil)
    85  			t = n.Left.Type
    86  		} else {
    87  			t = types.Types[TBOOL]
    88  		}
    89  		if t != nil {
    90  			switch {
    91  			case !okforeq[t.Etype]:
    92  				yyerrorl(n.Pos, "cannot switch on %L", n.Left)
    93  			case t.IsSlice():
    94  				nilonly = "slice"
    95  			case t.IsArray() && !IsComparable(t):
    96  				yyerrorl(n.Pos, "cannot switch on %L", n.Left)
    97  			case t.IsStruct():
    98  				if f := IncomparableField(t); f != nil {
    99  					yyerrorl(n.Pos, "cannot switch on %L (struct containing %v cannot be compared)", n.Left, f.Type)
   100  				}
   101  			case t.Etype == TFUNC:
   102  				nilonly = "func"
   103  			case t.IsMap():
   104  				nilonly = "map"
   105  			}
   106  		}
   107  	}
   108  
   109  	n.Type = t
   110  
   111  	var def, niltype *Node
   112  	for _, ncase := range n.List.Slice() {
   113  		if ncase.List.Len() == 0 {
   114  			// default
   115  			if def != nil {
   116  				setlineno(ncase)
   117  				yyerrorl(ncase.Pos, "multiple defaults in switch (first at %v)", def.Line())
   118  			} else {
   119  				def = ncase
   120  			}
   121  		} else {
   122  			ls := ncase.List.Slice()
   123  			for i1, n1 := range ls {
   124  				setlineno(n1)
   125  				ls[i1] = typecheck(ls[i1], ctxExpr|Etype)
   126  				n1 = ls[i1]
   127  				if n1.Type == nil || t == nil {
   128  					continue
   129  				}
   130  
   131  				setlineno(ncase)
   132  				switch top {
   133  				// expression switch
   134  				case ctxExpr:
   135  					ls[i1] = defaultlit(ls[i1], t)
   136  					n1 = ls[i1]
   137  					switch {
   138  					case n1.Op == OTYPE:
   139  						yyerrorl(ncase.Pos, "type %v is not an expression", n1.Type)
   140  					case n1.Type != nil && assignop(n1.Type, t, nil) == 0 && assignop(t, n1.Type, nil) == 0:
   141  						if n.Left != nil {
   142  							yyerrorl(ncase.Pos, "invalid case %v in switch on %v (mismatched types %v and %v)", n1, n.Left, n1.Type, t)
   143  						} else {
   144  							yyerrorl(ncase.Pos, "invalid case %v in switch (mismatched types %v and bool)", n1, n1.Type)
   145  						}
   146  					case nilonly != "" && !n1.isNil():
   147  						yyerrorl(ncase.Pos, "invalid case %v in switch (can only compare %s %v to nil)", n1, nilonly, n.Left)
   148  					case t.IsInterface() && !n1.Type.IsInterface() && !IsComparable(n1.Type):
   149  						yyerrorl(ncase.Pos, "invalid case %L in switch (incomparable type)", n1)
   150  					}
   151  
   152  				// type switch
   153  				case Etype:
   154  					var missing, have *types.Field
   155  					var ptr int
   156  					switch {
   157  					case n1.Op == OLITERAL && n1.Type.IsKind(TNIL):
   158  						// case nil:
   159  						if niltype != nil {
   160  							yyerrorl(ncase.Pos, "multiple nil cases in type switch (first at %v)", niltype.Line())
   161  						} else {
   162  							niltype = ncase
   163  						}
   164  					case n1.Op != OTYPE && n1.Type != nil: // should this be ||?
   165  						yyerrorl(ncase.Pos, "%L is not a type", n1)
   166  						// reset to original type
   167  						n1 = n.Left.Right
   168  						ls[i1] = n1
   169  					case !n1.Type.IsInterface() && t.IsInterface() && !implements(n1.Type, t, &missing, &have, &ptr):
   170  						if have != nil && !missing.Broke() && !have.Broke() {
   171  							yyerrorl(ncase.Pos, "impossible type switch case: %L cannot have dynamic type %v"+
   172  								" (wrong type for %v method)\n\thave %v%S\n\twant %v%S", n.Left.Right, n1.Type, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
   173  						} else if !missing.Broke() {
   174  							if ptr != 0 {
   175  								yyerrorl(ncase.Pos, "impossible type switch case: %L cannot have dynamic type %v"+
   176  									" (%v method has pointer receiver)", n.Left.Right, n1.Type, missing.Sym)
   177  							} else {
   178  								yyerrorl(ncase.Pos, "impossible type switch case: %L cannot have dynamic type %v"+
   179  									" (missing %v method)", n.Left.Right, n1.Type, missing.Sym)
   180  							}
   181  						}
   182  					}
   183  				}
   184  			}
   185  		}
   186  
   187  		if n.Type == nil || n.Type.IsUntyped() {
   188  			// if the value we're switching on has no type or is untyped,
   189  			// we've already printed an error and don't need to continue
   190  			// typechecking the body
   191  			return
   192  		}
   193  
   194  		if top == Etype {
   195  			ll := ncase.List
   196  			if ncase.Rlist.Len() != 0 {
   197  				nvar := ncase.Rlist.First()
   198  				if ll.Len() == 1 && ll.First().Type != nil && !ll.First().Type.IsKind(TNIL) {
   199  					// single entry type switch
   200  					nvar.Type = ll.First().Type
   201  				} else {
   202  					// multiple entry type switch or default
   203  					nvar.Type = n.Type
   204  				}
   205  
   206  				nvar = typecheck(nvar, ctxExpr|ctxAssign)
   207  				ncase.Rlist.SetFirst(nvar)
   208  			}
   209  		}
   210  
   211  		typecheckslice(ncase.Nbody.Slice(), ctxStmt)
   212  	}
   213  	switch top {
   214  	// expression switch
   215  	case ctxExpr:
   216  		checkDupExprCases(n.Left, n.List.Slice())
   217  	}
   218  }
   219  
   220  // walkswitch walks a switch statement.
   221  func walkswitch(sw *Node) {
   222  	// convert switch {...} to switch true {...}
   223  	if sw.Left == nil {
   224  		sw.Left = nodbool(true)
   225  		sw.Left = typecheck(sw.Left, ctxExpr)
   226  		sw.Left = defaultlit(sw.Left, nil)
   227  	}
   228  
   229  	if sw.Left.Op == OTYPESW {
   230  		var s typeSwitch
   231  		s.walk(sw)
   232  	} else {
   233  		var s exprSwitch
   234  		s.walk(sw)
   235  	}
   236  }
   237  
   238  // walk generates an AST implementing sw.
   239  // sw is an expression switch.
   240  // The AST is generally of the form of a linear
   241  // search using if..goto, although binary search
   242  // is used with long runs of constants.
   243  func (s *exprSwitch) walk(sw *Node) {
   244  	// Guard against double walk, see #25776.
   245  	if sw.List.Len() == 0 && sw.Nbody.Len() > 0 {
   246  		return // Was fatal, but eliminating every possible source of double-walking is hard
   247  	}
   248  
   249  	casebody(sw, nil)
   250  
   251  	cond := sw.Left
   252  	sw.Left = nil
   253  
   254  	s.kind = switchKindExpr
   255  	if Isconst(cond, CTBOOL) {
   256  		s.kind = switchKindTrue
   257  		if !cond.Val().U.(bool) {
   258  			s.kind = switchKindFalse
   259  		}
   260  	}
   261  
   262  	// Given "switch string(byteslice)",
   263  	// with all cases being constants (or the default case),
   264  	// use a zero-cost alias of the byte slice.
   265  	// In theory, we could be more aggressive,
   266  	// allowing any side-effect-free expressions in cases,
   267  	// but it's a bit tricky because some of that information
   268  	// is unavailable due to the introduction of temporaries during order.
   269  	// Restricting to constants is simple and probably powerful enough.
   270  	// Do this before calling walkexpr on cond,
   271  	// because walkexpr will lower the string
   272  	// conversion into a runtime call.
   273  	// See issue 24937 for more discussion.
   274  	if cond.Op == OBYTES2STR {
   275  		ok := true
   276  		for _, cas := range sw.List.Slice() {
   277  			if cas.Op != OCASE {
   278  				Fatalf("switch string(byteslice) bad op: %v", cas.Op)
   279  			}
   280  			if cas.Left != nil && !Isconst(cas.Left, CTSTR) {
   281  				ok = false
   282  				break
   283  			}
   284  		}
   285  		if ok {
   286  			cond.Op = OBYTES2STRTMP
   287  		}
   288  	}
   289  
   290  	cond = walkexpr(cond, &sw.Ninit)
   291  	t := sw.Type
   292  	if t == nil {
   293  		return
   294  	}
   295  
   296  	// convert the switch into OIF statements
   297  	var cas []*Node
   298  	if s.kind == switchKindTrue || s.kind == switchKindFalse {
   299  		s.exprname = nodbool(s.kind == switchKindTrue)
   300  	} else if consttype(cond) > 0 {
   301  		// leave constants to enable dead code elimination (issue 9608)
   302  		s.exprname = cond
   303  	} else {
   304  		s.exprname = temp(cond.Type)
   305  		cas = []*Node{nod(OAS, s.exprname, cond)} // This gets walk()ed again in walkstmtlist just before end of this function.  See #29562.
   306  		typecheckslice(cas, ctxStmt)
   307  	}
   308  
   309  	// Enumerate the cases and prepare the default case.
   310  	clauses := s.genCaseClauses(sw.List.Slice())
   311  	sw.List.Set(nil)
   312  	cc := clauses.list
   313  
   314  	// handle the cases in order
   315  	for len(cc) > 0 {
   316  		run := 1
   317  		if okforcmp[t.Etype] && cc[0].isconst {
   318  			// do binary search on runs of constants
   319  			for ; run < len(cc) && cc[run].isconst; run++ {
   320  			}
   321  			// sort and compile constants
   322  			sort.Sort(caseClauseByConstVal(cc[:run]))
   323  		}
   324  
   325  		a := s.walkCases(cc[:run])
   326  		cas = append(cas, a)
   327  		cc = cc[run:]
   328  	}
   329  
   330  	// handle default case
   331  	if nerrors == 0 {
   332  		cas = append(cas, clauses.defjmp)
   333  		sw.Nbody.Prepend(cas...)
   334  		walkstmtlist(sw.Nbody.Slice())
   335  	}
   336  }
   337  
   338  // walkCases generates an AST implementing the cases in cc.
   339  func (s *exprSwitch) walkCases(cc []caseClause) *Node {
   340  	if len(cc) < binarySearchMin {
   341  		// linear search
   342  		var cas []*Node
   343  		for _, c := range cc {
   344  			n := c.node
   345  			lno := setlineno(n)
   346  
   347  			a := nod(OIF, nil, nil)
   348  			if rng := n.List.Slice(); rng != nil {
   349  				// Integer range.
   350  				// exprname is a temp or a constant,
   351  				// so it is safe to evaluate twice.
   352  				// In most cases, this conjunction will be
   353  				// rewritten by walkinrange into a single comparison.
   354  				low := nod(OGE, s.exprname, rng[0])
   355  				high := nod(OLE, s.exprname, rng[1])
   356  				a.Left = nod(OANDAND, low, high)
   357  			} else if (s.kind != switchKindTrue && s.kind != switchKindFalse) || assignop(n.Left.Type, s.exprname.Type, nil) == OCONVIFACE || assignop(s.exprname.Type, n.Left.Type, nil) == OCONVIFACE {
   358  				a.Left = nod(OEQ, s.exprname, n.Left) // if name == val
   359  			} else if s.kind == switchKindTrue {
   360  				a.Left = n.Left // if val
   361  			} else {
   362  				// s.kind == switchKindFalse
   363  				a.Left = nod(ONOT, n.Left, nil) // if !val
   364  			}
   365  			a.Left = typecheck(a.Left, ctxExpr)
   366  			a.Left = defaultlit(a.Left, nil)
   367  			a.Nbody.Set1(n.Right) // goto l
   368  
   369  			cas = append(cas, a)
   370  			lineno = lno
   371  		}
   372  		return liststmt(cas)
   373  	}
   374  
   375  	// find the middle and recur
   376  	half := len(cc) / 2
   377  	a := nod(OIF, nil, nil)
   378  	n := cc[half-1].node
   379  	var mid *Node
   380  	if rng := n.List.Slice(); rng != nil {
   381  		mid = rng[1] // high end of range
   382  	} else {
   383  		mid = n.Left
   384  	}
   385  	le := nod(OLE, s.exprname, mid)
   386  	if Isconst(mid, CTSTR) {
   387  		// Search by length and then by value; see caseClauseByConstVal.
   388  		lenlt := nod(OLT, nod(OLEN, s.exprname, nil), nod(OLEN, mid, nil))
   389  		leneq := nod(OEQ, nod(OLEN, s.exprname, nil), nod(OLEN, mid, nil))
   390  		a.Left = nod(OOROR, lenlt, nod(OANDAND, leneq, le))
   391  	} else {
   392  		a.Left = le
   393  	}
   394  	a.Left = typecheck(a.Left, ctxExpr)
   395  	a.Left = defaultlit(a.Left, nil)
   396  	a.Nbody.Set1(s.walkCases(cc[:half]))
   397  	a.Rlist.Set1(s.walkCases(cc[half:]))
   398  	return a
   399  }
   400  
   401  // casebody builds separate lists of statements and cases.
   402  // It makes labels between cases and statements
   403  // and deals with fallthrough, break, and unreachable statements.
   404  func casebody(sw *Node, typeswvar *Node) {
   405  	if sw.List.Len() == 0 {
   406  		return
   407  	}
   408  
   409  	lno := setlineno(sw)
   410  
   411  	var cas []*Node  // cases
   412  	var stat []*Node // statements
   413  	var def *Node    // defaults
   414  	br := nod(OBREAK, nil, nil)
   415  
   416  	for _, n := range sw.List.Slice() {
   417  		setlineno(n)
   418  		if n.Op != OXCASE {
   419  			Fatalf("casebody %v", n.Op)
   420  		}
   421  		n.Op = OCASE
   422  		needvar := n.List.Len() != 1 || n.List.First().Op == OLITERAL
   423  
   424  		lbl := autolabel(".s")
   425  		jmp := nodSym(OGOTO, nil, lbl)
   426  		switch n.List.Len() {
   427  		case 0:
   428  			// default
   429  			if def != nil {
   430  				yyerrorl(n.Pos, "more than one default case")
   431  			}
   432  			// reuse original default case
   433  			n.Right = jmp
   434  			def = n
   435  		case 1:
   436  			// one case -- reuse OCASE node
   437  			n.Left = n.List.First()
   438  			n.Right = jmp
   439  			n.List.Set(nil)
   440  			cas = append(cas, n)
   441  		default:
   442  			// Expand multi-valued cases and detect ranges of integer cases.
   443  			if typeswvar != nil || sw.Left.Type.IsInterface() || !n.List.First().Type.IsInteger() || n.List.Len() < integerRangeMin {
   444  				// Can't use integer ranges. Expand each case into a separate node.
   445  				for _, n1 := range n.List.Slice() {
   446  					cas = append(cas, nod(OCASE, n1, jmp))
   447  				}
   448  				break
   449  			}
   450  			// Find integer ranges within runs of constants.
   451  			s := n.List.Slice()
   452  			j := 0
   453  			for j < len(s) {
   454  				// Find a run of constants.
   455  				var run int
   456  				for run = j; run < len(s) && Isconst(s[run], CTINT); run++ {
   457  				}
   458  				if run-j >= integerRangeMin {
   459  					// Search for integer ranges in s[j:run].
   460  					// Typechecking is done, so all values are already in an appropriate range.
   461  					search := s[j:run]
   462  					sort.Sort(constIntNodesByVal(search))
   463  					for beg, end := 0, 1; end <= len(search); end++ {
   464  						if end < len(search) && search[end].Int64() == search[end-1].Int64()+1 {
   465  							continue
   466  						}
   467  						if end-beg >= integerRangeMin {
   468  							// Record range in List.
   469  							c := nod(OCASE, nil, jmp)
   470  							c.List.Set2(search[beg], search[end-1])
   471  							cas = append(cas, c)
   472  						} else {
   473  							// Not large enough for range; record separately.
   474  							for _, n := range search[beg:end] {
   475  								cas = append(cas, nod(OCASE, n, jmp))
   476  							}
   477  						}
   478  						beg = end
   479  					}
   480  					j = run
   481  				}
   482  				// Advance to next constant, adding individual non-constant
   483  				// or as-yet-unhandled constant cases as we go.
   484  				for ; j < len(s) && (j < run || !Isconst(s[j], CTINT)); j++ {
   485  					cas = append(cas, nod(OCASE, s[j], jmp))
   486  				}
   487  			}
   488  		}
   489  
   490  		stat = append(stat, nodSym(OLABEL, nil, lbl))
   491  		if typeswvar != nil && needvar && n.Rlist.Len() != 0 {
   492  			l := []*Node{
   493  				nod(ODCL, n.Rlist.First(), nil),
   494  				nod(OAS, n.Rlist.First(), typeswvar),
   495  			}
   496  			typecheckslice(l, ctxStmt)
   497  			stat = append(stat, l...)
   498  		}
   499  		stat = append(stat, n.Nbody.Slice()...)
   500  
   501  		// Search backwards for the index of the fallthrough
   502  		// statement. Do not assume it'll be in the last
   503  		// position, since in some cases (e.g. when the statement
   504  		// list contains autotmp_ variables), one or more OVARKILL
   505  		// nodes will be at the end of the list.
   506  		fallIndex := len(stat) - 1
   507  		for stat[fallIndex].Op == OVARKILL {
   508  			fallIndex--
   509  		}
   510  		last := stat[fallIndex]
   511  		if last.Op != OFALL {
   512  			stat = append(stat, br)
   513  		}
   514  	}
   515  
   516  	stat = append(stat, br)
   517  	if def != nil {
   518  		cas = append(cas, def)
   519  	}
   520  
   521  	sw.List.Set(cas)
   522  	sw.Nbody.Set(stat)
   523  	lineno = lno
   524  }
   525  
   526  // genCaseClauses generates the caseClauses value for clauses.
   527  func (s *exprSwitch) genCaseClauses(clauses []*Node) caseClauses {
   528  	var cc caseClauses
   529  	for _, n := range clauses {
   530  		if n.Left == nil && n.List.Len() == 0 {
   531  			// default case
   532  			if cc.defjmp != nil {
   533  				Fatalf("duplicate default case not detected during typechecking")
   534  			}
   535  			cc.defjmp = n.Right
   536  			continue
   537  		}
   538  		c := caseClause{node: n, ordinal: len(cc.list)}
   539  		if n.List.Len() > 0 {
   540  			c.isconst = true
   541  		}
   542  		switch consttype(n.Left) {
   543  		case CTFLT, CTINT, CTRUNE, CTSTR:
   544  			c.isconst = true
   545  		}
   546  		cc.list = append(cc.list, c)
   547  	}
   548  
   549  	if cc.defjmp == nil {
   550  		cc.defjmp = nod(OBREAK, nil, nil)
   551  	}
   552  	return cc
   553  }
   554  
   555  // genCaseClauses generates the caseClauses value for clauses.
   556  func (s *typeSwitch) genCaseClauses(clauses []*Node) caseClauses {
   557  	var cc caseClauses
   558  	for _, n := range clauses {
   559  		switch {
   560  		case n.Left == nil:
   561  			// default case
   562  			if cc.defjmp != nil {
   563  				Fatalf("duplicate default case not detected during typechecking")
   564  			}
   565  			cc.defjmp = n.Right
   566  			continue
   567  		case n.Left.Op == OLITERAL:
   568  			// nil case in type switch
   569  			if cc.niljmp != nil {
   570  				Fatalf("duplicate nil case not detected during typechecking")
   571  			}
   572  			cc.niljmp = n.Right
   573  			continue
   574  		}
   575  
   576  		// general case
   577  		c := caseClause{
   578  			node:    n,
   579  			ordinal: len(cc.list),
   580  			isconst: !n.Left.Type.IsInterface(),
   581  			hash:    typehash(n.Left.Type),
   582  		}
   583  		cc.list = append(cc.list, c)
   584  	}
   585  
   586  	if cc.defjmp == nil {
   587  		cc.defjmp = nod(OBREAK, nil, nil)
   588  	}
   589  
   590  	// diagnose duplicate cases
   591  	s.checkDupCases(cc.list)
   592  	return cc
   593  }
   594  
   595  func (s *typeSwitch) checkDupCases(cc []caseClause) {
   596  	if len(cc) < 2 {
   597  		return
   598  	}
   599  	// We store seen types in a map keyed by type hash.
   600  	// It is possible, but very unlikely, for multiple distinct types to have the same hash.
   601  	seen := make(map[uint32][]*Node)
   602  	// To avoid many small allocations of length 1 slices,
   603  	// also set up a single large slice to slice into.
   604  	nn := make([]*Node, 0, len(cc))
   605  Outer:
   606  	for _, c := range cc {
   607  		prev, ok := seen[c.hash]
   608  		if !ok {
   609  			// First entry for this hash.
   610  			nn = append(nn, c.node)
   611  			seen[c.hash] = nn[len(nn)-1 : len(nn) : len(nn)]
   612  			continue
   613  		}
   614  		for _, n := range prev {
   615  			if types.Identical(n.Left.Type, c.node.Left.Type) {
   616  				yyerrorl(c.node.Pos, "duplicate case %v in type switch\n\tprevious case at %v", c.node.Left.Type, n.Line())
   617  				// avoid double-reporting errors
   618  				continue Outer
   619  			}
   620  		}
   621  		seen[c.hash] = append(seen[c.hash], c.node)
   622  	}
   623  }
   624  
   625  func checkDupExprCases(exprname *Node, clauses []*Node) {
   626  	// boolean (naked) switch, nothing to do.
   627  	if exprname == nil {
   628  		return
   629  	}
   630  	// The common case is that s's expression is not an interface.
   631  	// In that case, all constant clauses have the same type,
   632  	// so checking for duplicates can be done solely by value.
   633  	if !exprname.Type.IsInterface() {
   634  		seen := make(map[interface{}]*Node)
   635  		for _, ncase := range clauses {
   636  			for _, n := range ncase.List.Slice() {
   637  				// Can't check for duplicates that aren't constants, per the spec. Issue 15896.
   638  				// Don't check for duplicate bools. Although the spec allows it,
   639  				// (1) the compiler hasn't checked it in the past, so compatibility mandates it, and
   640  				// (2) it would disallow useful things like
   641  				//       case GOARCH == "arm" && GOARM == "5":
   642  				//       case GOARCH == "arm":
   643  				//     which would both evaluate to false for non-ARM compiles.
   644  				if ct := consttype(n); ct == 0 || ct == CTBOOL {
   645  					continue
   646  				}
   647  
   648  				val := n.Val().Interface()
   649  				prev, dup := seen[val]
   650  				if !dup {
   651  					seen[val] = n
   652  					continue
   653  				}
   654  				yyerrorl(ncase.Pos, "duplicate case %s in switch\n\tprevious case at %v",
   655  					nodeAndVal(n), prev.Line())
   656  			}
   657  		}
   658  		return
   659  	}
   660  
   661  	// s's expression is an interface. This is fairly rare, so
   662  	// keep this simple. Case expressions are only duplicates if
   663  	// they have the same value and identical types.
   664  	//
   665  	// In general, we have to use eqtype to test type identity,
   666  	// because == gives false negatives for anonymous types and
   667  	// the byte/uint8 and rune/int32 builtin type aliases.
   668  	// However, this is not a problem here, because constant
   669  	// expressions are always untyped or have a named type, and we
   670  	// explicitly handle the builtin type aliases below.
   671  	//
   672  	// This approach may need to be revisited though if we fix
   673  	// #21866 by treating all type aliases like byte/uint8 and
   674  	// rune/int32.
   675  	type typeVal struct {
   676  		typ *types.Type
   677  		val interface{}
   678  	}
   679  	seen := make(map[typeVal]*Node)
   680  	for _, ncase := range clauses {
   681  		for _, n := range ncase.List.Slice() {
   682  			if ct := consttype(n); ct == 0 || ct == CTBOOL || ct == CTNIL {
   683  				continue
   684  			}
   685  			tv := typeVal{
   686  				typ: n.Type,
   687  				val: n.Val().Interface(),
   688  			}
   689  			switch tv.typ {
   690  			case types.Bytetype:
   691  				tv.typ = types.Types[TUINT8]
   692  			case types.Runetype:
   693  				tv.typ = types.Types[TINT32]
   694  			}
   695  			prev, dup := seen[tv]
   696  			if !dup {
   697  				seen[tv] = n
   698  				continue
   699  			}
   700  			yyerrorl(ncase.Pos, "duplicate case %s in switch\n\tprevious case at %v",
   701  				nodeAndVal(n), prev.Line())
   702  		}
   703  	}
   704  }
   705  
   706  func nodeAndVal(n *Node) string {
   707  	show := n.String()
   708  	val := n.Val().Interface()
   709  	if s := fmt.Sprintf("%#v", val); show != s {
   710  		show += " (value " + s + ")"
   711  	}
   712  	return show
   713  }
   714  
   715  // walk generates an AST that implements sw,
   716  // where sw is a type switch.
   717  // The AST is generally of the form of a linear
   718  // search using if..goto, although binary search
   719  // is used with long runs of concrete types.
   720  func (s *typeSwitch) walk(sw *Node) {
   721  	cond := sw.Left
   722  	sw.Left = nil
   723  
   724  	if cond == nil {
   725  		sw.List.Set(nil)
   726  		return
   727  	}
   728  	if cond.Right == nil {
   729  		yyerrorl(sw.Pos, "type switch must have an assignment")
   730  		return
   731  	}
   732  
   733  	cond.Right = walkexpr(cond.Right, &sw.Ninit)
   734  	if !cond.Right.Type.IsInterface() {
   735  		yyerrorl(sw.Pos, "type switch must be on an interface")
   736  		return
   737  	}
   738  
   739  	var cas []*Node
   740  
   741  	// predeclare temporary variables and the boolean var
   742  	s.facename = temp(cond.Right.Type)
   743  
   744  	a := nod(OAS, s.facename, cond.Right)
   745  	a = typecheck(a, ctxStmt)
   746  	cas = append(cas, a)
   747  
   748  	s.okname = temp(types.Types[TBOOL])
   749  	s.okname = typecheck(s.okname, ctxExpr)
   750  
   751  	s.hashname = temp(types.Types[TUINT32])
   752  	s.hashname = typecheck(s.hashname, ctxExpr)
   753  
   754  	// set up labels and jumps
   755  	casebody(sw, s.facename)
   756  
   757  	clauses := s.genCaseClauses(sw.List.Slice())
   758  	sw.List.Set(nil)
   759  	def := clauses.defjmp
   760  
   761  	// For empty interfaces, do:
   762  	//     if e._type == nil {
   763  	//         do nil case if it exists, otherwise default
   764  	//     }
   765  	//     h := e._type.hash
   766  	// Use a similar strategy for non-empty interfaces.
   767  
   768  	// Get interface descriptor word.
   769  	// For empty interfaces this will be the type.
   770  	// For non-empty interfaces this will be the itab.
   771  	itab := nod(OITAB, s.facename, nil)
   772  
   773  	// Check for nil first.
   774  	i := nod(OIF, nil, nil)
   775  	i.Left = nod(OEQ, itab, nodnil())
   776  	if clauses.niljmp != nil {
   777  		// Do explicit nil case right here.
   778  		i.Nbody.Set1(clauses.niljmp)
   779  	} else {
   780  		// Jump to default case.
   781  		lbl := autolabel(".s")
   782  		i.Nbody.Set1(nodSym(OGOTO, nil, lbl))
   783  		// Wrap default case with label.
   784  		blk := nod(OBLOCK, nil, nil)
   785  		blk.List.Set2(nodSym(OLABEL, nil, lbl), def)
   786  		def = blk
   787  	}
   788  	i.Left = typecheck(i.Left, ctxExpr)
   789  	i.Left = defaultlit(i.Left, nil)
   790  	cas = append(cas, i)
   791  
   792  	// Load hash from type or itab.
   793  	h := nodSym(ODOTPTR, itab, nil)
   794  	h.Type = types.Types[TUINT32]
   795  	h.SetTypecheck(1)
   796  	if cond.Right.Type.IsEmptyInterface() {
   797  		h.Xoffset = int64(2 * Widthptr) // offset of hash in runtime._type
   798  	} else {
   799  		h.Xoffset = int64(2 * Widthptr) // offset of hash in runtime.itab
   800  	}
   801  	h.SetBounded(true) // guaranteed not to fault
   802  	a = nod(OAS, s.hashname, h)
   803  	a = typecheck(a, ctxStmt)
   804  	cas = append(cas, a)
   805  
   806  	cc := clauses.list
   807  
   808  	// insert type equality check into each case block
   809  	for _, c := range cc {
   810  		c.node.Right = s.typeone(c.node)
   811  	}
   812  
   813  	// generate list of if statements, binary search for constant sequences
   814  	for len(cc) > 0 {
   815  		if !cc[0].isconst {
   816  			n := cc[0].node
   817  			cas = append(cas, n.Right)
   818  			cc = cc[1:]
   819  			continue
   820  		}
   821  
   822  		// identify run of constants
   823  		var run int
   824  		for run = 1; run < len(cc) && cc[run].isconst; run++ {
   825  		}
   826  
   827  		// sort by hash
   828  		sort.Sort(caseClauseByType(cc[:run]))
   829  
   830  		// for debugging: linear search
   831  		if false {
   832  			for i := 0; i < run; i++ {
   833  				n := cc[i].node
   834  				cas = append(cas, n.Right)
   835  			}
   836  			continue
   837  		}
   838  
   839  		// combine adjacent cases with the same hash
   840  		var batch []caseClause
   841  		for i, j := 0, 0; i < run; i = j {
   842  			hash := []*Node{cc[i].node.Right}
   843  			for j = i + 1; j < run && cc[i].hash == cc[j].hash; j++ {
   844  				hash = append(hash, cc[j].node.Right)
   845  			}
   846  			cc[i].node.Right = liststmt(hash)
   847  			batch = append(batch, cc[i])
   848  		}
   849  
   850  		// binary search among cases to narrow by hash
   851  		cas = append(cas, s.walkCases(batch))
   852  		cc = cc[run:]
   853  	}
   854  
   855  	// handle default case
   856  	if nerrors == 0 {
   857  		cas = append(cas, def)
   858  		sw.Nbody.Prepend(cas...)
   859  		sw.List.Set(nil)
   860  		walkstmtlist(sw.Nbody.Slice())
   861  	}
   862  }
   863  
   864  // typeone generates an AST that jumps to the
   865  // case body if the variable is of type t.
   866  func (s *typeSwitch) typeone(t *Node) *Node {
   867  	var name *Node
   868  	var init Nodes
   869  	if t.Rlist.Len() == 0 {
   870  		name = nblank
   871  		nblank = typecheck(nblank, ctxExpr|ctxAssign)
   872  	} else {
   873  		name = t.Rlist.First()
   874  		init.Append(nod(ODCL, name, nil))
   875  		a := nod(OAS, name, nil)
   876  		a = typecheck(a, ctxStmt)
   877  		init.Append(a)
   878  	}
   879  
   880  	a := nod(OAS2, nil, nil)
   881  	a.List.Set2(name, s.okname) // name, ok =
   882  	b := nod(ODOTTYPE, s.facename, nil)
   883  	b.Type = t.Left.Type // interface.(type)
   884  	a.Rlist.Set1(b)
   885  	a = typecheck(a, ctxStmt)
   886  	a = walkexpr(a, &init)
   887  	init.Append(a)
   888  
   889  	c := nod(OIF, nil, nil)
   890  	c.Left = s.okname
   891  	c.Nbody.Set1(t.Right) // if ok { goto l }
   892  
   893  	init.Append(c)
   894  	return init.asblock()
   895  }
   896  
   897  // walkCases generates an AST implementing the cases in cc.
   898  func (s *typeSwitch) walkCases(cc []caseClause) *Node {
   899  	if len(cc) < binarySearchMin {
   900  		var cas []*Node
   901  		for _, c := range cc {
   902  			n := c.node
   903  			if !c.isconst {
   904  				Fatalf("typeSwitch walkCases")
   905  			}
   906  			a := nod(OIF, nil, nil)
   907  			a.Left = nod(OEQ, s.hashname, nodintconst(int64(c.hash)))
   908  			a.Left = typecheck(a.Left, ctxExpr)
   909  			a.Left = defaultlit(a.Left, nil)
   910  			a.Nbody.Set1(n.Right)
   911  			cas = append(cas, a)
   912  		}
   913  		return liststmt(cas)
   914  	}
   915  
   916  	// find the middle and recur
   917  	half := len(cc) / 2
   918  	a := nod(OIF, nil, nil)
   919  	a.Left = nod(OLE, s.hashname, nodintconst(int64(cc[half-1].hash)))
   920  	a.Left = typecheck(a.Left, ctxExpr)
   921  	a.Left = defaultlit(a.Left, nil)
   922  	a.Nbody.Set1(s.walkCases(cc[:half]))
   923  	a.Rlist.Set1(s.walkCases(cc[half:]))
   924  	return a
   925  }
   926  
   927  // caseClauseByConstVal sorts clauses by constant value to enable binary search.
   928  type caseClauseByConstVal []caseClause
   929  
   930  func (x caseClauseByConstVal) Len() int      { return len(x) }
   931  func (x caseClauseByConstVal) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
   932  func (x caseClauseByConstVal) Less(i, j int) bool {
   933  	// n1 and n2 might be individual constants or integer ranges.
   934  	// We have checked for duplicates already,
   935  	// so ranges can be safely represented by any value in the range.
   936  	n1 := x[i].node
   937  	var v1 interface{}
   938  	if s := n1.List.Slice(); s != nil {
   939  		v1 = s[0].Val().U
   940  	} else {
   941  		v1 = n1.Left.Val().U
   942  	}
   943  
   944  	n2 := x[j].node
   945  	var v2 interface{}
   946  	if s := n2.List.Slice(); s != nil {
   947  		v2 = s[0].Val().U
   948  	} else {
   949  		v2 = n2.Left.Val().U
   950  	}
   951  
   952  	switch v1 := v1.(type) {
   953  	case *Mpflt:
   954  		return v1.Cmp(v2.(*Mpflt)) < 0
   955  	case *Mpint:
   956  		return v1.Cmp(v2.(*Mpint)) < 0
   957  	case string:
   958  		// Sort strings by length and then by value.
   959  		// It is much cheaper to compare lengths than values,
   960  		// and all we need here is consistency.
   961  		// We respect this sorting in exprSwitch.walkCases.
   962  		a := v1
   963  		b := v2.(string)
   964  		if len(a) != len(b) {
   965  			return len(a) < len(b)
   966  		}
   967  		return a < b
   968  	}
   969  
   970  	Fatalf("caseClauseByConstVal passed bad clauses %v < %v", x[i].node.Left, x[j].node.Left)
   971  	return false
   972  }
   973  
   974  type caseClauseByType []caseClause
   975  
   976  func (x caseClauseByType) Len() int      { return len(x) }
   977  func (x caseClauseByType) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
   978  func (x caseClauseByType) Less(i, j int) bool {
   979  	c1, c2 := x[i], x[j]
   980  	// sort by hash code, then ordinal (for the rare case of hash collisions)
   981  	if c1.hash != c2.hash {
   982  		return c1.hash < c2.hash
   983  	}
   984  	return c1.ordinal < c2.ordinal
   985  }
   986  
   987  type constIntNodesByVal []*Node
   988  
   989  func (x constIntNodesByVal) Len() int      { return len(x) }
   990  func (x constIntNodesByVal) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
   991  func (x constIntNodesByVal) Less(i, j int) bool {
   992  	return x[i].Val().U.(*Mpint).Cmp(x[j].Val().U.(*Mpint)) < 0
   993  }