...

Source file src/go/types/assignments.go

Documentation: go/types

     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  	"go/ast"
    12  	"go/token"
    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  // x.mode is set to invalid if the assignment failed.
    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 (issue #39634, crash 12)
    31  		check.errorf(x, 0, "cannot assign %s to %s in %s", x, T, context)
    32  		return
    33  	}
    34  
    35  	if isUntyped(x.typ) {
    36  		target := T
    37  		// spec: "If an untyped constant is assigned to a variable of interface
    38  		// type or the blank identifier, the constant is first converted to type
    39  		// bool, rune, int, float64, complex128 or string respectively, depending
    40  		// on whether the value is a boolean, rune, integer, floating-point,
    41  		// complex, or string constant."
    42  		if T == nil || isNonTypeParamInterface(T) {
    43  			if T == nil && x.typ == Typ[UntypedNil] {
    44  				check.errorf(x, _UntypedNil, "use of untyped nil in %s", context)
    45  				x.mode = invalid
    46  				return
    47  			}
    48  			target = Default(x.typ)
    49  		}
    50  		newType, val, code := check.implicitTypeAndValue(x, target)
    51  		if code != 0 {
    52  			msg := check.sprintf("cannot use %s as %s value in %s", x, target, context)
    53  			switch code {
    54  			case _TruncatedFloat:
    55  				msg += " (truncated)"
    56  			case _NumericOverflow:
    57  				msg += " (overflows)"
    58  			default:
    59  				code = _IncompatibleAssign
    60  			}
    61  			check.error(x, code, msg)
    62  			x.mode = invalid
    63  			return
    64  		}
    65  		if val != nil {
    66  			x.val = val
    67  			check.updateExprVal(x.expr, val)
    68  		}
    69  		if newType != x.typ {
    70  			x.typ = newType
    71  			check.updateExprType(x.expr, newType, false)
    72  		}
    73  	}
    74  
    75  	// A generic (non-instantiated) function value cannot be assigned to a variable.
    76  	if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 {
    77  		check.errorf(x, _WrongTypeArgCount, "cannot use generic function %s without instantiation in %s", x, context)
    78  	}
    79  
    80  	// spec: "If a left-hand side is the blank identifier, any typed or
    81  	// non-constant value except for the predeclared identifier nil may
    82  	// be assigned to it."
    83  	if T == nil {
    84  		return
    85  	}
    86  
    87  	reason := ""
    88  	if ok, code := x.assignableTo(check, T, &reason); !ok {
    89  		if compilerErrorMessages {
    90  			if reason != "" {
    91  				check.errorf(x, code, "cannot use %s as type %s in %s:\n\t%s", x, T, context, reason)
    92  			} else {
    93  				check.errorf(x, code, "cannot use %s as type %s in %s", x, T, context)
    94  			}
    95  		} else {
    96  			if reason != "" {
    97  				check.errorf(x, code, "cannot use %s as %s value in %s: %s", x, T, context, reason)
    98  			} else {
    99  				check.errorf(x, code, "cannot use %s as %s value in %s", x, T, context)
   100  			}
   101  		}
   102  		x.mode = invalid
   103  	}
   104  }
   105  
   106  func (check *Checker) initConst(lhs *Const, x *operand) {
   107  	if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
   108  		if lhs.typ == nil {
   109  			lhs.typ = Typ[Invalid]
   110  		}
   111  		return
   112  	}
   113  
   114  	// rhs must be a constant
   115  	if x.mode != constant_ {
   116  		check.errorf(x, _InvalidConstInit, "%s is not constant", x)
   117  		if lhs.typ == nil {
   118  			lhs.typ = Typ[Invalid]
   119  		}
   120  		return
   121  	}
   122  	assert(isConstType(x.typ))
   123  
   124  	// If the lhs doesn't have a type yet, use the type of x.
   125  	if lhs.typ == nil {
   126  		lhs.typ = x.typ
   127  	}
   128  
   129  	check.assignment(x, lhs.typ, "constant declaration")
   130  	if x.mode == invalid {
   131  		return
   132  	}
   133  
   134  	lhs.val = x.val
   135  }
   136  
   137  func (check *Checker) initVar(lhs *Var, x *operand, context string) Type {
   138  	if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
   139  		if lhs.typ == nil {
   140  			lhs.typ = Typ[Invalid]
   141  		}
   142  		return nil
   143  	}
   144  
   145  	// If the lhs doesn't have a type yet, use the type of x.
   146  	if lhs.typ == nil {
   147  		typ := x.typ
   148  		if isUntyped(typ) {
   149  			// convert untyped types to default types
   150  			if typ == Typ[UntypedNil] {
   151  				check.errorf(x, _UntypedNil, "use of untyped nil in %s", context)
   152  				lhs.typ = Typ[Invalid]
   153  				return nil
   154  			}
   155  			typ = Default(typ)
   156  		}
   157  		lhs.typ = typ
   158  	}
   159  
   160  	check.assignment(x, lhs.typ, context)
   161  	if x.mode == invalid {
   162  		return nil
   163  	}
   164  
   165  	return x.typ
   166  }
   167  
   168  func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type {
   169  	if x.mode == invalid || x.typ == Typ[Invalid] {
   170  		check.useLHS(lhs)
   171  		return nil
   172  	}
   173  
   174  	// Determine if the lhs is a (possibly parenthesized) identifier.
   175  	ident, _ := unparen(lhs).(*ast.Ident)
   176  
   177  	// Don't evaluate lhs if it is the blank identifier.
   178  	if ident != nil && ident.Name == "_" {
   179  		check.recordDef(ident, nil)
   180  		check.assignment(x, nil, "assignment to _ identifier")
   181  		if x.mode == invalid {
   182  			return nil
   183  		}
   184  		return x.typ
   185  	}
   186  
   187  	// If the lhs is an identifier denoting a variable v, this assignment
   188  	// is not a 'use' of v. Remember current value of v.used and restore
   189  	// after evaluating the lhs via check.expr.
   190  	var v *Var
   191  	var v_used bool
   192  	if ident != nil {
   193  		if obj := check.lookup(ident.Name); obj != nil {
   194  			// It's ok to mark non-local variables, but ignore variables
   195  			// from other packages to avoid potential race conditions with
   196  			// dot-imported variables.
   197  			if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {
   198  				v = w
   199  				v_used = v.used
   200  			}
   201  		}
   202  	}
   203  
   204  	var z operand
   205  	check.expr(&z, lhs)
   206  	if v != nil {
   207  		v.used = v_used // restore v.used
   208  	}
   209  
   210  	if z.mode == invalid || z.typ == Typ[Invalid] {
   211  		return nil
   212  	}
   213  
   214  	// spec: "Each left-hand side operand must be addressable, a map index
   215  	// expression, or the blank identifier. Operands may be parenthesized."
   216  	switch z.mode {
   217  	case invalid:
   218  		return nil
   219  	case variable, mapindex:
   220  		// ok
   221  	default:
   222  		if sel, ok := z.expr.(*ast.SelectorExpr); ok {
   223  			var op operand
   224  			check.expr(&op, sel.X)
   225  			if op.mode == mapindex {
   226  				check.errorf(&z, _UnaddressableFieldAssign, "cannot assign to struct field %s in map", ExprString(z.expr))
   227  				return nil
   228  			}
   229  		}
   230  		check.errorf(&z, _UnassignableOperand, "cannot assign to %s", &z)
   231  		return nil
   232  	}
   233  
   234  	check.assignment(x, z.typ, "assignment")
   235  	if x.mode == invalid {
   236  		return nil
   237  	}
   238  
   239  	return x.typ
   240  }
   241  
   242  // operandTypes returns the list of types for the given operands.
   243  func operandTypes(list []*operand) (res []Type) {
   244  	for _, x := range list {
   245  		res = append(res, x.typ)
   246  	}
   247  	return res
   248  }
   249  
   250  // varTypes returns the list of types for the given variables.
   251  func varTypes(list []*Var) (res []Type) {
   252  	for _, x := range list {
   253  		res = append(res, x.typ)
   254  	}
   255  	return res
   256  }
   257  
   258  // typesSummary returns a string of the form "(t1, t2, ...)" where the
   259  // ti's are user-friendly string representations for the given types.
   260  // If variadic is set and the last type is a slice, its string is of
   261  // the form "...E" where E is the slice's element type.
   262  func (check *Checker) typesSummary(list []Type, variadic bool) string {
   263  	var res []string
   264  	for i, t := range list {
   265  		var s string
   266  		switch {
   267  		case t == nil:
   268  			fallthrough // should not happen but be cautious
   269  		case t == Typ[Invalid]:
   270  			s = "<T>"
   271  		case isUntyped(t):
   272  			if isNumeric(t) {
   273  				// Do not imply a specific type requirement:
   274  				// "have number, want float64" is better than
   275  				// "have untyped int, want float64" or
   276  				// "have int, want float64".
   277  				s = "number"
   278  			} else {
   279  				// If we don't have a number, omit the "untyped" qualifier
   280  				// for compactness.
   281  				s = strings.Replace(t.(*Basic).name, "untyped ", "", -1)
   282  			}
   283  		case variadic && i == len(list)-1:
   284  			s = check.sprintf("...%s", t.(*Slice).elem)
   285  		}
   286  		if s == "" {
   287  			s = check.sprintf("%s", t)
   288  		}
   289  		res = append(res, s)
   290  	}
   291  	return "(" + strings.Join(res, ", ") + ")"
   292  }
   293  
   294  func measure(x int, unit string) string {
   295  	if x != 1 {
   296  		unit += "s"
   297  	}
   298  	return fmt.Sprintf("%d %s", x, unit)
   299  }
   300  
   301  func (check *Checker) assignError(rhs []ast.Expr, nvars, nvals int) {
   302  	vars := measure(nvars, "variable")
   303  	vals := measure(nvals, "value")
   304  	rhs0 := rhs[0]
   305  
   306  	if len(rhs) == 1 {
   307  		if call, _ := unparen(rhs0).(*ast.CallExpr); call != nil {
   308  			check.errorf(rhs0, _WrongAssignCount, "assignment mismatch: %s but %s returns %s", vars, call.Fun, vals)
   309  			return
   310  		}
   311  	}
   312  	check.errorf(rhs0, _WrongAssignCount, "assignment mismatch: %s but %s", vars, vals)
   313  }
   314  
   315  // If returnStmt != nil, initVars is called to type-check the assignment
   316  // of return expressions, and returnStmt is the return statement.
   317  func (check *Checker) initVars(lhs []*Var, origRHS []ast.Expr, returnStmt ast.Stmt) {
   318  	rhs, commaOk := check.exprList(origRHS, len(lhs) == 2 && returnStmt == nil)
   319  
   320  	if len(lhs) != len(rhs) {
   321  		// invalidate lhs
   322  		for _, obj := range lhs {
   323  			obj.used = true // avoid declared but not used errors
   324  			if obj.typ == nil {
   325  				obj.typ = Typ[Invalid]
   326  			}
   327  		}
   328  		// don't report an error if we already reported one
   329  		for _, x := range rhs {
   330  			if x.mode == invalid {
   331  				return
   332  			}
   333  		}
   334  		if returnStmt != nil {
   335  			var at positioner = returnStmt
   336  			qualifier := "not enough"
   337  			if len(rhs) > len(lhs) {
   338  				at = rhs[len(lhs)].expr // report at first extra value
   339  				qualifier = "too many"
   340  			} else if len(rhs) > 0 {
   341  				at = rhs[len(rhs)-1].expr // report at last value
   342  			}
   343  			err := newErrorf(at, _WrongResultCount, "%s return values", qualifier)
   344  			err.errorf(token.NoPos, "have %s", check.typesSummary(operandTypes(rhs), false))
   345  			err.errorf(token.NoPos, "want %s", check.typesSummary(varTypes(lhs), false))
   346  			check.report(err)
   347  			return
   348  		}
   349  		if compilerErrorMessages {
   350  			check.assignError(origRHS, len(lhs), len(rhs))
   351  		} else {
   352  			check.errorf(rhs[0], _WrongAssignCount, "cannot initialize %d variables with %d values", len(lhs), len(rhs))
   353  		}
   354  		return
   355  	}
   356  
   357  	context := "assignment"
   358  	if returnStmt != nil {
   359  		context = "return statement"
   360  	}
   361  
   362  	if commaOk {
   363  		var a [2]Type
   364  		for i := range a {
   365  			a[i] = check.initVar(lhs[i], rhs[i], context)
   366  		}
   367  		check.recordCommaOkTypes(origRHS[0], a)
   368  		return
   369  	}
   370  
   371  	for i, lhs := range lhs {
   372  		check.initVar(lhs, rhs[i], context)
   373  	}
   374  }
   375  
   376  func (check *Checker) assignVars(lhs, origRHS []ast.Expr) {
   377  	rhs, commaOk := check.exprList(origRHS, len(lhs) == 2)
   378  
   379  	if len(lhs) != len(rhs) {
   380  		check.useLHS(lhs...)
   381  		// don't report an error if we already reported one
   382  		for _, x := range rhs {
   383  			if x.mode == invalid {
   384  				return
   385  			}
   386  		}
   387  		if compilerErrorMessages {
   388  			check.assignError(origRHS, len(lhs), len(rhs))
   389  		} else {
   390  			check.errorf(rhs[0], _WrongAssignCount, "cannot assign %d values to %d variables", len(rhs), len(lhs))
   391  		}
   392  		return
   393  	}
   394  
   395  	if commaOk {
   396  		var a [2]Type
   397  		for i := range a {
   398  			a[i] = check.assignVar(lhs[i], rhs[i])
   399  		}
   400  		check.recordCommaOkTypes(origRHS[0], a)
   401  		return
   402  	}
   403  
   404  	for i, lhs := range lhs {
   405  		check.assignVar(lhs, rhs[i])
   406  	}
   407  }
   408  
   409  func (check *Checker) shortVarDecl(pos positioner, lhs, rhs []ast.Expr) {
   410  	top := len(check.delayed)
   411  	scope := check.scope
   412  
   413  	// collect lhs variables
   414  	seen := make(map[string]bool, len(lhs))
   415  	lhsVars := make([]*Var, len(lhs))
   416  	newVars := make([]*Var, 0, len(lhs))
   417  	hasErr := false
   418  	for i, lhs := range lhs {
   419  		ident, _ := lhs.(*ast.Ident)
   420  		if ident == nil {
   421  			check.useLHS(lhs)
   422  			// TODO(rFindley) this is redundant with a parser error. Consider omitting?
   423  			check.errorf(lhs, _BadDecl, "non-name %s on left side of :=", lhs)
   424  			hasErr = true
   425  			continue
   426  		}
   427  
   428  		name := ident.Name
   429  		if name != "_" {
   430  			if seen[name] {
   431  				check.errorf(lhs, _RepeatedDecl, "%s repeated on left side of :=", lhs)
   432  				hasErr = true
   433  				continue
   434  			}
   435  			seen[name] = true
   436  		}
   437  
   438  		// Use the correct obj if the ident is redeclared. The
   439  		// variable's scope starts after the declaration; so we
   440  		// must use Scope.Lookup here and call Scope.Insert
   441  		// (via check.declare) later.
   442  		if alt := scope.Lookup(name); alt != nil {
   443  			check.recordUse(ident, alt)
   444  			// redeclared object must be a variable
   445  			if obj, _ := alt.(*Var); obj != nil {
   446  				lhsVars[i] = obj
   447  			} else {
   448  				check.errorf(lhs, _UnassignableOperand, "cannot assign to %s", lhs)
   449  				hasErr = true
   450  			}
   451  			continue
   452  		}
   453  
   454  		// declare new variable
   455  		obj := NewVar(ident.Pos(), check.pkg, name, nil)
   456  		lhsVars[i] = obj
   457  		if name != "_" {
   458  			newVars = append(newVars, obj)
   459  		}
   460  		check.recordDef(ident, obj)
   461  	}
   462  
   463  	// create dummy variables where the lhs is invalid
   464  	for i, obj := range lhsVars {
   465  		if obj == nil {
   466  			lhsVars[i] = NewVar(lhs[i].Pos(), check.pkg, "_", nil)
   467  		}
   468  	}
   469  
   470  	check.initVars(lhsVars, rhs, nil)
   471  
   472  	// process function literals in rhs expressions before scope changes
   473  	check.processDelayed(top)
   474  
   475  	if len(newVars) == 0 && !hasErr {
   476  		check.softErrorf(pos, _NoNewVar, "no new variables on left side of :=")
   477  		return
   478  	}
   479  
   480  	// declare new variables
   481  	// spec: "The scope of a constant or variable identifier declared inside
   482  	// a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
   483  	// for short variable declarations) and ends at the end of the innermost
   484  	// containing block."
   485  	scopePos := rhs[len(rhs)-1].End()
   486  	for _, obj := range newVars {
   487  		check.declare(scope, nil, obj, scopePos) // id = nil: recordDef already called
   488  	}
   489  }
   490  

View as plain text