Skip to content

Commit 91a40f4

Browse files
griesemergopherbot
authored andcommitted
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 <[email protected]> Reviewed-by: Robert Griesemer <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Robert Griesemer <[email protected]> Auto-Submit: Robert Griesemer <[email protected]>
1 parent a6f564c commit 91a40f4

File tree

5 files changed

+60
-46
lines changed

5 files changed

+60
-46
lines changed

src/cmd/compile/internal/types2/assignments.go

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -360,19 +360,21 @@ func (check *Checker) initVars(lhs []*Var, orig_rhs []syntax.Expr, returnStmt sy
360360
// If we don't have an n:n mapping, the rhs must be a single expression
361361
// resulting in 2 or more values; otherwise we have an assignment mismatch.
362362
if r != 1 {
363-
if returnStmt != nil {
364-
rhs := check.exprList(orig_rhs)
365-
check.returnError(returnStmt, lhs, rhs)
366-
} else {
367-
check.assignError(orig_rhs, l, r)
363+
// Only report a mismatch error if there are no other errors on the rhs.
364+
if check.use(orig_rhs...) {
365+
if returnStmt != nil {
366+
rhs := check.exprList(orig_rhs)
367+
check.returnError(returnStmt, lhs, rhs)
368+
} else {
369+
check.assignError(orig_rhs, l, r)
370+
}
368371
}
369372
// ensure that LHS variables have a type
370373
for _, v := range lhs {
371374
if v.typ == nil {
372375
v.typ = Typ[Invalid]
373376
}
374377
}
375-
check.use(orig_rhs...)
376378
return
377379
}
378380

@@ -389,8 +391,7 @@ func (check *Checker) initVars(lhs []*Var, orig_rhs []syntax.Expr, returnStmt sy
389391
}
390392

391393
// In all other cases we have an assignment mismatch.
392-
// Only report a mismatch error if there was no error
393-
// on the rhs.
394+
// Only report a mismatch error if there are no other errors on the rhs.
394395
if rhs[0].mode != invalid {
395396
if returnStmt != nil {
396397
check.returnError(returnStmt, lhs, rhs)
@@ -432,9 +433,12 @@ func (check *Checker) assignVars(lhs, orig_rhs []syntax.Expr) {
432433
// If we don't have an n:n mapping, the rhs must be a single expression
433434
// resulting in 2 or more values; otherwise we have an assignment mismatch.
434435
if r != 1 {
435-
check.assignError(orig_rhs, l, r)
436-
check.useLHS(lhs...)
437-
check.use(orig_rhs...)
436+
// Only report a mismatch error if there are no other errors on the lhs or rhs.
437+
okLHS := check.useLHS(lhs...)
438+
okRHS := check.use(orig_rhs...)
439+
if okLHS && okRHS {
440+
check.assignError(orig_rhs, l, r)
441+
}
438442
return
439443
}
440444

@@ -451,8 +455,7 @@ func (check *Checker) assignVars(lhs, orig_rhs []syntax.Expr) {
451455
}
452456

453457
// In all other cases we have an assignment mismatch.
454-
// Only report a mismatch error if there was no error
455-
// on the rhs.
458+
// Only report a mismatch error if there are no other errors on the rhs.
456459
if rhs[0].mode != invalid {
457460
check.assignError(orig_rhs, l, r)
458461
}

src/cmd/compile/internal/types2/call.go

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -699,23 +699,27 @@ Error:
699699
// Useful to make sure expressions are evaluated
700700
// (and variables are "used") in the presence of
701701
// other errors. Arguments may be nil.
702-
func (check *Checker) use(args ...syntax.Expr) {
703-
for _, e := range args {
704-
check.use1(e, false)
705-
}
706-
}
702+
// Reports if all arguments evaluated without error.
703+
func (check *Checker) use(args ...syntax.Expr) bool { return check.useN(args, false) }
707704

708705
// useLHS is like use, but doesn't "use" top-level identifiers.
709706
// It should be called instead of use if the arguments are
710707
// expressions on the lhs of an assignment.
711-
func (check *Checker) useLHS(args ...syntax.Expr) {
708+
func (check *Checker) useLHS(args ...syntax.Expr) bool { return check.useN(args, true) }
709+
710+
func (check *Checker) useN(args []syntax.Expr, lhs bool) bool {
711+
ok := true
712712
for _, e := range args {
713-
check.use1(e, true)
713+
if !check.use1(e, lhs) {
714+
ok = false
715+
}
714716
}
717+
return ok
715718
}
716719

717-
func (check *Checker) use1(e syntax.Expr, lhs bool) {
720+
func (check *Checker) use1(e syntax.Expr, lhs bool) bool {
718721
var x operand
722+
x.mode = value // anything but invalid
719723
switch n := unparen(e).(type) {
720724
case nil:
721725
// nothing to do
@@ -745,10 +749,9 @@ func (check *Checker) use1(e syntax.Expr, lhs bool) {
745749
v.used = v_used // restore v.used
746750
}
747751
case *syntax.ListExpr:
748-
for _, e := range n.ElemList {
749-
check.use1(e, lhs)
750-
}
752+
return check.useN(n.ElemList, lhs)
751753
default:
752754
check.rawExpr(&x, e, nil, true)
753755
}
756+
return x.mode != invalid
754757
}

src/go/types/assignments.go

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -358,19 +358,21 @@ func (check *Checker) initVars(lhs []*Var, orig_rhs []ast.Expr, returnStmt ast.S
358358
// If we don't have an n:n mapping, the rhs must be a single expression
359359
// resulting in 2 or more values; otherwise we have an assignment mismatch.
360360
if r != 1 {
361-
if returnStmt != nil {
362-
rhs := check.exprList(orig_rhs)
363-
check.returnError(returnStmt, lhs, rhs)
364-
} else {
365-
check.assignError(orig_rhs, l, r)
361+
// Only report a mismatch error if there are no other errors on the rhs.
362+
if check.use(orig_rhs...) {
363+
if returnStmt != nil {
364+
rhs := check.exprList(orig_rhs)
365+
check.returnError(returnStmt, lhs, rhs)
366+
} else {
367+
check.assignError(orig_rhs, l, r)
368+
}
366369
}
367370
// ensure that LHS variables have a type
368371
for _, v := range lhs {
369372
if v.typ == nil {
370373
v.typ = Typ[Invalid]
371374
}
372375
}
373-
check.use(orig_rhs...)
374376
return
375377
}
376378

@@ -387,8 +389,7 @@ func (check *Checker) initVars(lhs []*Var, orig_rhs []ast.Expr, returnStmt ast.S
387389
}
388390

389391
// In all other cases we have an assignment mismatch.
390-
// Only report a mismatch error if there was no error
391-
// on the rhs.
392+
// Only report a mismatch error if there are no other errors on the rhs.
392393
if rhs[0].mode != invalid {
393394
if returnStmt != nil {
394395
check.returnError(returnStmt, lhs, rhs)
@@ -430,9 +431,12 @@ func (check *Checker) assignVars(lhs, orig_rhs []ast.Expr) {
430431
// If we don't have an n:n mapping, the rhs must be a single expression
431432
// resulting in 2 or more values; otherwise we have an assignment mismatch.
432433
if r != 1 {
433-
check.assignError(orig_rhs, l, r)
434-
check.useLHS(lhs...)
435-
check.use(orig_rhs...)
434+
// Only report a mismatch error if there are no other errors on the lhs or rhs.
435+
okLHS := check.useLHS(lhs...)
436+
okRHS := check.use(orig_rhs...)
437+
if okLHS && okRHS {
438+
check.assignError(orig_rhs, l, r)
439+
}
436440
return
437441
}
438442

@@ -449,8 +453,7 @@ func (check *Checker) assignVars(lhs, orig_rhs []ast.Expr) {
449453
}
450454

451455
// In all other cases we have an assignment mismatch.
452-
// Only report a mismatch error if there was no error
453-
// on the rhs.
456+
// Only report a mismatch error if there are no other errors on the rhs.
454457
if rhs[0].mode != invalid {
455458
check.assignError(orig_rhs, l, r)
456459
}

src/go/types/call.go

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -746,23 +746,27 @@ Error:
746746
// Useful to make sure expressions are evaluated
747747
// (and variables are "used") in the presence of
748748
// other errors. Arguments may be nil.
749-
func (check *Checker) use(args ...ast.Expr) {
750-
for _, e := range args {
751-
check.use1(e, false)
752-
}
753-
}
749+
// Reports if all arguments evaluated without error.
750+
func (check *Checker) use(args ...ast.Expr) bool { return check.useN(args, false) }
754751

755752
// useLHS is like use, but doesn't "use" top-level identifiers.
756753
// It should be called instead of use if the arguments are
757754
// expressions on the lhs of an assignment.
758-
func (check *Checker) useLHS(args ...ast.Expr) {
755+
func (check *Checker) useLHS(args ...ast.Expr) bool { return check.useN(args, true) }
756+
757+
func (check *Checker) useN(args []ast.Expr, lhs bool) bool {
758+
ok := true
759759
for _, e := range args {
760-
check.use1(e, true)
760+
if !check.use1(e, lhs) {
761+
ok = false
762+
}
761763
}
764+
return ok
762765
}
763766

764-
func (check *Checker) use1(e ast.Expr, lhs bool) {
767+
func (check *Checker) use1(e ast.Expr, lhs bool) bool {
765768
var x operand
769+
x.mode = value // anything but invalid
766770
switch n := unparen(e).(type) {
767771
case nil:
768772
// nothing to do
@@ -794,4 +798,5 @@ func (check *Checker) use1(e ast.Expr, lhs bool) {
794798
default:
795799
check.rawExpr(&x, e, nil, true)
796800
}
801+
return x.mode != invalid
797802
}

test/fixedbugs/issue19012.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ func f(x int, y uint) {
1515
if true {
1616
return "a" > 10 // ERROR "^too many arguments to return$|return with value in function with no return|no result values expected|mismatched types"
1717
}
18-
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"
18+
return "gopher" == true, 10 // ERROR "^too many arguments to return$|return with value in function with no return|no result values expected|mismatched types"
1919
}
2020

2121
func main() {

0 commit comments

Comments
 (0)