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
7package types
8
9import (
10	"fmt"
11	"go/ast"
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.
20func (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, commaok, commaerr:
27		// ok
28	default:
29		// we may get here because of other problems (issue #39634, crash 12)
30		check.errorf(x, 0, "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 T == nil || IsInterface(T) && !isTypeParam(T) {
42			if T == nil && x.typ == Typ[UntypedNil] {
43				check.errorf(x, _UntypedNil, "use of untyped nil in %s", context)
44				x.mode = invalid
45				return
46			}
47			target = Default(x.typ)
48		}
49		newType, val, code := check.implicitTypeAndValue(x, target)
50		if code != 0 {
51			msg := check.sprintf("cannot use %s as %s value in %s", x, target, context)
52			switch code {
53			case _TruncatedFloat:
54				msg += " (truncated)"
55			case _NumericOverflow:
56				msg += " (overflows)"
57			default:
58				code = _IncompatibleAssign
59			}
60			check.error(x, code, msg)
61			x.mode = invalid
62			return
63		}
64		if val != nil {
65			x.val = val
66			check.updateExprVal(x.expr, val)
67		}
68		if newType != x.typ {
69			x.typ = newType
70			check.updateExprType(x.expr, newType, false)
71		}
72	}
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, _WrongTypeArgCount, "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, code := x.assignableTo(check, T, &reason); !ok {
88		if compilerErrorMessages {
89			if reason != "" {
90				check.errorf(x, code, "cannot use %s as type %s in %s:\n\t%s", x, T, context, reason)
91			} else {
92				check.errorf(x, code, "cannot use %s as type %s in %s", x, T, context)
93			}
94		} else {
95			if reason != "" {
96				check.errorf(x, code, "cannot use %s as %s value in %s: %s", x, T, context, reason)
97			} else {
98				check.errorf(x, code, "cannot use %s as %s value in %s", x, T, context)
99			}
100		}
101		x.mode = invalid
102	}
103}
104
105func (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, _InvalidConstInit, "%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
136func (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		return nil
142	}
143
144	// If the lhs doesn't have a type yet, use the type of x.
145	if lhs.typ == nil {
146		typ := x.typ
147		if isUntyped(typ) {
148			// convert untyped types to default types
149			if typ == Typ[UntypedNil] {
150				check.errorf(x, _UntypedNil, "use of untyped nil in %s", context)
151				lhs.typ = Typ[Invalid]
152				return nil
153			}
154			typ = Default(typ)
155		}
156		lhs.typ = typ
157	}
158
159	check.assignment(x, lhs.typ, context)
160	if x.mode == invalid {
161		return nil
162	}
163
164	return x.typ
165}
166
167func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type {
168	if x.mode == invalid || x.typ == Typ[Invalid] {
169		check.useLHS(lhs)
170		return nil
171	}
172
173	// Determine if the lhs is a (possibly parenthesized) identifier.
174	ident, _ := unparen(lhs).(*ast.Ident)
175
176	// Don't evaluate lhs if it is the blank identifier.
177	if ident != nil && ident.Name == "_" {
178		check.recordDef(ident, nil)
179		check.assignment(x, nil, "assignment to _ identifier")
180		if x.mode == invalid {
181			return nil
182		}
183		return x.typ
184	}
185
186	// If the lhs is an identifier denoting a variable v, this assignment
187	// is not a 'use' of v. Remember current value of v.used and restore
188	// after evaluating the lhs via check.expr.
189	var v *Var
190	var v_used bool
191	if ident != nil {
192		if obj := check.lookup(ident.Name); obj != nil {
193			// It's ok to mark non-local variables, but ignore variables
194			// from other packages to avoid potential race conditions with
195			// dot-imported variables.
196			if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {
197				v = w
198				v_used = v.used
199			}
200		}
201	}
202
203	var z operand
204	check.expr(&z, lhs)
205	if v != nil {
206		v.used = v_used // restore v.used
207	}
208
209	if z.mode == invalid || z.typ == Typ[Invalid] {
210		return nil
211	}
212
213	// spec: "Each left-hand side operand must be addressable, a map index
214	// expression, or the blank identifier. Operands may be parenthesized."
215	switch z.mode {
216	case invalid:
217		return nil
218	case variable, mapindex:
219		// ok
220	default:
221		if sel, ok := z.expr.(*ast.SelectorExpr); ok {
222			var op operand
223			check.expr(&op, sel.X)
224			if op.mode == mapindex {
225				check.errorf(&z, _UnaddressableFieldAssign, "cannot assign to struct field %s in map", ExprString(z.expr))
226				return nil
227			}
228		}
229		check.errorf(&z, _UnassignableOperand, "cannot assign to %s", &z)
230		return nil
231	}
232
233	check.assignment(x, z.typ, "assignment")
234	if x.mode == invalid {
235		return nil
236	}
237
238	return x.typ
239}
240
241// operandTypes returns the list of types for the given operands.
242func operandTypes(list []*operand) (res []Type) {
243	for _, x := range list {
244		res = append(res, x.typ)
245	}
246	return res
247}
248
249// varTypes returns the list of types for the given variables.
250func varTypes(list []*Var) (res []Type) {
251	for _, x := range list {
252		res = append(res, x.typ)
253	}
254	return res
255}
256
257// typesSummary returns a string of the form "(t1, t2, ...)" where the
258// ti's are user-friendly string representations for the given types.
259// If variadic is set and the last type is a slice, its string is of
260// the form "...E" where E is the slice's element type.
261func (check *Checker) typesSummary(list []Type, variadic bool) string {
262	var res []string
263	for i, t := range list {
264		var s string
265		switch {
266		case t == nil:
267			fallthrough // should not happend but be cautious
268		case t == Typ[Invalid]:
269			s = "<T>"
270		case isUntyped(t):
271			if isNumeric(t) {
272				// Do not imply a specific type requirement:
273				// "have number, want float64" is better than
274				// "have untyped int, want float64" or
275				// "have int, want float64".
276				s = "number"
277			} else {
278				// If we don't have a number, omit the "untyped" qualifier
279				// for compactness.
280				s = strings.Replace(t.(*Basic).name, "untyped ", "", -1)
281			}
282		case variadic && i == len(list)-1:
283			s = check.sprintf("...%s", t.(*Slice).elem)
284		}
285		if s == "" {
286			s = check.sprintf("%s", t)
287		}
288		res = append(res, s)
289	}
290	return "(" + strings.Join(res, ", ") + ")"
291}
292
293func (check *Checker) assignError(rhs []ast.Expr, nvars, nvals int) {
294	measure := func(x int, unit string) string {
295		s := fmt.Sprintf("%d %s", x, unit)
296		if x != 1 {
297			s += "s"
298		}
299		return s
300	}
301
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 the return statement.
317func (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			check.errorf(at, _WrongResultCount, "%s return values\n\thave %s\n\twant %s",
344				qualifier,
345				check.typesSummary(operandTypes(rhs), false),
346				check.typesSummary(varTypes(lhs), false),
347			)
348			return
349		}
350		if compilerErrorMessages {
351			check.assignError(origRHS, len(lhs), len(rhs))
352		} else {
353			check.errorf(rhs[0], _WrongAssignCount, "cannot initialize %d variables with %d values", len(lhs), len(rhs))
354		}
355		return
356	}
357
358	context := "assignment"
359	if returnStmt != nil {
360		context = "return statement"
361	}
362
363	if commaOk {
364		var a [2]Type
365		for i := range a {
366			a[i] = check.initVar(lhs[i], rhs[i], context)
367		}
368		check.recordCommaOkTypes(origRHS[0], a)
369		return
370	}
371
372	for i, lhs := range lhs {
373		check.initVar(lhs, rhs[i], context)
374	}
375}
376
377func (check *Checker) assignVars(lhs, origRHS []ast.Expr) {
378	rhs, commaOk := check.exprList(origRHS, len(lhs) == 2)
379
380	if len(lhs) != len(rhs) {
381		check.useLHS(lhs...)
382		// don't report an error if we already reported one
383		for _, x := range rhs {
384			if x.mode == invalid {
385				return
386			}
387		}
388		if compilerErrorMessages {
389			check.assignError(origRHS, len(lhs), len(rhs))
390		} else {
391			check.errorf(rhs[0], _WrongAssignCount, "cannot assign %d values to %d variables", len(rhs), len(lhs))
392		}
393		return
394	}
395
396	if commaOk {
397		var a [2]Type
398		for i := range a {
399			a[i] = check.assignVar(lhs[i], rhs[i])
400		}
401		check.recordCommaOkTypes(origRHS[0], a)
402		return
403	}
404
405	for i, lhs := range lhs {
406		check.assignVar(lhs, rhs[i])
407	}
408}
409
410func (check *Checker) shortVarDecl(pos positioner, lhs, rhs []ast.Expr) {
411	top := len(check.delayed)
412	scope := check.scope
413
414	// collect lhs variables
415	seen := make(map[string]bool, len(lhs))
416	lhsVars := make([]*Var, len(lhs))
417	newVars := make([]*Var, 0, len(lhs))
418	hasErr := false
419	for i, lhs := range lhs {
420		ident, _ := lhs.(*ast.Ident)
421		if ident == nil {
422			check.useLHS(lhs)
423			// TODO(rFindley) this is redundant with a parser error. Consider omitting?
424			check.errorf(lhs, _BadDecl, "non-name %s on left side of :=", lhs)
425			hasErr = true
426			continue
427		}
428
429		name := ident.Name
430		if name != "_" {
431			if seen[name] {
432				check.errorf(lhs, _RepeatedDecl, "%s repeated on left side of :=", lhs)
433				hasErr = true
434				continue
435			}
436			seen[name] = true
437		}
438
439		// Use the correct obj if the ident is redeclared. The
440		// variable's scope starts after the declaration; so we
441		// must use Scope.Lookup here and call Scope.Insert
442		// (via check.declare) later.
443		if alt := scope.Lookup(name); alt != nil {
444			check.recordUse(ident, alt)
445			// redeclared object must be a variable
446			if obj, _ := alt.(*Var); obj != nil {
447				lhsVars[i] = obj
448			} else {
449				check.errorf(lhs, _UnassignableOperand, "cannot assign to %s", lhs)
450				hasErr = true
451			}
452			continue
453		}
454
455		// declare new variable
456		obj := NewVar(ident.Pos(), check.pkg, name, nil)
457		lhsVars[i] = obj
458		if name != "_" {
459			newVars = append(newVars, obj)
460		}
461		check.recordDef(ident, obj)
462	}
463
464	// create dummy variables where the lhs is invalid
465	for i, obj := range lhsVars {
466		if obj == nil {
467			lhsVars[i] = NewVar(lhs[i].Pos(), check.pkg, "_", nil)
468		}
469	}
470
471	check.initVars(lhsVars, rhs, nil)
472
473	// process function literals in rhs expressions before scope changes
474	check.processDelayed(top)
475
476	if len(newVars) == 0 && !hasErr {
477		check.softErrorf(pos, _NoNewVar, "no new variables on left side of :=")
478		return
479	}
480
481	// declare new variables
482	// spec: "The scope of a constant or variable identifier declared inside
483	// a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
484	// for short variable declarations) and ends at the end of the innermost
485	// containing block."
486	scopePos := rhs[len(rhs)-1].End()
487	for _, obj := range newVars {
488		check.declare(scope, nil, obj, scopePos) // id = nil: recordDef already called
489	}
490}
491