Skip to content

Commit 1d3d80f

Browse files
authored
Rollup merge of #70633 - kper:master, r=estebank
Confusing suggestion on incorrect closing `}` Compiler returns ``` error: unexpected closing delimiter: `}` --> main.rs:20:1 | 9 | ErrorHandled::Reported => {} | -- this block is empty, you might have not meant to close it temp ... 20 | } | ^ unexpected closing delimiter error: aborting due to previous error ```
2 parents 413a129 + f96b92f commit 1d3d80f

7 files changed

+104
-6
lines changed

src/librustc_parse/lexer/tokentrees.rs

+35-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::{StringReader, UnmatchedBrace};
22

3-
use rustc_ast::token::{self, Token};
3+
use rustc_ast::token::{self, DelimToken, Token};
44
use rustc_ast::tokenstream::{
55
DelimSpan,
66
IsJoint::{self, *},
@@ -22,6 +22,7 @@ impl<'a> StringReader<'a> {
2222
matching_delim_spans: Vec::new(),
2323
last_unclosed_found_span: None,
2424
last_delim_empty_block_spans: FxHashMap::default(),
25+
matching_block_spans: Vec::new(),
2526
};
2627
let res = tt_reader.parse_all_token_trees();
2728
(res, tt_reader.unmatched_braces)
@@ -42,6 +43,9 @@ struct TokenTreesReader<'a> {
4243
last_unclosed_found_span: Option<Span>,
4344
/// Collect empty block spans that might have been auto-inserted by editors.
4445
last_delim_empty_block_spans: FxHashMap<token::DelimToken, Span>,
46+
/// Collect the spans of braces (Open, Close). Used only
47+
/// for detecting if blocks are empty and only braces.
48+
matching_block_spans: Vec<(Span, Span)>,
4549
}
4650

4751
impl<'a> TokenTreesReader<'a> {
@@ -77,6 +81,7 @@ impl<'a> TokenTreesReader<'a> {
7781

7882
fn parse_token_tree(&mut self) -> PResult<'a, TreeAndJoint> {
7983
let sm = self.string_reader.sess.source_map();
84+
8085
match self.token.kind {
8186
token::Eof => {
8287
let msg = "this file contains an unclosed delimiter";
@@ -146,6 +151,14 @@ impl<'a> TokenTreesReader<'a> {
146151
}
147152
}
148153

154+
match (open_brace, delim) {
155+
//only add braces
156+
(DelimToken::Brace, DelimToken::Brace) => {
157+
self.matching_block_spans.push((open_brace_span, close_brace_span));
158+
}
159+
_ => {}
160+
}
161+
149162
if self.open_braces.is_empty() {
150163
// Clear up these spans to avoid suggesting them as we've found
151164
// properly matched delimiters so far for an entire block.
@@ -164,6 +177,7 @@ impl<'a> TokenTreesReader<'a> {
164177
token::CloseDelim(other) => {
165178
let mut unclosed_delimiter = None;
166179
let mut candidate = None;
180+
167181
if self.last_unclosed_found_span != Some(self.token.span) {
168182
// do not complain about the same unclosed delimiter multiple times
169183
self.last_unclosed_found_span = Some(self.token.span);
@@ -224,12 +238,27 @@ impl<'a> TokenTreesReader<'a> {
224238
let mut err =
225239
self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, &msg);
226240

227-
if let Some(span) = self.last_delim_empty_block_spans.remove(&delim) {
228-
err.span_label(
229-
span,
230-
"this block is empty, you might have not meant to close it",
231-
);
241+
// Braces are added at the end, so the last element is the biggest block
242+
if let Some(parent) = self.matching_block_spans.last() {
243+
if let Some(span) = self.last_delim_empty_block_spans.remove(&delim) {
244+
// Check if the (empty block) is in the last properly closed block
245+
if (parent.0.to(parent.1)).contains(span) {
246+
err.span_label(
247+
span,
248+
"block is empty, you might have not meant to close it",
249+
);
250+
} else {
251+
err.span_label(parent.0, "this opening brace...");
252+
253+
err.span_label(parent.1, "...matches this closing brace");
254+
}
255+
} else {
256+
err.span_label(parent.0, "this opening brace...");
257+
258+
err.span_label(parent.1, "...matches this closing brace");
259+
}
232260
}
261+
233262
err.span_label(self.token.span, "unexpected closing delimiter");
234263
Err(err)
235264
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
pub enum ErrorHandled {
2+
Reported,
3+
TooGeneric,
4+
}
5+
6+
impl ErrorHandled {
7+
pub fn assert_reported(self) {
8+
match self {
9+
ErrorHandled::Reported => {}
10+
ErrorHandled::TooGeneric => panic!(),
11+
}
12+
}
13+
}
14+
15+
fn struct_generic(x: Vec<i32>) {
16+
for v in x {
17+
println!("{}", v);
18+
}
19+
}
20+
} //~ ERROR unexpected closing delimiter: `}`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error: unexpected closing delimiter: `}`
2+
--> $DIR/issue-70583-block-is-empty-1.rs:20:1
3+
|
4+
LL | fn struct_generic(x: Vec<i32>) {
5+
| - this opening brace...
6+
...
7+
LL | }
8+
| - ...matches this closing brace
9+
LL | }
10+
| ^ unexpected closing delimiter
11+
12+
error: aborting due to previous error
13+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
pub enum ErrorHandled {
2+
Reported,
3+
TooGeneric,
4+
}
5+
6+
impl ErrorHandled {
7+
pub fn assert_reported(self) {
8+
match self {
9+
ErrorHandled::Reported => {}}
10+
//^~ ERROR block is empty, you might have not meant to close it
11+
ErrorHandled::TooGeneric => panic!(),
12+
}
13+
}
14+
} //~ ERROR unexpected closing delimiter: `}`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: unexpected closing delimiter: `}`
2+
--> $DIR/issue-70583-block-is-empty-2.rs:14:1
3+
|
4+
LL | ErrorHandled::Reported => {}}
5+
| -- block is empty, you might have not meant to close it
6+
...
7+
LL | }
8+
| ^ unexpected closing delimiter
9+
10+
error: aborting due to previous error
11+

src/test/ui/parser/macro-mismatched-delim-paren-brace.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
error: unexpected closing delimiter: `}`
22
--> $DIR/macro-mismatched-delim-paren-brace.rs:5:1
33
|
4+
LL | fn main() {
5+
| - this opening brace...
6+
...
7+
LL | }
8+
| - ...matches this closing brace
49
LL | }
510
| ^ unexpected closing delimiter
611

src/test/ui/parser/mismatched-delim-brace-empty-block.stderr

+6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
error: unexpected closing delimiter: `}`
22
--> $DIR/mismatched-delim-brace-empty-block.rs:5:1
33
|
4+
LL | fn main() {
5+
| - this opening brace...
6+
LL |
7+
LL | }
8+
| - ...matches this closing brace
9+
LL | let _ = ();
410
LL | }
511
| ^ unexpected closing delimiter
612

0 commit comments

Comments
 (0)