Source file src/cmd/compile/internal/types2/stmt.go

     1  // Copyright 2012 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  // This file implements typechecking of statements.
     6  
     7  package types2
     8  
     9  import (
    10  	"cmd/compile/internal/syntax"
    11  	"go/constant"
    12  	"internal/buildcfg"
    13  	. "internal/types/errors"
    14  	"sort"
    15  )
    16  
    17  func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body *syntax.BlockStmt, iota constant.Value) {
    18  	if check.conf.IgnoreFuncBodies {
    19  		panic("function body not ignored")
    20  	}
    21  
    22  	if check.conf.Trace {
    23  		check.trace(body.Pos(), "-- %s: %s", name, sig)
    24  	}
    25  
    26  	// save/restore current environment and set up function environment
    27  	// (and use 0 indentation at function start)
    28  	defer func(env environment, indent int) {
    29  		check.environment = env
    30  		check.indent = indent
    31  	}(check.environment, check.indent)
    32  	check.environment = environment{
    33  		decl:  decl,
    34  		scope: sig.scope,
    35  		iota:  iota,
    36  		sig:   sig,
    37  	}
    38  	check.indent = 0
    39  
    40  	check.stmtList(0, body.List)
    41  
    42  	if check.hasLabel && !check.conf.IgnoreBranchErrors {
    43  		check.labels(body)
    44  	}
    45  
    46  	if sig.results.Len() > 0 && !check.isTerminating(body, "") {
    47  		check.error(body.Rbrace, MissingReturn, "missing return")
    48  	}
    49  
    50  	// spec: "Implementation restriction: A compiler may make it illegal to
    51  	// declare a variable inside a function body if the variable is never used."
    52  	check.usage(sig.scope)
    53  }
    54  
    55  func (check *Checker) usage(scope *Scope) {
    56  	var unused []*Var
    57  	for name, elem := range scope.elems {
    58  		elem = resolve(name, elem)
    59  		if v, _ := elem.(*Var); v != nil && !v.used {
    60  			unused = append(unused, v)
    61  		}
    62  	}
    63  	sort.Slice(unused, func(i, j int) bool {
    64  		return cmpPos(unused[i].pos, unused[j].pos) < 0
    65  	})
    66  	for _, v := range unused {
    67  		check.softErrorf(v.pos, UnusedVar, "%s declared and not used", quote(v.name))
    68  	}
    69  
    70  	for _, scope := range scope.children {
    71  		// Don't go inside function literal scopes a second time;
    72  		// they are handled explicitly by funcBody.
    73  		if !scope.isFunc {
    74  			check.usage(scope)
    75  		}
    76  	}
    77  }
    78  
    79  // stmtContext is a bitset describing which
    80  // control-flow statements are permissible,
    81  // and provides additional context information
    82  // for better error messages.
    83  type stmtContext uint
    84  
    85  const (
    86  	// permissible control-flow statements
    87  	breakOk stmtContext = 1 << iota
    88  	continueOk
    89  	fallthroughOk
    90  
    91  	// additional context information
    92  	finalSwitchCase
    93  	inTypeSwitch
    94  )
    95  
    96  func (check *Checker) simpleStmt(s syntax.Stmt) {
    97  	if s != nil {
    98  		check.stmt(0, s)
    99  	}
   100  }
   101  
   102  func trimTrailingEmptyStmts(list []syntax.Stmt) []syntax.Stmt {
   103  	for i := len(list); i > 0; i-- {
   104  		if _, ok := list[i-1].(*syntax.EmptyStmt); !ok {
   105  			return list[:i]
   106  		}
   107  	}
   108  	return nil
   109  }
   110  
   111  func (check *Checker) stmtList(ctxt stmtContext, list []syntax.Stmt) {
   112  	ok := ctxt&fallthroughOk != 0
   113  	inner := ctxt &^ fallthroughOk
   114  	list = trimTrailingEmptyStmts(list) // trailing empty statements are "invisible" to fallthrough analysis
   115  	for i, s := range list {
   116  		inner := inner
   117  		if ok && i+1 == len(list) {
   118  			inner |= fallthroughOk
   119  		}
   120  		check.stmt(inner, s)
   121  	}
   122  }
   123  
   124  func (check *Checker) multipleSwitchDefaults(list []*syntax.CaseClause) {
   125  	var first *syntax.CaseClause
   126  	for _, c := range list {
   127  		if c.Cases == nil {
   128  			if first != nil {
   129  				check.errorf(c, DuplicateDefault, "multiple defaults (first at %s)", first.Pos())
   130  				// TODO(gri) probably ok to bail out after first error (and simplify this code)
   131  			} else {
   132  				first = c
   133  			}
   134  		}
   135  	}
   136  }
   137  
   138  func (check *Checker) multipleSelectDefaults(list []*syntax.CommClause) {
   139  	var first *syntax.CommClause
   140  	for _, c := range list {
   141  		if c.Comm == nil {
   142  			if first != nil {
   143  				check.errorf(c, DuplicateDefault, "multiple defaults (first at %s)", first.Pos())
   144  				// TODO(gri) probably ok to bail out after first error (and simplify this code)
   145  			} else {
   146  				first = c
   147  			}
   148  		}
   149  	}
   150  }
   151  
   152  func (check *Checker) openScope(node syntax.Node, comment string) {
   153  	check.openScopeUntil(node, syntax.EndPos(node), comment)
   154  }
   155  
   156  func (check *Checker) openScopeUntil(node syntax.Node, end syntax.Pos, comment string) {
   157  	scope := NewScope(check.scope, node.Pos(), end, comment)
   158  	check.recordScope(node, scope)
   159  	check.scope = scope
   160  }
   161  
   162  func (check *Checker) closeScope() {
   163  	check.scope = check.scope.Parent()
   164  }
   165  
   166  func (check *Checker) suspendedCall(keyword string, call syntax.Expr) {
   167  	code := InvalidDefer
   168  	if keyword == "go" {
   169  		code = InvalidGo
   170  	}
   171  
   172  	if _, ok := call.(*syntax.CallExpr); !ok {
   173  		check.errorf(call, code, "expression in %s must be function call", keyword)
   174  		check.use(call)
   175  		return
   176  	}
   177  
   178  	var x operand
   179  	var msg string
   180  	switch check.rawExpr(nil, &x, call, nil, false) {
   181  	case conversion:
   182  		msg = "requires function call, not conversion"
   183  	case expression:
   184  		msg = "discards result of"
   185  		code = UnusedResults
   186  	case statement:
   187  		return
   188  	default:
   189  		panic("unreachable")
   190  	}
   191  	check.errorf(&x, code, "%s %s %s", keyword, msg, &x)
   192  }
   193  
   194  // goVal returns the Go value for val, or nil.
   195  func goVal(val constant.Value) interface{} {
   196  	// val should exist, but be conservative and check
   197  	if val == nil {
   198  		return nil
   199  	}
   200  	// Match implementation restriction of other compilers.
   201  	// gc only checks duplicates for integer, floating-point
   202  	// and string values, so only create Go values for these
   203  	// types.
   204  	switch val.Kind() {
   205  	case constant.Int:
   206  		if x, ok := constant.Int64Val(val); ok {
   207  			return x
   208  		}
   209  		if x, ok := constant.Uint64Val(val); ok {
   210  			return x
   211  		}
   212  	case constant.Float:
   213  		if x, ok := constant.Float64Val(val); ok {
   214  			return x
   215  		}
   216  	case constant.String:
   217  		return constant.StringVal(val)
   218  	}
   219  	return nil
   220  }
   221  
   222  // A valueMap maps a case value (of a basic Go type) to a list of positions
   223  // where the same case value appeared, together with the corresponding case
   224  // types.
   225  // Since two case values may have the same "underlying" value but different
   226  // types we need to also check the value's types (e.g., byte(1) vs myByte(1))
   227  // when the switch expression is of interface type.
   228  type (
   229  	valueMap  map[interface{}][]valueType // underlying Go value -> valueType
   230  	valueType struct {
   231  		pos syntax.Pos
   232  		typ Type
   233  	}
   234  )
   235  
   236  func (check *Checker) caseValues(x *operand, values []syntax.Expr, seen valueMap) {
   237  L:
   238  	for _, e := range values {
   239  		var v operand
   240  		check.expr(nil, &v, e)
   241  		if x.mode == invalid || v.mode == invalid {
   242  			continue L
   243  		}
   244  		check.convertUntyped(&v, x.typ)
   245  		if v.mode == invalid {
   246  			continue L
   247  		}
   248  		// Order matters: By comparing v against x, error positions are at the case values.
   249  		res := v // keep original v unchanged
   250  		check.comparison(&res, x, syntax.Eql, true)
   251  		if res.mode == invalid {
   252  			continue L
   253  		}
   254  		if v.mode != constant_ {
   255  			continue L // we're done
   256  		}
   257  		// look for duplicate values
   258  		if val := goVal(v.val); val != nil {
   259  			// look for duplicate types for a given value
   260  			// (quadratic algorithm, but these lists tend to be very short)
   261  			for _, vt := range seen[val] {
   262  				if Identical(v.typ, vt.typ) {
   263  					err := check.newError(DuplicateCase)
   264  					err.addf(&v, "duplicate case %s in expression switch", &v)
   265  					err.addf(vt.pos, "previous case")
   266  					err.report()
   267  					continue L
   268  				}
   269  			}
   270  			seen[val] = append(seen[val], valueType{v.Pos(), v.typ})
   271  		}
   272  	}
   273  }
   274  
   275  // isNil reports whether the expression e denotes the predeclared value nil.
   276  func (check *Checker) isNil(e syntax.Expr) bool {
   277  	// The only way to express the nil value is by literally writing nil (possibly in parentheses).
   278  	if name, _ := syntax.Unparen(e).(*syntax.Name); name != nil {
   279  		_, ok := check.lookup(name.Value).(*Nil)
   280  		return ok
   281  	}
   282  	return false
   283  }
   284  
   285  // If the type switch expression is invalid, x is nil.
   286  func (check *Checker) caseTypes(x *operand, types []syntax.Expr, seen map[Type]syntax.Expr) (T Type) {
   287  	var dummy operand
   288  L:
   289  	for _, e := range types {
   290  		// The spec allows the value nil instead of a type.
   291  		if check.isNil(e) {
   292  			T = nil
   293  			check.expr(nil, &dummy, e) // run e through expr so we get the usual Info recordings
   294  		} else {
   295  			T = check.varType(e)
   296  			if !isValid(T) {
   297  				continue L
   298  			}
   299  		}
   300  		// look for duplicate types
   301  		// (quadratic algorithm, but type switches tend to be reasonably small)
   302  		for t, other := range seen {
   303  			if T == nil && t == nil || T != nil && t != nil && Identical(T, t) {
   304  				// talk about "case" rather than "type" because of nil case
   305  				Ts := "nil"
   306  				if T != nil {
   307  					Ts = TypeString(T, check.qualifier)
   308  				}
   309  				err := check.newError(DuplicateCase)
   310  				err.addf(e, "duplicate case %s in type switch", Ts)
   311  				err.addf(other, "previous case")
   312  				err.report()
   313  				continue L
   314  			}
   315  		}
   316  		seen[T] = e
   317  		if x != nil && T != nil {
   318  			check.typeAssertion(e, x, T, true)
   319  		}
   320  	}
   321  	return
   322  }
   323  
   324  // TODO(gri) Once we are certain that typeHash is correct in all situations, use this version of caseTypes instead.
   325  // (Currently it may be possible that different types have identical names and import paths due to ImporterFrom.)
   326  //
   327  // func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []syntax.Expr, seen map[string]syntax.Expr) (T Type) {
   328  // 	var dummy operand
   329  // L:
   330  // 	for _, e := range types {
   331  // 		// The spec allows the value nil instead of a type.
   332  // 		var hash string
   333  // 		if check.isNil(e) {
   334  // 			check.expr(nil, &dummy, e) // run e through expr so we get the usual Info recordings
   335  // 			T = nil
   336  // 			hash = "<nil>" // avoid collision with a type named nil
   337  // 		} else {
   338  // 			T = check.varType(e)
   339  // 			if !isValid(T) {
   340  // 				continue L
   341  // 			}
   342  // 			hash = typeHash(T, nil)
   343  // 		}
   344  // 		// look for duplicate types
   345  // 		if other := seen[hash]; other != nil {
   346  // 			// talk about "case" rather than "type" because of nil case
   347  // 			Ts := "nil"
   348  // 			if T != nil {
   349  // 				Ts = TypeString(T, check.qualifier)
   350  // 			}
   351  // 			err := check.newError(_DuplicateCase)
   352  // 			err.addf(e, "duplicate case %s in type switch", Ts)
   353  // 			err.addf(other, "previous case")
   354  // 			err.report()
   355  // 			continue L
   356  // 		}
   357  // 		seen[hash] = e
   358  // 		if T != nil {
   359  // 			check.typeAssertion(e, x, xtyp, T, true)
   360  // 		}
   361  // 	}
   362  // 	return
   363  // }
   364  
   365  // stmt typechecks statement s.
   366  func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
   367  	// statements must end with the same top scope as they started with
   368  	if debug {
   369  		defer func(scope *Scope) {
   370  			// don't check if code is panicking
   371  			if p := recover(); p != nil {
   372  				panic(p)
   373  			}
   374  			assert(scope == check.scope)
   375  		}(check.scope)
   376  	}
   377  
   378  	// process collected function literals before scope changes
   379  	defer check.processDelayed(len(check.delayed))
   380  
   381  	// reset context for statements of inner blocks
   382  	inner := ctxt &^ (fallthroughOk | finalSwitchCase | inTypeSwitch)
   383  
   384  	switch s := s.(type) {
   385  	case *syntax.EmptyStmt:
   386  		// ignore
   387  
   388  	case *syntax.DeclStmt:
   389  		check.declStmt(s.DeclList)
   390  
   391  	case *syntax.LabeledStmt:
   392  		check.hasLabel = true
   393  		check.stmt(ctxt, s.Stmt)
   394  
   395  	case *syntax.ExprStmt:
   396  		// spec: "With the exception of specific built-in functions,
   397  		// function and method calls and receive operations can appear
   398  		// in statement context. Such statements may be parenthesized."
   399  		var x operand
   400  		kind := check.rawExpr(nil, &x, s.X, nil, false)
   401  		var msg string
   402  		var code Code
   403  		switch x.mode {
   404  		default:
   405  			if kind == statement {
   406  				return
   407  			}
   408  			msg = "is not used"
   409  			code = UnusedExpr
   410  		case builtin:
   411  			msg = "must be called"
   412  			code = UncalledBuiltin
   413  		case typexpr:
   414  			msg = "is not an expression"
   415  			code = NotAnExpr
   416  		}
   417  		check.errorf(&x, code, "%s %s", &x, msg)
   418  
   419  	case *syntax.SendStmt:
   420  		var ch, val operand
   421  		check.expr(nil, &ch, s.Chan)
   422  		check.expr(nil, &val, s.Value)
   423  		if ch.mode == invalid || val.mode == invalid {
   424  			return
   425  		}
   426  		u := coreType(ch.typ)
   427  		if u == nil {
   428  			check.errorf(s, InvalidSend, invalidOp+"cannot send to %s: no core type", &ch)
   429  			return
   430  		}
   431  		uch, _ := u.(*Chan)
   432  		if uch == nil {
   433  			check.errorf(s, InvalidSend, invalidOp+"cannot send to non-channel %s", &ch)
   434  			return
   435  		}
   436  		if uch.dir == RecvOnly {
   437  			check.errorf(s, InvalidSend, invalidOp+"cannot send to receive-only channel %s", &ch)
   438  			return
   439  		}
   440  		check.assignment(&val, uch.elem, "send")
   441  
   442  	case *syntax.AssignStmt:
   443  		if s.Rhs == nil {
   444  			// x++ or x--
   445  			// (no need to call unpackExpr as s.Lhs must be single-valued)
   446  			var x operand
   447  			check.expr(nil, &x, s.Lhs)
   448  			if x.mode == invalid {
   449  				return
   450  			}
   451  			if !allNumeric(x.typ) {
   452  				check.errorf(s.Lhs, NonNumericIncDec, invalidOp+"%s%s%s (non-numeric type %s)", s.Lhs, s.Op, s.Op, x.typ)
   453  				return
   454  			}
   455  			check.assignVar(s.Lhs, nil, &x, "assignment")
   456  			return
   457  		}
   458  
   459  		lhs := syntax.UnpackListExpr(s.Lhs)
   460  		rhs := syntax.UnpackListExpr(s.Rhs)
   461  		switch s.Op {
   462  		case 0:
   463  			check.assignVars(lhs, rhs)
   464  			return
   465  		case syntax.Def:
   466  			check.shortVarDecl(s.Pos(), lhs, rhs)
   467  			return
   468  		}
   469  
   470  		// assignment operations
   471  		if len(lhs) != 1 || len(rhs) != 1 {
   472  			check.errorf(s, MultiValAssignOp, "assignment operation %s requires single-valued expressions", s.Op)
   473  			return
   474  		}
   475  
   476  		var x operand
   477  		check.binary(&x, nil, lhs[0], rhs[0], s.Op)
   478  		check.assignVar(lhs[0], nil, &x, "assignment")
   479  
   480  	case *syntax.CallStmt:
   481  		kind := "go"
   482  		if s.Tok == syntax.Defer {
   483  			kind = "defer"
   484  		}
   485  		check.suspendedCall(kind, s.Call)
   486  
   487  	case *syntax.ReturnStmt:
   488  		res := check.sig.results
   489  		// Return with implicit results allowed for function with named results.
   490  		// (If one is named, all are named.)
   491  		results := syntax.UnpackListExpr(s.Results)
   492  		if len(results) == 0 && res.Len() > 0 && res.vars[0].name != "" {
   493  			// spec: "Implementation restriction: A compiler may disallow an empty expression
   494  			// list in a "return" statement if a different entity (constant, type, or variable)
   495  			// with the same name as a result parameter is in scope at the place of the return."
   496  			for _, obj := range res.vars {
   497  				if alt := check.lookup(obj.name); alt != nil && alt != obj {
   498  					err := check.newError(OutOfScopeResult)
   499  					err.addf(s, "result parameter %s not in scope at return", quote(obj.name))
   500  					err.addf(alt, "inner declaration of %s", obj)
   501  					err.report()
   502  					// ok to continue
   503  				}
   504  			}
   505  		} else {
   506  			var lhs []*Var
   507  			if res.Len() > 0 {
   508  				lhs = res.vars
   509  			}
   510  			check.initVars(lhs, results, s)
   511  		}
   512  
   513  	case *syntax.BranchStmt:
   514  		if s.Label != nil {
   515  			check.hasLabel = true
   516  			break // checked in 2nd pass (check.labels)
   517  		}
   518  		if check.conf.IgnoreBranchErrors {
   519  			break
   520  		}
   521  		switch s.Tok {
   522  		case syntax.Break:
   523  			if ctxt&breakOk == 0 {
   524  				check.error(s, MisplacedBreak, "break not in for, switch, or select statement")
   525  			}
   526  		case syntax.Continue:
   527  			if ctxt&continueOk == 0 {
   528  				check.error(s, MisplacedContinue, "continue not in for statement")
   529  			}
   530  		case syntax.Fallthrough:
   531  			if ctxt&fallthroughOk == 0 {
   532  				var msg string
   533  				switch {
   534  				case ctxt&finalSwitchCase != 0:
   535  					msg = "cannot fallthrough final case in switch"
   536  				case ctxt&inTypeSwitch != 0:
   537  					msg = "cannot fallthrough in type switch"
   538  				default:
   539  					msg = "fallthrough statement out of place"
   540  				}
   541  				check.error(s, MisplacedFallthrough, msg)
   542  			}
   543  		case syntax.Goto:
   544  			// goto's must have labels, should have been caught above
   545  			fallthrough
   546  		default:
   547  			check.errorf(s, InvalidSyntaxTree, "branch statement: %s", s.Tok)
   548  		}
   549  
   550  	case *syntax.BlockStmt:
   551  		check.openScope(s, "block")
   552  		defer check.closeScope()
   553  
   554  		check.stmtList(inner, s.List)
   555  
   556  	case *syntax.IfStmt:
   557  		check.openScope(s, "if")
   558  		defer check.closeScope()
   559  
   560  		check.simpleStmt(s.Init)
   561  		var x operand
   562  		check.expr(nil, &x, s.Cond)
   563  		if x.mode != invalid && !allBoolean(x.typ) {
   564  			check.error(s.Cond, InvalidCond, "non-boolean condition in if statement")
   565  		}
   566  		check.stmt(inner, s.Then)
   567  		// The parser produces a correct AST but if it was modified
   568  		// elsewhere the else branch may be invalid. Check again.
   569  		switch s.Else.(type) {
   570  		case nil:
   571  			// valid or error already reported
   572  		case *syntax.IfStmt, *syntax.BlockStmt:
   573  			check.stmt(inner, s.Else)
   574  		default:
   575  			check.error(s.Else, InvalidSyntaxTree, "invalid else branch in if statement")
   576  		}
   577  
   578  	case *syntax.SwitchStmt:
   579  		inner |= breakOk
   580  		check.openScope(s, "switch")
   581  		defer check.closeScope()
   582  
   583  		check.simpleStmt(s.Init)
   584  
   585  		if g, _ := s.Tag.(*syntax.TypeSwitchGuard); g != nil {
   586  			check.typeSwitchStmt(inner|inTypeSwitch, s, g)
   587  		} else {
   588  			check.switchStmt(inner, s)
   589  		}
   590  
   591  	case *syntax.SelectStmt:
   592  		inner |= breakOk
   593  
   594  		check.multipleSelectDefaults(s.Body)
   595  
   596  		for i, clause := range s.Body {
   597  			if clause == nil {
   598  				continue // error reported before
   599  			}
   600  
   601  			// clause.Comm must be a SendStmt, RecvStmt, or default case
   602  			valid := false
   603  			var rhs syntax.Expr // rhs of RecvStmt, or nil
   604  			switch s := clause.Comm.(type) {
   605  			case nil, *syntax.SendStmt:
   606  				valid = true
   607  			case *syntax.AssignStmt:
   608  				if _, ok := s.Rhs.(*syntax.ListExpr); !ok {
   609  					rhs = s.Rhs
   610  				}
   611  			case *syntax.ExprStmt:
   612  				rhs = s.X
   613  			}
   614  
   615  			// if present, rhs must be a receive operation
   616  			if rhs != nil {
   617  				if x, _ := syntax.Unparen(rhs).(*syntax.Operation); x != nil && x.Y == nil && x.Op == syntax.Recv {
   618  					valid = true
   619  				}
   620  			}
   621  
   622  			if !valid {
   623  				check.error(clause.Comm, InvalidSelectCase, "select case must be send or receive (possibly with assignment)")
   624  				continue
   625  			}
   626  			end := s.Rbrace
   627  			if i+1 < len(s.Body) {
   628  				end = s.Body[i+1].Pos()
   629  			}
   630  			check.openScopeUntil(clause, end, "case")
   631  			if clause.Comm != nil {
   632  				check.stmt(inner, clause.Comm)
   633  			}
   634  			check.stmtList(inner, clause.Body)
   635  			check.closeScope()
   636  		}
   637  
   638  	case *syntax.ForStmt:
   639  		inner |= breakOk | continueOk
   640  
   641  		if rclause, _ := s.Init.(*syntax.RangeClause); rclause != nil {
   642  			check.rangeStmt(inner, s, rclause)
   643  			break
   644  		}
   645  
   646  		check.openScope(s, "for")
   647  		defer check.closeScope()
   648  
   649  		check.simpleStmt(s.Init)
   650  		if s.Cond != nil {
   651  			var x operand
   652  			check.expr(nil, &x, s.Cond)
   653  			if x.mode != invalid && !allBoolean(x.typ) {
   654  				check.error(s.Cond, InvalidCond, "non-boolean condition in for statement")
   655  			}
   656  		}
   657  		check.simpleStmt(s.Post)
   658  		// spec: "The init statement may be a short variable
   659  		// declaration, but the post statement must not."
   660  		if s, _ := s.Post.(*syntax.AssignStmt); s != nil && s.Op == syntax.Def {
   661  			// The parser already reported an error.
   662  			check.use(s.Lhs) // avoid follow-up errors
   663  		}
   664  		check.stmt(inner, s.Body)
   665  
   666  	default:
   667  		check.error(s, InvalidSyntaxTree, "invalid statement")
   668  	}
   669  }
   670  
   671  func (check *Checker) switchStmt(inner stmtContext, s *syntax.SwitchStmt) {
   672  	// init statement already handled
   673  
   674  	var x operand
   675  	if s.Tag != nil {
   676  		check.expr(nil, &x, s.Tag)
   677  		// By checking assignment of x to an invisible temporary
   678  		// (as a compiler would), we get all the relevant checks.
   679  		check.assignment(&x, nil, "switch expression")
   680  		if x.mode != invalid && !Comparable(x.typ) && !hasNil(x.typ) {
   681  			check.errorf(&x, InvalidExprSwitch, "cannot switch on %s (%s is not comparable)", &x, x.typ)
   682  			x.mode = invalid
   683  		}
   684  	} else {
   685  		// spec: "A missing switch expression is
   686  		// equivalent to the boolean value true."
   687  		x.mode = constant_
   688  		x.typ = Typ[Bool]
   689  		x.val = constant.MakeBool(true)
   690  		// TODO(gri) should have a better position here
   691  		pos := s.Rbrace
   692  		if len(s.Body) > 0 {
   693  			pos = s.Body[0].Pos()
   694  		}
   695  		x.expr = syntax.NewName(pos, "true")
   696  	}
   697  
   698  	check.multipleSwitchDefaults(s.Body)
   699  
   700  	seen := make(valueMap) // map of seen case values to positions and types
   701  	for i, clause := range s.Body {
   702  		if clause == nil {
   703  			check.error(clause, InvalidSyntaxTree, "incorrect expression switch case")
   704  			continue
   705  		}
   706  		end := s.Rbrace
   707  		inner := inner
   708  		if i+1 < len(s.Body) {
   709  			end = s.Body[i+1].Pos()
   710  			inner |= fallthroughOk
   711  		} else {
   712  			inner |= finalSwitchCase
   713  		}
   714  		check.caseValues(&x, syntax.UnpackListExpr(clause.Cases), seen)
   715  		check.openScopeUntil(clause, end, "case")
   716  		check.stmtList(inner, clause.Body)
   717  		check.closeScope()
   718  	}
   719  }
   720  
   721  func (check *Checker) typeSwitchStmt(inner stmtContext, s *syntax.SwitchStmt, guard *syntax.TypeSwitchGuard) {
   722  	// init statement already handled
   723  
   724  	// A type switch guard must be of the form:
   725  	//
   726  	//     TypeSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "type" ")" .
   727  	//                          \__lhs__/        \___rhs___/
   728  
   729  	// check lhs, if any
   730  	lhs := guard.Lhs
   731  	if lhs != nil {
   732  		if lhs.Value == "_" {
   733  			// _ := x.(type) is an invalid short variable declaration
   734  			check.softErrorf(lhs, NoNewVar, "no new variable on left side of :=")
   735  			lhs = nil // avoid declared and not used error below
   736  		} else {
   737  			check.recordDef(lhs, nil) // lhs variable is implicitly declared in each cause clause
   738  		}
   739  	}
   740  
   741  	// check rhs
   742  	var x operand
   743  	check.expr(nil, &x, guard.X)
   744  	if x.mode == invalid {
   745  		return
   746  	}
   747  
   748  	// TODO(gri) we may want to permit type switches on type parameter values at some point
   749  	var sx *operand // switch expression against which cases are compared against; nil if invalid
   750  	if isTypeParam(x.typ) {
   751  		check.errorf(&x, InvalidTypeSwitch, "cannot use type switch on type parameter value %s", &x)
   752  	} else {
   753  		if _, ok := under(x.typ).(*Interface); ok {
   754  			sx = &x
   755  		} else {
   756  			check.errorf(&x, InvalidTypeSwitch, "%s is not an interface", &x)
   757  		}
   758  	}
   759  
   760  	check.multipleSwitchDefaults(s.Body)
   761  
   762  	var lhsVars []*Var                 // list of implicitly declared lhs variables
   763  	seen := make(map[Type]syntax.Expr) // map of seen types to positions
   764  	for i, clause := range s.Body {
   765  		if clause == nil {
   766  			check.error(s, InvalidSyntaxTree, "incorrect type switch case")
   767  			continue
   768  		}
   769  		end := s.Rbrace
   770  		if i+1 < len(s.Body) {
   771  			end = s.Body[i+1].Pos()
   772  		}
   773  		// Check each type in this type switch case.
   774  		cases := syntax.UnpackListExpr(clause.Cases)
   775  		T := check.caseTypes(sx, cases, seen)
   776  		check.openScopeUntil(clause, end, "case")
   777  		// If lhs exists, declare a corresponding variable in the case-local scope.
   778  		if lhs != nil {
   779  			// spec: "The TypeSwitchGuard may include a short variable declaration.
   780  			// When that form is used, the variable is declared at the beginning of
   781  			// the implicit block in each clause. In clauses with a case listing
   782  			// exactly one type, the variable has that type; otherwise, the variable
   783  			// has the type of the expression in the TypeSwitchGuard."
   784  			if len(cases) != 1 || T == nil {
   785  				T = x.typ
   786  			}
   787  			obj := NewVar(lhs.Pos(), check.pkg, lhs.Value, T)
   788  			// TODO(mdempsky): Just use clause.Colon? Why did I even suggest
   789  			// "at the end of the TypeSwitchCase" in go.dev/issue/16794 instead?
   790  			scopePos := clause.Pos() // for default clause (len(List) == 0)
   791  			if n := len(cases); n > 0 {
   792  				scopePos = syntax.EndPos(cases[n-1])
   793  			}
   794  			check.declare(check.scope, nil, obj, scopePos)
   795  			check.recordImplicit(clause, obj)
   796  			// For the "declared and not used" error, all lhs variables act as
   797  			// one; i.e., if any one of them is 'used', all of them are 'used'.
   798  			// Collect them for later analysis.
   799  			lhsVars = append(lhsVars, obj)
   800  		}
   801  		check.stmtList(inner, clause.Body)
   802  		check.closeScope()
   803  	}
   804  
   805  	// If lhs exists, we must have at least one lhs variable that was used.
   806  	// (We can't use check.usage because that only looks at one scope; and
   807  	// we don't want to use the same variable for all scopes and change the
   808  	// variable type underfoot.)
   809  	if lhs != nil {
   810  		var used bool
   811  		for _, v := range lhsVars {
   812  			if v.used {
   813  				used = true
   814  			}
   815  			v.used = true // avoid usage error when checking entire function
   816  		}
   817  		if !used {
   818  			check.softErrorf(lhs, UnusedVar, "%s declared and not used", lhs.Value)
   819  		}
   820  	}
   821  }
   822  
   823  func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *syntax.RangeClause) {
   824  	// Convert syntax form to local variables.
   825  	type Expr = syntax.Expr
   826  	type identType = syntax.Name
   827  	identName := func(n *identType) string { return n.Value }
   828  	sKey := rclause.Lhs // possibly nil
   829  	var sValue, sExtra syntax.Expr
   830  	if p, _ := sKey.(*syntax.ListExpr); p != nil {
   831  		if len(p.ElemList) < 2 {
   832  			check.error(s, InvalidSyntaxTree, "invalid lhs in range clause")
   833  			return
   834  		}
   835  		// len(p.ElemList) >= 2
   836  		sKey = p.ElemList[0]
   837  		sValue = p.ElemList[1]
   838  		if len(p.ElemList) > 2 {
   839  			// delay error reporting until we know more
   840  			sExtra = p.ElemList[2]
   841  		}
   842  	}
   843  	isDef := rclause.Def
   844  	rangeVar := rclause.X
   845  	noNewVarPos := s
   846  
   847  	// Do not use rclause anymore.
   848  	rclause = nil
   849  
   850  	// Everything from here on is shared between cmd/compile/internal/types2 and go/types.
   851  
   852  	// check expression to iterate over
   853  	var x operand
   854  	check.expr(nil, &x, rangeVar)
   855  
   856  	// determine key/value types
   857  	var key, val Type
   858  	if x.mode != invalid {
   859  		// Ranging over a type parameter is permitted if it has a core type.
   860  		k, v, cause, isFunc, ok := rangeKeyVal(x.typ, func(v goVersion) bool {
   861  			return check.allowVersion(x.expr, v)
   862  		})
   863  		switch {
   864  		case !ok && cause != "":
   865  			check.softErrorf(&x, InvalidRangeExpr, "cannot range over %s: %s", &x, cause)
   866  		case !ok:
   867  			check.softErrorf(&x, InvalidRangeExpr, "cannot range over %s", &x)
   868  		case k == nil && sKey != nil:
   869  			check.softErrorf(sKey, InvalidIterVar, "range over %s permits no iteration variables", &x)
   870  		case v == nil && sValue != nil:
   871  			check.softErrorf(sValue, InvalidIterVar, "range over %s permits only one iteration variable", &x)
   872  		case sExtra != nil:
   873  			check.softErrorf(sExtra, InvalidIterVar, "range clause permits at most two iteration variables")
   874  		case isFunc && ((k == nil) != (sKey == nil) || (v == nil) != (sValue == nil)):
   875  			var count string
   876  			switch {
   877  			case k == nil:
   878  				count = "no iteration variables"
   879  			case v == nil:
   880  				count = "one iteration variable"
   881  			default:
   882  				count = "two iteration variables"
   883  			}
   884  			check.softErrorf(&x, InvalidIterVar, "range over %s must have %s", &x, count)
   885  		}
   886  		key, val = k, v
   887  	}
   888  
   889  	// Open the for-statement block scope now, after the range clause.
   890  	// Iteration variables declared with := need to go in this scope (was go.dev/issue/51437).
   891  	check.openScope(s, "range")
   892  	defer check.closeScope()
   893  
   894  	// check assignment to/declaration of iteration variables
   895  	// (irregular assignment, cannot easily map to existing assignment checks)
   896  
   897  	// lhs expressions and initialization value (rhs) types
   898  	lhs := [2]Expr{sKey, sValue} // sKey, sValue may be nil
   899  	rhs := [2]Type{key, val}     // key, val may be nil
   900  
   901  	rangeOverInt := isInteger(x.typ)
   902  
   903  	if isDef {
   904  		// short variable declaration
   905  		var vars []*Var
   906  		for i, lhs := range lhs {
   907  			if lhs == nil {
   908  				continue
   909  			}
   910  
   911  			// determine lhs variable
   912  			var obj *Var
   913  			if ident, _ := lhs.(*identType); ident != nil {
   914  				// declare new variable
   915  				name := identName(ident)
   916  				obj = NewVar(ident.Pos(), check.pkg, name, nil)
   917  				check.recordDef(ident, obj)
   918  				// _ variables don't count as new variables
   919  				if name != "_" {
   920  					vars = append(vars, obj)
   921  				}
   922  			} else {
   923  				check.errorf(lhs, InvalidSyntaxTree, "cannot declare %s", lhs)
   924  				obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable
   925  			}
   926  			assert(obj.typ == nil)
   927  
   928  			// initialize lhs iteration variable, if any
   929  			typ := rhs[i]
   930  			if typ == nil {
   931  				obj.typ = Typ[Invalid]
   932  				obj.used = true // don't complain about unused variable
   933  				continue
   934  			}
   935  
   936  			if rangeOverInt {
   937  				assert(i == 0) // at most one iteration variable (rhs[1] == nil for rangeOverInt)
   938  				check.initVar(obj, &x, "range clause")
   939  			} else {
   940  				var y operand
   941  				y.mode = value
   942  				y.expr = lhs // we don't have a better rhs expression to use here
   943  				y.typ = typ
   944  				check.initVar(obj, &y, "assignment") // error is on variable, use "assignment" not "range clause"
   945  			}
   946  			assert(obj.typ != nil)
   947  		}
   948  
   949  		// declare variables
   950  		if len(vars) > 0 {
   951  			scopePos := s.Body.Pos()
   952  			for _, obj := range vars {
   953  				check.declare(check.scope, nil /* recordDef already called */, obj, scopePos)
   954  			}
   955  		} else {
   956  			check.error(noNewVarPos, NoNewVar, "no new variables on left side of :=")
   957  		}
   958  	} else if sKey != nil /* lhs[0] != nil */ {
   959  		// ordinary assignment
   960  		for i, lhs := range lhs {
   961  			if lhs == nil {
   962  				continue
   963  			}
   964  
   965  			// assign to lhs iteration variable, if any
   966  			typ := rhs[i]
   967  			if typ == nil {
   968  				continue
   969  			}
   970  
   971  			if rangeOverInt {
   972  				assert(i == 0) // at most one iteration variable (rhs[1] == nil for rangeOverInt)
   973  				check.assignVar(lhs, nil, &x, "range clause")
   974  				// If the assignment succeeded, if x was untyped before, it now
   975  				// has a type inferred via the assignment. It must be an integer.
   976  				// (go.dev/issues/67027)
   977  				if x.mode != invalid && !isInteger(x.typ) {
   978  					check.softErrorf(lhs, InvalidRangeExpr, "cannot use iteration variable of type %s", x.typ)
   979  				}
   980  			} else {
   981  				var y operand
   982  				y.mode = value
   983  				y.expr = lhs // we don't have a better rhs expression to use here
   984  				y.typ = typ
   985  				check.assignVar(lhs, nil, &y, "assignment") // error is on variable, use "assignment" not "range clause"
   986  			}
   987  		}
   988  	} else if rangeOverInt {
   989  		// If we don't have any iteration variables, we still need to
   990  		// check that a (possibly untyped) integer range expression x
   991  		// is valid.
   992  		// We do this by checking the assignment _ = x. This ensures
   993  		// that an untyped x can be converted to a value of its default
   994  		// type (rune or int).
   995  		check.assignment(&x, nil, "range clause")
   996  	}
   997  
   998  	check.stmt(inner, s.Body)
   999  }
  1000  
  1001  // RangeKeyVal returns the key and value types for a range over typ.
  1002  // Exported for use by the compiler (does not exist in go/types).
  1003  func RangeKeyVal(typ Type) (Type, Type) {
  1004  	key, val, _, _, _ := rangeKeyVal(typ, nil)
  1005  	return key, val
  1006  }
  1007  
  1008  // rangeKeyVal returns the key and value type produced by a range clause
  1009  // over an expression of type typ.
  1010  // If allowVersion != nil, it is used to check the required language version.
  1011  // If the range clause is not permitted, rangeKeyVal returns ok = false.
  1012  // When ok = false, rangeKeyVal may also return a reason in cause.
  1013  func rangeKeyVal(typ Type, allowVersion func(goVersion) bool) (key, val Type, cause string, isFunc, ok bool) {
  1014  	bad := func(cause string) (Type, Type, string, bool, bool) {
  1015  		return Typ[Invalid], Typ[Invalid], cause, false, false
  1016  	}
  1017  	toSig := func(t Type) *Signature {
  1018  		sig, _ := coreType(t).(*Signature)
  1019  		return sig
  1020  	}
  1021  
  1022  	orig := typ
  1023  	switch typ := arrayPtrDeref(coreType(typ)).(type) {
  1024  	case nil:
  1025  		return bad("no core type")
  1026  	case *Basic:
  1027  		if isString(typ) {
  1028  			return Typ[Int], universeRune, "", false, true // use 'rune' name
  1029  		}
  1030  		if isInteger(typ) {
  1031  			if allowVersion != nil && !allowVersion(go1_22) {
  1032  				return bad("requires go1.22 or later")
  1033  			}
  1034  			return orig, nil, "", false, true
  1035  		}
  1036  	case *Array:
  1037  		return Typ[Int], typ.elem, "", false, true
  1038  	case *Slice:
  1039  		return Typ[Int], typ.elem, "", false, true
  1040  	case *Map:
  1041  		return typ.key, typ.elem, "", false, true
  1042  	case *Chan:
  1043  		if typ.dir == SendOnly {
  1044  			return bad("receive from send-only channel")
  1045  		}
  1046  		return typ.elem, nil, "", false, true
  1047  	case *Signature:
  1048  		if !buildcfg.Experiment.RangeFunc && allowVersion != nil && !allowVersion(go1_23) {
  1049  			return bad("requires go1.23 or later")
  1050  		}
  1051  		assert(typ.Recv() == nil)
  1052  		switch {
  1053  		case typ.Params().Len() != 1:
  1054  			return bad("func must be func(yield func(...) bool): wrong argument count")
  1055  		case toSig(typ.Params().At(0).Type()) == nil:
  1056  			return bad("func must be func(yield func(...) bool): argument is not func")
  1057  		case typ.Results().Len() != 0:
  1058  			return bad("func must be func(yield func(...) bool): unexpected results")
  1059  		}
  1060  		cb := toSig(typ.Params().At(0).Type())
  1061  		assert(cb.Recv() == nil)
  1062  		switch {
  1063  		case cb.Params().Len() > 2:
  1064  			return bad("func must be func(yield func(...) bool): yield func has too many parameters")
  1065  		case cb.Results().Len() != 1 || !isBoolean(cb.Results().At(0).Type()):
  1066  			return bad("func must be func(yield func(...) bool): yield func does not return bool")
  1067  		}
  1068  		if cb.Params().Len() >= 1 {
  1069  			key = cb.Params().At(0).Type()
  1070  		}
  1071  		if cb.Params().Len() >= 2 {
  1072  			val = cb.Params().At(1).Type()
  1073  		}
  1074  		return key, val, "", true, true
  1075  	}
  1076  	return
  1077  }
  1078  

View as plain text