From 779886f1825c49ec880c9f79f1dd8d488dc0caf0 Mon Sep 17 00:00:00 2001 From: Thomas Karpiniec Date: Wed, 25 Oct 2017 00:04:01 +1100 Subject: [PATCH 1/2] Improve recovery after unexpected tokens parsing sequence --- src/libsyntax/parse/parser.rs | 18 +++++++++++++++++- src/libsyntax/parse/token.rs | 10 ++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 07fa2a4d1a7..cf56be25665 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1033,7 +1033,23 @@ impl<'a> Parser<'a> { } else { if let Err(e) = self.expect(t) { fe(e); - break; + // Attempt to keep parsing if it was a similar separator + if let Some(ref tokens) = t.similar_tokens() { + if tokens.contains(&self.token) { + self.bump(); + } + } + // Attempt to keep parsing if it was an omitted separator + match f(self) { + Ok(t) => { + v.push(t); + continue; + }, + Err(mut e) => { + e.cancel(); + break; + } + } } } } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 20db87cfc82..09dc05a4167 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -433,6 +433,16 @@ impl Token { }) } + /// Returns tokens that are likely to be typed accidentally instead of the current token. + /// Enables better error recovery when the wrong token is found. + pub fn similar_tokens(&self) -> Option> { + match *self { + Comma => Some(vec![Dot, Lt]), + Semi => Some(vec![Colon]), + _ => None + } + } + /// Returns `true` if the token is either a special identifier or a keyword. pub fn is_reserved_ident(&self) -> bool { self.is_special_ident() || self.is_used_keyword() || self.is_unused_keyword() From ae6a9e6fd2a7138d04c03e2a30458d7ebcc68627 Mon Sep 17 00:00:00 2001 From: Thomas Karpiniec Date: Wed, 25 Oct 2017 07:39:15 +1100 Subject: [PATCH 2/2] Update tests for less noisy error messages --- .../restricted/tuple-struct-fields/test.rs | 2 +- .../restricted/tuple-struct-fields/test2.rs | 1 - .../restricted/tuple-struct-fields/test3.rs | 1 - src/test/ui/similar-tokens.rs | 19 +++++++++++++++++++ src/test/ui/similar-tokens.stderr | 8 ++++++++ 5 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/similar-tokens.rs create mode 100644 src/test/ui/similar-tokens.stderr diff --git a/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test.rs b/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test.rs index d17b604717e..d4ea76d6c26 100644 --- a/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test.rs +++ b/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test.rs @@ -13,5 +13,5 @@ mod foo { struct S1(pub(in foo) (), pub(T), pub(crate) (), pub(((), T))); struct S2(pub((foo)) ()); //~^ ERROR expected `,`, found `(` - //~| ERROR expected one of `;` or `where`, found `(` + //~| ERROR cannot find type `foo` in this scope } diff --git a/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test2.rs b/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test2.rs index 166d5e27e8d..fed9432c6a0 100644 --- a/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test2.rs +++ b/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test2.rs @@ -14,7 +14,6 @@ macro_rules! define_struct { struct S2(pub (in foo) ()); struct S3(pub $t ()); //~^ ERROR expected `,`, found `(` - //~| ERROR expected one of `;` or `where`, found `(` } } diff --git a/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test3.rs b/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test3.rs index edab175f4cd..dd2cb0e2184 100644 --- a/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test3.rs +++ b/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test3.rs @@ -14,7 +14,6 @@ macro_rules! define_struct { struct S2(pub (in foo) ()); struct S3(pub($t) ()); //~^ ERROR expected `,`, found `(` - //~| ERROR expected one of `;` or `where`, found `(` } } diff --git a/src/test/ui/similar-tokens.rs b/src/test/ui/similar-tokens.rs new file mode 100644 index 00000000000..986382bc8ee --- /dev/null +++ b/src/test/ui/similar-tokens.rs @@ -0,0 +1,19 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod x { + pub struct A; + pub struct B; +} + +// `.` is similar to `,` so list parsing should continue to closing `}` +use x::{A. B}; + +fn main() {} diff --git a/src/test/ui/similar-tokens.stderr b/src/test/ui/similar-tokens.stderr new file mode 100644 index 00000000000..cf0ed646db7 --- /dev/null +++ b/src/test/ui/similar-tokens.stderr @@ -0,0 +1,8 @@ +error: expected one of `,` or `as`, found `.` + --> $DIR/similar-tokens.rs:17:10 + | +17 | use x::{A. B}; + | ^ expected one of `,` or `as` here + +error: aborting due to previous error +