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

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

View as plain text