Auto merge of #45503 - thombles:tk/i44339-v5, r=petrochenkov
Improve diagnostics when list of tokens has incorrect separators Make `parse_seq_to_before_tokens` more resilient to error conditions. Where possible it is better if it can consume up to the final bracket before returning. This change improves the diagnostics in a couple of situations: ``` struct S(pub () ()); // omitted separator use std::{foo. bar}; // used a similar but wrong separator ``` Fixes #44339 r? @petrochenkov
This commit is contained in:
commit
c1a0b6d9eb
7 changed files with 55 additions and 4 deletions
|
@ -1033,7 +1033,23 @@ impl<'a> Parser<'a> {
|
||||||
} else {
|
} else {
|
||||||
if let Err(e) = self.expect(t) {
|
if let Err(e) = self.expect(t) {
|
||||||
fe(e);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<Vec<Token>> {
|
||||||
|
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.
|
/// Returns `true` if the token is either a special identifier or a keyword.
|
||||||
pub fn is_reserved_ident(&self) -> bool {
|
pub fn is_reserved_ident(&self) -> bool {
|
||||||
self.is_special_ident() || self.is_used_keyword() || self.is_unused_keyword()
|
self.is_special_ident() || self.is_used_keyword() || self.is_unused_keyword()
|
||||||
|
|
|
@ -13,5 +13,5 @@ mod foo {
|
||||||
struct S1(pub(in foo) (), pub(T), pub(crate) (), pub(((), T)));
|
struct S1(pub(in foo) (), pub(T), pub(crate) (), pub(((), T)));
|
||||||
struct S2(pub((foo)) ());
|
struct S2(pub((foo)) ());
|
||||||
//~^ ERROR expected `,`, found `(`
|
//~^ ERROR expected `,`, found `(`
|
||||||
//~| ERROR expected one of `;` or `where`, found `(`
|
//~| ERROR cannot find type `foo` in this scope
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ macro_rules! define_struct {
|
||||||
struct S2(pub (in foo) ());
|
struct S2(pub (in foo) ());
|
||||||
struct S3(pub $t ());
|
struct S3(pub $t ());
|
||||||
//~^ ERROR expected `,`, found `(`
|
//~^ ERROR expected `,`, found `(`
|
||||||
//~| ERROR expected one of `;` or `where`, found `(`
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ macro_rules! define_struct {
|
||||||
struct S2(pub (in foo) ());
|
struct S2(pub (in foo) ());
|
||||||
struct S3(pub($t) ());
|
struct S3(pub($t) ());
|
||||||
//~^ ERROR expected `,`, found `(`
|
//~^ ERROR expected `,`, found `(`
|
||||||
//~| ERROR expected one of `;` or `where`, found `(`
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
19
src/test/ui/similar-tokens.rs
Normal file
19
src/test/ui/similar-tokens.rs
Normal file
|
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
|
8
src/test/ui/similar-tokens.stderr
Normal file
8
src/test/ui/similar-tokens.stderr
Normal file
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue