Skip to content

Commit

Permalink
Rollup merge of rust-lang#65364 - XiangQingW:master, r=estebank
Browse files Browse the repository at this point in the history
Collect occurrences of empty blocks for mismatched braces diagnostic

Fix rust-lang#63904
  • Loading branch information
tmandry committed Oct 18, 2019
2 parents 739dd55 + fe819a0 commit c3eaee3
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 3 deletions.
21 changes: 19 additions & 2 deletions src/libsyntax/parse/lexer/tokentrees.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use rustc_data_structures::fx::FxHashMap;
use syntax_pos::Span;

use crate::print::pprust::token_to_string;
Expand All @@ -16,6 +17,7 @@ impl<'a> StringReader<'a> {
unmatched_braces: Vec::new(),
matching_delim_spans: Vec::new(),
last_unclosed_found_span: None,
last_delim_empty_block_spans: FxHashMap::default()
};
let res = tt_reader.parse_all_token_trees();
(res, tt_reader.unmatched_braces)
Expand All @@ -34,6 +36,7 @@ struct TokenTreesReader<'a> {
/// Used only for error recovery when arriving to EOF with mismatched braces.
matching_delim_spans: Vec<(token::DelimToken, Span, Span)>,
last_unclosed_found_span: Option<Span>,
last_delim_empty_block_spans: FxHashMap<token::DelimToken, Span>
}

impl<'a> TokenTreesReader<'a> {
Expand Down Expand Up @@ -121,13 +124,20 @@ impl<'a> TokenTreesReader<'a> {
// Correct delimiter.
token::CloseDelim(d) if d == delim => {
let (open_brace, open_brace_span) = self.open_braces.pop().unwrap();
let close_brace_span = self.token.span;

if tts.is_empty() {
let empty_block_span = open_brace_span.to(close_brace_span);
self.last_delim_empty_block_spans.insert(delim, empty_block_span);
}

if self.open_braces.len() == 0 {
// Clear up these spans to avoid suggesting them as we've found
// properly matched delimiters so far for an entire block.
self.matching_delim_spans.clear();
} else {
self.matching_delim_spans.push(
(open_brace, open_brace_span, self.token.span),
(open_brace, open_brace_span, close_brace_span),
);
}
// Parse the close delimiter.
Expand Down Expand Up @@ -193,13 +203,20 @@ impl<'a> TokenTreesReader<'a> {
tts.into()
).into())
},
token::CloseDelim(_) => {
token::CloseDelim(delim) => {
// An unexpected closing delimiter (i.e., there is no
// matching opening delimiter).
let token_str = token_to_string(&self.token);
let msg = format!("unexpected close delimiter: `{}`", token_str);
let mut err = self.string_reader.sess.span_diagnostic
.struct_span_err(self.token.span, &msg);

if let Some(span) = self.last_delim_empty_block_spans.remove(&delim) {
err.span_label(
span,
"this block is empty, you might have not meant to close it"
);
}
err.span_label(self.token.span, "unexpected close delimiter");
Err(err)
},
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/parse/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub enum BinOpToken {
}

/// A delimiter token.
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
pub enum DelimToken {
/// A round parenthesis (i.e., `(` or `)`).
Paren,
Expand Down
5 changes: 5 additions & 0 deletions src/test/ui/parser/mismatched-delim-brace-empty-block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fn main() {

}
let _ = ();
} //~ ERROR unexpected close delimiter
14 changes: 14 additions & 0 deletions src/test/ui/parser/mismatched-delim-brace-empty-block.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: unexpected close delimiter: `}`
--> $DIR/mismatched-delim-brace-empty-block.rs:5:1
|
LL | fn main() {
| ___________-
LL | |
LL | | }
| |_- this block is empty, you might have not meant to close it
LL | let _ = ();
LL | }
| ^ unexpected close delimiter

error: aborting due to previous error

0 comments on commit c3eaee3

Please sign in to comment.