3 BlockCheckMode, BinOpKind, Expr, ExprKind, Item, ItemKind, Pat, PatKind, PathSegment, QSelf,
4 Ty, TyKind, VariantData, Ident,
6 use crate::parse::{SeqSep, token, PResult, Parser};
7 use crate::parse::parser::{BlockMode, PathStyle, SemiColonMode, TokenType, TokenExpectType};
8 use crate::print::pprust;
10 use crate::source_map::Spanned;
11 use crate::symbol::{kw, sym};
13 use crate::util::parser::AssocOp;
14 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
15 use syntax_pos::{Span, DUMMY_SP, MultiSpan};
16 use log::{debug, trace};
19 FileNotFoundForModule {
22 secondary_path: String,
28 secondary_path: String,
31 InclusiveRangeWithNoEnd,
35 fn span_err<S: Into<MultiSpan>>(
38 handler: &errors::Handler,
39 ) -> DiagnosticBuilder<'_> {
41 Error::FileNotFoundForModule {
47 let mut err = struct_span_err!(
51 "file not found for module `{}`",
55 "name the file either {} or {} inside the directory \"{}\"",
62 Error::DuplicatePaths { ref mod_name, ref default_path, ref secondary_path } => {
63 let mut err = struct_span_err!(
67 "file for module `{}` found at both {} and {}",
72 err.help("delete or rename one of them to remove the ambiguity");
75 Error::UselessDocComment => {
76 let mut err = struct_span_err!(
80 "found a documentation comment that doesn't document anything",
82 err.help("doc comments must come before what they document, maybe a comment was \
83 intended with `//`?");
86 Error::InclusiveRangeWithNoEnd => {
87 let mut err = struct_span_err!(
91 "inclusive range with no end",
93 err.help("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)");
100 pub trait RecoverQPath: Sized + 'static {
101 const PATH_STYLE: PathStyle = PathStyle::Expr;
102 fn to_ty(&self) -> Option<P<Ty>>;
103 fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self;
106 impl RecoverQPath for Ty {
107 const PATH_STYLE: PathStyle = PathStyle::Type;
108 fn to_ty(&self) -> Option<P<Ty>> {
109 Some(P(self.clone()))
111 fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self {
114 node: TyKind::Path(qself, path),
115 id: ast::DUMMY_NODE_ID,
120 impl RecoverQPath for Pat {
121 fn to_ty(&self) -> Option<P<Ty>> {
124 fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self {
127 node: PatKind::Path(qself, path),
128 id: ast::DUMMY_NODE_ID,
133 impl RecoverQPath for Expr {
134 fn to_ty(&self) -> Option<P<Ty>> {
137 fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self {
140 node: ExprKind::Path(qself, path),
141 attrs: ThinVec::new(),
142 id: ast::DUMMY_NODE_ID,
147 impl<'a> Parser<'a> {
148 pub fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> {
149 self.span_fatal(self.span, m)
152 pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
153 self.sess.span_diagnostic.struct_span_fatal(sp, m)
156 pub fn span_fatal_err<S: Into<MultiSpan>>(&self, sp: S, err: Error) -> DiagnosticBuilder<'a> {
157 err.span_err(sp, self.diagnostic())
160 pub fn bug(&self, m: &str) -> ! {
161 self.sess.span_diagnostic.span_bug(self.span, m)
164 pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) {
165 self.sess.span_diagnostic.span_err(sp, m)
168 crate fn struct_span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
169 self.sess.span_diagnostic.struct_span_err(sp, m)
172 crate fn span_bug<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> ! {
173 self.sess.span_diagnostic.span_bug(sp, m)
176 crate fn cancel(&self, err: &mut DiagnosticBuilder<'_>) {
177 self.sess.span_diagnostic.cancel(err)
180 crate fn diagnostic(&self) -> &'a errors::Handler {
181 &self.sess.span_diagnostic
184 crate fn expected_ident_found(&self) -> DiagnosticBuilder<'a> {
185 let mut err = self.struct_span_err(
187 &format!("expected identifier, found {}", self.this_token_descr()),
189 if let token::Ident(ident, false) = &self.token {
190 if ident.is_raw_guess() {
193 "you can escape reserved keywords to use them as identifiers",
194 format!("r#{}", ident),
195 Applicability::MaybeIncorrect,
199 if let Some(token_descr) = self.token_descr() {
200 err.span_label(self.span, format!("expected identifier, found {}", token_descr));
202 err.span_label(self.span, "expected identifier");
203 if self.token == token::Comma && self.look_ahead(1, |t| t.is_ident()) {
208 Applicability::MachineApplicable,
215 pub fn expected_one_of_not_found(
217 edible: &[token::Token],
218 inedible: &[token::Token],
219 ) -> PResult<'a, bool /* recovered */> {
220 fn tokens_to_string(tokens: &[TokenType]) -> String {
221 let mut i = tokens.iter();
222 // This might be a sign we need a connect method on Iterator.
224 .map_or(String::new(), |t| t.to_string());
225 i.enumerate().fold(b, |mut b, (i, a)| {
226 if tokens.len() > 2 && i == tokens.len() - 2 {
228 } else if tokens.len() == 2 && i == tokens.len() - 2 {
233 b.push_str(&a.to_string());
238 let mut expected = edible.iter()
239 .map(|x| TokenType::Token(x.clone()))
240 .chain(inedible.iter().map(|x| TokenType::Token(x.clone())))
241 .chain(self.expected_tokens.iter().cloned())
242 .collect::<Vec<_>>();
243 expected.sort_by_cached_key(|x| x.to_string());
245 let expect = tokens_to_string(&expected[..]);
246 let actual = self.this_token_to_string();
247 let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 {
248 let short_expect = if expected.len() > 6 {
249 format!("{} possible tokens", expected.len())
253 (format!("expected one of {}, found `{}`", expect, actual),
254 (self.sess.source_map().next_point(self.prev_span),
255 format!("expected one of {} here", short_expect)))
256 } else if expected.is_empty() {
257 (format!("unexpected token: `{}`", actual),
258 (self.prev_span, "unexpected token after this".to_string()))
260 (format!("expected {}, found `{}`", expect, actual),
261 (self.sess.source_map().next_point(self.prev_span),
262 format!("expected {} here", expect)))
264 self.last_unexpected_token_span = Some(self.span);
265 let mut err = self.fatal(&msg_exp);
266 if self.token.is_ident_named(sym::and) {
267 err.span_suggestion_short(
269 "use `&&` instead of `and` for the boolean operator",
271 Applicability::MaybeIncorrect,
274 if self.token.is_ident_named(sym::or) {
275 err.span_suggestion_short(
277 "use `||` instead of `or` for the boolean operator",
279 Applicability::MaybeIncorrect,
282 let sp = if self.token == token::Token::Eof {
283 // This is EOF, don't want to point at the following char, but rather the last token
288 match self.recover_closing_delimiter(&expected.iter().filter_map(|tt| match tt {
289 TokenType::Token(t) => Some(t.clone()),
291 }).collect::<Vec<_>>(), err) {
294 return Ok(recovered);
298 let is_semi_suggestable = expected.iter().any(|t| match t {
299 TokenType::Token(token::Semi) => true, // we expect a `;` here
301 }) && ( // a `;` would be expected before the current keyword
302 self.token.is_keyword(kw::Break) ||
303 self.token.is_keyword(kw::Continue) ||
304 self.token.is_keyword(kw::For) ||
305 self.token.is_keyword(kw::If) ||
306 self.token.is_keyword(kw::Let) ||
307 self.token.is_keyword(kw::Loop) ||
308 self.token.is_keyword(kw::Match) ||
309 self.token.is_keyword(kw::Return) ||
310 self.token.is_keyword(kw::While)
312 let cm = self.sess.source_map();
313 match (cm.lookup_line(self.span.lo()), cm.lookup_line(sp.lo())) {
314 (Ok(ref a), Ok(ref b)) if a.line != b.line && is_semi_suggestable => {
315 // The spans are in different lines, expected `;` and found `let` or `return`.
316 // High likelihood that it is only a missing `;`.
317 err.span_suggestion_short(
319 "a semicolon may be missing here",
321 Applicability::MaybeIncorrect,
326 (Ok(ref a), Ok(ref b)) if a.line == b.line => {
327 // When the spans are in the same line, it means that the only content between
328 // them is whitespace, point at the found token in that case:
330 // X | () => { syntax error };
331 // | ^^^^^ expected one of 8 possible tokens here
333 // instead of having:
335 // X | () => { syntax error };
336 // | -^^^^^ unexpected token
338 // | expected one of 8 possible tokens here
339 err.span_label(self.span, label_exp);
341 _ if self.prev_span == syntax_pos::DUMMY_SP => {
342 // Account for macro context where the previous span might not be
343 // available to avoid incorrect output (#54841).
344 err.span_label(self.span, "unexpected token");
347 err.span_label(sp, label_exp);
348 err.span_label(self.span, "unexpected token");
354 /// Eats and discards tokens until one of `kets` is encountered. Respects token trees,
355 /// passes through any errors encountered. Used for error recovery.
356 crate fn eat_to_tokens(&mut self, kets: &[&token::Token]) {
357 let handler = self.diagnostic();
359 if let Err(ref mut err) = self.parse_seq_to_before_tokens(
362 TokenExpectType::Expect,
363 |p| Ok(p.parse_token_tree()),
369 /// This function checks if there are trailing angle brackets and produces
370 /// a diagnostic to suggest removing them.
372 /// ```ignore (diagnostic)
373 /// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
374 /// ^^ help: remove extra angle brackets
376 crate fn check_trailing_angle_brackets(&mut self, segment: &PathSegment, end: token::Token) {
377 // This function is intended to be invoked after parsing a path segment where there are two
380 // 1. A specific token is expected after the path segment.
381 // eg. `x.foo(`, `x.foo::<u32>(` (parenthesis - method call),
382 // `Foo::`, or `Foo::<Bar>::` (mod sep - continued path).
383 // 2. No specific token is expected after the path segment.
384 // eg. `x.foo` (field access)
386 // This function is called after parsing `.foo` and before parsing the token `end` (if
387 // present). This includes any angle bracket arguments, such as `.foo::<u32>` or
390 // We only care about trailing angle brackets if we previously parsed angle bracket
391 // arguments. This helps stop us incorrectly suggesting that extra angle brackets be
392 // removed in this case:
394 // `x.foo >> (3)` (where `x.foo` is a `u32` for example)
396 // This case is particularly tricky as we won't notice it just looking at the tokens -
397 // it will appear the same (in terms of upcoming tokens) as below (since the `::<u32>` will
398 // have already been parsed):
400 // `x.foo::<u32>>>(3)`
401 let parsed_angle_bracket_args = segment.args
403 .map(|args| args.is_angle_bracketed())
407 "check_trailing_angle_brackets: parsed_angle_bracket_args={:?}",
408 parsed_angle_bracket_args,
410 if !parsed_angle_bracket_args {
414 // Keep the span at the start so we can highlight the sequence of `>` characters to be
418 // We need to look-ahead to see if we have `>` characters without moving the cursor forward
419 // (since we might have the field access case and the characters we're eating are
420 // actual operators and not trailing characters - ie `x.foo >> 3`).
421 let mut position = 0;
423 // We can encounter `>` or `>>` tokens in any order, so we need to keep track of how
424 // many of each (so we can correctly pluralize our error messages) and continue to
426 let mut number_of_shr = 0;
427 let mut number_of_gt = 0;
428 while self.look_ahead(position, |t| {
429 trace!("check_trailing_angle_brackets: t={:?}", t);
430 if *t == token::BinOp(token::BinOpToken::Shr) {
433 } else if *t == token::Gt {
443 // If we didn't find any trailing `>` characters, then we have nothing to error about.
445 "check_trailing_angle_brackets: number_of_gt={:?} number_of_shr={:?}",
446 number_of_gt, number_of_shr,
448 if number_of_gt < 1 && number_of_shr < 1 {
452 // Finally, double check that we have our end token as otherwise this is the
454 if self.look_ahead(position, |t| {
455 trace!("check_trailing_angle_brackets: t={:?}", t);
458 // Eat from where we started until the end token so that parsing can continue
459 // as if we didn't have those extra angle brackets.
460 self.eat_to_tokens(&[&end]);
461 let span = lo.until(self.span);
463 let plural = number_of_gt > 1 || number_of_shr >= 1;
467 &format!("unmatched angle bracket{}", if plural { "s" } else { "" }),
471 &format!("remove extra angle bracket{}", if plural { "s" } else { "" }),
473 Applicability::MachineApplicable,
479 /// Produce an error if comparison operators are chained (RFC #558).
480 /// We only need to check lhs, not rhs, because all comparison ops
481 /// have same precedence and are left-associative
482 crate fn check_no_chained_comparison(&self, lhs: &Expr, outer_op: &AssocOp) {
483 debug_assert!(outer_op.is_comparison(),
484 "check_no_chained_comparison: {:?} is not comparison",
487 ExprKind::Binary(op, _, _) if op.node.is_comparison() => {
488 // respan to include both operators
489 let op_span = op.span.to(self.span);
490 let mut err = self.diagnostic().struct_span_err(op_span,
491 "chained comparison operators require parentheses");
492 if op.node == BinOpKind::Lt &&
493 *outer_op == AssocOp::Less || // Include `<` to provide this recommendation
494 *outer_op == AssocOp::Greater // even in a case like the following:
495 { // Foo<Bar<Baz<Qux, ()>>>
497 "use `::<...>` instead of `<...>` if you meant to specify type arguments");
498 err.help("or use `(...)` if you meant to specify fn arguments");
506 crate fn maybe_report_ambiguous_plus(
509 impl_dyn_multi: bool,
512 if !allow_plus && impl_dyn_multi {
513 let sum_with_parens = format!("({})", pprust::ty_to_string(&ty));
514 self.struct_span_err(ty.span, "ambiguous `+` in a type")
517 "use parentheses to disambiguate",
519 Applicability::MachineApplicable,
525 crate fn maybe_report_invalid_custom_discriminants(
527 discriminant_spans: Vec<Span>,
528 variants: &[Spanned<ast::Variant_>],
530 let has_fields = variants.iter().any(|variant| match variant.node.data {
531 VariantData::Tuple(..) | VariantData::Struct(..) => true,
532 VariantData::Unit(..) => false,
535 if !discriminant_spans.is_empty() && has_fields {
536 let mut err = self.struct_span_err(
537 discriminant_spans.clone(),
538 "custom discriminant values are not allowed in enums with fields",
540 for sp in discriminant_spans {
541 err.span_label(sp, "invalid custom discriminant");
543 for variant in variants.iter() {
544 if let VariantData::Struct(fields, ..) | VariantData::Tuple(fields, ..) =
547 let fields = if fields.len() > 1 {
554 &format!("variant with {fields} defined here", fields = fields),
563 crate fn maybe_recover_from_bad_type_plus(
567 ) -> PResult<'a, ()> {
568 // Do not add `+` to expected tokens.
569 if !allow_plus || !self.token.is_like_plus() {
574 let bounds = self.parse_generic_bounds(None)?;
575 let sum_span = ty.span.to(self.prev_span);
577 let mut err = struct_span_err!(
578 self.sess.span_diagnostic,
581 "expected a path on the left-hand side of `+`, not `{}`",
582 pprust::ty_to_string(ty)
586 TyKind::Rptr(ref lifetime, ref mut_ty) => {
587 let sum_with_parens = pprust::to_string(|s| {
588 use crate::print::pprust::PrintState;
591 s.print_opt_lifetime(lifetime)?;
592 s.print_mutability(mut_ty.mutbl)?;
594 s.print_type(&mut_ty.ty)?;
595 s.print_type_bounds(" +", &bounds)?;
600 "try adding parentheses",
602 Applicability::MachineApplicable,
605 TyKind::Ptr(..) | TyKind::BareFn(..) => {
606 err.span_label(sum_span, "perhaps you forgot parentheses?");
609 err.span_label(sum_span, "expected a path");
616 /// Try to recover from associated item paths like `[T]::AssocItem`/`(T, U)::AssocItem`.
617 /// Attempt to convert the base expression/pattern/type into a type, parse the `::AssocItem`
618 /// tail, and combine them into a `<Ty>::AssocItem` expression/pattern/type.
619 crate fn maybe_recover_from_bad_qpath<T: RecoverQPath>(
622 allow_recovery: bool,
623 ) -> PResult<'a, P<T>> {
624 // Do not add `::` to expected tokens.
625 if allow_recovery && self.token == token::ModSep {
626 if let Some(ty) = base.to_ty() {
627 return self.maybe_recover_from_bad_qpath_stage_2(ty.span, ty);
633 /// Given an already parsed `Ty` parse the `::AssocItem` tail and
634 /// combine them into a `<Ty>::AssocItem` expression/pattern/type.
635 crate fn maybe_recover_from_bad_qpath_stage_2<T: RecoverQPath>(
639 ) -> PResult<'a, P<T>> {
640 self.expect(&token::ModSep)?;
642 let mut path = ast::Path {
643 segments: Vec::new(),
646 self.parse_path_segments(&mut path.segments, T::PATH_STYLE)?;
647 path.span = ty_span.to(self.prev_span);
652 .span_to_snippet(ty_span)
653 .unwrap_or_else(|_| pprust::ty_to_string(&ty));
655 .struct_span_err(path.span, "missing angle brackets in associated item path")
657 // this is a best-effort recovery
660 format!("<{}>::{}", ty_str, path),
661 Applicability::MaybeIncorrect,
665 let path_span = ty_span.shrink_to_hi(); // use an empty path since `position` == 0
676 crate fn maybe_consume_incorrect_semicolon(&mut self, items: &[P<Item>]) -> bool {
677 if self.eat(&token::Semi) {
678 let mut err = self.struct_span_err(self.prev_span, "expected item, found `;`");
679 err.span_suggestion_short(
681 "remove this semicolon",
683 Applicability::MachineApplicable,
685 if !items.is_empty() {
686 let previous_item = &items[items.len() - 1];
687 let previous_item_kind_name = match previous_item.node {
688 // say "braced struct" because tuple-structs and
689 // braceless-empty-struct declarations do take a semicolon
690 ItemKind::Struct(..) => Some("braced struct"),
691 ItemKind::Enum(..) => Some("enum"),
692 ItemKind::Trait(..) => Some("trait"),
693 ItemKind::Union(..) => Some("union"),
696 if let Some(name) = previous_item_kind_name {
698 "{} declarations are not followed by a semicolon",
710 /// Create a `DiagnosticBuilder` for an unexpected token `t` and try to recover if it is a
711 /// closing delimiter.
712 pub fn unexpected_try_recover(
715 ) -> PResult<'a, bool /* recovered */> {
716 let token_str = pprust::token_to_string(t);
717 let this_token_str = self.this_token_descr();
718 let (prev_sp, sp) = match (&self.token, self.subparser_name) {
719 // Point at the end of the macro call when reaching end of macro arguments.
720 (token::Token::Eof, Some(_)) => {
721 let sp = self.sess.source_map().next_point(self.span);
724 // We don't want to point at the following span after DUMMY_SP.
725 // This happens when the parser finds an empty TokenStream.
726 _ if self.prev_span == DUMMY_SP => (self.span, self.span),
727 // EOF, don't want to point at the following char, but rather the last token.
728 (token::Token::Eof, None) => (self.prev_span, self.span),
729 _ => (self.sess.source_map().next_point(self.prev_span), self.span),
732 "expected `{}`, found {}",
734 match (&self.token, self.subparser_name) {
735 (token::Token::Eof, Some(origin)) => format!("end of {}", origin),
739 let mut err = self.struct_span_err(sp, &msg);
740 let label_exp = format!("expected `{}`", token_str);
741 match self.recover_closing_delimiter(&[t.clone()], err) {
744 return Ok(recovered);
747 let cm = self.sess.source_map();
748 match (cm.lookup_line(prev_sp.lo()), cm.lookup_line(sp.lo())) {
749 (Ok(ref a), Ok(ref b)) if a.line == b.line => {
750 // When the spans are in the same line, it means that the only content
751 // between them is whitespace, point only at the found token.
752 err.span_label(sp, label_exp);
755 err.span_label(prev_sp, label_exp);
756 err.span_label(sp, "unexpected token");
762 /// Consume alternative await syntaxes like `await <expr>`, `await? <expr>`, `await(<expr>)`
763 /// and `await { <expr> }`.
764 crate fn parse_incorrect_await_syntax(
768 ) -> PResult<'a, (Span, ExprKind)> {
769 let is_question = self.eat(&token::Question); // Handle `await? <expr>`.
770 let expr = if self.token == token::OpenDelim(token::Brace) {
771 // Handle `await { <expr> }`.
772 // This needs to be handled separatedly from the next arm to avoid
773 // interpreting `await { <expr> }?` as `<expr>?.await`.
774 self.parse_block_expr(
777 BlockCheckMode::Default,
782 }.map_err(|mut err| {
783 err.span_label(await_sp, "while parsing this incorrect await expression");
786 let expr_str = self.sess.source_map().span_to_snippet(expr.span)
787 .unwrap_or_else(|_| pprust::expr_to_string(&expr));
788 let suggestion = format!("{}.await{}", expr_str, if is_question { "?" } else { "" });
789 let sp = lo.to(expr.span);
790 let app = match expr.node {
791 ExprKind::Try(_) => Applicability::MaybeIncorrect, // `await <expr>?`
792 _ => Applicability::MachineApplicable,
794 self.struct_span_err(sp, "incorrect use of `await`")
795 .span_suggestion(sp, "`await` is a postfix operation", suggestion, app)
797 Ok((sp, ExprKind::Await(ast::AwaitOrigin::FieldLike, expr)))
800 /// If encountering `future.await()`, consume and emit error.
801 crate fn recover_from_await_method_call(&mut self) {
802 if self.token == token::OpenDelim(token::Paren) &&
803 self.look_ahead(1, |t| t == &token::CloseDelim(token::Paren))
808 let sp = lo.to(self.span);
810 self.struct_span_err(sp, "incorrect use of `await`")
813 "`await` is not a method call, remove the parentheses",
815 Applicability::MachineApplicable,
820 crate fn could_ascription_be_path(&self, node: &ast::ExprKind) -> bool {
821 self.token.is_ident() &&
822 if let ast::ExprKind::Path(..) = node { true } else { false } &&
823 !self.token.is_reserved_ident() && // v `foo:bar(baz)`
824 self.look_ahead(1, |t| t == &token::OpenDelim(token::Paren)) ||
825 self.look_ahead(1, |t| t == &token::Lt) && // `foo:bar<baz`
826 self.look_ahead(2, |t| t.is_ident()) ||
827 self.look_ahead(1, |t| t == &token::Colon) && // `foo:bar:baz`
828 self.look_ahead(2, |t| t.is_ident()) ||
829 self.look_ahead(1, |t| t == &token::ModSep) && // `foo:bar::baz`
830 self.look_ahead(2, |t| t.is_ident())
833 crate fn bad_type_ascription(
835 err: &mut DiagnosticBuilder<'a>,
841 err.span_label(self.span, "expecting a type here because of type ascription");
842 let cm = self.sess.source_map();
843 let next_pos = cm.lookup_char_pos(next_sp.lo());
844 let op_pos = cm.lookup_char_pos(cur_op_span.hi());
845 if op_pos.line != next_pos.line {
848 "try using a semicolon",
850 Applicability::MaybeIncorrect,
856 "maybe you meant to write a path separator here",
858 Applicability::MaybeIncorrect,
861 err.note("type ascription is a nightly-only feature that lets \
862 you annotate an expression with a type: `<expr>: <type>`")
865 "this expression expects an ascribed type after the colon",
867 .help("this might be indicative of a syntax error elsewhere");
872 crate fn recover_seq_parse_error(
874 delim: token::DelimToken,
876 result: PResult<'a, P<Expr>>,
882 // recover from parse error
883 self.consume_block(delim);
884 self.mk_expr(lo.to(self.prev_span), ExprKind::Err, ThinVec::new())
889 crate fn recover_closing_delimiter(
891 tokens: &[token::Token],
892 mut err: DiagnosticBuilder<'a>,
893 ) -> PResult<'a, bool> {
895 // we want to use the last closing delim that would apply
896 for (i, unmatched) in self.unclosed_delims.iter().enumerate().rev() {
897 if tokens.contains(&token::CloseDelim(unmatched.expected_delim))
898 && Some(self.span) > unmatched.unclosed_span
905 // Recover and assume that the detected unclosed delimiter was meant for
906 // this location. Emit the diagnostic and act as if the delimiter was
907 // present for the parser's sake.
909 // Don't attempt to recover from this unclosed delimiter more than once.
910 let unmatched = self.unclosed_delims.remove(pos);
911 let delim = TokenType::Token(token::CloseDelim(unmatched.expected_delim));
913 // We want to suggest the inclusion of the closing delimiter where it makes
914 // the most sense, which is immediately after the last token:
919 // | help: `)` may belong here (FIXME: #58270)
921 // unclosed delimiter
922 if let Some(sp) = unmatched.unclosed_span {
923 err.span_label(sp, "unclosed delimiter");
925 err.span_suggestion_short(
926 self.sess.source_map().next_point(self.prev_span),
927 &format!("{} may belong here", delim.to_string()),
929 Applicability::MaybeIncorrect,
932 self.expected_tokens.clear(); // reduce errors
939 /// Recover from `pub` keyword in places where it seems _reasonable_ but isn't valid.
940 crate fn eat_bad_pub(&mut self) {
941 if self.token.is_keyword(kw::Pub) {
942 match self.parse_visibility(false) {
945 .struct_span_err(vis.span, "unnecessary visibility qualifier")
946 .span_label(vis.span, "`pub` not permitted here")
949 Err(mut err) => err.emit(),
954 // Eat tokens until we can be relatively sure we reached the end of the
955 // statement. This is something of a best-effort heuristic.
957 // We terminate when we find an unmatched `}` (without consuming it).
958 crate fn recover_stmt(&mut self) {
959 self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore)
962 // If `break_on_semi` is `Break`, then we will stop consuming tokens after
963 // finding (and consuming) a `;` outside of `{}` or `[]` (note that this is
964 // approximate - it can mean we break too early due to macros, but that
965 // should only lead to sub-optimal recovery, not inaccurate parsing).
967 // If `break_on_block` is `Break`, then we will stop consuming tokens
968 // after finding (and consuming) a brace-delimited block.
969 crate fn recover_stmt_(&mut self, break_on_semi: SemiColonMode, break_on_block: BlockMode) {
970 let mut brace_depth = 0;
971 let mut bracket_depth = 0;
972 let mut in_block = false;
973 debug!("recover_stmt_ enter loop (semi={:?}, block={:?})",
974 break_on_semi, break_on_block);
976 debug!("recover_stmt_ loop {:?}", self.token);
978 token::OpenDelim(token::DelimToken::Brace) => {
981 if break_on_block == BlockMode::Break &&
987 token::OpenDelim(token::DelimToken::Bracket) => {
991 token::CloseDelim(token::DelimToken::Brace) => {
992 if brace_depth == 0 {
993 debug!("recover_stmt_ return - close delim {:?}", self.token);
998 if in_block && bracket_depth == 0 && brace_depth == 0 {
999 debug!("recover_stmt_ return - block end {:?}", self.token);
1003 token::CloseDelim(token::DelimToken::Bracket) => {
1005 if bracket_depth < 0 {
1011 debug!("recover_stmt_ return - Eof");
1016 if break_on_semi == SemiColonMode::Break &&
1018 bracket_depth == 0 {
1019 debug!("recover_stmt_ return - Semi");
1023 token::Comma if break_on_semi == SemiColonMode::Comma &&
1025 bracket_depth == 0 =>
1027 debug!("recover_stmt_ return - Semi");
1037 crate fn check_for_for_in_in_typo(&mut self, in_span: Span) {
1038 if self.eat_keyword(kw::In) {
1039 // a common typo: `for _ in in bar {}`
1040 let mut err = self.sess.span_diagnostic.struct_span_err(
1042 "expected iterable, found keyword `in`",
1044 err.span_suggestion_short(
1045 in_span.until(self.prev_span),
1046 "remove the duplicated `in`",
1048 Applicability::MachineApplicable,
1054 crate fn expected_semi_or_open_brace(&mut self) -> PResult<'a, ast::TraitItem> {
1055 let token_str = self.this_token_descr();
1056 let mut err = self.fatal(&format!("expected `;` or `{{`, found {}", token_str));
1057 err.span_label(self.span, "expected `;` or `{`");
1061 crate fn eat_incorrect_doc_comment(&mut self, applied_to: &str) {
1062 if let token::DocComment(_) = self.token {
1063 let mut err = self.diagnostic().struct_span_err(
1065 &format!("documentation comments cannot be applied to {}", applied_to),
1067 err.span_label(self.span, "doc comments are not allowed here");
1070 } else if self.token == token::Pound && self.look_ahead(1, |t| {
1071 *t == token::OpenDelim(token::Bracket)
1074 // Skip every token until next possible arg.
1075 while self.token != token::CloseDelim(token::Bracket) {
1078 let sp = lo.to(self.span);
1080 let mut err = self.diagnostic().struct_span_err(
1082 &format!("attributes cannot be applied to {}", applied_to),
1084 err.span_label(sp, "attributes are not allowed here");
1089 crate fn argument_without_type(
1091 err: &mut DiagnosticBuilder<'_>,
1094 is_trait_item: bool,
1095 ) -> Option<Ident> {
1096 // If we find a pattern followed by an identifier, it could be an (incorrect)
1097 // C-style parameter declaration.
1098 if self.check_ident() && self.look_ahead(1, |t| {
1099 *t == token::Comma || *t == token::CloseDelim(token::Paren)
1100 }) { // `fn foo(String s) {}`
1101 let ident = self.parse_ident().unwrap();
1102 let span = pat.span.with_hi(ident.span.hi());
1104 err.span_suggestion(
1106 "declare the type after the parameter binding",
1107 String::from("<identifier>: <type>"),
1108 Applicability::HasPlaceholders,
1111 } else if let PatKind::Ident(_, ident, _) = pat.node {
1112 if require_name && (
1114 self.token == token::Comma ||
1115 self.token == token::CloseDelim(token::Paren)
1116 ) { // `fn foo(a, b) {}` or `fn foo(usize, usize) {}`
1117 err.span_suggestion(
1119 "if this was a parameter name, give it a type",
1120 format!("{}: TypeName", ident),
1121 Applicability::HasPlaceholders,
1123 err.span_suggestion(
1125 "if this is a type, explicitly ignore the parameter name",
1126 format!("_: {}", ident),
1127 Applicability::MachineApplicable,
1129 err.note("anonymous parameters are removed in the 2018 edition (see RFC 1685)");
1136 crate fn recover_arg_parse(&mut self) -> PResult<'a, (P<ast::Pat>, P<ast::Ty>)> {
1137 let pat = self.parse_pat(Some("argument name"))?;
1138 self.expect(&token::Colon)?;
1139 let ty = self.parse_ty()?;
1141 let mut err = self.diagnostic().struct_span_err_with_code(
1143 "patterns aren't allowed in methods without bodies",
1144 DiagnosticId::Error("E0642".into()),
1146 err.span_suggestion_short(
1148 "give this argument a name or use an underscore to ignore it",
1150 Applicability::MachineApplicable,
1154 // Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
1156 node: PatKind::Wild,
1158 id: ast::DUMMY_NODE_ID
1163 crate fn recover_bad_self_arg(
1166 is_trait_item: bool,
1167 ) -> PResult<'a, ast::Arg> {
1168 let sp = arg.pat.span;
1169 arg.ty.node = TyKind::Err;
1170 let mut err = self.struct_span_err(sp, "unexpected `self` parameter in function");
1172 err.span_label(sp, "must be the first associated function parameter");
1174 err.span_label(sp, "not valid as function parameter");
1175 err.note("`self` is only valid as the first parameter of an associated function");
1181 crate fn consume_block(&mut self, delim: token::DelimToken) {
1182 let mut brace_depth = 0;
1184 if self.eat(&token::OpenDelim(delim)) {
1186 } else if self.eat(&token::CloseDelim(delim)) {
1187 if brace_depth == 0 {
1193 } else if self.token == token::Eof || self.eat(&token::CloseDelim(token::NoDelim)) {
1201 crate fn expected_expression_found(&self) -> DiagnosticBuilder<'a> {
1202 let (span, msg) = match (&self.token, self.subparser_name) {
1203 (&token::Token::Eof, Some(origin)) => {
1204 let sp = self.sess.source_map().next_point(self.span);
1205 (sp, format!("expected expression, found end of {}", origin))
1207 _ => (self.span, format!(
1208 "expected expression, found {}",
1209 self.this_token_descr(),
1212 let mut err = self.struct_span_err(span, &msg);
1213 let sp = self.sess.source_map().start_point(self.span);
1214 if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) {
1215 self.sess.expr_parentheses_needed(&mut err, *sp, None);
1217 err.span_label(span, "expected expression");