Skip to content

Commit e6ce3ef

Browse files
committed
Collect occurrences of for mismatched braces diagnostic
Change-Id: I20ba0b62308370ee961141fa1aefc4b9c9f0cb3a
1 parent 80b861b commit e6ce3ef

File tree

4 files changed

+31
-3
lines changed

4 files changed

+31
-3
lines changed

src/libsyntax/parse/lexer/tokentrees.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use rustc_data_structures::fx::FxHashMap;
12
use syntax_pos::Span;
23

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

3942
impl<'a> TokenTreesReader<'a> {
@@ -121,13 +124,20 @@ impl<'a> TokenTreesReader<'a> {
121124
// Correct delimiter.
122125
token::CloseDelim(d) if d == delim => {
123126
let (open_brace, open_brace_span) = self.open_braces.pop().unwrap();
127+
let close_brace_span = self.token.span;
128+
129+
if close_brace_span.lo() == open_brace_span.hi() {
130+
let empty_block_span = open_brace_span.to(close_brace_span);
131+
self.last_delim_empty_block_spans.insert(delim, empty_block_span);
132+
}
133+
124134
if self.open_braces.len() == 0 {
125135
// Clear up these spans to avoid suggesting them as we've found
126136
// properly matched delimiters so far for an entire block.
127137
self.matching_delim_spans.clear();
128138
} else {
129139
self.matching_delim_spans.push(
130-
(open_brace, open_brace_span, self.token.span),
140+
(open_brace, open_brace_span, close_brace_span),
131141
);
132142
}
133143
// Parse the close delimiter.
@@ -193,13 +203,17 @@ impl<'a> TokenTreesReader<'a> {
193203
tts.into()
194204
).into())
195205
},
196-
token::CloseDelim(_) => {
206+
token::CloseDelim(delim) => {
197207
// An unexpected closing delimiter (i.e., there is no
198208
// matching opening delimiter).
199209
let token_str = token_to_string(&self.token);
200210
let msg = format!("unexpected close delimiter: `{}`", token_str);
201211
let mut err = self.string_reader.sess.span_diagnostic
202212
.struct_span_err(self.token.span, &msg);
213+
214+
if let Some(span) = self.last_delim_empty_block_spans.remove(&delim) {
215+
err.span_label(span, "this block is empty, you might have not meant to close it");
216+
}
203217
err.span_label(self.token.span, "unexpected close delimiter");
204218
Err(err)
205219
},

src/libsyntax/parse/token.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub enum BinOpToken {
3636
}
3737

3838
/// A delimiter token.
39-
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
39+
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
4040
pub enum DelimToken {
4141
/// A round parenthesis (i.e., `(` or `)`).
4242
Paren,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn main() {}
2+
let _ = ();
3+
} //~ ERROR unexpected close delimiter
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: unexpected close delimiter: `}`
2+
--> $DIR/mismatched-delim-brace-empty-block.rs:3:1
3+
|
4+
LL | fn main() {}
5+
| -- this block is empty, you might have not meant to close it
6+
LL | let _ = ();
7+
LL | }
8+
| ^ unexpected close delimiter
9+
10+
error: aborting due to previous error
11+

0 commit comments

Comments
 (0)