diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index de187a3f5e0dc..c5f830c0d0420 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -424,7 +424,7 @@ impl cstore::CStore { let source_file = sess.parse_sess.source_map().new_source_file(source_name, def.body); let local_span = Span::with_root_ctxt(source_file.start_pos, source_file.end_pos); let (body, mut errors) = source_file_to_stream(&sess.parse_sess, source_file, None); - emit_unclosed_delims(&mut errors, &sess.diagnostic()); + emit_unclosed_delims(&mut errors, &sess.parse_sess); // Mark the attrs as used let attrs = data.get_item_attrs(id.index, sess); diff --git a/src/librustc_passes/entry.rs b/src/librustc_passes/entry.rs index bf68807a0c29b..660047190608d 100644 --- a/src/librustc_passes/entry.rs +++ b/src/librustc_passes/entry.rs @@ -154,6 +154,14 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(De } fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) { + let sp = tcx.hir().krate().span; + if *tcx.sess.parse_sess.reached_eof.borrow() { + // There's an unclosed brace that made the parser reach `Eof`, we shouldn't complain about + // the missing `fn main()` then as it might have been hidden inside an unclosed block. + tcx.sess.delay_span_bug(sp, "`main` not found, but expected unclosed brace error"); + return; + } + // There is no main function. let mut err = struct_err!(tcx.sess, E0601, "`main` function not found in crate `{}`", tcx.crate_name(LOCAL_CRATE)); @@ -173,7 +181,6 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) { } else { String::from("consider adding a `main` function at the crate level") }; - let sp = tcx.hir().krate().span; // The file may be empty, which leads to the diagnostic machinery not emitting this // note. This is a relatively simple way to detect that case and emit a span-less // note instead. diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index e6dc9a4c13417..48cf117f65ae6 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -23,7 +23,7 @@ mod unicode_chars; #[derive(Clone, Debug)] pub struct UnmatchedBrace { pub expected_delim: token::DelimToken, - pub found_delim: token::DelimToken, + pub found_delim: Option, pub found_span: Span, pub unclosed_span: Option, pub candidate_span: Option, diff --git a/src/libsyntax/parse/lexer/tokentrees.rs b/src/libsyntax/parse/lexer/tokentrees.rs index 853723de14f44..de8ac2c71e818 100644 --- a/src/libsyntax/parse/lexer/tokentrees.rs +++ b/src/libsyntax/parse/lexer/tokentrees.rs @@ -80,6 +80,13 @@ impl<'a> TokenTreesReader<'a> { .struct_span_err(self.token.span, msg); for &(_, sp) in &self.open_braces { err.span_label(sp, "un-closed delimiter"); + self.unmatched_braces.push(UnmatchedBrace { + expected_delim: token::DelimToken::Brace, + found_delim: None, + found_span: self.token.span, + unclosed_span: Some(sp), + candidate_span: None, + }); } if let Some((delim, _)) = self.open_braces.last() { @@ -170,7 +177,7 @@ impl<'a> TokenTreesReader<'a> { let (tok, _) = self.open_braces.pop().unwrap(); self.unmatched_braces.push(UnmatchedBrace { expected_delim: tok, - found_delim: other, + found_delim: Some(other), found_span: self.token.span, unclosed_span: unclosed_delimiter, candidate_span: candidate, diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index f5e416b722bbf..6d8ecdf805b01 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -1,7 +1,7 @@ //! The main parser interface. use crate::ast; -use crate::parse::parser::{Parser, emit_unclosed_delims}; +use crate::parse::parser::{Parser, emit_unclosed_delims, make_unclosed_delims_error}; use crate::parse::token::Nonterminal; use crate::tokenstream::{self, TokenStream, TokenTree}; use crate::print::pprust; @@ -108,7 +108,7 @@ pub fn parse_stream_from_source_str( sess.source_map().new_source_file(name, source), override_span, ); - emit_unclosed_delims(&mut errors, &sess.span_diagnostic); + emit_unclosed_delims(&mut errors, &sess); stream } @@ -242,18 +242,9 @@ pub fn maybe_file_to_stream( err.buffer(&mut buffer); // Not using `emit_unclosed_delims` to use `db.buffer` for unmatched in unmatched_braces { - let mut db = sess.span_diagnostic.struct_span_err(unmatched.found_span, &format!( - "incorrect close delimiter: `{}`", - pprust::token_kind_to_string(&token::CloseDelim(unmatched.found_delim)), - )); - db.span_label(unmatched.found_span, "incorrect close delimiter"); - if let Some(sp) = unmatched.candidate_span { - db.span_label(sp, "close delimiter possibly meant for this"); + if let Some(err) = make_unclosed_delims_error(unmatched, &sess) { + err.buffer(&mut buffer); } - if let Some(sp) = unmatched.unclosed_span { - db.span_label(sp, "un-closed delimiter"); - } - db.buffer(&mut buffer); } Err(buffer) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 6ead1ce811d49..e81d4573b73e5 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -27,7 +27,7 @@ use crate::symbol::{kw, sym, Symbol}; use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint}; use crate::ThinVec; -use errors::{Applicability, DiagnosticId, FatalError}; +use errors::{Applicability, DiagnosticBuilder, DiagnosticId, FatalError}; use rustc_target::spec::abi::{self, Abi}; use syntax_pos::{Span, BytePos, DUMMY_SP, FileName}; use log::debug; @@ -148,8 +148,7 @@ pub struct Parser<'a> { impl<'a> Drop for Parser<'a> { fn drop(&mut self) { - let diag = self.diagnostic(); - emit_unclosed_delims(&mut self.unclosed_delims, diag); + emit_unclosed_delims(&mut self.unclosed_delims, &self.sess); } } @@ -1370,20 +1369,31 @@ impl<'a> Parser<'a> { } } -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_kind_to_string(&token::CloseDelim(unmatched.found_delim)), - )); - err.span_label(unmatched.found_span, "incorrect close delimiter"); - if let Some(sp) = unmatched.candidate_span { - err.span_label(sp, "close delimiter possibly meant for this"); - } - if let Some(sp) = unmatched.unclosed_span { - err.span_label(sp, "un-closed delimiter"); - } - err.emit(); +crate fn make_unclosed_delims_error( + unmatched: UnmatchedBrace, + sess: &ParseSess, +) -> Option> { + // `None` here means an `Eof` was found. We already emit those errors elsewhere, we add them to + // `unmatched_braces` only for error recovery in the `Parser`. + let found_delim = unmatched.found_delim?; + let mut err = sess.span_diagnostic.struct_span_err(unmatched.found_span, &format!( + "incorrect close delimiter: `{}`", + pprust::token_kind_to_string(&token::CloseDelim(found_delim)), + )); + err.span_label(unmatched.found_span, "incorrect close delimiter"); + if let Some(sp) = unmatched.candidate_span { + err.span_label(sp, "close delimiter possibly meant for this"); + } + if let Some(sp) = unmatched.unclosed_span { + err.span_label(sp, "un-closed delimiter"); + } + Some(err) +} + +pub fn emit_unclosed_delims(unclosed_delims: &mut Vec, sess: &ParseSess) { + *sess.reached_eof.borrow_mut() |= unclosed_delims.iter() + .any(|unmatched_delim| unmatched_delim.found_delim.is_none()); + for unmatched in unclosed_delims.drain(..) { + make_unclosed_delims_error(unmatched, sess).map(|mut e| e.emit()); } - unclosed_delims.clear(); } diff --git a/src/libsyntax/parse/parser/diagnostics.rs b/src/libsyntax/parse/parser/diagnostics.rs index ab2b4519cb72a..fcf3b4c0aa891 100644 --- a/src/libsyntax/parse/parser/diagnostics.rs +++ b/src/libsyntax/parse/parser/diagnostics.rs @@ -171,6 +171,12 @@ impl RecoverQPath for Expr { } } +/// Control whether the closing delimiter should be consumed when calling `Parser::consume_block`. +crate enum ConsumeClosingDelim { + Yes, + No, +} + impl<'a> Parser<'a> { pub fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> { self.span_fatal(self.token.span, m) @@ -1105,8 +1111,8 @@ impl<'a> Parser<'a> { Ok(x) => x, Err(mut err) => { err.emit(); - // Recover from parse error. - self.consume_block(delim); + // Recover from parse error, callers expect the closing delim to be consumed. + self.consume_block(delim, ConsumeClosingDelim::Yes); self.mk_expr(lo.to(self.prev_span), ExprKind::Err, ThinVec::new()) } } @@ -1135,6 +1141,11 @@ impl<'a> Parser<'a> { // Don't attempt to recover from this unclosed delimiter more than once. let unmatched = self.unclosed_delims.remove(pos); let delim = TokenType::Token(token::CloseDelim(unmatched.expected_delim)); + if unmatched.found_delim.is_none() { + // We encountered `Eof`, set this fact here to avoid complaining about missing + // `fn main()` when we found place to suggest the closing brace. + *self.sess.reached_eof.borrow_mut() = true; + } // We want to suggest the inclusion of the closing delimiter where it makes // the most sense, which is immediately after the last token: @@ -1154,9 +1165,16 @@ impl<'a> Parser<'a> { delim.to_string(), Applicability::MaybeIncorrect, ); - err.emit(); - self.expected_tokens.clear(); // reduce errors - Ok(true) + if unmatched.found_delim.is_none() { + // Encountered `Eof` when lexing blocks. Do not recover here to avoid knockdown + // errors which would be emitted elsewhere in the parser and let other error + // recovery consume the rest of the file. + Err(err) + } else { + err.emit(); + self.expected_tokens.clear(); // Reduce the number of errors. + Ok(true) + } } _ => Err(err), } @@ -1164,7 +1182,12 @@ impl<'a> Parser<'a> { /// Recovers from `pub` keyword in places where it seems _reasonable_ but isn't valid. pub(super) fn eat_bad_pub(&mut self) { - if self.token.is_keyword(kw::Pub) { + // When `unclosed_delims` is populated, it means that the code being parsed is already + // quite malformed, which might mean that, for example, a pub struct definition could be + // parsed as being a trait item, which is invalid and this error would trigger + // unconditionally, resulting in misleading diagnostics. Because of this, we only attempt + // this nice to have recovery for code that is otherwise well formed. + if self.token.is_keyword(kw::Pub) && self.unclosed_delims.is_empty() { match self.parse_visibility(false) { Ok(vis) => { self.diagnostic() @@ -1422,15 +1445,26 @@ impl<'a> Parser<'a> { Ok(param) } - pub(super) fn consume_block(&mut self, delim: token::DelimToken) { + pub(super) fn consume_block( + &mut self, + delim: token::DelimToken, + consume_close: ConsumeClosingDelim, + ) { let mut brace_depth = 0; loop { if self.eat(&token::OpenDelim(delim)) { brace_depth += 1; - } else if self.eat(&token::CloseDelim(delim)) { + } else if self.check(&token::CloseDelim(delim)) { if brace_depth == 0 { + if let ConsumeClosingDelim::Yes = consume_close { + // Some of the callers of this method expect to be able to parse the + // closing delimiter themselves, so we leave it alone. Otherwise we advance + // the parser. + self.bump(); + } return; } else { + self.bump(); brace_depth -= 1; continue; } diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index fe12533619033..5b60e7e6dba05 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -1,5 +1,5 @@ -use super::{Parser, PResult, PathStyle, SemiColonMode, BlockMode}; -use super::diagnostics::{Error, dummy_arg}; +use super::{Parser, PResult, PathStyle}; +use super::diagnostics::{Error, dummy_arg, ConsumeClosingDelim}; use crate::maybe_whole; use crate::ptr::P; @@ -339,7 +339,7 @@ impl<'a> Parser<'a> { let ident = self.parse_ident().unwrap(); self.bump(); // `(` let kw_name = self.recover_first_param(); - self.consume_block(token::Paren); + self.consume_block(token::Paren, ConsumeClosingDelim::Yes); let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) { self.eat_to_tokens(&[&token::OpenDelim(token::Brace)]); self.bump(); // `{` @@ -357,7 +357,7 @@ impl<'a> Parser<'a> { let msg = format!("missing `{}` for {} definition", kw, kw_name); let mut err = self.diagnostic().struct_span_err(sp, &msg); if !ambiguous { - self.consume_block(token::Brace); + self.consume_block(token::Brace, ConsumeClosingDelim::Yes); let suggestion = format!("add `{}` here to parse `{}` as a public {}", kw, ident, @@ -672,7 +672,8 @@ impl<'a> Parser<'a> { Err(mut err) => { err.emit(); if !at_end { - self.recover_stmt_(SemiColonMode::Break, BlockMode::Break); + self.consume_block(token::Brace, ConsumeClosingDelim::Yes); + break; } } } @@ -861,7 +862,8 @@ impl<'a> Parser<'a> { Err(mut e) => { e.emit(); if !at_end { - self.recover_stmt_(SemiColonMode::Break, BlockMode::Break); + self.consume_block(token::Brace, ConsumeClosingDelim::Yes); + break; } } } @@ -1520,7 +1522,7 @@ impl<'a> Parser<'a> { if self.eat(&token::OpenDelim(token::Brace)) { while self.token != token::CloseDelim(token::Brace) { let field = self.parse_struct_decl_field().map_err(|e| { - self.recover_stmt(); + self.consume_block(token::Brace, ConsumeClosingDelim::No); recovered = true; e }); @@ -1528,6 +1530,7 @@ impl<'a> Parser<'a> { Ok(field) => fields.push(field), Err(mut err) => { err.emit(); + break; } } } diff --git a/src/libsyntax/sess.rs b/src/libsyntax/sess.rs index 28a0868d5dd1e..323fe01f067ef 100644 --- a/src/libsyntax/sess.rs +++ b/src/libsyntax/sess.rs @@ -73,6 +73,8 @@ pub struct ParseSess { pub ambiguous_block_expr_parse: Lock>, pub injected_crate_name: Once, crate gated_spans: GatedSpans, + /// The parser has reached `Eof` due to an unclosed brace. Used to silence unnecessary errors. + pub reached_eof: Lock, } impl ParseSess { @@ -101,6 +103,7 @@ impl ParseSess { ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), injected_crate_name: Once::new(), gated_spans: GatedSpans::default(), + reached_eof: Lock::new(false), } } diff --git a/src/test/ui/did_you_mean/issue-40006.rs b/src/test/ui/did_you_mean/issue-40006.rs index a1184f757e2ab..b3c1f60b7ebf6 100644 --- a/src/test/ui/did_you_mean/issue-40006.rs +++ b/src/test/ui/did_you_mean/issue-40006.rs @@ -1,5 +1,4 @@ -impl dyn X { //~ ERROR cannot be made into an object -//~^ ERROR missing +impl dyn A { //~ ERROR missing Y } @@ -7,10 +6,25 @@ struct S; trait X { //~ ERROR missing X() {} - fn xxx() { ### } //~ ERROR missing - //~^ ERROR expected - L = M; //~ ERROR missing - Z = { 2 + 3 }; //~ ERROR expected one of + fn xxx() { ### } + L = M; + Z = { 2 + 3 }; + ::Y (); +} + +trait A { //~ ERROR missing + X() {} +} +trait B { + fn xxx() { ### } //~ ERROR expected +} +trait C { //~ ERROR missing `fn`, `type`, or `const` for trait-item declaration + L = M; +} +trait D { //~ ERROR missing `fn`, `type`, or `const` for trait-item declaration + Z = { 2 + 3 }; +} +trait E { ::Y (); //~ ERROR expected one of } @@ -21,5 +35,5 @@ impl S { } fn main() { - S.hello_method(); + S.hello_method(); //~ no method named `hello_method` found for type `S` in the current scope } diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index 5b384045a486a..f0baa175d63b7 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -1,70 +1,70 @@ error: missing `fn`, `type`, or `const` for impl-item declaration --> $DIR/issue-40006.rs:1:13 | -LL | impl dyn X { +LL | impl dyn A { | _____________^ -LL | | LL | | Y | |____^ missing `fn`, `type`, or `const` error: missing `fn`, `type`, or `const` for trait-item declaration - --> $DIR/issue-40006.rs:8:10 + --> $DIR/issue-40006.rs:7:10 | LL | trait X { | __________^ LL | | X() {} | |____^ missing `fn`, `type`, or `const` +error: missing `fn`, `type`, or `const` for trait-item declaration + --> $DIR/issue-40006.rs:15:10 + | +LL | trait A { + | __________^ +LL | | X() {} + | |____^ missing `fn`, `type`, or `const` + error: expected `[`, found `#` - --> $DIR/issue-40006.rs:10:17 + --> $DIR/issue-40006.rs:19:17 | LL | fn xxx() { ### } | ^ expected `[` error: missing `fn`, `type`, or `const` for trait-item declaration - --> $DIR/issue-40006.rs:10:21 + --> $DIR/issue-40006.rs:21:10 | -LL | fn xxx() { ### } - | _____________________^ -LL | | +LL | trait C { + | __________^ LL | | L = M; | |____^ missing `fn`, `type`, or `const` error: missing `fn`, `type`, or `const` for trait-item declaration - --> $DIR/issue-40006.rs:12:11 + --> $DIR/issue-40006.rs:24:10 | -LL | L = M; - | ___________^ +LL | trait D { + | __________^ LL | | Z = { 2 + 3 }; | |____^ missing `fn`, `type`, or `const` -error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `;` - --> $DIR/issue-40006.rs:13:18 - | -LL | Z = { 2 + 3 }; - | ^ expected one of 7 possible tokens here - error: expected one of `!` or `::`, found `(` - --> $DIR/issue-40006.rs:14:9 + --> $DIR/issue-40006.rs:28:9 | LL | ::Y (); | ^ expected one of `!` or `::` here error: missing `fn`, `type`, or `const` for impl-item declaration - --> $DIR/issue-40006.rs:18:8 + --> $DIR/issue-40006.rs:32:8 | LL | pub hello_method(&self) { | ^ missing `fn`, `type`, or `const` -error[E0038]: the trait `X` cannot be made into an object - --> $DIR/issue-40006.rs:1:6 +error[E0599]: no method named `hello_method` found for type `S` in the current scope + --> $DIR/issue-40006.rs:38:7 | -LL | impl dyn X { - | ^^^^^ the trait `X` cannot be made into an object +LL | struct S; + | --------- method `hello_method` not found for this ... -LL | fn xxx() { ### } - | --- associated function `xxx` has no `self` parameter +LL | S.hello_method(); + | ^^^^^^^^^^^^ method not found in `S` error: aborting due to 9 previous errors -For more information about this error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-60075.rs b/src/test/ui/issues/issue-60075.rs index 5788716a52629..1f53a92793236 100644 --- a/src/test/ui/issues/issue-60075.rs +++ b/src/test/ui/issues/issue-60075.rs @@ -5,8 +5,7 @@ trait T { let _ = if true { }); //~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `;` -//~^^ ERROR expected one of `.`, `;`, `?`, `else`, or an operator, found `}` -//~^^^ ERROR 6:11: 6:12: expected identifier, found `;` -//~^^^^ ERROR missing `fn`, `type`, or `const` for trait-item declaration +//~| ERROR expected one of `.`, `;`, `?`, `else`, or an operator, found `}` +//~| ERROR expected identifier, found `;` Some(4) } diff --git a/src/test/ui/issues/issue-60075.stderr b/src/test/ui/issues/issue-60075.stderr index ac97d32a6e15b..961a546d8d620 100644 --- a/src/test/ui/issues/issue-60075.stderr +++ b/src/test/ui/issues/issue-60075.stderr @@ -19,17 +19,5 @@ error: expected identifier, found `;` LL | }); | ^ expected identifier -error: missing `fn`, `type`, or `const` for trait-item declaration - --> $DIR/issue-60075.rs:6:12 - | -LL | }); - | ____________^ -LL | | -LL | | -LL | | -LL | | -LL | | Some(4) - | |________^ missing `fn`, `type`, or `const` - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors diff --git a/src/test/ui/parser-recovery-1.rs b/src/test/ui/parser-recovery-1.rs index 8126525c34f95..21d36048e6703 100644 --- a/src/test/ui/parser-recovery-1.rs +++ b/src/test/ui/parser-recovery-1.rs @@ -3,7 +3,6 @@ // Test that we can recover from missing braces in the parser. trait Foo { -//~^ ERROR `main` function not found fn bar() { let x = foo(); //~^ ERROR cannot find function `foo` in this scope diff --git a/src/test/ui/parser-recovery-1.stderr b/src/test/ui/parser-recovery-1.stderr index ffe2b3322fc81..83f8ef63c9954 100644 --- a/src/test/ui/parser-recovery-1.stderr +++ b/src/test/ui/parser-recovery-1.stderr @@ -1,9 +1,8 @@ error: this file contains an un-closed delimiter - --> $DIR/parser-recovery-1.rs:16:55 + --> $DIR/parser-recovery-1.rs:15:55 | LL | trait Foo { | - un-closed delimiter -LL | LL | fn bar() { | - this delimiter might not be properly closed... ... @@ -14,36 +13,23 @@ LL | } | ^ error: unexpected token: `;` - --> $DIR/parser-recovery-1.rs:13:15 + --> $DIR/parser-recovery-1.rs:12:15 | LL | let x = y.; | ^ error[E0425]: cannot find function `foo` in this scope - --> $DIR/parser-recovery-1.rs:8:17 + --> $DIR/parser-recovery-1.rs:7:17 | LL | let x = foo(); | ^^^ not found in this scope error[E0425]: cannot find value `y` in this scope - --> $DIR/parser-recovery-1.rs:13:13 + --> $DIR/parser-recovery-1.rs:12:13 | LL | let x = y.; | ^ not found in this scope -error[E0601]: `main` function not found in crate `parser_recovery_1` - --> $DIR/parser-recovery-1.rs:5:1 - | -LL | / trait Foo { -LL | | -LL | | fn bar() { -LL | | let x = foo(); -... | -LL | | -LL | | } - | |______________________________________________________^ consider adding a `main` function to `$DIR/parser-recovery-1.rs` - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0425, E0601. -For more information about an error, try `rustc --explain E0425`. +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/parser/issue-2354.rs b/src/test/ui/parser/issue-2354.rs index a14eb6e32fc91..c4fc471618283 100644 --- a/src/test/ui/parser/issue-2354.rs +++ b/src/test/ui/parser/issue-2354.rs @@ -1,7 +1,4 @@ fn foo() { //~ NOTE un-closed delimiter -//~^ ERROR `main` function not found -//~^^ NOTE main function must be defined -//~^^^ NOTE you have one or more functions match Some(10) { //~^ NOTE this delimiter might not be properly closed... Some(y) => { panic!(); } @@ -14,5 +11,5 @@ fn bar() { while (i < 1000) {} } -fn main() {} //~ NOTE here is a function named `main` - //~ ERROR this file contains an un-closed delimiter +fn main() {} +//~ ERROR this file contains an un-closed delimiter diff --git a/src/test/ui/parser/issue-2354.stderr b/src/test/ui/parser/issue-2354.stderr index 038e3dcfa40a9..45199b02cb8d4 100644 --- a/src/test/ui/parser/issue-2354.stderr +++ b/src/test/ui/parser/issue-2354.stderr @@ -1,9 +1,8 @@ error: this file contains an un-closed delimiter - --> $DIR/issue-2354.rs:18:66 + --> $DIR/issue-2354.rs:15:53 | LL | fn foo() { | - un-closed delimiter -... LL | match Some(10) { | - this delimiter might not be properly closed... ... @@ -11,28 +10,7 @@ LL | } | - ...as it matches this but it has different indentation ... LL | - | ^ - -error[E0601]: `main` function not found in crate `issue_2354` - --> $DIR/issue-2354.rs:1:1 - | -LL | / fn foo() { -LL | | -LL | | -LL | | -... | -LL | | fn main() {} -LL | | - | |_________________________________________________________________^ the main function must be defined at the crate level (in `$DIR/issue-2354.rs`) - | -note: here is a function named `main` - --> $DIR/issue-2354.rs:17:1 - | -LL | fn main() {} - | ^^^^^^^^^^^^ - = note: you have one or more functions named `main` not defined at the crate level - = help: either move the `main` function definitions or attach the `#[main]` attribute to one of them + | ^ -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/parser/issue-62973.stderr b/src/test/ui/parser/issue-62973.stderr index e73776dc7b465..82122ef0b6fd0 100644 --- a/src/test/ui/parser/issue-62973.stderr +++ b/src/test/ui/parser/issue-62973.stderr @@ -13,9 +13,11 @@ error: expected one of `,` or `}`, found `{` --> $DIR/issue-62973.rs:6:25 | LL | fn p() { match s { v, E { [) {) } - | - ^ expected one of `,` or `}` here - | | - | while parsing this struct + | - - -^ expected one of `,` or `}` here + | | | | + | | | help: `}` may belong here + | | while parsing this struct + | unclosed delimiter error: struct literals are not allowed here --> $DIR/issue-62973.rs:6:16 diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs new file mode 100644 index 0000000000000..8d89905909e94 --- /dev/null +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs @@ -0,0 +1,12 @@ +impl T for () { //~ ERROR cannot find trait `T` in this scope + +fn foo(&self) {} + +trait T { //~ ERROR expected one of + fn foo(&self); +} + +pub(crate) struct Bar(); + +fn main() {} +//~ ERROR this file contains an un-closed delimiter diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr new file mode 100644 index 0000000000000..9bf54181a079c --- /dev/null +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr @@ -0,0 +1,33 @@ +error: this file contains an un-closed delimiter + --> $DIR/missing-close-brace-in-impl-trait.rs:12:53 + | +LL | impl T for () { + | - un-closed delimiter +... +LL | + | ^ + +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found keyword `trait` + --> $DIR/missing-close-brace-in-impl-trait.rs:5:1 + | +LL | impl T for () { + | - unclosed delimiter +LL | +LL | fn foo(&self) {} + | - + | | + | expected one of 10 possible tokens here + | help: `}` may belong here +LL | +LL | trait T { + | ^^^^^ unexpected token + +error[E0405]: cannot find trait `T` in this scope + --> $DIR/missing-close-brace-in-impl-trait.rs:1:6 + | +LL | impl T for () { + | ^ not found in this scope + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0405`. diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-struct.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-struct.rs new file mode 100644 index 0000000000000..5b716b1467cb1 --- /dev/null +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-struct.rs @@ -0,0 +1,14 @@ +pub(crate) struct Bar { + foo: T, + +trait T { //~ ERROR expected identifier, found keyword `trait` +//~^ ERROR expected `:`, found `T` + fn foo(&self); +} + + +impl T for Bar { +fn foo(&self) {} +} + +fn main() {} //~ ERROR this file contains an un-closed delimiter diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr new file mode 100644 index 0000000000000..ce399dbbf456d --- /dev/null +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr @@ -0,0 +1,28 @@ +error: this file contains an un-closed delimiter + --> $DIR/missing-close-brace-in-struct.rs:14:66 + | +LL | pub(crate) struct Bar { + | - un-closed delimiter +... +LL | fn main() {} + | ^ + +error: expected identifier, found keyword `trait` + --> $DIR/missing-close-brace-in-struct.rs:4:1 + | +LL | trait T { + | ^^^^^ expected identifier, found keyword + | +help: you can escape reserved keywords to use them as identifiers + | +LL | r#trait T { + | ^^^^^^^ + +error: expected `:`, found `T` + --> $DIR/missing-close-brace-in-struct.rs:4:7 + | +LL | trait T { + | ^ expected `:` + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs new file mode 100644 index 0000000000000..7954719541127 --- /dev/null +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs @@ -0,0 +1,10 @@ +trait T { + fn foo(&self); + +pub(crate) struct Bar(); //~ ERROR expected one of + +impl T for Bar { +fn foo(&self) {} +} + +fn main() {} //~ ERROR this file contains an un-closed delimiter diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr new file mode 100644 index 0000000000000..4bfb4c1cb3a52 --- /dev/null +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr @@ -0,0 +1,25 @@ +error: this file contains an un-closed delimiter + --> $DIR/missing-close-brace-in-trait.rs:10:66 + | +LL | trait T { + | - un-closed delimiter +... +LL | fn main() {} + | ^ + +error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found keyword `pub` + --> $DIR/missing-close-brace-in-trait.rs:4:1 + | +LL | trait T { + | - unclosed delimiter +LL | fn foo(&self); + | - + | | + | expected one of 7 possible tokens here + | help: `}` may belong here +LL | +LL | pub(crate) struct Bar(); + | ^^^ unexpected token + +error: aborting due to 2 previous errors +