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

View as plain text