From 1970e3e3b7b6c42676acc22071ced887ac68b520 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 24 Nov 2021 16:18:57 -0800 Subject: [PATCH] go/types: restore original assignment error messages This is the missing portion of the port of CL 351669 from types2 to go/types, now that we have a local flag to control for compiler error messages. Mostly a clean port but for adjustments to error reporting which requires error codes in go/types. Prerequisite for port of CL 364874. Change-Id: I5fc8c83003e4396351f42e9adb08f4ebc8a05653 Reviewed-on: https://go-review.googlesource.com/c/go/+/367195 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/go/types/assignments.go | 35 +++++++++++++++++++++++++++++++++-- src/go/types/expr.go | 6 +++++- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/go/types/assignments.go b/src/go/types/assignments.go index 7e6a230b48..8e9724e911 100644 --- a/src/go/types/assignments.go +++ b/src/go/types/assignments.go @@ -7,6 +7,7 @@ package types import ( + "fmt" "go/ast" "go/token" ) @@ -237,6 +238,28 @@ func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type { return x.typ } +func (check *Checker) assignError(rhs []ast.Expr, nvars, nvals int) { + measure := func(x int, unit string) string { + s := fmt.Sprintf("%d %s", x, unit) + if x != 1 { + s += "s" + } + return s + } + + vars := measure(nvars, "variable") + vals := measure(nvals, "value") + rhs0 := rhs[0] + + if len(rhs) == 1 { + if call, _ := unparen(rhs0).(*ast.CallExpr); call != nil { + check.errorf(rhs0, _WrongAssignCount, "assignment mismatch: %s but %s returns %s", vars, call.Fun, vals) + return + } + } + check.errorf(rhs0, _WrongAssignCount, "assignment mismatch: %s but %s", vars, vals) +} + // If returnPos is valid, initVars is called to type-check the assignment of // return expressions, and returnPos is the position of the return statement. func (check *Checker) initVars(lhs []*Var, origRHS []ast.Expr, returnPos token.Pos) { @@ -260,7 +283,11 @@ func (check *Checker) initVars(lhs []*Var, origRHS []ast.Expr, returnPos token.P check.errorf(atPos(returnPos), _WrongResultCount, "wrong number of return values (want %d, got %d)", len(lhs), len(rhs)) return } - check.errorf(rhs[0], _WrongAssignCount, "cannot initialize %d variables with %d values", len(lhs), len(rhs)) + if compilerErrorMessages { + check.assignError(origRHS, len(lhs), len(rhs)) + } else { + check.errorf(rhs[0], _WrongAssignCount, "cannot initialize %d variables with %d values", len(lhs), len(rhs)) + } return } @@ -294,7 +321,11 @@ func (check *Checker) assignVars(lhs, origRHS []ast.Expr) { return } } - check.errorf(rhs[0], _WrongAssignCount, "cannot assign %d values to %d variables", len(rhs), len(lhs)) + if compilerErrorMessages { + check.assignError(origRHS, len(lhs), len(rhs)) + } else { + check.errorf(rhs[0], _WrongAssignCount, "cannot assign %d values to %d variables", len(rhs), len(lhs)) + } return } diff --git a/src/go/types/expr.go b/src/go/types/expr.go index c49865aec6..dd18abaf13 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -1657,7 +1657,11 @@ func (check *Checker) singleValue(x *operand) { // tuple types are never named - no need for underlying type below if t, ok := x.typ.(*Tuple); ok { assert(t.Len() != 1) - check.errorf(x, _TooManyValues, "%d-valued %s where single value is expected", t.Len(), x) + if compilerErrorMessages { + check.errorf(x, _TooManyValues, "multiple-value %s in single-value context", x) + } else { + check.errorf(x, _TooManyValues, "%d-valued %s where single value is expected", t.Len(), x) + } x.mode = invalid } } -- 2.48.1