// 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 {
v.typ = Typ[Invalid]
}
}
- check.use(orig_rhs...)
return
}
}
// 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)
// 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
}
}
// 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)
}
// 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
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
}
// 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 {
v.typ = Typ[Invalid]
}
}
- check.use(orig_rhs...)
return
}
}
// 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)
// 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
}
}
// 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)
}
// 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
default:
check.rawExpr(&x, e, nil, true)
}
+ return x.mode != invalid
}
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() {