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/types/errors"
    13  	"slices"
    14  )
    15  
    16  // decl may be nil
    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  		version: check.version, // TODO(adonovan): would decl.version (if decl != nil) be better?
    36  		iota:    iota,
    37  		sig:     sig,
    38  	}
    39  	check.indent = 0
    40  
    41  	check.stmtList(0, body.List)
    42  
    43  	if check.hasLabel && !check.conf.IgnoreBranchErrors {
    44  		check.labels(body)
    45  	}
    46  
    47  	if sig.results.Len() > 0 && !check.isTerminating(body, "") {
    48  		check.error(body.Rbrace, MissingReturn, "missing return")
    49  	}
    50  
    51  	// spec: "Implementation restriction: A compiler may make it illegal to
    52  	// declare a variable inside a function body if the variable is never used."
    53  	check.usage(sig.scope)
    54  }
    55  
    56  func (check *Checker) usage(scope *Scope) {
    57  	needUse := func(kind VarKind) bool {
    58  		return !(kind == RecvVar || kind == ParamVar || kind == ResultVar)
    59  	}
    60  	var unused []*Var
    61  	for name, elem := range scope.elems {
    62  		elem = resolve(name, elem)
    63  		if v, _ := elem.(*Var); v != nil && needUse(v.kind) && !check.usedVars[v] {
    64  			unused = append(unused, v)
    65  		}
    66  	}
    67  	slices.SortFunc(unused, func(a, b *Var) int {
    68  		return cmpPos(a.pos, b.pos)
    69  	})
    70  	for _, v := range unused {
    71  		check.softErrorf(v.pos, UnusedVar, "declared and not used: %s", v.name)
    72  	}
    73  
    74  	for _, scope := range scope.children {
    75  		// Don't go inside function literal scopes a second time;
    76  		// they are handled explicitly by funcBody.
    77  		if !scope.isFunc {
    78  			check.usage(scope)
    79  		}
    80  	}
    81  }
    82  
    83  // stmtContext is a bitset describing which
    84  // control-flow statements are permissible,
    85  // and provides additional context information
    86  // for better error messages.
    87  type stmtContext uint
    88  
    89  const (
    90  	// permissible control-flow statements
    91  	breakOk stmtContext = 1 << iota
    92  	continueOk
    93  	fallthroughOk
    94  
    95  	// additional context information
    96  	finalSwitchCase
    97  	inTypeSwitch
    98  )
    99  
   100  func (check *Checker) simpleStmt(s syntax.Stmt) {
   101  	if s != nil {
   102  		check.stmt(0, s)
   103  	}
   104  }
   105  
   106  func trimTrailingEmptyStmts(list []syntax.Stmt) []syntax.Stmt {
   107  	for i := len(list); i > 0; i-- {
   108  		if _, ok := list[i-1].(*syntax.EmptyStmt); !ok {
   109  			return list[:i]
   110  		}
   111  	}
   112  	return nil
   113  }
   114  
   115  func (check *Checker) stmtList(ctxt stmtContext, list []syntax.Stmt) {
   116  	ok := ctxt&fallthroughOk != 0
   117  	inner := ctxt &^ fallthroughOk
   118  	list = trimTrailingEmptyStmts(list) // trailing empty statements are "invisible" to fallthrough analysis
   119  	for i, s := range list {
   120  		inner := inner
   121  		if ok && i+1 == len(list) {
   122  			inner |= fallthroughOk
   123  		}
   124  		check.stmt(inner, s)
   125  	}
   126  }
   127  
   128  func (check *Checker) multipleSwitchDefaults(list []*syntax.CaseClause) {
   129  	var first *syntax.CaseClause
   130  	for _, c := range list {
   131  		if c.Cases == nil {
   132  			if first != nil {
   133  				check.errorf(c, DuplicateDefault, "multiple defaults (first at %s)", first.Pos())
   134  				// TODO(gri) probably ok to bail out after first error (and simplify this code)
   135  			} else {
   136  				first = c
   137  			}
   138  		}
   139  	}
   140  }
   141  
   142  func (check *Checker) multipleSelectDefaults(list []*syntax.CommClause) {
   143  	var first *syntax.CommClause
   144  	for _, c := range list {
   145  		if c.Comm == nil {
   146  			if first != nil {
   147  				check.errorf(c, DuplicateDefault, "multiple defaults (first at %s)", first.Pos())
   148  				// TODO(gri) probably ok to bail out after first error (and simplify this code)
   149  			} else {
   150  				first = c
   151  			}
   152  		}
   153  	}
   154  }
   155  
   156  func (check *Checker) openScope(node syntax.Node, comment string) {
   157  	scope := NewScope(check.scope, node.Pos(), syntax.EndPos(node), 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  // caseTypes typechecks the type expressions of a type case, checks for duplicate types
   286  // using the seen map, and verifies that each type is valid with respect to the type of
   287  // the operand x corresponding to the type switch expression. If that expression is not
   288  // valid, x must be nil.
   289  //
   290  //	switch <x>.(type) {
   291  //	case <types>: ...
   292  //	...
   293  //	}
   294  //
   295  // caseTypes returns the case-specific type for a variable v introduced through a short
   296  // variable declaration by the type switch:
   297  //
   298  //	switch v := <x>.(type) {
   299  //	case <types>: // T is the type of <v> in this case
   300  //	...
   301  //	}
   302  //
   303  // If there is exactly one type expression, T is the type of that expression. If there
   304  // are multiple type expressions, or if predeclared nil is among the types, the result
   305  // is the type of x. If x is invalid (nil), the result is the invalid type.
   306  func (check *Checker) caseTypes(x *operand, types []syntax.Expr, seen map[Type]syntax.Expr) Type {
   307  	var T Type
   308  	var dummy operand
   309  L:
   310  	for _, e := range types {
   311  		// The spec allows the value nil instead of a type.
   312  		if check.isNil(e) {
   313  			T = nil
   314  			check.expr(nil, &dummy, e) // run e through expr so we get the usual Info recordings
   315  		} else {
   316  			T = check.varType(e)
   317  			if !isValid(T) {
   318  				continue L
   319  			}
   320  		}
   321  		// look for duplicate types
   322  		// (quadratic algorithm, but type switches tend to be reasonably small)
   323  		for t, other := range seen {
   324  			if T == nil && t == nil || T != nil && t != nil && Identical(T, t) {
   325  				// talk about "case" rather than "type" because of nil case
   326  				Ts := "nil"
   327  				if T != nil {
   328  					Ts = TypeString(T, check.qualifier)
   329  				}
   330  				err := check.newError(DuplicateCase)
   331  				err.addf(e, "duplicate case %s in type switch", Ts)
   332  				err.addf(other, "previous case")
   333  				err.report()
   334  				continue L
   335  			}
   336  		}
   337  		seen[T] = e
   338  		if x != nil && T != nil {
   339  			check.typeAssertion(e, x, T, true)
   340  		}
   341  	}
   342  
   343  	// spec: "In clauses with a case listing exactly one type, the variable has that type;
   344  	// otherwise, the variable has the type of the expression in the TypeSwitchGuard.
   345  	if len(types) != 1 || T == nil {
   346  		T = Typ[Invalid]
   347  		if x != nil {
   348  			T = x.typ
   349  		}
   350  	}
   351  
   352  	assert(T != nil)
   353  	return T
   354  }
   355  
   356  // TODO(gri) Once we are certain that typeHash is correct in all situations, use this version of caseTypes instead.
   357  // (Currently it may be possible that different types have identical names and import paths due to ImporterFrom.)
   358  func (check *Checker) caseTypes_currently_unused(x *operand, xtyp *Interface, types []syntax.Expr, seen map[string]syntax.Expr) Type {
   359  	var T Type
   360  	var dummy operand
   361  L:
   362  	for _, e := range types {
   363  		// The spec allows the value nil instead of a type.
   364  		var hash string
   365  		if check.isNil(e) {
   366  			check.expr(nil, &dummy, e) // run e through expr so we get the usual Info recordings
   367  			T = nil
   368  			hash = "<nil>" // avoid collision with a type named nil
   369  		} else {
   370  			T = check.varType(e)
   371  			if !isValid(T) {
   372  				continue L
   373  			}
   374  			panic("enable typeHash(T, nil)")
   375  			// hash = typeHash(T, nil)
   376  		}
   377  		// look for duplicate types
   378  		if other := seen[hash]; other != nil {
   379  			// talk about "case" rather than "type" because of nil case
   380  			Ts := "nil"
   381  			if T != nil {
   382  				Ts = TypeString(T, check.qualifier)
   383  			}
   384  			err := check.newError(DuplicateCase)
   385  			err.addf(e, "duplicate case %s in type switch", Ts)
   386  			err.addf(other, "previous case")
   387  			err.report()
   388  			continue L
   389  		}
   390  		seen[hash] = e
   391  		if T != nil {
   392  			check.typeAssertion(e, x, T, true)
   393  		}
   394  	}
   395  
   396  	// spec: "In clauses with a case listing exactly one type, the variable has that type;
   397  	// otherwise, the variable has the type of the expression in the TypeSwitchGuard.
   398  	if len(types) != 1 || T == nil {
   399  		T = Typ[Invalid]
   400  		if x != nil {
   401  			T = x.typ
   402  		}
   403  	}
   404  
   405  	assert(T != nil)
   406  	return T
   407  }
   408  
   409  // stmt typechecks statement s.
   410  func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
   411  	// statements must end with the same top scope as they started with
   412  	if debug {
   413  		defer func(scope *Scope) {
   414  			// don't check if code is panicking
   415  			if p := recover(); p != nil {
   416  				panic(p)
   417  			}
   418  			assert(scope == check.scope)
   419  		}(check.scope)
   420  	}
   421  
   422  	// process collected function literals before scope changes
   423  	defer check.processDelayed(len(check.delayed))
   424  
   425  	// reset context for statements of inner blocks
   426  	inner := ctxt &^ (fallthroughOk | finalSwitchCase | inTypeSwitch)
   427  
   428  	switch s := s.(type) {
   429  	case *syntax.EmptyStmt:
   430  		// ignore
   431  
   432  	case *syntax.DeclStmt:
   433  		check.declStmt(s.DeclList)
   434  
   435  	case *syntax.LabeledStmt:
   436  		check.hasLabel = true
   437  		check.stmt(ctxt, s.Stmt)
   438  
   439  	case *syntax.ExprStmt:
   440  		// spec: "With the exception of specific built-in functions,
   441  		// function and method calls and receive operations can appear
   442  		// in statement context. Such statements may be parenthesized."
   443  		var x operand
   444  		kind := check.rawExpr(nil, &x, s.X, nil, false)
   445  		var msg string
   446  		var code Code
   447  		switch x.mode {
   448  		default:
   449  			if kind == statement {
   450  				return
   451  			}
   452  			msg = "is not used"
   453  			code = UnusedExpr
   454  		case builtin:
   455  			msg = "must be called"
   456  			code = UncalledBuiltin
   457  		case typexpr:
   458  			msg = "is not an expression"
   459  			code = NotAnExpr
   460  		}
   461  		check.errorf(&x, code, "%s %s", &x, msg)
   462  
   463  	case *syntax.SendStmt:
   464  		var ch, val operand
   465  		check.expr(nil, &ch, s.Chan)
   466  		check.expr(nil, &val, s.Value)
   467  		if ch.mode == invalid || val.mode == invalid {
   468  			return
   469  		}
   470  		if elem := check.chanElem(s, &ch, false); elem != nil {
   471  			check.assignment(&val, elem, "send")
   472  		}
   473  
   474  	case *syntax.AssignStmt:
   475  		if s.Rhs == nil {
   476  			// x++ or x--
   477  			// (no need to call unpackExpr as s.Lhs must be single-valued)
   478  			var x operand
   479  			check.expr(nil, &x, s.Lhs)
   480  			if x.mode == invalid {
   481  				return
   482  			}
   483  			if !allNumeric(x.typ) {
   484  				check.errorf(s.Lhs, NonNumericIncDec, invalidOp+"%s%s%s (non-numeric type %s)", s.Lhs, s.Op, s.Op, x.typ)
   485  				return
   486  			}
   487  			check.assignVar(s.Lhs, nil, &x, "assignment")
   488  			return
   489  		}
   490  
   491  		lhs := syntax.UnpackListExpr(s.Lhs)
   492  		rhs := syntax.UnpackListExpr(s.Rhs)
   493  		switch s.Op {
   494  		case 0:
   495  			check.assignVars(lhs, rhs)
   496  			return
   497  		case syntax.Def:
   498  			check.shortVarDecl(s.Pos(), lhs, rhs)
   499  			return
   500  		}
   501  
   502  		// assignment operations
   503  		if len(lhs) != 1 || len(rhs) != 1 {
   504  			check.errorf(s, MultiValAssignOp, "assignment operation %s requires single-valued expressions", s.Op)
   505  			return
   506  		}
   507  
   508  		var x operand
   509  		check.binary(&x, nil, lhs[0], rhs[0], s.Op)
   510  		check.assignVar(lhs[0], nil, &x, "assignment")
   511  
   512  	case *syntax.CallStmt:
   513  		kind := "go"
   514  		if s.Tok == syntax.Defer {
   515  			kind = "defer"
   516  		}
   517  		check.suspendedCall(kind, s.Call)
   518  
   519  	case *syntax.ReturnStmt:
   520  		res := check.sig.results
   521  		// Return with implicit results allowed for function with named results.
   522  		// (If one is named, all are named.)
   523  		results := syntax.UnpackListExpr(s.Results)
   524  		if len(results) == 0 && res.Len() > 0 && res.vars[0].name != "" {
   525  			// spec: "Implementation restriction: A compiler may disallow an empty expression
   526  			// list in a "return" statement if a different entity (constant, type, or variable)
   527  			// with the same name as a result parameter is in scope at the place of the return."
   528  			for _, obj := range res.vars {
   529  				if alt := check.lookup(obj.name); alt != nil && alt != obj {
   530  					err := check.newError(OutOfScopeResult)
   531  					err.addf(s, "result parameter %s not in scope at return", obj.name)
   532  					err.addf(alt, "inner declaration of %s", obj)
   533  					err.report()
   534  					// ok to continue
   535  				}
   536  			}
   537  		} else {
   538  			var lhs []*Var
   539  			if res.Len() > 0 {
   540  				lhs = res.vars
   541  			}
   542  			check.initVars(lhs, results, s)
   543  		}
   544  
   545  	case *syntax.BranchStmt:
   546  		if s.Label != nil {
   547  			check.hasLabel = true
   548  			break // checked in 2nd pass (check.labels)
   549  		}
   550  		if check.conf.IgnoreBranchErrors {
   551  			break
   552  		}
   553  		switch s.Tok {
   554  		case syntax.Break:
   555  			if ctxt&breakOk == 0 {
   556  				check.error(s, MisplacedBreak, "break not in for, switch, or select statement")
   557  			}
   558  		case syntax.Continue:
   559  			if ctxt&continueOk == 0 {
   560  				check.error(s, MisplacedContinue, "continue not in for statement")
   561  			}
   562  		case syntax.Fallthrough:
   563  			if ctxt&fallthroughOk == 0 {
   564  				var msg string
   565  				switch {
   566  				case ctxt&finalSwitchCase != 0:
   567  					msg = "cannot fallthrough final case in switch"
   568  				case ctxt&inTypeSwitch != 0:
   569  					msg = "cannot fallthrough in type switch"
   570  				default:
   571  					msg = "fallthrough statement out of place"
   572  				}
   573  				check.error(s, MisplacedFallthrough, msg)
   574  			}
   575  		case syntax.Goto:
   576  			// goto's must have labels, should have been caught above
   577  			fallthrough
   578  		default:
   579  			check.errorf(s, InvalidSyntaxTree, "branch statement: %s", s.Tok)
   580  		}
   581  
   582  	case *syntax.BlockStmt:
   583  		check.openScope(s, "block")
   584  		defer check.closeScope()
   585  
   586  		check.stmtList(inner, s.List)
   587  
   588  	case *syntax.IfStmt:
   589  		check.openScope(s, "if")
   590  		defer check.closeScope()
   591  
   592  		check.simpleStmt(s.Init)
   593  		var x operand
   594  		check.expr(nil, &x, s.Cond)
   595  		if x.mode != invalid && !allBoolean(x.typ) {
   596  			check.error(s.Cond, InvalidCond, "non-boolean condition in if statement")
   597  		}
   598  		check.stmt(inner, s.Then)
   599  		// The parser produces a correct AST but if it was modified
   600  		// elsewhere the else branch may be invalid. Check again.
   601  		switch s.Else.(type) {
   602  		case nil:
   603  			// valid or error already reported
   604  		case *syntax.IfStmt, *syntax.BlockStmt:
   605  			check.stmt(inner, s.Else)
   606  		default:
   607  			check.error(s.Else, InvalidSyntaxTree, "invalid else branch in if statement")
   608  		}
   609  
   610  	case *syntax.SwitchStmt:
   611  		inner |= breakOk
   612  		check.openScope(s, "switch")
   613  		defer check.closeScope()
   614  
   615  		check.simpleStmt(s.Init)
   616  
   617  		if g, _ := s.Tag.(*syntax.TypeSwitchGuard); g != nil {
   618  			check.typeSwitchStmt(inner|inTypeSwitch, s, g)
   619  		} else {
   620  			check.switchStmt(inner, s)
   621  		}
   622  
   623  	case *syntax.SelectStmt:
   624  		inner |= breakOk
   625  
   626  		check.multipleSelectDefaults(s.Body)
   627  
   628  		for _, clause := range s.Body {
   629  			if clause == nil {
   630  				continue // error reported before
   631  			}
   632  
   633  			// clause.Comm must be a SendStmt, RecvStmt, or default case
   634  			valid := false
   635  			var rhs syntax.Expr // rhs of RecvStmt, or nil
   636  			switch s := clause.Comm.(type) {
   637  			case nil, *syntax.SendStmt:
   638  				valid = true
   639  			case *syntax.AssignStmt:
   640  				if _, ok := s.Rhs.(*syntax.ListExpr); !ok {
   641  					rhs = s.Rhs
   642  				}
   643  			case *syntax.ExprStmt:
   644  				rhs = s.X
   645  			}
   646  
   647  			// if present, rhs must be a receive operation
   648  			if rhs != nil {
   649  				if x, _ := syntax.Unparen(rhs).(*syntax.Operation); x != nil && x.Y == nil && x.Op == syntax.Recv {
   650  					valid = true
   651  				}
   652  			}
   653  
   654  			if !valid {
   655  				check.error(clause.Comm, InvalidSelectCase, "select case must be send or receive (possibly with assignment)")
   656  				continue
   657  			}
   658  			check.openScope(clause, "case")
   659  			if clause.Comm != nil {
   660  				check.stmt(inner, clause.Comm)
   661  			}
   662  			check.stmtList(inner, clause.Body)
   663  			check.closeScope()
   664  		}
   665  
   666  	case *syntax.ForStmt:
   667  		inner |= breakOk | continueOk
   668  
   669  		if rclause, _ := s.Init.(*syntax.RangeClause); rclause != nil {
   670  			// extract sKey, sValue, s.Extra from the range clause
   671  			sKey := rclause.Lhs            // possibly nil
   672  			var sValue, sExtra syntax.Expr // possibly nil
   673  			if p, _ := sKey.(*syntax.ListExpr); p != nil {
   674  				if len(p.ElemList) < 2 {
   675  					check.error(s, InvalidSyntaxTree, "invalid lhs in range clause")
   676  					return
   677  				}
   678  				// len(p.ElemList) >= 2
   679  				sKey = p.ElemList[0]
   680  				sValue = p.ElemList[1]
   681  				if len(p.ElemList) > 2 {
   682  					// delay error reporting until we know more
   683  					sExtra = p.ElemList[2]
   684  				}
   685  			}
   686  			check.rangeStmt(inner, s, s, sKey, sValue, sExtra, rclause.X, rclause.Def)
   687  			break
   688  		}
   689  
   690  		check.openScope(s, "for")
   691  		defer check.closeScope()
   692  
   693  		check.simpleStmt(s.Init)
   694  		if s.Cond != nil {
   695  			var x operand
   696  			check.expr(nil, &x, s.Cond)
   697  			if x.mode != invalid && !allBoolean(x.typ) {
   698  				check.error(s.Cond, InvalidCond, "non-boolean condition in for statement")
   699  			}
   700  		}
   701  		check.simpleStmt(s.Post)
   702  		// spec: "The init statement may be a short variable
   703  		// declaration, but the post statement must not."
   704  		if s, _ := s.Post.(*syntax.AssignStmt); s != nil && s.Op == syntax.Def {
   705  			// The parser already reported an error.
   706  			check.use(s.Lhs) // avoid follow-up errors
   707  		}
   708  		check.stmt(inner, s.Body)
   709  
   710  	default:
   711  		check.error(s, InvalidSyntaxTree, "invalid statement")
   712  	}
   713  }
   714  
   715  func (check *Checker) switchStmt(inner stmtContext, s *syntax.SwitchStmt) {
   716  	// init statement already handled
   717  
   718  	var x operand
   719  	if s.Tag != nil {
   720  		check.expr(nil, &x, s.Tag)
   721  		// By checking assignment of x to an invisible temporary
   722  		// (as a compiler would), we get all the relevant checks.
   723  		check.assignment(&x, nil, "switch expression")
   724  		if x.mode != invalid && !Comparable(x.typ) && !hasNil(x.typ) {
   725  			check.errorf(&x, InvalidExprSwitch, "cannot switch on %s (%s is not comparable)", &x, x.typ)
   726  			x.mode = invalid
   727  		}
   728  	} else {
   729  		// spec: "A missing switch expression is
   730  		// equivalent to the boolean value true."
   731  		x.mode = constant_
   732  		x.typ = Typ[Bool]
   733  		x.val = constant.MakeBool(true)
   734  		// TODO(gri) should have a better position here
   735  		pos := s.Rbrace
   736  		if len(s.Body) > 0 {
   737  			pos = s.Body[0].Pos()
   738  		}
   739  		x.expr = syntax.NewName(pos, "true")
   740  	}
   741  
   742  	check.multipleSwitchDefaults(s.Body)
   743  
   744  	seen := make(valueMap) // map of seen case values to positions and types
   745  	for i, clause := range s.Body {
   746  		if clause == nil {
   747  			check.error(clause, InvalidSyntaxTree, "incorrect expression switch case")
   748  			continue
   749  		}
   750  		inner := inner
   751  		if i+1 < len(s.Body) {
   752  			inner |= fallthroughOk
   753  		} else {
   754  			inner |= finalSwitchCase
   755  		}
   756  		check.caseValues(&x, syntax.UnpackListExpr(clause.Cases), seen)
   757  		check.openScope(clause, "case")
   758  		check.stmtList(inner, clause.Body)
   759  		check.closeScope()
   760  	}
   761  }
   762  
   763  func (check *Checker) typeSwitchStmt(inner stmtContext, s *syntax.SwitchStmt, guard *syntax.TypeSwitchGuard) {
   764  	// init statement already handled
   765  
   766  	// A type switch guard must be of the form:
   767  	//
   768  	//     TypeSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "type" ")" .
   769  	//                          \__lhs__/        \___rhs___/
   770  
   771  	// check lhs, if any
   772  	lhs := guard.Lhs
   773  	if lhs != nil {
   774  		if lhs.Value == "_" {
   775  			// _ := x.(type) is an invalid short variable declaration
   776  			check.softErrorf(lhs, NoNewVar, "no new variable on left side of :=")
   777  			lhs = nil // avoid declared and not used error below
   778  		} else {
   779  			check.recordDef(lhs, nil) // lhs variable is implicitly declared in each cause clause
   780  		}
   781  	}
   782  
   783  	// check rhs
   784  	var sx *operand // switch expression against which cases are compared against; nil if invalid
   785  	{
   786  		var x operand
   787  		check.expr(nil, &x, guard.X)
   788  		if x.mode != invalid {
   789  			if isTypeParam(x.typ) {
   790  				check.errorf(&x, InvalidTypeSwitch, "cannot use type switch on type parameter value %s", &x)
   791  			} else if IsInterface(x.typ) {
   792  				sx = &x
   793  			} else {
   794  				check.errorf(&x, InvalidTypeSwitch, "%s is not an interface", &x)
   795  			}
   796  		}
   797  	}
   798  
   799  	check.multipleSwitchDefaults(s.Body)
   800  
   801  	var lhsVars []*Var                 // list of implicitly declared lhs variables
   802  	seen := make(map[Type]syntax.Expr) // map of seen types to positions
   803  	for _, clause := range s.Body {
   804  		if clause == nil {
   805  			check.error(s, InvalidSyntaxTree, "incorrect type switch case")
   806  			continue
   807  		}
   808  		// Check each type in this type switch case.
   809  		cases := syntax.UnpackListExpr(clause.Cases)
   810  		T := check.caseTypes(sx, cases, seen)
   811  		check.openScope(clause, "case")
   812  		// If lhs exists, declare a corresponding variable in the case-local scope.
   813  		if lhs != nil {
   814  			obj := newVar(LocalVar, lhs.Pos(), check.pkg, lhs.Value, T)
   815  			check.declare(check.scope, nil, obj, clause.Colon)
   816  			check.recordImplicit(clause, obj)
   817  			// For the "declared and not used" error, all lhs variables act as
   818  			// one; i.e., if any one of them is 'used', all of them are 'used'.
   819  			// Collect them for later analysis.
   820  			lhsVars = append(lhsVars, obj)
   821  		}
   822  		check.stmtList(inner, clause.Body)
   823  		check.closeScope()
   824  	}
   825  
   826  	// If lhs exists, we must have at least one lhs variable that was used.
   827  	// (We can't use check.usage because that only looks at one scope; and
   828  	// we don't want to use the same variable for all scopes and change the
   829  	// variable type underfoot.)
   830  	if lhs != nil {
   831  		var used bool
   832  		for _, v := range lhsVars {
   833  			if check.usedVars[v] {
   834  				used = true
   835  			}
   836  			check.usedVars[v] = true // avoid usage error when checking entire function
   837  		}
   838  		if !used {
   839  			check.softErrorf(lhs, UnusedVar, "%s declared and not used", lhs.Value)
   840  		}
   841  	}
   842  }
   843  

View as plain text