github.com/bir3/gocompiler@v0.9.2202/src/go/types/assignments.go (about)

     1  // Copyright 2013 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 initialization and assignment checks.
     6  
     7  package types
     8  
     9  import (
    10  	"fmt"
    11  	"github.com/bir3/gocompiler/src/go/ast"
    12  	. "github.com/bir3/gocompiler/src/internal/types/errors"
    13  	"strings"
    14  )
    15  
    16  // assignment reports whether x can be assigned to a variable of type T,
    17  // if necessary by attempting to convert untyped values to the appropriate
    18  // type. context describes the context in which the assignment takes place.
    19  // Use T == nil to indicate assignment to an untyped blank identifier.
    20  // If the assignment check fails, x.mode is set to invalid.
    21  func (check *Checker) assignment(x *operand, T Type, context string) {
    22  	check.singleValue(x)
    23  
    24  	switch x.mode {
    25  	case invalid:
    26  		return	// error reported before
    27  	case constant_, variable, mapindex, value, commaok, commaerr:
    28  		// ok
    29  	default:
    30  		// we may get here because of other problems (go.dev/issue/39634, crash 12)
    31  		// TODO(gri) do we need a new "generic" error code here?
    32  		check.errorf(x, IncompatibleAssign, "cannot assign %s to %s in %s", x, T, context)
    33  		x.mode = invalid
    34  		return
    35  	}
    36  
    37  	if isUntyped(x.typ) {
    38  		target := T
    39  		// spec: "If an untyped constant is assigned to a variable of interface
    40  		// type or the blank identifier, the constant is first converted to type
    41  		// bool, rune, int, float64, complex128 or string respectively, depending
    42  		// on whether the value is a boolean, rune, integer, floating-point,
    43  		// complex, or string constant."
    44  		if T == nil || isNonTypeParamInterface(T) {
    45  			if T == nil && x.typ == Typ[UntypedNil] {
    46  				check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context)
    47  				x.mode = invalid
    48  				return
    49  			}
    50  			target = Default(x.typ)
    51  		}
    52  		newType, val, code := check.implicitTypeAndValue(x, target)
    53  		if code != 0 {
    54  			msg := check.sprintf("cannot use %s as %s value in %s", x, target, context)
    55  			switch code {
    56  			case TruncatedFloat:
    57  				msg += " (truncated)"
    58  			case NumericOverflow:
    59  				msg += " (overflows)"
    60  			default:
    61  				code = IncompatibleAssign
    62  			}
    63  			check.error(x, code, msg)
    64  			x.mode = invalid
    65  			return
    66  		}
    67  		if val != nil {
    68  			x.val = val
    69  			check.updateExprVal(x.expr, val)
    70  		}
    71  		if newType != x.typ {
    72  			x.typ = newType
    73  			check.updateExprType(x.expr, newType, false)
    74  		}
    75  	}
    76  	// x.typ is typed
    77  
    78  	// A generic (non-instantiated) function value cannot be assigned to a variable.
    79  	if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 {
    80  		check.errorf(x, WrongTypeArgCount, "cannot use generic function %s without instantiation in %s", x, context)
    81  		x.mode = invalid
    82  		return
    83  	}
    84  
    85  	// spec: "If a left-hand side is the blank identifier, any typed or
    86  	// non-constant value except for the predeclared identifier nil may
    87  	// be assigned to it."
    88  	if T == nil {
    89  		return
    90  	}
    91  
    92  	cause := ""
    93  	if ok, code := x.assignableTo(check, T, &cause); !ok {
    94  		if cause != "" {
    95  			check.errorf(x, code, "cannot use %s as %s value in %s: %s", x, T, context, cause)
    96  		} else {
    97  			check.errorf(x, code, "cannot use %s as %s value in %s", x, T, context)
    98  		}
    99  		x.mode = invalid
   100  	}
   101  }
   102  
   103  func (check *Checker) initConst(lhs *Const, x *operand) {
   104  	if x.mode == invalid || !isValid(x.typ) || !isValid(lhs.typ) {
   105  		if lhs.typ == nil {
   106  			lhs.typ = Typ[Invalid]
   107  		}
   108  		return
   109  	}
   110  
   111  	// rhs must be a constant
   112  	if x.mode != constant_ {
   113  		check.errorf(x, InvalidConstInit, "%s is not constant", x)
   114  		if lhs.typ == nil {
   115  			lhs.typ = Typ[Invalid]
   116  		}
   117  		return
   118  	}
   119  	assert(isConstType(x.typ))
   120  
   121  	// If the lhs doesn't have a type yet, use the type of x.
   122  	if lhs.typ == nil {
   123  		lhs.typ = x.typ
   124  	}
   125  
   126  	check.assignment(x, lhs.typ, "constant declaration")
   127  	if x.mode == invalid {
   128  		return
   129  	}
   130  
   131  	lhs.val = x.val
   132  }
   133  
   134  // initVar checks the initialization lhs = x in a variable declaration.
   135  // If lhs doesn't have a type yet, it is given the type of x,
   136  // or Typ[Invalid] in case of an error.
   137  // If the initialization check fails, x.mode is set to invalid.
   138  func (check *Checker) initVar(lhs *Var, x *operand, context string) {
   139  	if x.mode == invalid || !isValid(x.typ) || !isValid(lhs.typ) {
   140  		if lhs.typ == nil {
   141  			lhs.typ = Typ[Invalid]
   142  		}
   143  		x.mode = invalid
   144  		return
   145  	}
   146  
   147  	// If lhs doesn't have a type yet, use the type of x.
   148  	if lhs.typ == nil {
   149  		typ := x.typ
   150  		if isUntyped(typ) {
   151  			// convert untyped types to default types
   152  			if typ == Typ[UntypedNil] {
   153  				check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context)
   154  				lhs.typ = Typ[Invalid]
   155  				x.mode = invalid
   156  				return
   157  			}
   158  			typ = Default(typ)
   159  		}
   160  		lhs.typ = typ
   161  	}
   162  
   163  	check.assignment(x, lhs.typ, context)
   164  }
   165  
   166  // lhsVar checks a lhs variable in an assignment and returns its type.
   167  // lhsVar takes care of not counting a lhs identifier as a "use" of
   168  // that identifier. The result is nil if it is the blank identifier,
   169  // and Typ[Invalid] if it is an invalid lhs expression.
   170  func (check *Checker) lhsVar(lhs ast.Expr) Type {
   171  	// Determine if the lhs is a (possibly parenthesized) identifier.
   172  	ident, _ := unparen(lhs).(*ast.Ident)
   173  
   174  	// Don't evaluate lhs if it is the blank identifier.
   175  	if ident != nil && ident.Name == "_" {
   176  		check.recordDef(ident, nil)
   177  		return nil
   178  	}
   179  
   180  	// If the lhs is an identifier denoting a variable v, this reference
   181  	// is not a 'use' of v. Remember current value of v.used and restore
   182  	// after evaluating the lhs via check.expr.
   183  	var v *Var
   184  	var v_used bool
   185  	if ident != nil {
   186  		if obj := check.lookup(ident.Name); obj != nil {
   187  			// It's ok to mark non-local variables, but ignore variables
   188  			// from other packages to avoid potential race conditions with
   189  			// dot-imported variables.
   190  			if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {
   191  				v = w
   192  				v_used = v.used
   193  			}
   194  		}
   195  	}
   196  
   197  	var x operand
   198  	check.expr(nil, &x, lhs)
   199  
   200  	if v != nil {
   201  		v.used = v_used	// restore v.used
   202  	}
   203  
   204  	if x.mode == invalid || !isValid(x.typ) {
   205  		return Typ[Invalid]
   206  	}
   207  
   208  	// spec: "Each left-hand side operand must be addressable, a map index
   209  	// expression, or the blank identifier. Operands may be parenthesized."
   210  	switch x.mode {
   211  	case invalid:
   212  		return Typ[Invalid]
   213  	case variable, mapindex:
   214  		// ok
   215  	default:
   216  		if sel, ok := x.expr.(*ast.SelectorExpr); ok {
   217  			var op operand
   218  			check.expr(nil, &op, sel.X)
   219  			if op.mode == mapindex {
   220  				check.errorf(&x, UnaddressableFieldAssign, "cannot assign to struct field %s in map", ExprString(x.expr))
   221  				return Typ[Invalid]
   222  			}
   223  		}
   224  		check.errorf(&x, UnassignableOperand, "cannot assign to %s (neither addressable nor a map index expression)", x.expr)
   225  		return Typ[Invalid]
   226  	}
   227  
   228  	return x.typ
   229  }
   230  
   231  // assignVar checks the assignment lhs = rhs (if x == nil), or lhs = x (if x != nil).
   232  // If x != nil, it must be the evaluation of rhs (and rhs will be ignored).
   233  // If the assignment check fails and x != nil, x.mode is set to invalid.
   234  func (check *Checker) assignVar(lhs, rhs ast.Expr, x *operand, context string) {
   235  	T := check.lhsVar(lhs)	// nil if lhs is _
   236  	if !isValid(T) {
   237  		if x != nil {
   238  			x.mode = invalid
   239  		} else {
   240  			check.use(rhs)
   241  		}
   242  		return
   243  	}
   244  
   245  	if x == nil {
   246  		var target *target
   247  		// avoid calling ExprString if not needed
   248  		if T != nil {
   249  			if _, ok := under(T).(*Signature); ok {
   250  				target = newTarget(T, ExprString(lhs))
   251  			}
   252  		}
   253  		x = new(operand)
   254  		check.expr(target, x, rhs)
   255  	}
   256  
   257  	if T == nil && context == "assignment" {
   258  		context = "assignment to _ identifier"
   259  	}
   260  	check.assignment(x, T, context)
   261  }
   262  
   263  // operandTypes returns the list of types for the given operands.
   264  func operandTypes(list []*operand) (res []Type) {
   265  	for _, x := range list {
   266  		res = append(res, x.typ)
   267  	}
   268  	return res
   269  }
   270  
   271  // varTypes returns the list of types for the given variables.
   272  func varTypes(list []*Var) (res []Type) {
   273  	for _, x := range list {
   274  		res = append(res, x.typ)
   275  	}
   276  	return res
   277  }
   278  
   279  // typesSummary returns a string of the form "(t1, t2, ...)" where the
   280  // ti's are user-friendly string representations for the given types.
   281  // If variadic is set and the last type is a slice, its string is of
   282  // the form "...E" where E is the slice's element type.
   283  func (check *Checker) typesSummary(list []Type, variadic bool) string {
   284  	var res []string
   285  	for i, t := range list {
   286  		var s string
   287  		switch {
   288  		case t == nil:
   289  			fallthrough	// should not happen but be cautious
   290  		case !isValid(t):
   291  			s = "unknown type"
   292  		case isUntyped(t):
   293  			if isNumeric(t) {
   294  				// Do not imply a specific type requirement:
   295  				// "have number, want float64" is better than
   296  				// "have untyped int, want float64" or
   297  				// "have int, want float64".
   298  				s = "number"
   299  			} else {
   300  				// If we don't have a number, omit the "untyped" qualifier
   301  				// for compactness.
   302  				s = strings.Replace(t.(*Basic).name, "untyped ", "", -1)
   303  			}
   304  		case variadic && i == len(list)-1:
   305  			s = check.sprintf("...%s", t.(*Slice).elem)
   306  		}
   307  		if s == "" {
   308  			s = check.sprintf("%s", t)
   309  		}
   310  		res = append(res, s)
   311  	}
   312  	return "(" + strings.Join(res, ", ") + ")"
   313  }
   314  
   315  func measure(x int, unit string) string {
   316  	if x != 1 {
   317  		unit += "s"
   318  	}
   319  	return fmt.Sprintf("%d %s", x, unit)
   320  }
   321  
   322  func (check *Checker) assignError(rhs []ast.Expr, l, r int) {
   323  	vars := measure(l, "variable")
   324  	vals := measure(r, "value")
   325  	rhs0 := rhs[0]
   326  
   327  	if len(rhs) == 1 {
   328  		if call, _ := unparen(rhs0).(*ast.CallExpr); call != nil {
   329  			check.errorf(rhs0, WrongAssignCount, "assignment mismatch: %s but %s returns %s", vars, call.Fun, vals)
   330  			return
   331  		}
   332  	}
   333  	check.errorf(rhs0, WrongAssignCount, "assignment mismatch: %s but %s", vars, vals)
   334  }
   335  
   336  func (check *Checker) returnError(at positioner, lhs []*Var, rhs []*operand) {
   337  	l, r := len(lhs), len(rhs)
   338  	qualifier := "not enough"
   339  	if r > l {
   340  		at = rhs[l]	// report at first extra value
   341  		qualifier = "too many"
   342  	} else if r > 0 {
   343  		at = rhs[r-1]	// report at last value
   344  	}
   345  	var err error_
   346  	err.code = WrongResultCount
   347  	err.errorf(at.Pos(), "%s return values", qualifier)
   348  	err.errorf(nopos, "have %s", check.typesSummary(operandTypes(rhs), false))
   349  	err.errorf(nopos, "want %s", check.typesSummary(varTypes(lhs), false))
   350  	check.report(&err)
   351  }
   352  
   353  // initVars type-checks assignments of initialization expressions orig_rhs
   354  // to variables lhs.
   355  // If returnStmt is non-nil, initVars type-checks the implicit assignment
   356  // of result expressions orig_rhs to function result parameters lhs.
   357  func (check *Checker) initVars(lhs []*Var, orig_rhs []ast.Expr, returnStmt ast.Stmt) {
   358  	context := "assignment"
   359  	if returnStmt != nil {
   360  		context = "return statement"
   361  	}
   362  
   363  	l, r := len(lhs), len(orig_rhs)
   364  
   365  	// If l == 1 and the rhs is a single call, for a better
   366  	// error message don't handle it as n:n mapping below.
   367  	isCall := false
   368  	if r == 1 {
   369  		_, isCall = unparen(orig_rhs[0]).(*ast.CallExpr)
   370  	}
   371  
   372  	// If we have a n:n mapping from lhs variable to rhs expression,
   373  	// each value can be assigned to its corresponding variable.
   374  	if l == r && !isCall {
   375  		var x operand
   376  		for i, lhs := range lhs {
   377  			desc := lhs.name
   378  			if returnStmt != nil && desc == "" {
   379  				desc = "result variable"
   380  			}
   381  			check.expr(newTarget(lhs.typ, desc), &x, orig_rhs[i])
   382  			check.initVar(lhs, &x, context)
   383  		}
   384  		return
   385  	}
   386  
   387  	// If we don't have an n:n mapping, the rhs must be a single expression
   388  	// resulting in 2 or more values; otherwise we have an assignment mismatch.
   389  	if r != 1 {
   390  		// Only report a mismatch error if there are no other errors on the rhs.
   391  		if check.use(orig_rhs...) {
   392  			if returnStmt != nil {
   393  				rhs := check.exprList(orig_rhs)
   394  				check.returnError(returnStmt, lhs, rhs)
   395  			} else {
   396  				check.assignError(orig_rhs, l, r)
   397  			}
   398  		}
   399  		// ensure that LHS variables have a type
   400  		for _, v := range lhs {
   401  			if v.typ == nil {
   402  				v.typ = Typ[Invalid]
   403  			}
   404  		}
   405  		return
   406  	}
   407  
   408  	rhs, commaOk := check.multiExpr(orig_rhs[0], l == 2 && returnStmt == nil)
   409  	r = len(rhs)
   410  	if l == r {
   411  		for i, lhs := range lhs {
   412  			check.initVar(lhs, rhs[i], context)
   413  		}
   414  		// Only record comma-ok expression if both initializations succeeded
   415  		// (go.dev/issue/59371).
   416  		if commaOk && rhs[0].mode != invalid && rhs[1].mode != invalid {
   417  			check.recordCommaOkTypes(orig_rhs[0], rhs)
   418  		}
   419  		return
   420  	}
   421  
   422  	// In all other cases we have an assignment mismatch.
   423  	// Only report a mismatch error if there are no other errors on the rhs.
   424  	if rhs[0].mode != invalid {
   425  		if returnStmt != nil {
   426  			check.returnError(returnStmt, lhs, rhs)
   427  		} else {
   428  			check.assignError(orig_rhs, l, r)
   429  		}
   430  	}
   431  	// ensure that LHS variables have a type
   432  	for _, v := range lhs {
   433  		if v.typ == nil {
   434  			v.typ = Typ[Invalid]
   435  		}
   436  	}
   437  	// orig_rhs[0] was already evaluated
   438  }
   439  
   440  // assignVars type-checks assignments of expressions orig_rhs to variables lhs.
   441  func (check *Checker) assignVars(lhs, orig_rhs []ast.Expr) {
   442  	l, r := len(lhs), len(orig_rhs)
   443  
   444  	// If l == 1 and the rhs is a single call, for a better
   445  	// error message don't handle it as n:n mapping below.
   446  	isCall := false
   447  	if r == 1 {
   448  		_, isCall = unparen(orig_rhs[0]).(*ast.CallExpr)
   449  	}
   450  
   451  	// If we have a n:n mapping from lhs variable to rhs expression,
   452  	// each value can be assigned to its corresponding variable.
   453  	if l == r && !isCall {
   454  		for i, lhs := range lhs {
   455  			check.assignVar(lhs, orig_rhs[i], nil, "assignment")
   456  		}
   457  		return
   458  	}
   459  
   460  	// If we don't have an n:n mapping, the rhs must be a single expression
   461  	// resulting in 2 or more values; otherwise we have an assignment mismatch.
   462  	if r != 1 {
   463  		// Only report a mismatch error if there are no other errors on the lhs or rhs.
   464  		okLHS := check.useLHS(lhs...)
   465  		okRHS := check.use(orig_rhs...)
   466  		if okLHS && okRHS {
   467  			check.assignError(orig_rhs, l, r)
   468  		}
   469  		return
   470  	}
   471  
   472  	rhs, commaOk := check.multiExpr(orig_rhs[0], l == 2)
   473  	r = len(rhs)
   474  	if l == r {
   475  		for i, lhs := range lhs {
   476  			check.assignVar(lhs, nil, rhs[i], "assignment")
   477  		}
   478  		// Only record comma-ok expression if both assignments succeeded
   479  		// (go.dev/issue/59371).
   480  		if commaOk && rhs[0].mode != invalid && rhs[1].mode != invalid {
   481  			check.recordCommaOkTypes(orig_rhs[0], rhs)
   482  		}
   483  		return
   484  	}
   485  
   486  	// In all other cases we have an assignment mismatch.
   487  	// Only report a mismatch error if there are no other errors on the rhs.
   488  	if rhs[0].mode != invalid {
   489  		check.assignError(orig_rhs, l, r)
   490  	}
   491  	check.useLHS(lhs...)
   492  	// orig_rhs[0] was already evaluated
   493  }
   494  
   495  func (check *Checker) shortVarDecl(pos positioner, lhs, rhs []ast.Expr) {
   496  	top := len(check.delayed)
   497  	scope := check.scope
   498  
   499  	// collect lhs variables
   500  	seen := make(map[string]bool, len(lhs))
   501  	lhsVars := make([]*Var, len(lhs))
   502  	newVars := make([]*Var, 0, len(lhs))
   503  	hasErr := false
   504  	for i, lhs := range lhs {
   505  		ident, _ := lhs.(*ast.Ident)
   506  		if ident == nil {
   507  			check.useLHS(lhs)
   508  			// TODO(rFindley) this is redundant with a parser error. Consider omitting?
   509  			check.errorf(lhs, BadDecl, "non-name %s on left side of :=", lhs)
   510  			hasErr = true
   511  			continue
   512  		}
   513  
   514  		name := ident.Name
   515  		if name != "_" {
   516  			if seen[name] {
   517  				check.errorf(lhs, RepeatedDecl, "%s repeated on left side of :=", lhs)
   518  				hasErr = true
   519  				continue
   520  			}
   521  			seen[name] = true
   522  		}
   523  
   524  		// Use the correct obj if the ident is redeclared. The
   525  		// variable's scope starts after the declaration; so we
   526  		// must use Scope.Lookup here and call Scope.Insert
   527  		// (via check.declare) later.
   528  		if alt := scope.Lookup(name); alt != nil {
   529  			check.recordUse(ident, alt)
   530  			// redeclared object must be a variable
   531  			if obj, _ := alt.(*Var); obj != nil {
   532  				lhsVars[i] = obj
   533  			} else {
   534  				check.errorf(lhs, UnassignableOperand, "cannot assign to %s", lhs)
   535  				hasErr = true
   536  			}
   537  			continue
   538  		}
   539  
   540  		// declare new variable
   541  		obj := NewVar(ident.Pos(), check.pkg, name, nil)
   542  		lhsVars[i] = obj
   543  		if name != "_" {
   544  			newVars = append(newVars, obj)
   545  		}
   546  		check.recordDef(ident, obj)
   547  	}
   548  
   549  	// create dummy variables where the lhs is invalid
   550  	for i, obj := range lhsVars {
   551  		if obj == nil {
   552  			lhsVars[i] = NewVar(lhs[i].Pos(), check.pkg, "_", nil)
   553  		}
   554  	}
   555  
   556  	check.initVars(lhsVars, rhs, nil)
   557  
   558  	// process function literals in rhs expressions before scope changes
   559  	check.processDelayed(top)
   560  
   561  	if len(newVars) == 0 && !hasErr {
   562  		check.softErrorf(pos, NoNewVar, "no new variables on left side of :=")
   563  		return
   564  	}
   565  
   566  	// declare new variables
   567  	// spec: "The scope of a constant or variable identifier declared inside
   568  	// a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
   569  	// for short variable declarations) and ends at the end of the innermost
   570  	// containing block."
   571  	scopePos := rhs[len(rhs)-1].End()
   572  	for _, obj := range newVars {
   573  		check.declare(scope, nil, obj, scopePos)	// id = nil: recordDef already called
   574  	}
   575  }