Auto merge of #65838 - estebank:resilient-recovery, r=Centril
Reduce amount of errors given unclosed delimiter When in a file with a non-terminated item, catch the error and consume the block instead of trying to recover it on a more granular way in order to reduce the amount of unrelated errors that would be fixed after adding the missing closing brace. Also point out the possible location of the missing closing brace. Fix #63690.
This commit is contained in:
commit
f49f388713
24 changed files with 293 additions and 153 deletions
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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<token::DelimToken>,
|
||||
pub found_span: Span,
|
||||
pub unclosed_span: Option<Span>,
|
||||
pub candidate_span: Option<Span>,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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,11 +1369,16 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedBrace>, handler: &errors::Handler) {
|
||||
for unmatched in unclosed_delims.iter() {
|
||||
let mut err = handler.struct_span_err(unmatched.found_span, &format!(
|
||||
crate fn make_unclosed_delims_error(
|
||||
unmatched: UnmatchedBrace,
|
||||
sess: &ParseSess,
|
||||
) -> Option<DiagnosticBuilder<'_>> {
|
||||
// `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(unmatched.found_delim)),
|
||||
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 {
|
||||
|
@ -1383,7 +1387,13 @@ pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedBrace>, handler:
|
|||
if let Some(sp) = unmatched.unclosed_span {
|
||||
err.span_label(sp, "un-closed delimiter");
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
unclosed_delims.clear();
|
||||
Some(err)
|
||||
}
|
||||
|
||||
pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedBrace>, 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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,17 +1165,29 @@ impl<'a> Parser<'a> {
|
|||
delim.to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
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 errors
|
||||
self.expected_tokens.clear(); // Reduce the number of errors.
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
_ => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,6 +73,8 @@ pub struct ParseSess {
|
|||
pub ambiguous_block_expr_parse: Lock<FxHashMap<Span, Span>>,
|
||||
pub injected_crate_name: Once<Symbol>,
|
||||
crate gated_spans: GatedSpans,
|
||||
/// The parser has reached `Eof` due to an unclosed brace. Used to silence unnecessary errors.
|
||||
pub reached_eof: Lock<bool>,
|
||||
}
|
||||
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 4 previous errors
|
||||
|
||||
error: aborting due to 5 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`.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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...
|
||||
...
|
||||
|
@ -13,26 +12,5 @@ LL | }
|
|||
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 previous error
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0601`.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<T>();
|
||||
|
||||
fn main() {}
|
||||
//~ ERROR this file contains an un-closed delimiter
|
|
@ -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`.
|
|
@ -0,0 +1,14 @@
|
|||
pub(crate) struct Bar<T> {
|
||||
foo: T,
|
||||
|
||||
trait T { //~ ERROR expected identifier, found keyword `trait`
|
||||
//~^ ERROR expected `:`, found `T`
|
||||
fn foo(&self);
|
||||
}
|
||||
|
||||
|
||||
impl T for Bar<usize> {
|
||||
fn foo(&self) {}
|
||||
}
|
||||
|
||||
fn main() {} //~ ERROR this file contains an un-closed delimiter
|
|
@ -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<T> {
|
||||
| - 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
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
trait T {
|
||||
fn foo(&self);
|
||||
|
||||
pub(crate) struct Bar<T>(); //~ ERROR expected one of
|
||||
|
||||
impl T for Bar<usize> {
|
||||
fn foo(&self) {}
|
||||
}
|
||||
|
||||
fn main() {} //~ ERROR this file contains an un-closed delimiter
|
|
@ -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<T>();
|
||||
| ^^^ unexpected token
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
Loading…
Add table
Reference in a new issue