]> Cypherpunks repositories - gostls13.git/commitdiff
go/parser: improve error recovery from invalid selector exprs
authorRob Findley <rfindley@google.com>
Fri, 19 Feb 2021 01:08:42 +0000 (20:08 -0500)
committerRobert Findley <rfindley@google.com>
Fri, 19 Feb 2021 01:53:53 +0000 (01:53 +0000)
Before this CL, the parser consumed the next token following an invalid
selector expr no matter what it was. This leads to poor error recovery
when this next token is a closing delimiter or other reasonable element
of a stop set. As a side-effect, x/tools tests broke when parser logic
for type parameters was introduced, as they threw off the parser
synchronization to the point where the x/tools test bailed out.

This CL introduces a targeted fix that allows the x/tools tests to pass.
More general improvement for parser error recovery should be done for
go1.17.

Change-Id: I44d73d34b6063e62d16a23d24ab7cbce6500239d
Reviewed-on: https://go-review.googlesource.com/c/go/+/293792
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>

src/go/parser/parser.go

index e12eee79bfbf776d819bc129cc4702431d545c5a..41c3f2943e12c083a39e6fe7057a38f1a7286748 100644 (file)
@@ -1754,7 +1754,14 @@ func (p *parser) parsePrimaryExpr(lhs bool) (x ast.Expr) {
                        default:
                                pos := p.pos
                                p.errorExpected(pos, "selector or type assertion")
-                               p.next() // make progress
+                               // TODO(rFindley) The check for token.RBRACE below is a targeted fix
+                               //                to error recovery sufficient to make the x/tools tests to
+                               //                pass with the new parsing logic introduced for type
+                               //                parameters. Remove this once error recovery has been
+                               //                more generally reconsidered.
+                               if p.tok != token.RBRACE {
+                                       p.next() // make progress
+                               }
                                sel := &ast.Ident{NamePos: pos, Name: "_"}
                                x = &ast.SelectorExpr{X: x, Sel: sel}
                        }