mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
go/types, types2: don't report assignment mismatch errors if there are other errors
Change the Checker.use/useLHS functions to report if all "used" expressions evaluated without error. Use that information to control whether to report an assignment mismatch error or not. This will reduce the number of errors reported per assignment, where the assignment mismatch is only one of the errors. Change-Id: Ia0fc3203253b002e4e1d5759d8d5644999af6884 Reviewed-on: https://go-review.googlesource.com/c/go/+/478756 Reviewed-by: Robert Findley <rfindley@google.com> Reviewed-by: Robert Griesemer <gri@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Robert Griesemer <gri@google.com> Auto-Submit: Robert Griesemer <gri@google.com>
This commit is contained in:
parent
a6f564c8e9
commit
91a40f43b6
@ -360,11 +360,14 @@ func (check *Checker) initVars(lhs []*Var, orig_rhs []syntax.Expr, returnStmt sy
|
||||
// If we don't have an n:n mapping, the rhs must be a single expression
|
||||
// resulting in 2 or more values; otherwise we have an assignment mismatch.
|
||||
if r != 1 {
|
||||
if returnStmt != nil {
|
||||
rhs := check.exprList(orig_rhs)
|
||||
check.returnError(returnStmt, lhs, rhs)
|
||||
} else {
|
||||
check.assignError(orig_rhs, l, r)
|
||||
// Only report a mismatch error if there are no other errors on the rhs.
|
||||
if check.use(orig_rhs...) {
|
||||
if returnStmt != nil {
|
||||
rhs := check.exprList(orig_rhs)
|
||||
check.returnError(returnStmt, lhs, rhs)
|
||||
} else {
|
||||
check.assignError(orig_rhs, l, r)
|
||||
}
|
||||
}
|
||||
// ensure that LHS variables have a type
|
||||
for _, v := range lhs {
|
||||
@ -372,7 +375,6 @@ func (check *Checker) initVars(lhs []*Var, orig_rhs []syntax.Expr, returnStmt sy
|
||||
v.typ = Typ[Invalid]
|
||||
}
|
||||
}
|
||||
check.use(orig_rhs...)
|
||||
return
|
||||
}
|
||||
|
||||
@ -389,8 +391,7 @@ func (check *Checker) initVars(lhs []*Var, orig_rhs []syntax.Expr, returnStmt sy
|
||||
}
|
||||
|
||||
// In all other cases we have an assignment mismatch.
|
||||
// Only report a mismatch error if there was no error
|
||||
// on the rhs.
|
||||
// Only report a mismatch error if there are no other errors on the rhs.
|
||||
if rhs[0].mode != invalid {
|
||||
if returnStmt != nil {
|
||||
check.returnError(returnStmt, lhs, rhs)
|
||||
@ -432,9 +433,12 @@ func (check *Checker) assignVars(lhs, orig_rhs []syntax.Expr) {
|
||||
// If we don't have an n:n mapping, the rhs must be a single expression
|
||||
// resulting in 2 or more values; otherwise we have an assignment mismatch.
|
||||
if r != 1 {
|
||||
check.assignError(orig_rhs, l, r)
|
||||
check.useLHS(lhs...)
|
||||
check.use(orig_rhs...)
|
||||
// Only report a mismatch error if there are no other errors on the lhs or rhs.
|
||||
okLHS := check.useLHS(lhs...)
|
||||
okRHS := check.use(orig_rhs...)
|
||||
if okLHS && okRHS {
|
||||
check.assignError(orig_rhs, l, r)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -451,8 +455,7 @@ func (check *Checker) assignVars(lhs, orig_rhs []syntax.Expr) {
|
||||
}
|
||||
|
||||
// In all other cases we have an assignment mismatch.
|
||||
// Only report a mismatch error if there was no error
|
||||
// on the rhs.
|
||||
// Only report a mismatch error if there are no other errors on the rhs.
|
||||
if rhs[0].mode != invalid {
|
||||
check.assignError(orig_rhs, l, r)
|
||||
}
|
||||
|
@ -699,23 +699,27 @@ Error:
|
||||
// Useful to make sure expressions are evaluated
|
||||
// (and variables are "used") in the presence of
|
||||
// other errors. Arguments may be nil.
|
||||
func (check *Checker) use(args ...syntax.Expr) {
|
||||
for _, e := range args {
|
||||
check.use1(e, false)
|
||||
}
|
||||
}
|
||||
// Reports if all arguments evaluated without error.
|
||||
func (check *Checker) use(args ...syntax.Expr) bool { return check.useN(args, false) }
|
||||
|
||||
// useLHS is like use, but doesn't "use" top-level identifiers.
|
||||
// It should be called instead of use if the arguments are
|
||||
// expressions on the lhs of an assignment.
|
||||
func (check *Checker) useLHS(args ...syntax.Expr) {
|
||||
func (check *Checker) useLHS(args ...syntax.Expr) bool { return check.useN(args, true) }
|
||||
|
||||
func (check *Checker) useN(args []syntax.Expr, lhs bool) bool {
|
||||
ok := true
|
||||
for _, e := range args {
|
||||
check.use1(e, true)
|
||||
if !check.use1(e, lhs) {
|
||||
ok = false
|
||||
}
|
||||
}
|
||||
return ok
|
||||
}
|
||||
|
||||
func (check *Checker) use1(e syntax.Expr, lhs bool) {
|
||||
func (check *Checker) use1(e syntax.Expr, lhs bool) bool {
|
||||
var x operand
|
||||
x.mode = value // anything but invalid
|
||||
switch n := unparen(e).(type) {
|
||||
case nil:
|
||||
// nothing to do
|
||||
@ -745,10 +749,9 @@ func (check *Checker) use1(e syntax.Expr, lhs bool) {
|
||||
v.used = v_used // restore v.used
|
||||
}
|
||||
case *syntax.ListExpr:
|
||||
for _, e := range n.ElemList {
|
||||
check.use1(e, lhs)
|
||||
}
|
||||
return check.useN(n.ElemList, lhs)
|
||||
default:
|
||||
check.rawExpr(&x, e, nil, true)
|
||||
}
|
||||
return x.mode != invalid
|
||||
}
|
||||
|
@ -358,11 +358,14 @@ func (check *Checker) initVars(lhs []*Var, orig_rhs []ast.Expr, returnStmt ast.S
|
||||
// If we don't have an n:n mapping, the rhs must be a single expression
|
||||
// resulting in 2 or more values; otherwise we have an assignment mismatch.
|
||||
if r != 1 {
|
||||
if returnStmt != nil {
|
||||
rhs := check.exprList(orig_rhs)
|
||||
check.returnError(returnStmt, lhs, rhs)
|
||||
} else {
|
||||
check.assignError(orig_rhs, l, r)
|
||||
// Only report a mismatch error if there are no other errors on the rhs.
|
||||
if check.use(orig_rhs...) {
|
||||
if returnStmt != nil {
|
||||
rhs := check.exprList(orig_rhs)
|
||||
check.returnError(returnStmt, lhs, rhs)
|
||||
} else {
|
||||
check.assignError(orig_rhs, l, r)
|
||||
}
|
||||
}
|
||||
// ensure that LHS variables have a type
|
||||
for _, v := range lhs {
|
||||
@ -370,7 +373,6 @@ func (check *Checker) initVars(lhs []*Var, orig_rhs []ast.Expr, returnStmt ast.S
|
||||
v.typ = Typ[Invalid]
|
||||
}
|
||||
}
|
||||
check.use(orig_rhs...)
|
||||
return
|
||||
}
|
||||
|
||||
@ -387,8 +389,7 @@ func (check *Checker) initVars(lhs []*Var, orig_rhs []ast.Expr, returnStmt ast.S
|
||||
}
|
||||
|
||||
// In all other cases we have an assignment mismatch.
|
||||
// Only report a mismatch error if there was no error
|
||||
// on the rhs.
|
||||
// Only report a mismatch error if there are no other errors on the rhs.
|
||||
if rhs[0].mode != invalid {
|
||||
if returnStmt != nil {
|
||||
check.returnError(returnStmt, lhs, rhs)
|
||||
@ -430,9 +431,12 @@ func (check *Checker) assignVars(lhs, orig_rhs []ast.Expr) {
|
||||
// If we don't have an n:n mapping, the rhs must be a single expression
|
||||
// resulting in 2 or more values; otherwise we have an assignment mismatch.
|
||||
if r != 1 {
|
||||
check.assignError(orig_rhs, l, r)
|
||||
check.useLHS(lhs...)
|
||||
check.use(orig_rhs...)
|
||||
// Only report a mismatch error if there are no other errors on the lhs or rhs.
|
||||
okLHS := check.useLHS(lhs...)
|
||||
okRHS := check.use(orig_rhs...)
|
||||
if okLHS && okRHS {
|
||||
check.assignError(orig_rhs, l, r)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -449,8 +453,7 @@ func (check *Checker) assignVars(lhs, orig_rhs []ast.Expr) {
|
||||
}
|
||||
|
||||
// In all other cases we have an assignment mismatch.
|
||||
// Only report a mismatch error if there was no error
|
||||
// on the rhs.
|
||||
// Only report a mismatch error if there are no other errors on the rhs.
|
||||
if rhs[0].mode != invalid {
|
||||
check.assignError(orig_rhs, l, r)
|
||||
}
|
||||
|
@ -746,23 +746,27 @@ Error:
|
||||
// Useful to make sure expressions are evaluated
|
||||
// (and variables are "used") in the presence of
|
||||
// other errors. Arguments may be nil.
|
||||
func (check *Checker) use(args ...ast.Expr) {
|
||||
for _, e := range args {
|
||||
check.use1(e, false)
|
||||
}
|
||||
}
|
||||
// Reports if all arguments evaluated without error.
|
||||
func (check *Checker) use(args ...ast.Expr) bool { return check.useN(args, false) }
|
||||
|
||||
// useLHS is like use, but doesn't "use" top-level identifiers.
|
||||
// It should be called instead of use if the arguments are
|
||||
// expressions on the lhs of an assignment.
|
||||
func (check *Checker) useLHS(args ...ast.Expr) {
|
||||
func (check *Checker) useLHS(args ...ast.Expr) bool { return check.useN(args, true) }
|
||||
|
||||
func (check *Checker) useN(args []ast.Expr, lhs bool) bool {
|
||||
ok := true
|
||||
for _, e := range args {
|
||||
check.use1(e, true)
|
||||
if !check.use1(e, lhs) {
|
||||
ok = false
|
||||
}
|
||||
}
|
||||
return ok
|
||||
}
|
||||
|
||||
func (check *Checker) use1(e ast.Expr, lhs bool) {
|
||||
func (check *Checker) use1(e ast.Expr, lhs bool) bool {
|
||||
var x operand
|
||||
x.mode = value // anything but invalid
|
||||
switch n := unparen(e).(type) {
|
||||
case nil:
|
||||
// nothing to do
|
||||
@ -794,4 +798,5 @@ func (check *Checker) use1(e ast.Expr, lhs bool) {
|
||||
default:
|
||||
check.rawExpr(&x, e, nil, true)
|
||||
}
|
||||
return x.mode != invalid
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ func f(x int, y uint) {
|
||||
if true {
|
||||
return "a" > 10 // ERROR "^too many arguments to return$|return with value in function with no return|no result values expected|mismatched types"
|
||||
}
|
||||
return "gopher" == true, 10 // ERROR "^too many arguments to return$|return with value in function with no return|no result values expected|mismatched types" "too many return values"
|
||||
return "gopher" == true, 10 // ERROR "^too many arguments to return$|return with value in function with no return|no result values expected|mismatched types"
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user