...

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  	"go/ast"
		11  	"go/token"
		12  )
		13  
		14  // assignment reports whether x can be assigned to a variable of type T,
		15  // if necessary by attempting to convert untyped values to the appropriate
		16  // type. context describes the context in which the assignment takes place.
		17  // Use T == nil to indicate assignment to an untyped blank identifier.
		18  // x.mode is set to invalid if the assignment failed.
		19  func (check *Checker) assignment(x *operand, T Type, context string) {
		20  	check.singleValue(x)
		21  
		22  	switch x.mode {
		23  	case invalid:
		24  		return // error reported before
		25  	case constant_, variable, mapindex, value, commaok, commaerr:
		26  		// ok
		27  	default:
		28  		// we may get here because of other problems (issue #39634, crash 12)
		29  		check.errorf(x, 0, "cannot assign %s to %s in %s", x, T, context)
		30  		return
		31  	}
		32  
		33  	if isUntyped(x.typ) {
		34  		target := T
		35  		// spec: "If an untyped constant is assigned to a variable of interface
		36  		// type or the blank identifier, the constant is first converted to type
		37  		// bool, rune, int, float64, complex128 or string respectively, depending
		38  		// on whether the value is a boolean, rune, integer, floating-point,
		39  		// complex, or string constant."
		40  		if T == nil || IsInterface(T) {
		41  			if T == nil && x.typ == Typ[UntypedNil] {
		42  				check.errorf(x, _UntypedNil, "use of untyped nil in %s", context)
		43  				x.mode = invalid
		44  				return
		45  			}
		46  			target = Default(x.typ)
		47  		}
		48  		newType, val, code := check.implicitTypeAndValue(x, target)
		49  		if code != 0 {
		50  			msg := check.sprintf("cannot use %s as %s value in %s", x, target, context)
		51  			switch code {
		52  			case _TruncatedFloat:
		53  				msg += " (truncated)"
		54  			case _NumericOverflow:
		55  				msg += " (overflows)"
		56  			default:
		57  				code = _IncompatibleAssign
		58  			}
		59  			check.error(x, code, 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  
		73  	// A generic (non-instantiated) function value cannot be assigned to a variable.
		74  	if sig := asSignature(x.typ); sig != nil && len(sig.tparams) > 0 {
		75  		check.errorf(x, _Todo, "cannot use generic function %s without instantiation in %s", x, context)
		76  	}
		77  
		78  	// spec: "If a left-hand side is the blank identifier, any typed or
		79  	// non-constant value except for the predeclared identifier nil may
		80  	// be assigned to it."
		81  	if T == nil {
		82  		return
		83  	}
		84  
		85  	reason := ""
		86  	if ok, code := x.assignableTo(check, T, &reason); !ok {
		87  		if reason != "" {
		88  			check.errorf(x, code, "cannot use %s as %s value in %s: %s", x, T, context, reason)
		89  		} else {
		90  			check.errorf(x, code, "cannot use %s as %s value in %s", x, T, context)
		91  		}
		92  		x.mode = invalid
		93  	}
		94  }
		95  
		96  func (check *Checker) initConst(lhs *Const, x *operand) {
		97  	if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
		98  		if lhs.typ == nil {
		99  			lhs.typ = Typ[Invalid]
	 100  		}
	 101  		return
	 102  	}
	 103  
	 104  	// rhs must be a constant
	 105  	if x.mode != constant_ {
	 106  		check.errorf(x, _InvalidConstInit, "%s is not constant", x)
	 107  		if lhs.typ == nil {
	 108  			lhs.typ = Typ[Invalid]
	 109  		}
	 110  		return
	 111  	}
	 112  	assert(isConstType(x.typ))
	 113  
	 114  	// If the lhs doesn't have a type yet, use the type of x.
	 115  	if lhs.typ == nil {
	 116  		lhs.typ = x.typ
	 117  	}
	 118  
	 119  	check.assignment(x, lhs.typ, "constant declaration")
	 120  	if x.mode == invalid {
	 121  		return
	 122  	}
	 123  
	 124  	lhs.val = x.val
	 125  }
	 126  
	 127  func (check *Checker) initVar(lhs *Var, x *operand, context string) Type {
	 128  	if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
	 129  		if lhs.typ == nil {
	 130  			lhs.typ = Typ[Invalid]
	 131  		}
	 132  		return nil
	 133  	}
	 134  
	 135  	// If the lhs doesn't have a type yet, use the type of x.
	 136  	if lhs.typ == nil {
	 137  		typ := x.typ
	 138  		if isUntyped(typ) {
	 139  			// convert untyped types to default types
	 140  			if typ == Typ[UntypedNil] {
	 141  				check.errorf(x, _UntypedNil, "use of untyped nil in %s", context)
	 142  				lhs.typ = Typ[Invalid]
	 143  				return nil
	 144  			}
	 145  			typ = Default(typ)
	 146  		}
	 147  		lhs.typ = typ
	 148  	}
	 149  
	 150  	check.assignment(x, lhs.typ, context)
	 151  	if x.mode == invalid {
	 152  		return nil
	 153  	}
	 154  
	 155  	return x.typ
	 156  }
	 157  
	 158  func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type {
	 159  	if x.mode == invalid || x.typ == Typ[Invalid] {
	 160  		check.useLHS(lhs)
	 161  		return nil
	 162  	}
	 163  
	 164  	// Determine if the lhs is a (possibly parenthesized) identifier.
	 165  	ident, _ := unparen(lhs).(*ast.Ident)
	 166  
	 167  	// Don't evaluate lhs if it is the blank identifier.
	 168  	if ident != nil && ident.Name == "_" {
	 169  		check.recordDef(ident, nil)
	 170  		check.assignment(x, nil, "assignment to _ identifier")
	 171  		if x.mode == invalid {
	 172  			return nil
	 173  		}
	 174  		return x.typ
	 175  	}
	 176  
	 177  	// If the lhs is an identifier denoting a variable v, this assignment
	 178  	// is not a 'use' of v. Remember current value of v.used and restore
	 179  	// after evaluating the lhs via check.expr.
	 180  	var v *Var
	 181  	var v_used bool
	 182  	if ident != nil {
	 183  		if obj := check.lookup(ident.Name); obj != nil {
	 184  			// It's ok to mark non-local variables, but ignore variables
	 185  			// from other packages to avoid potential race conditions with
	 186  			// dot-imported variables.
	 187  			if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {
	 188  				v = w
	 189  				v_used = v.used
	 190  			}
	 191  		}
	 192  	}
	 193  
	 194  	var z operand
	 195  	check.expr(&z, lhs)
	 196  	if v != nil {
	 197  		v.used = v_used // restore v.used
	 198  	}
	 199  
	 200  	if z.mode == invalid || z.typ == Typ[Invalid] {
	 201  		return nil
	 202  	}
	 203  
	 204  	// spec: "Each left-hand side operand must be addressable, a map index
	 205  	// expression, or the blank identifier. Operands may be parenthesized."
	 206  	switch z.mode {
	 207  	case invalid:
	 208  		return nil
	 209  	case variable, mapindex:
	 210  		// ok
	 211  	default:
	 212  		if sel, ok := z.expr.(*ast.SelectorExpr); ok {
	 213  			var op operand
	 214  			check.expr(&op, sel.X)
	 215  			if op.mode == mapindex {
	 216  				check.errorf(&z, _UnaddressableFieldAssign, "cannot assign to struct field %s in map", ExprString(z.expr))
	 217  				return nil
	 218  			}
	 219  		}
	 220  		check.errorf(&z, _UnassignableOperand, "cannot assign to %s", &z)
	 221  		return nil
	 222  	}
	 223  
	 224  	check.assignment(x, z.typ, "assignment")
	 225  	if x.mode == invalid {
	 226  		return nil
	 227  	}
	 228  
	 229  	return x.typ
	 230  }
	 231  
	 232  // If returnPos is valid, initVars is called to type-check the assignment of
	 233  // return expressions, and returnPos is the position of the return statement.
	 234  func (check *Checker) initVars(lhs []*Var, origRHS []ast.Expr, returnPos token.Pos) {
	 235  	rhs, commaOk := check.exprList(origRHS, len(lhs) == 2 && !returnPos.IsValid())
	 236  
	 237  	if len(lhs) != len(rhs) {
	 238  		// invalidate lhs
	 239  		for _, obj := range lhs {
	 240  			if obj.typ == nil {
	 241  				obj.typ = Typ[Invalid]
	 242  			}
	 243  		}
	 244  		// don't report an error if we already reported one
	 245  		for _, x := range rhs {
	 246  			if x.mode == invalid {
	 247  				return
	 248  			}
	 249  		}
	 250  		if returnPos.IsValid() {
	 251  			check.errorf(atPos(returnPos), _WrongResultCount, "wrong number of return values (want %d, got %d)", len(lhs), len(rhs))
	 252  			return
	 253  		}
	 254  		check.errorf(rhs[0], _WrongAssignCount, "cannot initialize %d variables with %d values", len(lhs), len(rhs))
	 255  		return
	 256  	}
	 257  
	 258  	context := "assignment"
	 259  	if returnPos.IsValid() {
	 260  		context = "return statement"
	 261  	}
	 262  
	 263  	if commaOk {
	 264  		var a [2]Type
	 265  		for i := range a {
	 266  			a[i] = check.initVar(lhs[i], rhs[i], context)
	 267  		}
	 268  		check.recordCommaOkTypes(origRHS[0], a)
	 269  		return
	 270  	}
	 271  
	 272  	for i, lhs := range lhs {
	 273  		check.initVar(lhs, rhs[i], context)
	 274  	}
	 275  }
	 276  
	 277  func (check *Checker) assignVars(lhs, origRHS []ast.Expr) {
	 278  	rhs, commaOk := check.exprList(origRHS, len(lhs) == 2)
	 279  
	 280  	if len(lhs) != len(rhs) {
	 281  		check.useLHS(lhs...)
	 282  		// don't report an error if we already reported one
	 283  		for _, x := range rhs {
	 284  			if x.mode == invalid {
	 285  				return
	 286  			}
	 287  		}
	 288  		check.errorf(rhs[0], _WrongAssignCount, "cannot assign %d values to %d variables", len(rhs), len(lhs))
	 289  		return
	 290  	}
	 291  
	 292  	if commaOk {
	 293  		var a [2]Type
	 294  		for i := range a {
	 295  			a[i] = check.assignVar(lhs[i], rhs[i])
	 296  		}
	 297  		check.recordCommaOkTypes(origRHS[0], a)
	 298  		return
	 299  	}
	 300  
	 301  	for i, lhs := range lhs {
	 302  		check.assignVar(lhs, rhs[i])
	 303  	}
	 304  }
	 305  
	 306  func (check *Checker) shortVarDecl(pos positioner, lhs, rhs []ast.Expr) {
	 307  	top := len(check.delayed)
	 308  	scope := check.scope
	 309  
	 310  	// collect lhs variables
	 311  	seen := make(map[string]bool, len(lhs))
	 312  	lhsVars := make([]*Var, len(lhs))
	 313  	newVars := make([]*Var, 0, len(lhs))
	 314  	hasErr := false
	 315  	for i, lhs := range lhs {
	 316  		ident, _ := lhs.(*ast.Ident)
	 317  		if ident == nil {
	 318  			check.useLHS(lhs)
	 319  			// TODO(rFindley) this is redundant with a parser error. Consider omitting?
	 320  			check.errorf(lhs, _BadDecl, "non-name %s on left side of :=", lhs)
	 321  			hasErr = true
	 322  			continue
	 323  		}
	 324  
	 325  		name := ident.Name
	 326  		if name != "_" {
	 327  			if seen[name] {
	 328  				check.errorf(lhs, _RepeatedDecl, "%s repeated on left side of :=", lhs)
	 329  				hasErr = true
	 330  				continue
	 331  			}
	 332  			seen[name] = true
	 333  		}
	 334  
	 335  		// Use the correct obj if the ident is redeclared. The
	 336  		// variable's scope starts after the declaration; so we
	 337  		// must use Scope.Lookup here and call Scope.Insert
	 338  		// (via check.declare) later.
	 339  		if alt := scope.Lookup(name); alt != nil {
	 340  			check.recordUse(ident, alt)
	 341  			// redeclared object must be a variable
	 342  			if obj, _ := alt.(*Var); obj != nil {
	 343  				lhsVars[i] = obj
	 344  			} else {
	 345  				check.errorf(lhs, _UnassignableOperand, "cannot assign to %s", lhs)
	 346  				hasErr = true
	 347  			}
	 348  			continue
	 349  		}
	 350  
	 351  		// declare new variable
	 352  		obj := NewVar(ident.Pos(), check.pkg, name, nil)
	 353  		lhsVars[i] = obj
	 354  		if name != "_" {
	 355  			newVars = append(newVars, obj)
	 356  		}
	 357  		check.recordDef(ident, obj)
	 358  	}
	 359  
	 360  	// create dummy variables where the lhs is invalid
	 361  	for i, obj := range lhsVars {
	 362  		if obj == nil {
	 363  			lhsVars[i] = NewVar(lhs[i].Pos(), check.pkg, "_", nil)
	 364  		}
	 365  	}
	 366  
	 367  	check.initVars(lhsVars, rhs, token.NoPos)
	 368  
	 369  	// process function literals in rhs expressions before scope changes
	 370  	check.processDelayed(top)
	 371  
	 372  	if len(newVars) == 0 && !hasErr {
	 373  		check.softErrorf(pos, _NoNewVar, "no new variables on left side of :=")
	 374  		return
	 375  	}
	 376  
	 377  	// declare new variables
	 378  	// spec: "The scope of a constant or variable identifier declared inside
	 379  	// a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
	 380  	// for short variable declarations) and ends at the end of the innermost
	 381  	// containing block."
	 382  	scopePos := rhs[len(rhs)-1].End()
	 383  	for _, obj := range newVars {
	 384  		check.declare(scope, nil, obj, scopePos) // id = nil: recordDef already called
	 385  	}
	 386  }
	 387  

View as plain text