From 2ec7d0b2281e57a456d6122dadd5646804a9d36e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 1 Mar 2019 16:28:04 -0800 Subject: [PATCH 01/11] Do not panic on missing close paren Fix #58856. --- src/libsyntax/parse/parser.rs | 4 +- src/test/ui/issues/issue-58856-1.rs | 9 ++++ src/test/ui/issues/issue-58856-1.stderr | 30 ++++++++++++++ src/test/ui/issues/issue-58856-2.rs | 13 ++++++ src/test/ui/issues/issue-58856-2.stderr | 55 +++++++++++++++++++++++++ 5 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/issues/issue-58856-1.rs create mode 100644 src/test/ui/issues/issue-58856-1.stderr create mode 100644 src/test/ui/issues/issue-58856-2.rs create mode 100644 src/test/ui/issues/issue-58856-2.stderr diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index fd5038a8614f2..dd4c2393fa58a 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -6332,8 +6332,10 @@ impl<'a> Parser<'a> { &token::CloseDelim(token::Paren), sep, parse_arg_fn)?; fn_inputs.append(&mut input); (fn_inputs, recovered) + } else if let Err(err) = self.expect_one_of(&[], &[]) { + return Err(err); } else { - return self.unexpected(); + (vec![self_arg], true) } } else { self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn)? diff --git a/src/test/ui/issues/issue-58856-1.rs b/src/test/ui/issues/issue-58856-1.rs new file mode 100644 index 0000000000000..9311bb0802f2a --- /dev/null +++ b/src/test/ui/issues/issue-58856-1.rs @@ -0,0 +1,9 @@ +impl A { +//~^ ERROR cannot find type `A` in this scope + fn b(self> + //~^ ERROR expected one of `)`, `,`, or `:`, found `>` + //~| ERROR expected one of `->`, `where`, or `{`, found `>` + //~| ERROR expected one of `->`, `async`, `const`, `crate`, `default`, `existential`, +} + +fn main() {} diff --git a/src/test/ui/issues/issue-58856-1.stderr b/src/test/ui/issues/issue-58856-1.stderr new file mode 100644 index 0000000000000..3cbfd375e785e --- /dev/null +++ b/src/test/ui/issues/issue-58856-1.stderr @@ -0,0 +1,30 @@ +error: expected one of `)`, `,`, or `:`, found `>` + --> $DIR/issue-58856-1.rs:3:14 + | +LL | fn b(self> + | - ^ + | | | + | | help: `)` may belong here + | unclosed delimiter + +error: expected one of `->`, `where`, or `{`, found `>` + --> $DIR/issue-58856-1.rs:3:14 + | +LL | fn b(self> + | ^ expected one of `->`, `where`, or `{` here + +error: expected one of `->`, `async`, `const`, `crate`, `default`, `existential`, `extern`, `fn`, `pub`, `type`, `unsafe`, `where`, or `}`, found `>` + --> $DIR/issue-58856-1.rs:3:14 + | +LL | fn b(self> + | ^ expected one of 13 possible tokens here + +error[E0412]: cannot find type `A` in this scope + --> $DIR/issue-58856-1.rs:1:6 + | +LL | impl A { + | ^ not found in this scope + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/issues/issue-58856-2.rs b/src/test/ui/issues/issue-58856-2.rs new file mode 100644 index 0000000000000..4c764761e8ec5 --- /dev/null +++ b/src/test/ui/issues/issue-58856-2.rs @@ -0,0 +1,13 @@ +trait Howness {} +impl Howness for () { + fn how_are_you(&self -> Empty { + //~^ ERROR expected one of `)` or `,`, found `->` + //~| ERROR method `how_are_you` is not a member of trait `Howness` + //~| ERROR cannot find type `Empty` in this scope + Empty + //~^ ERROR cannot find value `Empty` in this scope + } +} +//~^ ERROR expected one of `async`, `const`, `crate`, `default`, `existential`, `extern`, `fn`, + +fn main() {} diff --git a/src/test/ui/issues/issue-58856-2.stderr b/src/test/ui/issues/issue-58856-2.stderr new file mode 100644 index 0000000000000..30027278e23ca --- /dev/null +++ b/src/test/ui/issues/issue-58856-2.stderr @@ -0,0 +1,55 @@ +error: expected one of `)` or `,`, found `->` + --> $DIR/issue-58856-2.rs:3:26 + | +LL | fn how_are_you(&self -> Empty { + | - -^^ + | | | + | | help: `)` may belong here + | unclosed delimiter + +error: expected one of `async`, `const`, `crate`, `default`, `existential`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `)` + --> $DIR/issue-58856-2.rs:10:1 + | +LL | } + | - expected one of 11 possible tokens here +LL | } + | ^ unexpected token + +error[E0407]: method `how_are_you` is not a member of trait `Howness` + --> $DIR/issue-58856-2.rs:3:5 + | +LL | / fn how_are_you(&self -> Empty { +LL | | //~^ ERROR expected one of `)` or `,`, found `->` +LL | | //~| ERROR method `how_are_you` is not a member of trait `Howness` +LL | | //~| ERROR cannot find type `Empty` in this scope +LL | | Empty +LL | | //~^ ERROR cannot find value `Empty` in this scope +LL | | } + | |_____^ not a member of trait `Howness` + +error[E0412]: cannot find type `Empty` in this scope + --> $DIR/issue-58856-2.rs:3:29 + | +LL | fn how_are_you(&self -> Empty { + | ^^^^^ not found in this scope +help: possible candidates are found in other modules, you can import them into scope + | +LL | use std::io::Empty; + | +LL | use std::iter::Empty; + | + +error[E0425]: cannot find value `Empty` in this scope + --> $DIR/issue-58856-2.rs:7:9 + | +LL | Empty + | ^^^^^ not found in this scope +help: possible candidate is found in another module, you can import it into scope + | +LL | use std::sync::mpsc::TryRecvError::Empty; + | + +error: aborting due to 5 previous errors + +Some errors occurred: E0407, E0412, E0425. +For more information about an error, try `rustc --explain E0407`. From cc535a2a19444d7b96e80dc8f445d50452e5495d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 1 Mar 2019 21:47:06 -0800 Subject: [PATCH 02/11] Bail when encountering a second unexpected token in the same span --- src/libsyntax/parse/parser.rs | 14 +++++++--- src/test/ui/issues/issue-58856-1.rs | 7 +++-- src/test/ui/issues/issue-58856-1.stderr | 25 +++--------------- src/test/ui/issues/issue-58856-2.rs | 5 ++-- src/test/ui/issues/issue-58856-2.stderr | 35 ++++--------------------- src/test/ui/parser/recover-enum2.rs | 3 --- src/test/ui/parser/recover-enum2.stderr | 14 +--------- 7 files changed, 25 insertions(+), 78 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index dd4c2393fa58a..c27a1f79d8ccb 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -46,7 +46,7 @@ use crate::ThinVec; use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint}; use crate::symbol::{Symbol, keywords}; -use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; +use errors::{Applicability, DiagnosticBuilder, DiagnosticId, FatalError}; use rustc_target::spec::abi::{self, Abi}; use syntax_pos::{Span, MultiSpan, BytePos, FileName}; use log::{debug, trace}; @@ -256,6 +256,7 @@ pub struct Parser<'a> { /// it gets removed from here. Every entry left at the end gets emitted as an independent /// error. crate unclosed_delims: Vec, + last_unexpected_token_span: Option, } @@ -582,6 +583,7 @@ impl<'a> Parser<'a> { unmatched_angle_bracket_count: 0, max_angle_bracket_count: 0, unclosed_delims: Vec::new(), + last_unexpected_token_span: None, }; let tok = parser.next_tok(); @@ -775,6 +777,8 @@ impl<'a> Parser<'a> { } else if inedible.contains(&self.token) { // leave it in the input Ok(false) + } else if self.last_unexpected_token_span == Some(self.span) { + FatalError.raise(); } else { let mut expected = edible.iter() .map(|x| TokenType::Token(x.clone())) @@ -802,6 +806,7 @@ impl<'a> Parser<'a> { (self.sess.source_map().next_point(self.prev_span), format!("expected {} here", expect))) }; + self.last_unexpected_token_span = Some(self.span); let mut err = self.fatal(&msg_exp); if self.token.is_ident_named("and") { err.span_suggestion_short( @@ -6332,10 +6337,11 @@ impl<'a> Parser<'a> { &token::CloseDelim(token::Paren), sep, parse_arg_fn)?; fn_inputs.append(&mut input); (fn_inputs, recovered) - } else if let Err(err) = self.expect_one_of(&[], &[]) { - return Err(err); } else { - (vec![self_arg], true) + match self.expect_one_of(&[], &[]) { + Err(err) => return Err(err), + Ok(recovered) => (vec![self_arg], recovered), + } } } else { self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn)? diff --git a/src/test/ui/issues/issue-58856-1.rs b/src/test/ui/issues/issue-58856-1.rs index 9311bb0802f2a..f5edac0d2e316 100644 --- a/src/test/ui/issues/issue-58856-1.rs +++ b/src/test/ui/issues/issue-58856-1.rs @@ -1,9 +1,8 @@ +struct A; + impl A { -//~^ ERROR cannot find type `A` in this scope - fn b(self> + fn b(self> {} //~^ ERROR expected one of `)`, `,`, or `:`, found `>` - //~| ERROR expected one of `->`, `where`, or `{`, found `>` - //~| ERROR expected one of `->`, `async`, `const`, `crate`, `default`, `existential`, } fn main() {} diff --git a/src/test/ui/issues/issue-58856-1.stderr b/src/test/ui/issues/issue-58856-1.stderr index 3cbfd375e785e..85101e467b137 100644 --- a/src/test/ui/issues/issue-58856-1.stderr +++ b/src/test/ui/issues/issue-58856-1.stderr @@ -1,30 +1,11 @@ error: expected one of `)`, `,`, or `:`, found `>` - --> $DIR/issue-58856-1.rs:3:14 + --> $DIR/issue-58856-1.rs:4:14 | -LL | fn b(self> +LL | fn b(self> {} | - ^ | | | | | help: `)` may belong here | unclosed delimiter -error: expected one of `->`, `where`, or `{`, found `>` - --> $DIR/issue-58856-1.rs:3:14 - | -LL | fn b(self> - | ^ expected one of `->`, `where`, or `{` here - -error: expected one of `->`, `async`, `const`, `crate`, `default`, `existential`, `extern`, `fn`, `pub`, `type`, `unsafe`, `where`, or `}`, found `>` - --> $DIR/issue-58856-1.rs:3:14 - | -LL | fn b(self> - | ^ expected one of 13 possible tokens here - -error[E0412]: cannot find type `A` in this scope - --> $DIR/issue-58856-1.rs:1:6 - | -LL | impl A { - | ^ not found in this scope - -error: aborting due to 4 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/issues/issue-58856-2.rs b/src/test/ui/issues/issue-58856-2.rs index 4c764761e8ec5..acc38e4c20163 100644 --- a/src/test/ui/issues/issue-58856-2.rs +++ b/src/test/ui/issues/issue-58856-2.rs @@ -1,11 +1,12 @@ +struct Empty; + trait Howness {} + impl Howness for () { fn how_are_you(&self -> Empty { //~^ ERROR expected one of `)` or `,`, found `->` //~| ERROR method `how_are_you` is not a member of trait `Howness` - //~| ERROR cannot find type `Empty` in this scope Empty - //~^ ERROR cannot find value `Empty` in this scope } } //~^ ERROR expected one of `async`, `const`, `crate`, `default`, `existential`, `extern`, `fn`, diff --git a/src/test/ui/issues/issue-58856-2.stderr b/src/test/ui/issues/issue-58856-2.stderr index 30027278e23ca..55a9e9d5cb863 100644 --- a/src/test/ui/issues/issue-58856-2.stderr +++ b/src/test/ui/issues/issue-58856-2.stderr @@ -1,5 +1,5 @@ error: expected one of `)` or `,`, found `->` - --> $DIR/issue-58856-2.rs:3:26 + --> $DIR/issue-58856-2.rs:6:26 | LL | fn how_are_you(&self -> Empty { | - -^^ @@ -8,7 +8,7 @@ LL | fn how_are_you(&self -> Empty { | unclosed delimiter error: expected one of `async`, `const`, `crate`, `default`, `existential`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `)` - --> $DIR/issue-58856-2.rs:10:1 + --> $DIR/issue-58856-2.rs:11:1 | LL | } | - expected one of 11 possible tokens here @@ -16,40 +16,15 @@ LL | } | ^ unexpected token error[E0407]: method `how_are_you` is not a member of trait `Howness` - --> $DIR/issue-58856-2.rs:3:5 + --> $DIR/issue-58856-2.rs:6:5 | LL | / fn how_are_you(&self -> Empty { LL | | //~^ ERROR expected one of `)` or `,`, found `->` LL | | //~| ERROR method `how_are_you` is not a member of trait `Howness` -LL | | //~| ERROR cannot find type `Empty` in this scope LL | | Empty -LL | | //~^ ERROR cannot find value `Empty` in this scope LL | | } | |_____^ not a member of trait `Howness` -error[E0412]: cannot find type `Empty` in this scope - --> $DIR/issue-58856-2.rs:3:29 - | -LL | fn how_are_you(&self -> Empty { - | ^^^^^ not found in this scope -help: possible candidates are found in other modules, you can import them into scope - | -LL | use std::io::Empty; - | -LL | use std::iter::Empty; - | - -error[E0425]: cannot find value `Empty` in this scope - --> $DIR/issue-58856-2.rs:7:9 - | -LL | Empty - | ^^^^^ not found in this scope -help: possible candidate is found in another module, you can import it into scope - | -LL | use std::sync::mpsc::TryRecvError::Empty; - | - -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors -Some errors occurred: E0407, E0412, E0425. -For more information about an error, try `rustc --explain E0407`. +For more information about this error, try `rustc --explain E0407`. diff --git a/src/test/ui/parser/recover-enum2.rs b/src/test/ui/parser/recover-enum2.rs index 65a187737879d..7f2f2cc7ab039 100644 --- a/src/test/ui/parser/recover-enum2.rs +++ b/src/test/ui/parser/recover-enum2.rs @@ -25,9 +25,6 @@ fn main() { // fail again enum Test4 { Nope(i32 {}) //~ ERROR: found `{` - //~^ ERROR: found `{` } } - // still recover later - let bad_syntax = _; //~ ERROR: expected expression, found reserved identifier `_` } diff --git a/src/test/ui/parser/recover-enum2.stderr b/src/test/ui/parser/recover-enum2.stderr index b308e644ad9f8..315bfde77c73c 100644 --- a/src/test/ui/parser/recover-enum2.stderr +++ b/src/test/ui/parser/recover-enum2.stderr @@ -10,17 +10,5 @@ error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `{` LL | Nope(i32 {}) //~ ERROR: found `{` | ^ expected one of 7 possible tokens here -error: expected one of `!`, `&&`, `&`, `(`, `)`, `*`, `+`, `,`, `...`, `::`, `<`, `?`, `[`, `_`, `crate`, `dyn`, `extern`, `fn`, `for`, `impl`, `pub`, `unsafe`, `}`, or lifetime, found `{` - --> $DIR/recover-enum2.rs:27:22 - | -LL | Nope(i32 {}) //~ ERROR: found `{` - | ^ expected one of 24 possible tokens here - -error: expected expression, found reserved identifier `_` - --> $DIR/recover-enum2.rs:32:22 - | -LL | let bad_syntax = _; //~ ERROR: expected expression, found reserved identifier `_` - | ^ expected expression - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors From ed2de5a8421822ecf9aa3df30bc6c2e55d4ea97d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 1 Mar 2019 22:14:22 -0800 Subject: [PATCH 03/11] Emit unclosed delimiters during recovery --- src/libsyntax/parse/parser.rs | 1 + src/test/ui/issues/issue-58856-1.rs | 4 ++++ src/test/ui/issues/issue-58856-1.stderr | 10 +++++++++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index c27a1f79d8ccb..0187ad743aa71 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -778,6 +778,7 @@ impl<'a> Parser<'a> { // leave it in the input Ok(false) } else if self.last_unexpected_token_span == Some(self.span) { + emit_unclosed_delims(&self.unclosed_delims, self.diagnostic()); FatalError.raise(); } else { let mut expected = edible.iter() diff --git a/src/test/ui/issues/issue-58856-1.rs b/src/test/ui/issues/issue-58856-1.rs index f5edac0d2e316..7dc3658776e60 100644 --- a/src/test/ui/issues/issue-58856-1.rs +++ b/src/test/ui/issues/issue-58856-1.rs @@ -5,4 +5,8 @@ impl A { //~^ ERROR expected one of `)`, `,`, or `:`, found `>` } +// verify that mismatched delimiters get emitted +fn foo(] {} +//~^ ERROR incorrect close delimiter + fn main() {} diff --git a/src/test/ui/issues/issue-58856-1.stderr b/src/test/ui/issues/issue-58856-1.stderr index 85101e467b137..f26ebbe15c5b9 100644 --- a/src/test/ui/issues/issue-58856-1.stderr +++ b/src/test/ui/issues/issue-58856-1.stderr @@ -7,5 +7,13 @@ LL | fn b(self> {} | | help: `)` may belong here | unclosed delimiter -error: aborting due to previous error +error: incorrect close delimiter: `]` + --> $DIR/issue-58856-1.rs:9:8 + | +LL | fn foo(] {} + | -^ incorrect close delimiter + | | + | un-closed delimiter + +error: aborting due to 2 previous errors From e38e915cdfaecb5a89d9bf2b041f19c6598ade09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 1 Mar 2019 22:35:21 -0800 Subject: [PATCH 04/11] Reduce test case --- src/test/ui/issues/issue-58856-1.rs | 8 +------- src/test/ui/issues/issue-58856-1.stderr | 14 +++----------- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/src/test/ui/issues/issue-58856-1.rs b/src/test/ui/issues/issue-58856-1.rs index 7dc3658776e60..db3984cd18987 100644 --- a/src/test/ui/issues/issue-58856-1.rs +++ b/src/test/ui/issues/issue-58856-1.rs @@ -1,12 +1,6 @@ -struct A; - impl A { - fn b(self> {} + fn b(self> //~^ ERROR expected one of `)`, `,`, or `:`, found `>` } -// verify that mismatched delimiters get emitted -fn foo(] {} -//~^ ERROR incorrect close delimiter - fn main() {} diff --git a/src/test/ui/issues/issue-58856-1.stderr b/src/test/ui/issues/issue-58856-1.stderr index f26ebbe15c5b9..20cdf55365fc7 100644 --- a/src/test/ui/issues/issue-58856-1.stderr +++ b/src/test/ui/issues/issue-58856-1.stderr @@ -1,19 +1,11 @@ error: expected one of `)`, `,`, or `:`, found `>` - --> $DIR/issue-58856-1.rs:4:14 + --> $DIR/issue-58856-1.rs:2:14 | -LL | fn b(self> {} +LL | fn b(self> | - ^ | | | | | help: `)` may belong here | unclosed delimiter -error: incorrect close delimiter: `]` - --> $DIR/issue-58856-1.rs:9:8 - | -LL | fn foo(] {} - | -^ incorrect close delimiter - | | - | un-closed delimiter - -error: aborting due to 2 previous errors +error: aborting due to previous error From c70a516c23ae19ce568166a81e64c92a4ecf540a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 3 Mar 2019 11:13:19 -0800 Subject: [PATCH 05/11] Panic when unmatched delimiters aren't emitted --- src/libsyntax/ext/tt/macro_parser.rs | 2 +- src/libsyntax/parse/parser.rs | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index fe1cffb092b1c..1a419e7fadaa0 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -761,7 +761,7 @@ pub fn parse( else if bb_items.is_empty() && next_items.is_empty() { return Failure( parser.span, - parser.token, + parser.token.clone(), "no rules expected this token in macro call", ); } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 0187ad743aa71..33fe81ea8c414 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -259,6 +259,13 @@ pub struct Parser<'a> { last_unexpected_token_span: Option, } +impl<'a> Drop for Parser<'a> { + fn drop(&mut self) { + if !self.unclosed_delims.is_empty() { + panic!("unclosed delimiter errors not emitted"); + } + } +} #[derive(Clone)] struct TokenCursor { From 51d0e86c221dbd937ca248f25a95dad787035b9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 3 Mar 2019 12:14:25 -0800 Subject: [PATCH 06/11] Emit missing unclosed delimiter errors --- src/librustc_metadata/cstore_impl.rs | 4 +- src/libsyntax/parse/parser.rs | 14 ++++-- src/libsyntax/parse/token.rs | 12 ++--- src/libsyntax_ext/proc_macro_server.rs | 4 +- src/test/ui/parser-recovery-2.stderr | 12 ++--- src/test/ui/resolve/token-error-correct-3.rs | 16 +++--- .../ui/resolve/token-error-correct-3.stderr | 49 +++++++++---------- 7 files changed, 56 insertions(+), 55 deletions(-) diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index f49b88f14e60e..67a249e605ecc 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -439,8 +439,8 @@ impl cstore::CStore { let source_file = sess.parse_sess.source_map().new_source_file(source_name, def.body); let local_span = Span::new(source_file.start_pos, source_file.end_pos, NO_EXPANSION); - let (body, errors) = source_file_to_stream(&sess.parse_sess, source_file, None); - emit_unclosed_delims(&errors, &sess.diagnostic()); + let (body, mut errors) = source_file_to_stream(&sess.parse_sess, source_file, None); + emit_unclosed_delims(&mut errors, &sess.diagnostic()); // Mark the attrs as used let attrs = data.get_item_attrs(id.index, sess); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 33fe81ea8c414..bde14e192e96b 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -7798,7 +7798,10 @@ impl<'a> Parser<'a> { attributes_allowed: bool, ) -> PResult<'a, Option>> { let (ret, tokens) = self.collect_tokens(|this| { - this.parse_item_implementation(attrs, macros_allowed, attributes_allowed) + let item = this.parse_item_implementation(attrs, macros_allowed, attributes_allowed); + let diag = this.diagnostic(); + emit_unclosed_delims(&mut this.unclosed_delims, diag); + item })?; // Once we've parsed an item and recorded the tokens we got while @@ -8555,8 +8558,8 @@ impl<'a> Parser<'a> { module: self.parse_mod_items(&token::Eof, lo)?, span: lo.to(self.span), }); - emit_unclosed_delims(&self.unclosed_delims, self.diagnostic()); - self.unclosed_delims.clear(); + let diag = self.diagnostic(); + emit_unclosed_delims(&mut self.unclosed_delims, diag); krate } @@ -8587,8 +8590,8 @@ impl<'a> Parser<'a> { } } -pub fn emit_unclosed_delims(unclosed_delims: &[UnmatchedBrace], handler: &errors::Handler) { - for unmatched in unclosed_delims { +pub fn emit_unclosed_delims(unclosed_delims: &mut Vec, handler: &errors::Handler) { + for unmatched in unclosed_delims.iter() { let mut err = handler.struct_span_err(unmatched.found_span, &format!( "incorrect close delimiter: `{}`", pprust::token_to_string(&token::Token::CloseDelim(unmatched.found_delim)), @@ -8602,4 +8605,5 @@ pub fn emit_unclosed_delims(unclosed_delims: &[UnmatchedBrace], handler: &errors } err.emit(); } + unclosed_delims.clear(); } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index eec422d6266c3..bb4da12bae893 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -675,9 +675,9 @@ impl Nonterminal { // FIXME(#43081): Avoid this pretty-print + reparse hack let source = pprust::nonterminal_to_string(self); let filename = FileName::macro_expansion_source_code(&source); - let (tokens_for_real, errors) = + let (tokens_for_real, mut errors) = parse_stream_from_source_str(filename, source, sess, Some(span)); - emit_unclosed_delims(&errors, &sess.span_diagnostic); + emit_unclosed_delims(&mut errors, &sess.span_diagnostic); // During early phases of the compiler the AST could get modified // directly (e.g., attributes added or removed) and the internal cache @@ -740,13 +740,13 @@ fn prepend_attrs(sess: &ParseSess, let source = pprust::attr_to_string(attr); let macro_filename = FileName::macro_expansion_source_code(&source); if attr.is_sugared_doc { - let (stream, errors) = parse_stream_from_source_str( + let (stream, mut errors) = parse_stream_from_source_str( macro_filename, source, sess, Some(span), ); - emit_unclosed_delims(&errors, &sess.span_diagnostic); + emit_unclosed_delims(&mut errors, &sess.span_diagnostic); builder.push(stream); continue } @@ -763,13 +763,13 @@ fn prepend_attrs(sess: &ParseSess, // ... and for more complicated paths, fall back to a reparse hack that // should eventually be removed. } else { - let (stream, errors) = parse_stream_from_source_str( + let (stream, mut errors) = parse_stream_from_source_str( macro_filename, source, sess, Some(span), ); - emit_unclosed_delims(&errors, &sess.span_diagnostic); + emit_unclosed_delims(&mut errors, &sess.span_diagnostic); brackets.push(stream); } diff --git a/src/libsyntax_ext/proc_macro_server.rs b/src/libsyntax_ext/proc_macro_server.rs index 4c4b33c04422b..5822b5607f7df 100644 --- a/src/libsyntax_ext/proc_macro_server.rs +++ b/src/libsyntax_ext/proc_macro_server.rs @@ -410,13 +410,13 @@ impl server::TokenStream for Rustc<'_> { stream.is_empty() } fn from_str(&mut self, src: &str) -> Self::TokenStream { - let (tokens, errors) = parse::parse_stream_from_source_str( + let (tokens, mut errors) = parse::parse_stream_from_source_str( FileName::proc_macro_source_code(src.clone()), src.to_string(), self.sess, Some(self.call_site), ); - emit_unclosed_delims(&errors, &self.sess.span_diagnostic); + emit_unclosed_delims(&mut errors, &self.sess.span_diagnostic); tokens } fn to_string(&mut self, stream: &Self::TokenStream) -> String { diff --git a/src/test/ui/parser-recovery-2.stderr b/src/test/ui/parser-recovery-2.stderr index 76f7af38e776d..92d8cbc100a03 100644 --- a/src/test/ui/parser-recovery-2.stderr +++ b/src/test/ui/parser-recovery-2.stderr @@ -1,9 +1,3 @@ -error: unexpected token: `;` - --> $DIR/parser-recovery-2.rs:12:15 - | -LL | let x = y.; //~ ERROR unexpected token - | ^ - error: incorrect close delimiter: `)` --> $DIR/parser-recovery-2.rs:8:5 | @@ -13,6 +7,12 @@ LL | let x = foo(); //~ ERROR cannot find function `foo` in this scope LL | ) //~ ERROR incorrect close delimiter: `)` | ^ incorrect close delimiter +error: unexpected token: `;` + --> $DIR/parser-recovery-2.rs:12:15 + | +LL | let x = y.; //~ ERROR unexpected token + | ^ + error[E0425]: cannot find function `foo` in this scope --> $DIR/parser-recovery-2.rs:7:17 | diff --git a/src/test/ui/resolve/token-error-correct-3.rs b/src/test/ui/resolve/token-error-correct-3.rs index b1ca0bbfc57c1..05bdbeacf72fe 100644 --- a/src/test/ui/resolve/token-error-correct-3.rs +++ b/src/test/ui/resolve/token-error-correct-3.rs @@ -10,16 +10,14 @@ pub mod raw { pub fn ensure_dir_exists, F: FnOnce(&Path)>(path: P, callback: F) -> io::Result { - if !is_directory(path.as_ref()) { //~ ERROR: cannot find function `is_directory` - callback(path.as_ref(); //~ ERROR expected one of - fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types - //~^ expected (), found enum `std::result::Result` - //~| expected type `()` - //~| found type `std::result::Result` - //~| expected one of + if !is_directory(path.as_ref()) { + //~^ ERROR cannot find function `is_directory` + callback(path.as_ref(); + //~^ ERROR expected one of + //~| ERROR this function takes 1 parameter but 2 parameters were supplied + fs::create_dir_all(path.as_ref()).map(|()| true) } else { - //~^ ERROR: expected one of - //~| unexpected token + //~^ ERROR incorrect close delimiter: `}` Ok(false); } diff --git a/src/test/ui/resolve/token-error-correct-3.stderr b/src/test/ui/resolve/token-error-correct-3.stderr index a6bb83c71f313..0f1cbd6c2f772 100644 --- a/src/test/ui/resolve/token-error-correct-3.stderr +++ b/src/test/ui/resolve/token-error-correct-3.stderr @@ -1,39 +1,38 @@ -error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;` - --> $DIR/token-error-correct-3.rs:14:35 - | -LL | callback(path.as_ref(); //~ ERROR expected one of - | - ^ - | | | - | | help: `)` may belong here - | unclosed delimiter - -error: expected one of `.`, `;`, `?`, `}`, or an operator, found `)` - --> $DIR/token-error-correct-3.rs:20:9 +error: incorrect close delimiter: `}` + --> $DIR/token-error-correct-3.rs:19:9 | -LL | fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types - | - expected one of `.`, `;`, `?`, `}`, or an operator here +LL | if !is_directory(path.as_ref()) { + | - close delimiter possibly meant for this +LL | //~^ ERROR cannot find function `is_directory` +LL | callback(path.as_ref(); + | - un-closed delimiter ... LL | } else { - | ^ unexpected token + | ^ incorrect close delimiter + +error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;` + --> $DIR/token-error-correct-3.rs:15:35 + | +LL | callback(path.as_ref(); + | ^ expected one of `)`, `,`, `.`, `?`, or an operator here error[E0425]: cannot find function `is_directory` in this scope --> $DIR/token-error-correct-3.rs:13:13 | -LL | if !is_directory(path.as_ref()) { //~ ERROR: cannot find function `is_directory` +LL | if !is_directory(path.as_ref()) { | ^^^^^^^^^^^^ not found in this scope -error[E0308]: mismatched types +error[E0057]: this function takes 1 parameter but 2 parameters were supplied --> $DIR/token-error-correct-3.rs:15:13 | -LL | fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try adding a semicolon: `;` - | | - | expected (), found enum `std::result::Result` - | - = note: expected type `()` - found type `std::result::Result` +LL | / callback(path.as_ref(); +LL | | //~^ ERROR expected one of +LL | | //~| ERROR this function takes 1 parameter but 2 parameters were supplied +LL | | fs::create_dir_all(path.as_ref()).map(|()| true) +LL | | } else { + | |_________^ expected 1 parameter error: aborting due to 4 previous errors -Some errors occurred: E0308, E0425. -For more information about an error, try `rustc --explain E0308`. +Some errors occurred: E0057, E0425. +For more information about an error, try `rustc --explain E0057`. From ac6cc2d6b0aad0b1cc97f1db6d8e9d4f117eca95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 3 Mar 2019 12:45:49 -0800 Subject: [PATCH 07/11] Collect unclosed delimiters in parent parser --- src/libsyntax/parse/parser.rs | 17 +++++-- src/test/ui/parser-recovery-2.stderr | 12 ++--- src/test/ui/resolve/token-error-correct-3.rs | 4 +- .../ui/resolve/token-error-correct-3.stderr | 47 ++++++++++--------- 4 files changed, 45 insertions(+), 35 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index bde14e192e96b..348c26d2044b9 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1510,9 +1510,13 @@ impl<'a> Parser<'a> { pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, TraitItem> { maybe_whole!(self, NtTraitItem, |x| x); let attrs = self.parse_outer_attributes()?; + let mut unclosed_delims = vec![]; let (mut item, tokens) = self.collect_tokens(|this| { - this.parse_trait_item_(at_end, attrs) + let item = this.parse_trait_item_(at_end, attrs); + unclosed_delims.append(&mut this.unclosed_delims); + item })?; + self.unclosed_delims.append(&mut unclosed_delims); // See `parse_item` for why this clause is here. if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) { item.tokens = Some(tokens); @@ -6475,9 +6479,13 @@ impl<'a> Parser<'a> { pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, ImplItem> { maybe_whole!(self, NtImplItem, |x| x); let attrs = self.parse_outer_attributes()?; + let mut unclosed_delims = vec![]; let (mut item, tokens) = self.collect_tokens(|this| { - this.parse_impl_item_(at_end, attrs) + let item = this.parse_impl_item_(at_end, attrs); + unclosed_delims.append(&mut this.unclosed_delims); + item })?; + self.unclosed_delims.append(&mut unclosed_delims); // See `parse_item` for why this clause is here. if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) { @@ -7797,12 +7805,13 @@ impl<'a> Parser<'a> { macros_allowed: bool, attributes_allowed: bool, ) -> PResult<'a, Option>> { + let mut unclosed_delims = vec![]; let (ret, tokens) = self.collect_tokens(|this| { let item = this.parse_item_implementation(attrs, macros_allowed, attributes_allowed); - let diag = this.diagnostic(); - emit_unclosed_delims(&mut this.unclosed_delims, diag); + unclosed_delims.append(&mut this.unclosed_delims); item })?; + self.unclosed_delims.append(&mut unclosed_delims); // Once we've parsed an item and recorded the tokens we got while // parsing we may want to store `tokens` into the item we're about to diff --git a/src/test/ui/parser-recovery-2.stderr b/src/test/ui/parser-recovery-2.stderr index 92d8cbc100a03..76f7af38e776d 100644 --- a/src/test/ui/parser-recovery-2.stderr +++ b/src/test/ui/parser-recovery-2.stderr @@ -1,3 +1,9 @@ +error: unexpected token: `;` + --> $DIR/parser-recovery-2.rs:12:15 + | +LL | let x = y.; //~ ERROR unexpected token + | ^ + error: incorrect close delimiter: `)` --> $DIR/parser-recovery-2.rs:8:5 | @@ -7,12 +13,6 @@ LL | let x = foo(); //~ ERROR cannot find function `foo` in this scope LL | ) //~ ERROR incorrect close delimiter: `)` | ^ incorrect close delimiter -error: unexpected token: `;` - --> $DIR/parser-recovery-2.rs:12:15 - | -LL | let x = y.; //~ ERROR unexpected token - | ^ - error[E0425]: cannot find function `foo` in this scope --> $DIR/parser-recovery-2.rs:7:17 | diff --git a/src/test/ui/resolve/token-error-correct-3.rs b/src/test/ui/resolve/token-error-correct-3.rs index 05bdbeacf72fe..212b88ac8b05f 100644 --- a/src/test/ui/resolve/token-error-correct-3.rs +++ b/src/test/ui/resolve/token-error-correct-3.rs @@ -14,10 +14,10 @@ pub mod raw { //~^ ERROR cannot find function `is_directory` callback(path.as_ref(); //~^ ERROR expected one of - //~| ERROR this function takes 1 parameter but 2 parameters were supplied fs::create_dir_all(path.as_ref()).map(|()| true) + //~^ ERROR mismatched types } else { - //~^ ERROR incorrect close delimiter: `}` + //~^ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `)` Ok(false); } diff --git a/src/test/ui/resolve/token-error-correct-3.stderr b/src/test/ui/resolve/token-error-correct-3.stderr index 0f1cbd6c2f772..035a5ede45384 100644 --- a/src/test/ui/resolve/token-error-correct-3.stderr +++ b/src/test/ui/resolve/token-error-correct-3.stderr @@ -1,20 +1,20 @@ -error: incorrect close delimiter: `}` - --> $DIR/token-error-correct-3.rs:19:9 - | -LL | if !is_directory(path.as_ref()) { - | - close delimiter possibly meant for this -LL | //~^ ERROR cannot find function `is_directory` -LL | callback(path.as_ref(); - | - un-closed delimiter -... -LL | } else { - | ^ incorrect close delimiter - error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;` --> $DIR/token-error-correct-3.rs:15:35 | LL | callback(path.as_ref(); - | ^ expected one of `)`, `,`, `.`, `?`, or an operator here + | - ^ + | | | + | | help: `)` may belong here + | unclosed delimiter + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `)` + --> $DIR/token-error-correct-3.rs:19:9 + | +LL | fs::create_dir_all(path.as_ref()).map(|()| true) + | - expected one of `.`, `;`, `?`, `}`, or an operator here +LL | //~^ ERROR mismatched types +LL | } else { + | ^ unexpected token error[E0425]: cannot find function `is_directory` in this scope --> $DIR/token-error-correct-3.rs:13:13 @@ -22,17 +22,18 @@ error[E0425]: cannot find function `is_directory` in this scope LL | if !is_directory(path.as_ref()) { | ^^^^^^^^^^^^ not found in this scope -error[E0057]: this function takes 1 parameter but 2 parameters were supplied - --> $DIR/token-error-correct-3.rs:15:13 +error[E0308]: mismatched types + --> $DIR/token-error-correct-3.rs:17:13 + | +LL | fs::create_dir_all(path.as_ref()).map(|()| true) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try adding a semicolon: `;` + | | + | expected (), found enum `std::result::Result` | -LL | / callback(path.as_ref(); -LL | | //~^ ERROR expected one of -LL | | //~| ERROR this function takes 1 parameter but 2 parameters were supplied -LL | | fs::create_dir_all(path.as_ref()).map(|()| true) -LL | | } else { - | |_________^ expected 1 parameter + = note: expected type `()` + found type `std::result::Result` error: aborting due to 4 previous errors -Some errors occurred: E0057, E0425. -For more information about an error, try `rustc --explain E0057`. +Some errors occurred: E0308, E0425. +For more information about an error, try `rustc --explain E0308`. From f156d9220703d99709be32ea1be0be0d44535114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 3 Mar 2019 14:11:41 -0800 Subject: [PATCH 08/11] Always emit mismatched delim errors, never panic --- src/libsyntax/parse/parser.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 348c26d2044b9..860964a736f5e 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -262,7 +262,8 @@ pub struct Parser<'a> { impl<'a> Drop for Parser<'a> { fn drop(&mut self) { if !self.unclosed_delims.is_empty() { - panic!("unclosed delimiter errors not emitted"); + let diag = self.diagnostic(); + emit_unclosed_delims(&mut self.unclosed_delims, diag); } } } @@ -8567,8 +8568,6 @@ impl<'a> Parser<'a> { module: self.parse_mod_items(&token::Eof, lo)?, span: lo.to(self.span), }); - let diag = self.diagnostic(); - emit_unclosed_delims(&mut self.unclosed_delims, diag); krate } From 3818f8ba340de08f863b1c431fdf27f767dfca8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 3 Mar 2019 16:59:24 -0800 Subject: [PATCH 09/11] Add regression test for #58886 --- .../ui/parser/unclosed-delimiter-in-dep.rs | 6 +++++ .../parser/unclosed-delimiter-in-dep.stderr | 23 +++++++++++++++++++ src/test/ui/parser/unclosed_delim_mod.rs | 6 +++++ src/test/ui/parser/unclosed_delim_mod.stderr | 18 +++++++++++++++ 4 files changed, 53 insertions(+) create mode 100644 src/test/ui/parser/unclosed-delimiter-in-dep.rs create mode 100644 src/test/ui/parser/unclosed-delimiter-in-dep.stderr create mode 100644 src/test/ui/parser/unclosed_delim_mod.rs create mode 100644 src/test/ui/parser/unclosed_delim_mod.stderr diff --git a/src/test/ui/parser/unclosed-delimiter-in-dep.rs b/src/test/ui/parser/unclosed-delimiter-in-dep.rs new file mode 100644 index 0000000000000..6db1b66e9f785 --- /dev/null +++ b/src/test/ui/parser/unclosed-delimiter-in-dep.rs @@ -0,0 +1,6 @@ +mod unclosed_delim_mod; + +fn main() { + let _: usize = unclosed_delim_mod::new(); + //~^ ERROR mismatched types +} diff --git a/src/test/ui/parser/unclosed-delimiter-in-dep.stderr b/src/test/ui/parser/unclosed-delimiter-in-dep.stderr new file mode 100644 index 0000000000000..633c63bea9105 --- /dev/null +++ b/src/test/ui/parser/unclosed-delimiter-in-dep.stderr @@ -0,0 +1,23 @@ +error: incorrect close delimiter: `}` + --> $DIR/unclosed_delim_mod.rs:5:1 + | +LL | pub fn new() -> Result { + | - close delimiter possibly meant for this +LL | Ok(Value { + | - un-closed delimiter +LL | } +LL | } + | ^ incorrect close delimiter + +error[E0308]: mismatched types + --> $DIR/unclosed-delimiter-in-dep.rs:4:20 + | +LL | let _: usize = unclosed_delim_mod::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected usize, found enum `std::result::Result` + | + = note: expected type `usize` + found type `std::result::Result` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/unclosed_delim_mod.rs b/src/test/ui/parser/unclosed_delim_mod.rs new file mode 100644 index 0000000000000..b1664f49dc591 --- /dev/null +++ b/src/test/ui/parser/unclosed_delim_mod.rs @@ -0,0 +1,6 @@ +pub struct Value {} +pub fn new() -> Result { + Ok(Value { + } +} +//~^ ERROR incorrect close delimiter diff --git a/src/test/ui/parser/unclosed_delim_mod.stderr b/src/test/ui/parser/unclosed_delim_mod.stderr new file mode 100644 index 0000000000000..cc04eb531cbea --- /dev/null +++ b/src/test/ui/parser/unclosed_delim_mod.stderr @@ -0,0 +1,18 @@ +error: incorrect close delimiter: `}` + --> $DIR/unclosed_delim_mod.rs:5:1 + | +LL | pub fn new() -> Result { + | - close delimiter possibly meant for this +LL | Ok(Value { + | - un-closed delimiter +LL | } +LL | } + | ^ incorrect close delimiter + +error[E0601]: `main` function not found in crate `unclosed_delim_mod` + | + = note: consider adding a `main` function to `$DIR/unclosed_delim_mod.rs` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0601`. From 6f0f2fc6d6ca0800c8b8b95932010d51af4e4663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 4 Mar 2019 12:59:43 -0800 Subject: [PATCH 10/11] Simplify code --- src/libsyntax/parse/mod.rs | 11 +++++++++-- src/libsyntax/parse/parser.rs | 6 ++---- src/libsyntax/parse/token.rs | 21 +++------------------ src/libsyntax_ext/proc_macro_server.rs | 7 ++----- 4 files changed, 16 insertions(+), 29 deletions(-) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index b2d4d97d57d89..6583458b44694 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -6,6 +6,7 @@ use crate::source_map::{SourceMap, FilePathMapping}; use crate::feature_gate::UnstableFeatures; use crate::parse::parser::Parser; use crate::symbol::Symbol; +use crate::syntax::parse::parser::emit_unclosed_delims; use crate::tokenstream::{TokenStream, TokenTree}; use crate::diagnostics::plugin::ErrorMap; use crate::print::pprust::token_to_string; @@ -141,8 +142,14 @@ pub fn parse_stream_from_source_str( source: String, sess: &ParseSess, override_span: Option, -) -> (TokenStream, Vec) { - source_file_to_stream(sess, sess.source_map().new_source_file(name, source), override_span) +) -> TokenStream { + let (stream, mut errors) = source_file_to_stream( + sess, + sess.source_map().new_source_file(name, source), + override_span, + ); + emit_unclosed_delims(&mut errors, &sess.span_diagnostic); + stream } /// Creates a new parser from a source string. diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 860964a736f5e..58c1c5006bbf4 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -261,10 +261,8 @@ pub struct Parser<'a> { impl<'a> Drop for Parser<'a> { fn drop(&mut self) { - if !self.unclosed_delims.is_empty() { - let diag = self.diagnostic(); - emit_unclosed_delims(&mut self.unclosed_delims, diag); - } + let diag = self.diagnostic(); + emit_unclosed_delims(&mut self.unclosed_delims, diag); } } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index bb4da12bae893..2fa4f5263fbc5 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -10,7 +10,6 @@ use crate::print::pprust; use crate::ptr::P; use crate::symbol::keywords; use crate::syntax::parse::parse_stream_from_source_str; -use crate::syntax::parse::parser::emit_unclosed_delims; use crate::tokenstream::{self, DelimSpan, TokenStream, TokenTree}; use syntax_pos::symbol::{self, Symbol}; @@ -675,9 +674,7 @@ impl Nonterminal { // FIXME(#43081): Avoid this pretty-print + reparse hack let source = pprust::nonterminal_to_string(self); let filename = FileName::macro_expansion_source_code(&source); - let (tokens_for_real, mut errors) = - parse_stream_from_source_str(filename, source, sess, Some(span)); - emit_unclosed_delims(&mut errors, &sess.span_diagnostic); + let tokens_for_real = parse_stream_from_source_str(filename, source, sess, Some(span)); // During early phases of the compiler the AST could get modified // directly (e.g., attributes added or removed) and the internal cache @@ -740,13 +737,7 @@ fn prepend_attrs(sess: &ParseSess, let source = pprust::attr_to_string(attr); let macro_filename = FileName::macro_expansion_source_code(&source); if attr.is_sugared_doc { - let (stream, mut errors) = parse_stream_from_source_str( - macro_filename, - source, - sess, - Some(span), - ); - emit_unclosed_delims(&mut errors, &sess.span_diagnostic); + let stream = parse_stream_from_source_str(macro_filename, source, sess, Some(span)); builder.push(stream); continue } @@ -763,13 +754,7 @@ fn prepend_attrs(sess: &ParseSess, // ... and for more complicated paths, fall back to a reparse hack that // should eventually be removed. } else { - let (stream, mut errors) = parse_stream_from_source_str( - macro_filename, - source, - sess, - Some(span), - ); - emit_unclosed_delims(&mut errors, &sess.span_diagnostic); + let stream = parse_stream_from_source_str(macro_filename, source, sess, Some(span)); brackets.push(stream); } diff --git a/src/libsyntax_ext/proc_macro_server.rs b/src/libsyntax_ext/proc_macro_server.rs index 5822b5607f7df..a7ac95ba9ef50 100644 --- a/src/libsyntax_ext/proc_macro_server.rs +++ b/src/libsyntax_ext/proc_macro_server.rs @@ -12,7 +12,6 @@ use syntax::ast; use syntax::ext::base::ExtCtxt; use syntax::parse::lexer::comments; use syntax::parse::{self, token, ParseSess}; -use syntax::parse::parser::emit_unclosed_delims; use syntax::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint}; use syntax_pos::hygiene::{SyntaxContext, Transparency}; use syntax_pos::symbol::{keywords, Symbol}; @@ -410,14 +409,12 @@ impl server::TokenStream for Rustc<'_> { stream.is_empty() } fn from_str(&mut self, src: &str) -> Self::TokenStream { - let (tokens, mut errors) = parse::parse_stream_from_source_str( + parse::parse_stream_from_source_str( FileName::proc_macro_source_code(src.clone()), src.to_string(), self.sess, Some(self.call_site), - ); - emit_unclosed_delims(&mut errors, &self.sess.span_diagnostic); - tokens + ) } fn to_string(&mut self, stream: &Self::TokenStream) -> String { stream.to_string() From 551ea65c87ef567cb22856a769df2a75f2cbb235 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 6 Mar 2019 19:09:24 -0800 Subject: [PATCH 11/11] Rely on drop to emit unclosed delims --- src/libsyntax/parse/parser.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 58c1c5006bbf4..7e63da2704996 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -784,7 +784,6 @@ impl<'a> Parser<'a> { // leave it in the input Ok(false) } else if self.last_unexpected_token_span == Some(self.span) { - emit_unclosed_delims(&self.unclosed_delims, self.diagnostic()); FatalError.raise(); } else { let mut expected = edible.iter()