From 811d817eaf5d78522773ab9d21543629027e4ecb Mon Sep 17 00:00:00 2001 From: Kevin Per Date: Tue, 31 Mar 2020 22:15:22 +0200 Subject: [PATCH 1/8] Dropping "block is empty..." error message on incorrect closing delimiter #70583 --- src/librustc_parse/lexer/tokentrees.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/librustc_parse/lexer/tokentrees.rs b/src/librustc_parse/lexer/tokentrees.rs index b65b894172844..795512c21ed6d 100644 --- a/src/librustc_parse/lexer/tokentrees.rs +++ b/src/librustc_parse/lexer/tokentrees.rs @@ -77,6 +77,7 @@ impl<'a> TokenTreesReader<'a> { fn parse_token_tree(&mut self) -> PResult<'a, TreeAndJoint> { let sm = self.string_reader.sess.source_map(); + match self.token.kind { token::Eof => { let msg = "this file contains an unclosed delimiter"; @@ -216,7 +217,7 @@ impl<'a> TokenTreesReader<'a> { Ok(TokenTree::Delimited(delim_span, delim, tts).into()) } - token::CloseDelim(delim) => { + token::CloseDelim(_delim) => { // An unexpected closing delimiter (i.e., there is no // matching opening delimiter). let token_str = token_to_string(&self.token); @@ -224,13 +225,8 @@ impl<'a> TokenTreesReader<'a> { 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 closing delimiter"); + Err(err) } _ => { From af16794b2f8be96cb485f8660c16f1e1616a99a4 Mon Sep 17 00:00:00 2001 From: Kevin Per Date: Wed, 1 Apr 2020 08:16:23 +0200 Subject: [PATCH 2/8] Revert "Dropping "block is empty..." error message on incorrect closing delimiter #70583" This reverts commit 811d817eaf5d78522773ab9d21543629027e4ecb. --- src/librustc_parse/lexer/tokentrees.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/librustc_parse/lexer/tokentrees.rs b/src/librustc_parse/lexer/tokentrees.rs index 795512c21ed6d..b65b894172844 100644 --- a/src/librustc_parse/lexer/tokentrees.rs +++ b/src/librustc_parse/lexer/tokentrees.rs @@ -77,7 +77,6 @@ impl<'a> TokenTreesReader<'a> { fn parse_token_tree(&mut self) -> PResult<'a, TreeAndJoint> { let sm = self.string_reader.sess.source_map(); - match self.token.kind { token::Eof => { let msg = "this file contains an unclosed delimiter"; @@ -217,7 +216,7 @@ impl<'a> TokenTreesReader<'a> { Ok(TokenTree::Delimited(delim_span, delim, tts).into()) } - token::CloseDelim(_delim) => { + token::CloseDelim(delim) => { // An unexpected closing delimiter (i.e., there is no // matching opening delimiter). let token_str = token_to_string(&self.token); @@ -225,8 +224,13 @@ impl<'a> TokenTreesReader<'a> { 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 closing delimiter"); - Err(err) } _ => { From b85d5881992c07c51fb3f3eb113b00a5abbf74f0 Mon Sep 17 00:00:00 2001 From: Kevin Per Date: Thu, 2 Apr 2020 06:42:21 +0000 Subject: [PATCH 3/8] Check if the suggestion's `this block is empty...` span is in the last properly closed block. --- src/librustc_parse/lexer/tokentrees.rs | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/librustc_parse/lexer/tokentrees.rs b/src/librustc_parse/lexer/tokentrees.rs index b65b894172844..074f32adefd58 100644 --- a/src/librustc_parse/lexer/tokentrees.rs +++ b/src/librustc_parse/lexer/tokentrees.rs @@ -22,6 +22,7 @@ impl<'a> StringReader<'a> { matching_delim_spans: Vec::new(), last_unclosed_found_span: None, last_delim_empty_block_spans: FxHashMap::default(), + matching_block_spans: Vec::new(), }; let res = tt_reader.parse_all_token_trees(); (res, tt_reader.unmatched_braces) @@ -42,6 +43,9 @@ struct TokenTreesReader<'a> { last_unclosed_found_span: Option, /// Collect empty block spans that might have been auto-inserted by editors. last_delim_empty_block_spans: FxHashMap, + /// Collect the spans of braces (Open, Close). Used only + /// for detecting if blocks are empty + matching_block_spans: Vec<(Span, Span)>, } impl<'a> TokenTreesReader<'a> { @@ -77,6 +81,7 @@ impl<'a> TokenTreesReader<'a> { fn parse_token_tree(&mut self) -> PResult<'a, TreeAndJoint> { let sm = self.string_reader.sess.source_map(); + match self.token.kind { token::Eof => { let msg = "this file contains an unclosed delimiter"; @@ -146,6 +151,8 @@ impl<'a> TokenTreesReader<'a> { } } + self.matching_block_spans.push((open_brace_span, close_brace_span)); + if self.open_braces.is_empty() { // Clear up these spans to avoid suggesting them as we've found // properly matched delimiters so far for an entire block. @@ -164,6 +171,8 @@ impl<'a> TokenTreesReader<'a> { token::CloseDelim(other) => { let mut unclosed_delimiter = None; let mut candidate = None; + + if self.last_unclosed_found_span != Some(self.token.span) { // do not complain about the same unclosed delimiter multiple times self.last_unclosed_found_span = Some(self.token.span); @@ -225,10 +234,16 @@ impl<'a> TokenTreesReader<'a> { 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", - ); + // Braces are added at the end, so the last element is the biggest block + if let Some(parent) = self.matching_block_spans.last() { + // Check if the (empty block) is in the last properly closed block + if (parent.0.to(parent.1)).contains(span) { + err.span_label( + span, + "this block is empty, you might have not meant to close it", + ); + } + } } err.span_label(self.token.span, "unexpected closing delimiter"); Err(err) From 053a696ade1ba05508e099b56fe46ace264c169a Mon Sep 17 00:00:00 2001 From: Kevin Per Date: Thu, 2 Apr 2020 07:17:46 +0000 Subject: [PATCH 4/8] Writing tests --- .../ui/parser/issue-70583-block-is-empty-1.rs | 20 +++++++++++++++++++ .../issue-70583-block-is-empty-1.stderr | 8 ++++++++ .../ui/parser/issue-70583-block-is-empty-2.rs | 14 +++++++++++++ .../issue-70583-block-is-empty-2.stderr | 11 ++++++++++ 4 files changed, 53 insertions(+) create mode 100644 src/test/ui/parser/issue-70583-block-is-empty-1.rs create mode 100644 src/test/ui/parser/issue-70583-block-is-empty-1.stderr create mode 100644 src/test/ui/parser/issue-70583-block-is-empty-2.rs create mode 100644 src/test/ui/parser/issue-70583-block-is-empty-2.stderr diff --git a/src/test/ui/parser/issue-70583-block-is-empty-1.rs b/src/test/ui/parser/issue-70583-block-is-empty-1.rs new file mode 100644 index 0000000000000..889607825df91 --- /dev/null +++ b/src/test/ui/parser/issue-70583-block-is-empty-1.rs @@ -0,0 +1,20 @@ +pub enum ErrorHandled { + Reported, + TooGeneric, +} + +impl ErrorHandled { + pub fn assert_reported(self) { + match self { + ErrorHandled::Reported => {} + ErrorHandled::TooGeneric => panic!(), + } + } +} + +fn struct_generic(x: Vec) { + for v in x { + println!("{}", v); + } + } +} //~ ERROR unexpected closing delimiter: `}` diff --git a/src/test/ui/parser/issue-70583-block-is-empty-1.stderr b/src/test/ui/parser/issue-70583-block-is-empty-1.stderr new file mode 100644 index 0000000000000..8f807c0b0b2b9 --- /dev/null +++ b/src/test/ui/parser/issue-70583-block-is-empty-1.stderr @@ -0,0 +1,8 @@ +error: unexpected closing delimiter: `}` + --> $DIR/issue-70583-block-is-empty-1.rs:20:1 + | +LL | } + | ^ unexpected closing delimiter + +error: aborting due to previous error + diff --git a/src/test/ui/parser/issue-70583-block-is-empty-2.rs b/src/test/ui/parser/issue-70583-block-is-empty-2.rs new file mode 100644 index 0000000000000..c4381119dc9d8 --- /dev/null +++ b/src/test/ui/parser/issue-70583-block-is-empty-2.rs @@ -0,0 +1,14 @@ +pub enum ErrorHandled { + Reported, + TooGeneric, +} + +impl ErrorHandled { + pub fn assert_reported(self) { + match self { + ErrorHandled::Reported => {}} + //^~ ERROR this block is empty, you might have not mean to close it + ErrorHandled::TooGeneric => panic!(), + } + } +} //~ ERROR unexpected closing delimiter: `}` diff --git a/src/test/ui/parser/issue-70583-block-is-empty-2.stderr b/src/test/ui/parser/issue-70583-block-is-empty-2.stderr new file mode 100644 index 0000000000000..662fcc9987cb2 --- /dev/null +++ b/src/test/ui/parser/issue-70583-block-is-empty-2.stderr @@ -0,0 +1,11 @@ +error: unexpected closing delimiter: `}` + --> $DIR/issue-70583-block-is-empty-2.rs:14:1 + | +LL | ErrorHandled::Reported => {}} + | -- this block is empty, you might have not meant to close it +... +LL | } + | ^ unexpected closing delimiter + +error: aborting due to previous error + From d5cba6c895835401ce550f76eadc112293287372 Mon Sep 17 00:00:00 2001 From: Kevin Per Date: Fri, 3 Apr 2020 07:24:02 +0000 Subject: [PATCH 5/8] Fixing tests --- src/librustc_parse/lexer/tokentrees.rs | 1 - src/test/ui/parser/issue-70583-block-is-empty-1.rs | 2 +- src/test/ui/parser/issue-70583-block-is-empty-1.stderr | 3 +++ src/test/ui/parser/issue-70583-block-is-empty-2.rs | 4 ++-- src/test/ui/parser/issue-70583-block-is-empty-2.stderr | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/librustc_parse/lexer/tokentrees.rs b/src/librustc_parse/lexer/tokentrees.rs index 074f32adefd58..e7bb8c7cc14bd 100644 --- a/src/librustc_parse/lexer/tokentrees.rs +++ b/src/librustc_parse/lexer/tokentrees.rs @@ -172,7 +172,6 @@ impl<'a> TokenTreesReader<'a> { let mut unclosed_delimiter = None; let mut candidate = None; - if self.last_unclosed_found_span != Some(self.token.span) { // do not complain about the same unclosed delimiter multiple times self.last_unclosed_found_span = Some(self.token.span); diff --git a/src/test/ui/parser/issue-70583-block-is-empty-1.rs b/src/test/ui/parser/issue-70583-block-is-empty-1.rs index 889607825df91..f560f68f61368 100644 --- a/src/test/ui/parser/issue-70583-block-is-empty-1.rs +++ b/src/test/ui/parser/issue-70583-block-is-empty-1.rs @@ -16,5 +16,5 @@ fn struct_generic(x: Vec) { for v in x { println!("{}", v); } - } + } } //~ ERROR unexpected closing delimiter: `}` diff --git a/src/test/ui/parser/issue-70583-block-is-empty-1.stderr b/src/test/ui/parser/issue-70583-block-is-empty-1.stderr index 8f807c0b0b2b9..f4bbe9e86e964 100644 --- a/src/test/ui/parser/issue-70583-block-is-empty-1.stderr +++ b/src/test/ui/parser/issue-70583-block-is-empty-1.stderr @@ -1,6 +1,9 @@ error: unexpected closing delimiter: `}` --> $DIR/issue-70583-block-is-empty-1.rs:20:1 | +LL | ErrorHandled::Reported => {} + | -- this block is empty, you might have not meant to close it +... LL | } | ^ unexpected closing delimiter diff --git a/src/test/ui/parser/issue-70583-block-is-empty-2.rs b/src/test/ui/parser/issue-70583-block-is-empty-2.rs index c4381119dc9d8..4764d71936b2e 100644 --- a/src/test/ui/parser/issue-70583-block-is-empty-2.rs +++ b/src/test/ui/parser/issue-70583-block-is-empty-2.rs @@ -6,8 +6,8 @@ pub enum ErrorHandled { impl ErrorHandled { pub fn assert_reported(self) { match self { - ErrorHandled::Reported => {}} - //^~ ERROR this block is empty, you might have not mean to close it + ErrorHandled::Reported => {}} + //^~ ERROR this block is empty, you might have not meant to close it ErrorHandled::TooGeneric => panic!(), } } diff --git a/src/test/ui/parser/issue-70583-block-is-empty-2.stderr b/src/test/ui/parser/issue-70583-block-is-empty-2.stderr index 662fcc9987cb2..9511d9847fb15 100644 --- a/src/test/ui/parser/issue-70583-block-is-empty-2.stderr +++ b/src/test/ui/parser/issue-70583-block-is-empty-2.stderr @@ -1,7 +1,7 @@ error: unexpected closing delimiter: `}` --> $DIR/issue-70583-block-is-empty-2.rs:14:1 | -LL | ErrorHandled::Reported => {}} +LL | ErrorHandled::Reported => {}} | -- this block is empty, you might have not meant to close it ... LL | } From e21d101c45022ab34d5ad10605a16d6ce8116c94 Mon Sep 17 00:00:00 2001 From: Kevin Per Date: Sat, 4 Apr 2020 07:55:07 +0000 Subject: [PATCH 6/8] Show open and closed braces of last proper block --- src/librustc_parse/lexer/tokentrees.rs | 48 +++++++++++++++---- .../issue-70583-block-is-empty-1.stderr | 6 ++- .../macro-mismatched-delim-paren-brace.stderr | 5 ++ .../mismatched-delim-brace-empty-block.stderr | 6 +++ 4 files changed, 54 insertions(+), 11 deletions(-) diff --git a/src/librustc_parse/lexer/tokentrees.rs b/src/librustc_parse/lexer/tokentrees.rs index e7bb8c7cc14bd..09bbfe10fe5e1 100644 --- a/src/librustc_parse/lexer/tokentrees.rs +++ b/src/librustc_parse/lexer/tokentrees.rs @@ -1,6 +1,6 @@ use super::{StringReader, UnmatchedBrace}; -use rustc_ast::token::{self, Token}; +use rustc_ast::token::{self, Token, DelimToken}; use rustc_ast::tokenstream::{ DelimSpan, IsJoint::{self, *}, @@ -44,7 +44,7 @@ struct TokenTreesReader<'a> { /// Collect empty block spans that might have been auto-inserted by editors. last_delim_empty_block_spans: FxHashMap, /// Collect the spans of braces (Open, Close). Used only - /// for detecting if blocks are empty + /// for detecting if blocks are empty and only braces. matching_block_spans: Vec<(Span, Span)>, } @@ -151,7 +151,13 @@ impl<'a> TokenTreesReader<'a> { } } - self.matching_block_spans.push((open_brace_span, close_brace_span)); + match (open_brace, delim) { + //only add braces + (DelimToken::Brace, DelimToken::Brace) => { + self.matching_block_spans.push((open_brace_span, close_brace_span)); + } + _ => {} + } if self.open_braces.is_empty() { // Clear up these spans to avoid suggesting them as we've found @@ -232,18 +238,42 @@ impl<'a> TokenTreesReader<'a> { 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) { // Braces are added at the end, so the last element is the biggest block if let Some(parent) = self.matching_block_spans.last() { - // Check if the (empty block) is in the last properly closed block - if (parent.0.to(parent.1)).contains(span) { + + if let Some(span) = self.last_delim_empty_block_spans.remove(&delim) { + // Check if the (empty block) is in the last properly closed block + if (parent.0.to(parent.1)).contains(span) { + err.span_label( + span, + "this block is empty, you might have not meant to close it", + ); + } + else { + err.span_label( + parent.0, + "this opening brace...", + ); + + err.span_label( + parent.1, + "...matches this closing brace", + ); + } + } + else { + err.span_label( + parent.0, + "this opening brace...", + ); + err.span_label( - span, - "this block is empty, you might have not meant to close it", + parent.1, + "...matches this closing brace", ); } - } } + err.span_label(self.token.span, "unexpected closing delimiter"); Err(err) } diff --git a/src/test/ui/parser/issue-70583-block-is-empty-1.stderr b/src/test/ui/parser/issue-70583-block-is-empty-1.stderr index f4bbe9e86e964..39bf113ef83de 100644 --- a/src/test/ui/parser/issue-70583-block-is-empty-1.stderr +++ b/src/test/ui/parser/issue-70583-block-is-empty-1.stderr @@ -1,9 +1,11 @@ error: unexpected closing delimiter: `}` --> $DIR/issue-70583-block-is-empty-1.rs:20:1 | -LL | ErrorHandled::Reported => {} - | -- this block is empty, you might have not meant to close it +LL | fn struct_generic(x: Vec) { + | - this opening brace... ... +LL | } + | - ...matches this closing brace LL | } | ^ unexpected closing delimiter diff --git a/src/test/ui/parser/macro-mismatched-delim-paren-brace.stderr b/src/test/ui/parser/macro-mismatched-delim-paren-brace.stderr index 042142ac35033..424c7a60c196f 100644 --- a/src/test/ui/parser/macro-mismatched-delim-paren-brace.stderr +++ b/src/test/ui/parser/macro-mismatched-delim-paren-brace.stderr @@ -1,6 +1,11 @@ error: unexpected closing delimiter: `}` --> $DIR/macro-mismatched-delim-paren-brace.rs:5:1 | +LL | fn main() { + | - this opening brace... +... +LL | } + | - ...matches this closing brace LL | } | ^ unexpected closing delimiter diff --git a/src/test/ui/parser/mismatched-delim-brace-empty-block.stderr b/src/test/ui/parser/mismatched-delim-brace-empty-block.stderr index f1be5dc5ba7fa..c871e549c9ec3 100644 --- a/src/test/ui/parser/mismatched-delim-brace-empty-block.stderr +++ b/src/test/ui/parser/mismatched-delim-brace-empty-block.stderr @@ -1,6 +1,12 @@ error: unexpected closing delimiter: `}` --> $DIR/mismatched-delim-brace-empty-block.rs:5:1 | +LL | fn main() { + | - this opening brace... +LL | +LL | } + | - ...matches this closing brace +LL | let _ = (); LL | } | ^ unexpected closing delimiter From 2c6f84668e9f985aff261d317d3188d053ca29d1 Mon Sep 17 00:00:00 2001 From: Kevin Per Date: Sat, 4 Apr 2020 08:01:42 +0000 Subject: [PATCH 7/8] Drop `this` in error message to not reach 100 characters --- src/librustc_parse/lexer/tokentrees.rs | 2 +- src/test/ui/parser/issue-70583-block-is-empty-2.rs | 2 +- src/test/ui/parser/issue-70583-block-is-empty-2.stderr | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_parse/lexer/tokentrees.rs b/src/librustc_parse/lexer/tokentrees.rs index 09bbfe10fe5e1..2dda90c37343a 100644 --- a/src/librustc_parse/lexer/tokentrees.rs +++ b/src/librustc_parse/lexer/tokentrees.rs @@ -246,7 +246,7 @@ impl<'a> TokenTreesReader<'a> { if (parent.0.to(parent.1)).contains(span) { err.span_label( span, - "this block is empty, you might have not meant to close it", + "block is empty, you might have not meant to close it", ); } else { diff --git a/src/test/ui/parser/issue-70583-block-is-empty-2.rs b/src/test/ui/parser/issue-70583-block-is-empty-2.rs index 4764d71936b2e..80f53338a689e 100644 --- a/src/test/ui/parser/issue-70583-block-is-empty-2.rs +++ b/src/test/ui/parser/issue-70583-block-is-empty-2.rs @@ -7,7 +7,7 @@ impl ErrorHandled { pub fn assert_reported(self) { match self { ErrorHandled::Reported => {}} - //^~ ERROR this block is empty, you might have not meant to close it + //^~ ERROR block is empty, you might have not meant to close it ErrorHandled::TooGeneric => panic!(), } } diff --git a/src/test/ui/parser/issue-70583-block-is-empty-2.stderr b/src/test/ui/parser/issue-70583-block-is-empty-2.stderr index 9511d9847fb15..5d37b216427f6 100644 --- a/src/test/ui/parser/issue-70583-block-is-empty-2.stderr +++ b/src/test/ui/parser/issue-70583-block-is-empty-2.stderr @@ -2,7 +2,7 @@ error: unexpected closing delimiter: `}` --> $DIR/issue-70583-block-is-empty-2.rs:14:1 | LL | ErrorHandled::Reported => {}} - | -- this block is empty, you might have not meant to close it + | -- block is empty, you might have not meant to close it ... LL | } | ^ unexpected closing delimiter From f96b92f5097a31496b0b735a8647326c5dc2ecf8 Mon Sep 17 00:00:00 2001 From: Kevin Per Date: Sat, 4 Apr 2020 08:39:17 +0000 Subject: [PATCH 8/8] Run fmt --- src/librustc_parse/lexer/tokentrees.rs | 47 +++++++++----------------- 1 file changed, 16 insertions(+), 31 deletions(-) diff --git a/src/librustc_parse/lexer/tokentrees.rs b/src/librustc_parse/lexer/tokentrees.rs index 2dda90c37343a..c08659ec9f648 100644 --- a/src/librustc_parse/lexer/tokentrees.rs +++ b/src/librustc_parse/lexer/tokentrees.rs @@ -1,6 +1,6 @@ use super::{StringReader, UnmatchedBrace}; -use rustc_ast::token::{self, Token, DelimToken}; +use rustc_ast::token::{self, DelimToken, Token}; use rustc_ast::tokenstream::{ DelimSpan, IsJoint::{self, *}, @@ -238,40 +238,25 @@ impl<'a> TokenTreesReader<'a> { let mut err = self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, &msg); - // Braces are added at the end, so the last element is the biggest block - if let Some(parent) = self.matching_block_spans.last() { - - if let Some(span) = self.last_delim_empty_block_spans.remove(&delim) { - // Check if the (empty block) is in the last properly closed block - if (parent.0.to(parent.1)).contains(span) { - err.span_label( - span, - "block is empty, you might have not meant to close it", - ); - } - else { - err.span_label( - parent.0, - "this opening brace...", - ); - - err.span_label( - parent.1, - "...matches this closing brace", - ); - } - } - else { + // Braces are added at the end, so the last element is the biggest block + if let Some(parent) = self.matching_block_spans.last() { + if let Some(span) = self.last_delim_empty_block_spans.remove(&delim) { + // Check if the (empty block) is in the last properly closed block + if (parent.0.to(parent.1)).contains(span) { err.span_label( - parent.0, - "this opening brace...", + span, + "block is empty, you might have not meant to close it", ); + } else { + err.span_label(parent.0, "this opening brace..."); - err.span_label( - parent.1, - "...matches this closing brace", - ); + err.span_label(parent.1, "...matches this closing brace"); } + } else { + err.span_label(parent.0, "this opening brace..."); + + err.span_label(parent.1, "...matches this closing brace"); + } } err.span_label(self.token.span, "unexpected closing delimiter");