]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_parse/src/parser/diagnostics.rs
Rollup merge of #98617 - ChrisDenton:const-unwrap, r=Mark-Simulacrum
[rust.git] / compiler / rustc_parse / src / parser / diagnostics.rs
1 use super::pat::Expected;
2 use super::{
3     BlockMode, CommaRecoveryMode, Parser, PathStyle, Restrictions, SemiColonMode, SeqSep,
4     TokenExpectType, TokenType,
5 };
6
7 use crate::lexer::UnmatchedBrace;
8 use rustc_ast as ast;
9 use rustc_ast::ptr::P;
10 use rustc_ast::token::{self, Delimiter, Lit, LitKind, TokenKind};
11 use rustc_ast::util::parser::AssocOp;
12 use rustc_ast::{
13     AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode, Block,
14     BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, Mutability, Param, Pat,
15     PatKind, Path, PathSegment, QSelf, Ty, TyKind,
16 };
17 use rustc_ast_pretty::pprust;
18 use rustc_data_structures::fx::FxHashSet;
19 use rustc_errors::{
20     fluent, Applicability, DiagnosticBuilder, DiagnosticMessage, Handler, MultiSpan, PResult,
21 };
22 use rustc_errors::{pluralize, struct_span_err, Diagnostic, EmissionGuarantee, ErrorGuaranteed};
23 use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
24 use rustc_span::source_map::Spanned;
25 use rustc_span::symbol::{kw, Ident};
26 use rustc_span::{Span, SpanSnippetError, DUMMY_SP};
27 use std::ops::{Deref, DerefMut};
28
29 use std::mem::take;
30
31 use crate::parser;
32 use tracing::{debug, trace};
33
34 const TURBOFISH_SUGGESTION_STR: &str =
35     "use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments";
36
37 /// Creates a placeholder argument.
38 pub(super) fn dummy_arg(ident: Ident) -> Param {
39     let pat = P(Pat {
40         id: ast::DUMMY_NODE_ID,
41         kind: PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None),
42         span: ident.span,
43         tokens: None,
44     });
45     let ty = Ty { kind: TyKind::Err, span: ident.span, id: ast::DUMMY_NODE_ID, tokens: None };
46     Param {
47         attrs: AttrVec::default(),
48         id: ast::DUMMY_NODE_ID,
49         pat,
50         span: ident.span,
51         ty: P(ty),
52         is_placeholder: false,
53     }
54 }
55
56 pub enum Error {
57     UselessDocComment,
58 }
59
60 impl Error {
61     fn span_err(
62         self,
63         sp: impl Into<MultiSpan>,
64         handler: &Handler,
65     ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
66         match self {
67             Error::UselessDocComment => {
68                 let mut err = struct_span_err!(
69                     handler,
70                     sp,
71                     E0585,
72                     "found a documentation comment that doesn't document anything",
73                 );
74                 err.help(
75                     "doc comments must come before what they document, maybe a comment was \
76                           intended with `//`?",
77                 );
78                 err
79             }
80         }
81     }
82 }
83
84 pub(super) trait RecoverQPath: Sized + 'static {
85     const PATH_STYLE: PathStyle = PathStyle::Expr;
86     fn to_ty(&self) -> Option<P<Ty>>;
87     fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self;
88 }
89
90 impl RecoverQPath for Ty {
91     const PATH_STYLE: PathStyle = PathStyle::Type;
92     fn to_ty(&self) -> Option<P<Ty>> {
93         Some(P(self.clone()))
94     }
95     fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self {
96         Self {
97             span: path.span,
98             kind: TyKind::Path(qself, path),
99             id: ast::DUMMY_NODE_ID,
100             tokens: None,
101         }
102     }
103 }
104
105 impl RecoverQPath for Pat {
106     fn to_ty(&self) -> Option<P<Ty>> {
107         self.to_ty()
108     }
109     fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self {
110         Self {
111             span: path.span,
112             kind: PatKind::Path(qself, path),
113             id: ast::DUMMY_NODE_ID,
114             tokens: None,
115         }
116     }
117 }
118
119 impl RecoverQPath for Expr {
120     fn to_ty(&self) -> Option<P<Ty>> {
121         self.to_ty()
122     }
123     fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self {
124         Self {
125             span: path.span,
126             kind: ExprKind::Path(qself, path),
127             attrs: AttrVec::new(),
128             id: ast::DUMMY_NODE_ID,
129             tokens: None,
130         }
131     }
132 }
133
134 /// Control whether the closing delimiter should be consumed when calling `Parser::consume_block`.
135 pub(crate) enum ConsumeClosingDelim {
136     Yes,
137     No,
138 }
139
140 #[derive(Clone, Copy)]
141 pub enum AttemptLocalParseRecovery {
142     Yes,
143     No,
144 }
145
146 impl AttemptLocalParseRecovery {
147     pub fn yes(&self) -> bool {
148         match self {
149             AttemptLocalParseRecovery::Yes => true,
150             AttemptLocalParseRecovery::No => false,
151         }
152     }
153
154     pub fn no(&self) -> bool {
155         match self {
156             AttemptLocalParseRecovery::Yes => false,
157             AttemptLocalParseRecovery::No => true,
158         }
159     }
160 }
161
162 /// Information for emitting suggestions and recovering from
163 /// C-style `i++`, `--i`, etc.
164 #[derive(Debug, Copy, Clone)]
165 struct IncDecRecovery {
166     /// Is this increment/decrement its own statement?
167     standalone: IsStandalone,
168     /// Is this an increment or decrement?
169     op: IncOrDec,
170     /// Is this pre- or postfix?
171     fixity: UnaryFixity,
172 }
173
174 /// Is an increment or decrement expression its own statement?
175 #[derive(Debug, Copy, Clone)]
176 enum IsStandalone {
177     /// It's standalone, i.e., its own statement.
178     Standalone,
179     /// It's a subexpression, i.e., *not* standalone.
180     Subexpr,
181     /// It's maybe standalone; we're not sure.
182     Maybe,
183 }
184
185 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
186 enum IncOrDec {
187     Inc,
188     // FIXME: `i--` recovery isn't implemented yet
189     #[allow(dead_code)]
190     Dec,
191 }
192
193 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
194 enum UnaryFixity {
195     Pre,
196     Post,
197 }
198
199 impl IncOrDec {
200     fn chr(&self) -> char {
201         match self {
202             Self::Inc => '+',
203             Self::Dec => '-',
204         }
205     }
206
207     fn name(&self) -> &'static str {
208         match self {
209             Self::Inc => "increment",
210             Self::Dec => "decrement",
211         }
212     }
213 }
214
215 impl std::fmt::Display for UnaryFixity {
216     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
217         match self {
218             Self::Pre => write!(f, "prefix"),
219             Self::Post => write!(f, "postfix"),
220         }
221     }
222 }
223
224 struct MultiSugg {
225     msg: String,
226     patches: Vec<(Span, String)>,
227     applicability: Applicability,
228 }
229
230 impl MultiSugg {
231     fn emit<G: EmissionGuarantee>(self, err: &mut DiagnosticBuilder<'_, G>) {
232         err.multipart_suggestion(&self.msg, self.patches, self.applicability);
233     }
234
235     /// Overrides individual messages and applicabilities.
236     fn emit_many<G: EmissionGuarantee>(
237         err: &mut DiagnosticBuilder<'_, G>,
238         msg: &str,
239         applicability: Applicability,
240         suggestions: impl Iterator<Item = Self>,
241     ) {
242         err.multipart_suggestions(msg, suggestions.map(|s| s.patches), applicability);
243     }
244 }
245
246 #[derive(SessionDiagnostic)]
247 #[error(parser::maybe_report_ambiguous_plus)]
248 struct AmbiguousPlus {
249     pub sum_ty: String,
250     #[primary_span]
251     #[suggestion(code = "({sum_ty})")]
252     pub span: Span,
253 }
254
255 #[derive(SessionDiagnostic)]
256 #[error(parser::maybe_recover_from_bad_type_plus, code = "E0178")]
257 struct BadTypePlus {
258     pub ty: String,
259     #[primary_span]
260     pub span: Span,
261     #[subdiagnostic]
262     pub sub: BadTypePlusSub,
263 }
264
265 #[derive(SessionSubdiagnostic)]
266 pub enum BadTypePlusSub {
267     #[suggestion(
268         parser::add_paren,
269         code = "{sum_with_parens}",
270         applicability = "machine-applicable"
271     )]
272     AddParen {
273         sum_with_parens: String,
274         #[primary_span]
275         span: Span,
276     },
277     #[label(parser::forgot_paren)]
278     ForgotParen {
279         #[primary_span]
280         span: Span,
281     },
282     #[label(parser::expect_path)]
283     ExpectPath {
284         #[primary_span]
285         span: Span,
286     },
287 }
288
289 #[derive(SessionDiagnostic)]
290 #[error(parser::maybe_recover_from_bad_qpath_stage_2)]
291 struct BadQPathStage2 {
292     #[primary_span]
293     #[suggestion(applicability = "maybe-incorrect")]
294     span: Span,
295     ty: String,
296 }
297
298 #[derive(SessionDiagnostic)]
299 #[error(parser::incorrect_semicolon)]
300 struct IncorrectSemicolon<'a> {
301     #[primary_span]
302     #[suggestion_short(applicability = "machine-applicable")]
303     span: Span,
304     #[help]
305     opt_help: Option<()>,
306     name: &'a str,
307 }
308
309 #[derive(SessionDiagnostic)]
310 #[error(parser::incorrect_use_of_await)]
311 struct IncorrectUseOfAwait {
312     #[primary_span]
313     #[suggestion(parser::parentheses_suggestion, applicability = "machine-applicable")]
314     span: Span,
315 }
316
317 #[derive(SessionDiagnostic)]
318 #[error(parser::incorrect_use_of_await)]
319 struct IncorrectAwait {
320     #[primary_span]
321     span: Span,
322     #[suggestion(parser::postfix_suggestion, code = "{expr}.await{question_mark}")]
323     sugg_span: (Span, Applicability),
324     expr: String,
325     question_mark: &'static str,
326 }
327
328 #[derive(SessionDiagnostic)]
329 #[error(parser::in_in_typo)]
330 struct InInTypo {
331     #[primary_span]
332     span: Span,
333     #[suggestion(applicability = "machine-applicable")]
334     sugg_span: Span,
335 }
336
337 // SnapshotParser is used to create a snapshot of the parser
338 // without causing duplicate errors being emitted when the `Parser`
339 // is dropped.
340 pub struct SnapshotParser<'a> {
341     parser: Parser<'a>,
342     unclosed_delims: Vec<UnmatchedBrace>,
343 }
344
345 impl<'a> Deref for SnapshotParser<'a> {
346     type Target = Parser<'a>;
347
348     fn deref(&self) -> &Self::Target {
349         &self.parser
350     }
351 }
352
353 impl<'a> DerefMut for SnapshotParser<'a> {
354     fn deref_mut(&mut self) -> &mut Self::Target {
355         &mut self.parser
356     }
357 }
358
359 impl<'a> Parser<'a> {
360     #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
361     pub(super) fn span_err<S: Into<MultiSpan>>(
362         &self,
363         sp: S,
364         err: Error,
365     ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
366         err.span_err(sp, self.diagnostic())
367     }
368
369     #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
370     pub fn struct_span_err<S: Into<MultiSpan>>(
371         &self,
372         sp: S,
373         m: impl Into<DiagnosticMessage>,
374     ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
375         self.sess.span_diagnostic.struct_span_err(sp, m)
376     }
377
378     pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, m: impl Into<DiagnosticMessage>) -> ! {
379         self.sess.span_diagnostic.span_bug(sp, m)
380     }
381
382     pub(super) fn diagnostic(&self) -> &'a Handler {
383         &self.sess.span_diagnostic
384     }
385
386     /// Replace `self` with `snapshot.parser` and extend `unclosed_delims` with `snapshot.unclosed_delims`.
387     /// This is to avoid losing unclosed delims errors `create_snapshot_for_diagnostic` clears.
388     pub(super) fn restore_snapshot(&mut self, snapshot: SnapshotParser<'a>) {
389         *self = snapshot.parser;
390         self.unclosed_delims.extend(snapshot.unclosed_delims.clone());
391     }
392
393     pub fn unclosed_delims(&self) -> &[UnmatchedBrace] {
394         &self.unclosed_delims
395     }
396
397     /// Create a snapshot of the `Parser`.
398     pub fn create_snapshot_for_diagnostic(&self) -> SnapshotParser<'a> {
399         let mut snapshot = self.clone();
400         let unclosed_delims = self.unclosed_delims.clone();
401         // Clear `unclosed_delims` in snapshot to avoid
402         // duplicate errors being emitted when the `Parser`
403         // is dropped (which may or may not happen, depending
404         // if the parsing the snapshot is created for is successful)
405         snapshot.unclosed_delims.clear();
406         SnapshotParser { parser: snapshot, unclosed_delims }
407     }
408
409     pub(super) fn span_to_snippet(&self, span: Span) -> Result<String, SpanSnippetError> {
410         self.sess.source_map().span_to_snippet(span)
411     }
412
413     pub(super) fn expected_ident_found(&self) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
414         let mut err = self.struct_span_err(
415             self.token.span,
416             &format!("expected identifier, found {}", super::token_descr(&self.token)),
417         );
418         let valid_follow = &[
419             TokenKind::Eq,
420             TokenKind::Colon,
421             TokenKind::Comma,
422             TokenKind::Semi,
423             TokenKind::ModSep,
424             TokenKind::OpenDelim(Delimiter::Brace),
425             TokenKind::OpenDelim(Delimiter::Parenthesis),
426             TokenKind::CloseDelim(Delimiter::Brace),
427             TokenKind::CloseDelim(Delimiter::Parenthesis),
428         ];
429         match self.token.ident() {
430             Some((ident, false))
431                 if ident.is_raw_guess()
432                     && self.look_ahead(1, |t| valid_follow.contains(&t.kind)) =>
433             {
434                 err.span_suggestion_verbose(
435                     ident.span.shrink_to_lo(),
436                     &format!("escape `{}` to use it as an identifier", ident.name),
437                     "r#",
438                     Applicability::MaybeIncorrect,
439                 );
440             }
441             _ => {}
442         }
443         if let Some(token_descr) = super::token_descr_opt(&self.token) {
444             err.span_label(self.token.span, format!("expected identifier, found {}", token_descr));
445         } else {
446             err.span_label(self.token.span, "expected identifier");
447             if self.token == token::Comma && self.look_ahead(1, |t| t.is_ident()) {
448                 err.span_suggestion(
449                     self.token.span,
450                     "remove this comma",
451                     "",
452                     Applicability::MachineApplicable,
453                 );
454             }
455         }
456         err
457     }
458
459     pub(super) fn expected_one_of_not_found(
460         &mut self,
461         edible: &[TokenKind],
462         inedible: &[TokenKind],
463     ) -> PResult<'a, bool /* recovered */> {
464         debug!("expected_one_of_not_found(edible: {:?}, inedible: {:?})", edible, inedible);
465         fn tokens_to_string(tokens: &[TokenType]) -> String {
466             let mut i = tokens.iter();
467             // This might be a sign we need a connect method on `Iterator`.
468             let b = i.next().map_or_else(String::new, |t| t.to_string());
469             i.enumerate().fold(b, |mut b, (i, a)| {
470                 if tokens.len() > 2 && i == tokens.len() - 2 {
471                     b.push_str(", or ");
472                 } else if tokens.len() == 2 && i == tokens.len() - 2 {
473                     b.push_str(" or ");
474                 } else {
475                     b.push_str(", ");
476                 }
477                 b.push_str(&a.to_string());
478                 b
479             })
480         }
481
482         let mut expected = edible
483             .iter()
484             .map(|x| TokenType::Token(x.clone()))
485             .chain(inedible.iter().map(|x| TokenType::Token(x.clone())))
486             .chain(self.expected_tokens.iter().cloned())
487             .filter_map(|token| {
488                 // filter out suggestions which suggest the same token which was found and deemed incorrect
489                 fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool {
490                     if let TokenKind::Ident(current_sym, _) = found {
491                         if let TokenType::Keyword(suggested_sym) = expected {
492                             return current_sym == suggested_sym;
493                         }
494                     }
495                     false
496                 }
497                 if token != parser::TokenType::Token(self.token.kind.clone()) {
498                     let eq = is_ident_eq_keyword(&self.token.kind, &token);
499                     // if the suggestion is a keyword and the found token is an ident,
500                     // the content of which are equal to the suggestion's content,
501                     // we can remove that suggestion (see the return None statement below)
502
503                     // if this isn't the case however, and the suggestion is a token the
504                     // content of which is the same as the found token's, we remove it as well
505                     if !eq {
506                         if let TokenType::Token(kind) = &token {
507                             if kind == &self.token.kind {
508                                 return None;
509                             }
510                         }
511                         return Some(token);
512                     }
513                 }
514                 return None;
515             })
516             .collect::<Vec<_>>();
517         expected.sort_by_cached_key(|x| x.to_string());
518         expected.dedup();
519
520         let sm = self.sess.source_map();
521         let msg = format!("expected `;`, found {}", super::token_descr(&self.token));
522         let appl = Applicability::MachineApplicable;
523         if expected.contains(&TokenType::Token(token::Semi)) {
524             if self.token.span == DUMMY_SP || self.prev_token.span == DUMMY_SP {
525                 // Likely inside a macro, can't provide meaningful suggestions.
526             } else if !sm.is_multiline(self.prev_token.span.until(self.token.span)) {
527                 // The current token is in the same line as the prior token, not recoverable.
528             } else if [token::Comma, token::Colon].contains(&self.token.kind)
529                 && self.prev_token.kind == token::CloseDelim(Delimiter::Parenthesis)
530             {
531                 // Likely typo: The current token is on a new line and is expected to be
532                 // `.`, `;`, `?`, or an operator after a close delimiter token.
533                 //
534                 // let a = std::process::Command::new("echo")
535                 //         .arg("1")
536                 //         ,arg("2")
537                 //         ^
538                 // https://github.com/rust-lang/rust/issues/72253
539             } else if self.look_ahead(1, |t| {
540                 t == &token::CloseDelim(Delimiter::Brace)
541                     || t.can_begin_expr() && t.kind != token::Colon
542             }) && [token::Comma, token::Colon].contains(&self.token.kind)
543             {
544                 // Likely typo: `,` â†’ `;` or `:` â†’ `;`. This is triggered if the current token is
545                 // either `,` or `:`, and the next token could either start a new statement or is a
546                 // block close. For example:
547                 //
548                 //   let x = 32:
549                 //   let y = 42;
550                 self.bump();
551                 let sp = self.prev_token.span;
552                 self.struct_span_err(sp, &msg)
553                     .span_suggestion_short(sp, "change this to `;`", ";", appl)
554                     .emit();
555                 return Ok(true);
556             } else if self.look_ahead(0, |t| {
557                 t == &token::CloseDelim(Delimiter::Brace)
558                     || (t.can_begin_expr() && t != &token::Semi && t != &token::Pound)
559                     // Avoid triggering with too many trailing `#` in raw string.
560                     || (sm.is_multiline(
561                         self.prev_token.span.shrink_to_hi().until(self.token.span.shrink_to_lo())
562                     ) && t == &token::Pound)
563             }) {
564                 // Missing semicolon typo. This is triggered if the next token could either start a
565                 // new statement or is a block close. For example:
566                 //
567                 //   let x = 32
568                 //   let y = 42;
569                 let sp = self.prev_token.span.shrink_to_hi();
570                 self.struct_span_err(sp, &msg)
571                     .span_label(self.token.span, "unexpected token")
572                     .span_suggestion_short(sp, "add `;` here", ";", appl)
573                     .emit();
574                 return Ok(true);
575             }
576         }
577
578         let expect = tokens_to_string(&expected);
579         let actual = super::token_descr(&self.token);
580         let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 {
581             let short_expect = if expected.len() > 6 {
582                 format!("{} possible tokens", expected.len())
583             } else {
584                 expect.clone()
585             };
586             (
587                 format!("expected one of {expect}, found {actual}"),
588                 (self.prev_token.span.shrink_to_hi(), format!("expected one of {short_expect}")),
589             )
590         } else if expected.is_empty() {
591             (
592                 format!("unexpected token: {}", actual),
593                 (self.prev_token.span, "unexpected token after this".to_string()),
594             )
595         } else {
596             (
597                 format!("expected {expect}, found {actual}"),
598                 (self.prev_token.span.shrink_to_hi(), format!("expected {expect}")),
599             )
600         };
601         self.last_unexpected_token_span = Some(self.token.span);
602         let mut err = self.struct_span_err(self.token.span, &msg_exp);
603
604         // Add suggestion for a missing closing angle bracket if '>' is included in expected_tokens
605         // there are unclosed angle brackets
606         if self.unmatched_angle_bracket_count > 0
607             && self.token.kind == TokenKind::Eq
608             && expected.iter().any(|tok| matches!(tok, TokenType::Token(TokenKind::Gt)))
609         {
610             err.span_label(self.prev_token.span, "maybe try to close unmatched angle bracket");
611         }
612
613         let sp = if self.token == token::Eof {
614             // This is EOF; don't want to point at the following char, but rather the last token.
615             self.prev_token.span
616         } else {
617             label_sp
618         };
619         match self.recover_closing_delimiter(
620             &expected
621                 .iter()
622                 .filter_map(|tt| match tt {
623                     TokenType::Token(t) => Some(t.clone()),
624                     _ => None,
625                 })
626                 .collect::<Vec<_>>(),
627             err,
628         ) {
629             Err(e) => err = e,
630             Ok(recovered) => {
631                 return Ok(recovered);
632             }
633         }
634
635         if self.check_too_many_raw_str_terminators(&mut err) {
636             if expected.contains(&TokenType::Token(token::Semi)) && self.eat(&token::Semi) {
637                 err.emit();
638                 return Ok(true);
639             } else {
640                 return Err(err);
641             }
642         }
643
644         if self.prev_token.span == DUMMY_SP {
645             // Account for macro context where the previous span might not be
646             // available to avoid incorrect output (#54841).
647             err.span_label(self.token.span, label_exp);
648         } else if !sm.is_multiline(self.token.span.shrink_to_hi().until(sp.shrink_to_lo())) {
649             // When the spans are in the same line, it means that the only content between
650             // them is whitespace, point at the found token in that case:
651             //
652             // X |     () => { syntax error };
653             //   |                    ^^^^^ expected one of 8 possible tokens here
654             //
655             // instead of having:
656             //
657             // X |     () => { syntax error };
658             //   |                   -^^^^^ unexpected token
659             //   |                   |
660             //   |                   expected one of 8 possible tokens here
661             err.span_label(self.token.span, label_exp);
662         } else {
663             err.span_label(sp, label_exp);
664             err.span_label(self.token.span, "unexpected token");
665         }
666         self.maybe_annotate_with_ascription(&mut err, false);
667         Err(err)
668     }
669
670     fn check_too_many_raw_str_terminators(&mut self, err: &mut Diagnostic) -> bool {
671         let sm = self.sess.source_map();
672         match (&self.prev_token.kind, &self.token.kind) {
673             (
674                 TokenKind::Literal(Lit {
675                     kind: LitKind::StrRaw(n_hashes) | LitKind::ByteStrRaw(n_hashes),
676                     ..
677                 }),
678                 TokenKind::Pound,
679             ) if !sm.is_multiline(
680                 self.prev_token.span.shrink_to_hi().until(self.token.span.shrink_to_lo()),
681             ) =>
682             {
683                 let n_hashes: u8 = *n_hashes;
684                 err.set_primary_message("too many `#` when terminating raw string");
685                 let str_span = self.prev_token.span;
686                 let mut span = self.token.span;
687                 let mut count = 0;
688                 while self.token.kind == TokenKind::Pound
689                     && !sm.is_multiline(span.shrink_to_hi().until(self.token.span.shrink_to_lo()))
690                 {
691                     span = span.with_hi(self.token.span.hi());
692                     self.bump();
693                     count += 1;
694                 }
695                 err.set_span(span);
696                 err.span_suggestion(
697                     span,
698                     &format!("remove the extra `#`{}", pluralize!(count)),
699                     "",
700                     Applicability::MachineApplicable,
701                 );
702                 err.span_label(
703                     str_span,
704                     &format!("this raw string started with {n_hashes} `#`{}", pluralize!(n_hashes)),
705                 );
706                 true
707             }
708             _ => false,
709         }
710     }
711
712     pub fn maybe_suggest_struct_literal(
713         &mut self,
714         lo: Span,
715         s: BlockCheckMode,
716     ) -> Option<PResult<'a, P<Block>>> {
717         if self.token.is_ident() && self.look_ahead(1, |t| t == &token::Colon) {
718             // We might be having a struct literal where people forgot to include the path:
719             // fn foo() -> Foo {
720             //     field: value,
721             // }
722             let mut snapshot = self.create_snapshot_for_diagnostic();
723             let path =
724                 Path { segments: vec![], span: self.prev_token.span.shrink_to_lo(), tokens: None };
725             let struct_expr = snapshot.parse_struct_expr(None, path, AttrVec::new(), false);
726             let block_tail = self.parse_block_tail(lo, s, AttemptLocalParseRecovery::No);
727             return Some(match (struct_expr, block_tail) {
728                 (Ok(expr), Err(mut err)) => {
729                     // We have encountered the following:
730                     // fn foo() -> Foo {
731                     //     field: value,
732                     // }
733                     // Suggest:
734                     // fn foo() -> Foo { Path {
735                     //     field: value,
736                     // } }
737                     err.delay_as_bug();
738                     self.struct_span_err(
739                         expr.span,
740                         fluent::parser::struct_literal_body_without_path,
741                     )
742                     .multipart_suggestion(
743                         fluent::parser::suggestion,
744                         vec![
745                             (expr.span.shrink_to_lo(), "{ SomeStruct ".to_string()),
746                             (expr.span.shrink_to_hi(), " }".to_string()),
747                         ],
748                         Applicability::MaybeIncorrect,
749                     )
750                     .emit();
751                     self.restore_snapshot(snapshot);
752                     let mut tail = self.mk_block(
753                         vec![self.mk_stmt_err(expr.span)],
754                         s,
755                         lo.to(self.prev_token.span),
756                     );
757                     tail.could_be_bare_literal = true;
758                     Ok(tail)
759                 }
760                 (Err(err), Ok(tail)) => {
761                     // We have a block tail that contains a somehow valid type ascription expr.
762                     err.cancel();
763                     Ok(tail)
764                 }
765                 (Err(snapshot_err), Err(err)) => {
766                     // We don't know what went wrong, emit the normal error.
767                     snapshot_err.cancel();
768                     self.consume_block(Delimiter::Brace, ConsumeClosingDelim::Yes);
769                     Err(err)
770                 }
771                 (Ok(_), Ok(mut tail)) => {
772                     tail.could_be_bare_literal = true;
773                     Ok(tail)
774                 }
775             });
776         }
777         None
778     }
779
780     pub fn maybe_annotate_with_ascription(
781         &mut self,
782         err: &mut Diagnostic,
783         maybe_expected_semicolon: bool,
784     ) {
785         if let Some((sp, likely_path)) = self.last_type_ascription.take() {
786             let sm = self.sess.source_map();
787             let next_pos = sm.lookup_char_pos(self.token.span.lo());
788             let op_pos = sm.lookup_char_pos(sp.hi());
789
790             let allow_unstable = self.sess.unstable_features.is_nightly_build();
791
792             if likely_path {
793                 err.span_suggestion(
794                     sp,
795                     "maybe write a path separator here",
796                     "::",
797                     if allow_unstable {
798                         Applicability::MaybeIncorrect
799                     } else {
800                         Applicability::MachineApplicable
801                     },
802                 );
803                 self.sess.type_ascription_path_suggestions.borrow_mut().insert(sp);
804             } else if op_pos.line != next_pos.line && maybe_expected_semicolon {
805                 err.span_suggestion(
806                     sp,
807                     "try using a semicolon",
808                     ";",
809                     Applicability::MaybeIncorrect,
810                 );
811             } else if allow_unstable {
812                 err.span_label(sp, "tried to parse a type due to this type ascription");
813             } else {
814                 err.span_label(sp, "tried to parse a type due to this");
815             }
816             if allow_unstable {
817                 // Give extra information about type ascription only if it's a nightly compiler.
818                 err.note(
819                     "`#![feature(type_ascription)]` lets you annotate an expression with a type: \
820                      `<expr>: <type>`",
821                 );
822                 if !likely_path {
823                     // Avoid giving too much info when it was likely an unrelated typo.
824                     err.note(
825                         "see issue #23416 <https://github.com/rust-lang/rust/issues/23416> \
826                         for more information",
827                     );
828                 }
829             }
830         }
831     }
832
833     /// Eats and discards tokens until one of `kets` is encountered. Respects token trees,
834     /// passes through any errors encountered. Used for error recovery.
835     pub(super) fn eat_to_tokens(&mut self, kets: &[&TokenKind]) {
836         if let Err(err) =
837             self.parse_seq_to_before_tokens(kets, SeqSep::none(), TokenExpectType::Expect, |p| {
838                 Ok(p.parse_token_tree())
839             })
840         {
841             err.cancel();
842         }
843     }
844
845     /// This function checks if there are trailing angle brackets and produces
846     /// a diagnostic to suggest removing them.
847     ///
848     /// ```ignore (diagnostic)
849     /// let _ = [1, 2, 3].into_iter().collect::<Vec<usize>>>>();
850     ///                                                    ^^ help: remove extra angle brackets
851     /// ```
852     ///
853     /// If `true` is returned, then trailing brackets were recovered, tokens were consumed
854     /// up until one of the tokens in 'end' was encountered, and an error was emitted.
855     pub(super) fn check_trailing_angle_brackets(
856         &mut self,
857         segment: &PathSegment,
858         end: &[&TokenKind],
859     ) -> bool {
860         // This function is intended to be invoked after parsing a path segment where there are two
861         // cases:
862         //
863         // 1. A specific token is expected after the path segment.
864         //    eg. `x.foo(`, `x.foo::<u32>(` (parenthesis - method call),
865         //        `Foo::`, or `Foo::<Bar>::` (mod sep - continued path).
866         // 2. No specific token is expected after the path segment.
867         //    eg. `x.foo` (field access)
868         //
869         // This function is called after parsing `.foo` and before parsing the token `end` (if
870         // present). This includes any angle bracket arguments, such as `.foo::<u32>` or
871         // `Foo::<Bar>`.
872
873         // We only care about trailing angle brackets if we previously parsed angle bracket
874         // arguments. This helps stop us incorrectly suggesting that extra angle brackets be
875         // removed in this case:
876         //
877         // `x.foo >> (3)` (where `x.foo` is a `u32` for example)
878         //
879         // This case is particularly tricky as we won't notice it just looking at the tokens -
880         // it will appear the same (in terms of upcoming tokens) as below (since the `::<u32>` will
881         // have already been parsed):
882         //
883         // `x.foo::<u32>>>(3)`
884         let parsed_angle_bracket_args =
885             segment.args.as_ref().map_or(false, |args| args.is_angle_bracketed());
886
887         debug!(
888             "check_trailing_angle_brackets: parsed_angle_bracket_args={:?}",
889             parsed_angle_bracket_args,
890         );
891         if !parsed_angle_bracket_args {
892             return false;
893         }
894
895         // Keep the span at the start so we can highlight the sequence of `>` characters to be
896         // removed.
897         let lo = self.token.span;
898
899         // We need to look-ahead to see if we have `>` characters without moving the cursor forward
900         // (since we might have the field access case and the characters we're eating are
901         // actual operators and not trailing characters - ie `x.foo >> 3`).
902         let mut position = 0;
903
904         // We can encounter `>` or `>>` tokens in any order, so we need to keep track of how
905         // many of each (so we can correctly pluralize our error messages) and continue to
906         // advance.
907         let mut number_of_shr = 0;
908         let mut number_of_gt = 0;
909         while self.look_ahead(position, |t| {
910             trace!("check_trailing_angle_brackets: t={:?}", t);
911             if *t == token::BinOp(token::BinOpToken::Shr) {
912                 number_of_shr += 1;
913                 true
914             } else if *t == token::Gt {
915                 number_of_gt += 1;
916                 true
917             } else {
918                 false
919             }
920         }) {
921             position += 1;
922         }
923
924         // If we didn't find any trailing `>` characters, then we have nothing to error about.
925         debug!(
926             "check_trailing_angle_brackets: number_of_gt={:?} number_of_shr={:?}",
927             number_of_gt, number_of_shr,
928         );
929         if number_of_gt < 1 && number_of_shr < 1 {
930             return false;
931         }
932
933         // Finally, double check that we have our end token as otherwise this is the
934         // second case.
935         if self.look_ahead(position, |t| {
936             trace!("check_trailing_angle_brackets: t={:?}", t);
937             end.contains(&&t.kind)
938         }) {
939             // Eat from where we started until the end token so that parsing can continue
940             // as if we didn't have those extra angle brackets.
941             self.eat_to_tokens(end);
942             let span = lo.until(self.token.span);
943
944             let total_num_of_gt = number_of_gt + number_of_shr * 2;
945             self.struct_span_err(
946                 span,
947                 &format!("unmatched angle bracket{}", pluralize!(total_num_of_gt)),
948             )
949             .span_suggestion(
950                 span,
951                 &format!("remove extra angle bracket{}", pluralize!(total_num_of_gt)),
952                 "",
953                 Applicability::MachineApplicable,
954             )
955             .emit();
956             return true;
957         }
958         false
959     }
960
961     /// Check if a method call with an intended turbofish has been written without surrounding
962     /// angle brackets.
963     pub(super) fn check_turbofish_missing_angle_brackets(&mut self, segment: &mut PathSegment) {
964         if token::ModSep == self.token.kind && segment.args.is_none() {
965             let snapshot = self.create_snapshot_for_diagnostic();
966             self.bump();
967             let lo = self.token.span;
968             match self.parse_angle_args(None) {
969                 Ok(args) => {
970                     let span = lo.to(self.prev_token.span);
971                     // Detect trailing `>` like in `x.collect::Vec<_>>()`.
972                     let mut trailing_span = self.prev_token.span.shrink_to_hi();
973                     while self.token.kind == token::BinOp(token::Shr)
974                         || self.token.kind == token::Gt
975                     {
976                         trailing_span = trailing_span.to(self.token.span);
977                         self.bump();
978                     }
979                     if self.token.kind == token::OpenDelim(Delimiter::Parenthesis) {
980                         // Recover from bad turbofish: `foo.collect::Vec<_>()`.
981                         let args = AngleBracketedArgs { args, span }.into();
982                         segment.args = args;
983
984                         self.struct_span_err(
985                             span,
986                             "generic parameters without surrounding angle brackets",
987                         )
988                         .multipart_suggestion(
989                             "surround the type parameters with angle brackets",
990                             vec![
991                                 (span.shrink_to_lo(), "<".to_string()),
992                                 (trailing_span, ">".to_string()),
993                             ],
994                             Applicability::MachineApplicable,
995                         )
996                         .emit();
997                     } else {
998                         // This doesn't look like an invalid turbofish, can't recover parse state.
999                         self.restore_snapshot(snapshot);
1000                     }
1001                 }
1002                 Err(err) => {
1003                     // We couldn't parse generic parameters, unlikely to be a turbofish. Rely on
1004                     // generic parse error instead.
1005                     err.cancel();
1006                     self.restore_snapshot(snapshot);
1007                 }
1008             }
1009         }
1010     }
1011
1012     /// When writing a turbofish with multiple type parameters missing the leading `::`, we will
1013     /// encounter a parse error when encountering the first `,`.
1014     pub(super) fn check_mistyped_turbofish_with_multiple_type_params(
1015         &mut self,
1016         mut e: DiagnosticBuilder<'a, ErrorGuaranteed>,
1017         expr: &mut P<Expr>,
1018     ) -> PResult<'a, ()> {
1019         if let ExprKind::Binary(binop, _, _) = &expr.kind
1020             && let ast::BinOpKind::Lt = binop.node
1021             && self.eat(&token::Comma)
1022         {
1023             let x = self.parse_seq_to_before_end(
1024                 &token::Gt,
1025                 SeqSep::trailing_allowed(token::Comma),
1026                 |p| p.parse_generic_arg(None),
1027             );
1028             match x {
1029                 Ok((_, _, false)) => {
1030                     if self.eat(&token::Gt) {
1031                         e.span_suggestion_verbose(
1032                             binop.span.shrink_to_lo(),
1033                             TURBOFISH_SUGGESTION_STR,
1034                             "::",
1035                             Applicability::MaybeIncorrect,
1036                         )
1037                         .emit();
1038                         match self.parse_expr() {
1039                             Ok(_) => {
1040                                 *expr =
1041                                     self.mk_expr_err(expr.span.to(self.prev_token.span));
1042                                 return Ok(());
1043                             }
1044                             Err(err) => {
1045                                 *expr = self.mk_expr_err(expr.span);
1046                                 err.cancel();
1047                             }
1048                         }
1049                     }
1050                 }
1051                 Err(err) => {
1052                     err.cancel();
1053                 }
1054                 _ => {}
1055             }
1056         }
1057         Err(e)
1058     }
1059
1060     /// Check to see if a pair of chained operators looks like an attempt at chained comparison,
1061     /// e.g. `1 < x <= 3`. If so, suggest either splitting the comparison into two, or
1062     /// parenthesising the leftmost comparison.
1063     fn attempt_chained_comparison_suggestion(
1064         &mut self,
1065         err: &mut Diagnostic,
1066         inner_op: &Expr,
1067         outer_op: &Spanned<AssocOp>,
1068     ) -> bool /* advanced the cursor */ {
1069         if let ExprKind::Binary(op, ref l1, ref r1) = inner_op.kind {
1070             if let ExprKind::Field(_, ident) = l1.kind
1071                 && ident.as_str().parse::<i32>().is_err()
1072                 && !matches!(r1.kind, ExprKind::Lit(_))
1073             {
1074                 // The parser has encountered `foo.bar<baz`, the likelihood of the turbofish
1075                 // suggestion being the only one to apply is high.
1076                 return false;
1077             }
1078             let mut enclose = |left: Span, right: Span| {
1079                 err.multipart_suggestion(
1080                     "parenthesize the comparison",
1081                     vec![
1082                         (left.shrink_to_lo(), "(".to_string()),
1083                         (right.shrink_to_hi(), ")".to_string()),
1084                     ],
1085                     Applicability::MaybeIncorrect,
1086                 );
1087             };
1088             return match (op.node, &outer_op.node) {
1089                 // `x == y == z`
1090                 (BinOpKind::Eq, AssocOp::Equal) |
1091                 // `x < y < z` and friends.
1092                 (BinOpKind::Lt, AssocOp::Less | AssocOp::LessEqual) |
1093                 (BinOpKind::Le, AssocOp::LessEqual | AssocOp::Less) |
1094                 // `x > y > z` and friends.
1095                 (BinOpKind::Gt, AssocOp::Greater | AssocOp::GreaterEqual) |
1096                 (BinOpKind::Ge, AssocOp::GreaterEqual | AssocOp::Greater) => {
1097                     let expr_to_str = |e: &Expr| {
1098                         self.span_to_snippet(e.span)
1099                             .unwrap_or_else(|_| pprust::expr_to_string(&e))
1100                     };
1101                     err.span_suggestion_verbose(
1102                         inner_op.span.shrink_to_hi(),
1103                         "split the comparison into two",
1104                         format!(" && {}", expr_to_str(&r1)),
1105                         Applicability::MaybeIncorrect,
1106                     );
1107                     false // Keep the current parse behavior, where the AST is `(x < y) < z`.
1108                 }
1109                 // `x == y < z`
1110                 (BinOpKind::Eq, AssocOp::Less | AssocOp::LessEqual | AssocOp::Greater | AssocOp::GreaterEqual) => {
1111                     // Consume `z`/outer-op-rhs.
1112                     let snapshot = self.create_snapshot_for_diagnostic();
1113                     match self.parse_expr() {
1114                         Ok(r2) => {
1115                             // We are sure that outer-op-rhs could be consumed, the suggestion is
1116                             // likely correct.
1117                             enclose(r1.span, r2.span);
1118                             true
1119                         }
1120                         Err(expr_err) => {
1121                             expr_err.cancel();
1122                             self.restore_snapshot(snapshot);
1123                             false
1124                         }
1125                     }
1126                 }
1127                 // `x > y == z`
1128                 (BinOpKind::Lt | BinOpKind::Le | BinOpKind::Gt | BinOpKind::Ge, AssocOp::Equal) => {
1129                     let snapshot = self.create_snapshot_for_diagnostic();
1130                     // At this point it is always valid to enclose the lhs in parentheses, no
1131                     // further checks are necessary.
1132                     match self.parse_expr() {
1133                         Ok(_) => {
1134                             enclose(l1.span, r1.span);
1135                             true
1136                         }
1137                         Err(expr_err) => {
1138                             expr_err.cancel();
1139                             self.restore_snapshot(snapshot);
1140                             false
1141                         }
1142                     }
1143                 }
1144                 _ => false,
1145             };
1146         }
1147         false
1148     }
1149
1150     /// Produces an error if comparison operators are chained (RFC #558).
1151     /// We only need to check the LHS, not the RHS, because all comparison ops have same
1152     /// precedence (see `fn precedence`) and are left-associative (see `fn fixity`).
1153     ///
1154     /// This can also be hit if someone incorrectly writes `foo<bar>()` when they should have used
1155     /// the turbofish (`foo::<bar>()`) syntax. We attempt some heuristic recovery if that is the
1156     /// case.
1157     ///
1158     /// Keep in mind that given that `outer_op.is_comparison()` holds and comparison ops are left
1159     /// associative we can infer that we have:
1160     ///
1161     /// ```text
1162     ///           outer_op
1163     ///           /   \
1164     ///     inner_op   r2
1165     ///        /  \
1166     ///      l1    r1
1167     /// ```
1168     pub(super) fn check_no_chained_comparison(
1169         &mut self,
1170         inner_op: &Expr,
1171         outer_op: &Spanned<AssocOp>,
1172     ) -> PResult<'a, Option<P<Expr>>> {
1173         debug_assert!(
1174             outer_op.node.is_comparison(),
1175             "check_no_chained_comparison: {:?} is not comparison",
1176             outer_op.node,
1177         );
1178
1179         let mk_err_expr =
1180             |this: &Self, span| Ok(Some(this.mk_expr(span, ExprKind::Err, AttrVec::new())));
1181
1182         match inner_op.kind {
1183             ExprKind::Binary(op, ref l1, ref r1) if op.node.is_comparison() => {
1184                 let mut err = self.struct_span_err(
1185                     vec![op.span, self.prev_token.span],
1186                     "comparison operators cannot be chained",
1187                 );
1188
1189                 let suggest = |err: &mut Diagnostic| {
1190                     err.span_suggestion_verbose(
1191                         op.span.shrink_to_lo(),
1192                         TURBOFISH_SUGGESTION_STR,
1193                         "::",
1194                         Applicability::MaybeIncorrect,
1195                     );
1196                 };
1197
1198                 // Include `<` to provide this recommendation even in a case like
1199                 // `Foo<Bar<Baz<Qux, ()>>>`
1200                 if op.node == BinOpKind::Lt && outer_op.node == AssocOp::Less
1201                     || outer_op.node == AssocOp::Greater
1202                 {
1203                     if outer_op.node == AssocOp::Less {
1204                         let snapshot = self.create_snapshot_for_diagnostic();
1205                         self.bump();
1206                         // So far we have parsed `foo<bar<`, consume the rest of the type args.
1207                         let modifiers =
1208                             [(token::Lt, 1), (token::Gt, -1), (token::BinOp(token::Shr), -2)];
1209                         self.consume_tts(1, &modifiers);
1210
1211                         if !&[token::OpenDelim(Delimiter::Parenthesis), token::ModSep]
1212                             .contains(&self.token.kind)
1213                         {
1214                             // We don't have `foo< bar >(` or `foo< bar >::`, so we rewind the
1215                             // parser and bail out.
1216                             self.restore_snapshot(snapshot);
1217                         }
1218                     }
1219                     return if token::ModSep == self.token.kind {
1220                         // We have some certainty that this was a bad turbofish at this point.
1221                         // `foo< bar >::`
1222                         suggest(&mut err);
1223
1224                         let snapshot = self.create_snapshot_for_diagnostic();
1225                         self.bump(); // `::`
1226
1227                         // Consume the rest of the likely `foo<bar>::new()` or return at `foo<bar>`.
1228                         match self.parse_expr() {
1229                             Ok(_) => {
1230                                 // 99% certain that the suggestion is correct, continue parsing.
1231                                 err.emit();
1232                                 // FIXME: actually check that the two expressions in the binop are
1233                                 // paths and resynthesize new fn call expression instead of using
1234                                 // `ExprKind::Err` placeholder.
1235                                 mk_err_expr(self, inner_op.span.to(self.prev_token.span))
1236                             }
1237                             Err(expr_err) => {
1238                                 expr_err.cancel();
1239                                 // Not entirely sure now, but we bubble the error up with the
1240                                 // suggestion.
1241                                 self.restore_snapshot(snapshot);
1242                                 Err(err)
1243                             }
1244                         }
1245                     } else if token::OpenDelim(Delimiter::Parenthesis) == self.token.kind {
1246                         // We have high certainty that this was a bad turbofish at this point.
1247                         // `foo< bar >(`
1248                         suggest(&mut err);
1249                         // Consume the fn call arguments.
1250                         match self.consume_fn_args() {
1251                             Err(()) => Err(err),
1252                             Ok(()) => {
1253                                 err.emit();
1254                                 // FIXME: actually check that the two expressions in the binop are
1255                                 // paths and resynthesize new fn call expression instead of using
1256                                 // `ExprKind::Err` placeholder.
1257                                 mk_err_expr(self, inner_op.span.to(self.prev_token.span))
1258                             }
1259                         }
1260                     } else {
1261                         if !matches!(l1.kind, ExprKind::Lit(_))
1262                             && !matches!(r1.kind, ExprKind::Lit(_))
1263                         {
1264                             // All we know is that this is `foo < bar >` and *nothing* else. Try to
1265                             // be helpful, but don't attempt to recover.
1266                             err.help(TURBOFISH_SUGGESTION_STR);
1267                             err.help("or use `(...)` if you meant to specify fn arguments");
1268                         }
1269
1270                         // If it looks like a genuine attempt to chain operators (as opposed to a
1271                         // misformatted turbofish, for instance), suggest a correct form.
1272                         if self.attempt_chained_comparison_suggestion(&mut err, inner_op, outer_op)
1273                         {
1274                             err.emit();
1275                             mk_err_expr(self, inner_op.span.to(self.prev_token.span))
1276                         } else {
1277                             // These cases cause too many knock-down errors, bail out (#61329).
1278                             Err(err)
1279                         }
1280                     };
1281                 }
1282                 let recover =
1283                     self.attempt_chained_comparison_suggestion(&mut err, inner_op, outer_op);
1284                 err.emit();
1285                 if recover {
1286                     return mk_err_expr(self, inner_op.span.to(self.prev_token.span));
1287                 }
1288             }
1289             _ => {}
1290         }
1291         Ok(None)
1292     }
1293
1294     fn consume_fn_args(&mut self) -> Result<(), ()> {
1295         let snapshot = self.create_snapshot_for_diagnostic();
1296         self.bump(); // `(`
1297
1298         // Consume the fn call arguments.
1299         let modifiers = [
1300             (token::OpenDelim(Delimiter::Parenthesis), 1),
1301             (token::CloseDelim(Delimiter::Parenthesis), -1),
1302         ];
1303         self.consume_tts(1, &modifiers);
1304
1305         if self.token.kind == token::Eof {
1306             // Not entirely sure that what we consumed were fn arguments, rollback.
1307             self.restore_snapshot(snapshot);
1308             Err(())
1309         } else {
1310             // 99% certain that the suggestion is correct, continue parsing.
1311             Ok(())
1312         }
1313     }
1314
1315     pub(super) fn maybe_report_ambiguous_plus(&mut self, impl_dyn_multi: bool, ty: &Ty) {
1316         if impl_dyn_multi {
1317             self.sess.emit_err(AmbiguousPlus { sum_ty: pprust::ty_to_string(&ty), span: ty.span });
1318         }
1319     }
1320
1321     /// Swift lets users write `Ty?` to mean `Option<Ty>`. Parse the construct and recover from it.
1322     pub(super) fn maybe_recover_from_question_mark(&mut self, ty: P<Ty>) -> P<Ty> {
1323         if self.token == token::Question {
1324             self.bump();
1325             self.struct_span_err(self.prev_token.span, "invalid `?` in type")
1326                 .span_label(self.prev_token.span, "`?` is only allowed on expressions, not types")
1327                 .multipart_suggestion(
1328                     "if you meant to express that the type might not contain a value, use the `Option` wrapper type",
1329                     vec![
1330                         (ty.span.shrink_to_lo(), "Option<".to_string()),
1331                         (self.prev_token.span, ">".to_string()),
1332                     ],
1333                     Applicability::MachineApplicable,
1334                 )
1335                 .emit();
1336             self.mk_ty(ty.span.to(self.prev_token.span), TyKind::Err)
1337         } else {
1338             ty
1339         }
1340     }
1341
1342     pub(super) fn maybe_recover_from_bad_type_plus(&mut self, ty: &Ty) -> PResult<'a, ()> {
1343         // Do not add `+` to expected tokens.
1344         if !self.token.is_like_plus() {
1345             return Ok(());
1346         }
1347
1348         self.bump(); // `+`
1349         let bounds = self.parse_generic_bounds(None)?;
1350         let sum_span = ty.span.to(self.prev_token.span);
1351
1352         let sub = match ty.kind {
1353             TyKind::Rptr(ref lifetime, ref mut_ty) => {
1354                 let sum_with_parens = pprust::to_string(|s| {
1355                     s.s.word("&");
1356                     s.print_opt_lifetime(lifetime);
1357                     s.print_mutability(mut_ty.mutbl, false);
1358                     s.popen();
1359                     s.print_type(&mut_ty.ty);
1360                     if !bounds.is_empty() {
1361                         s.word(" + ");
1362                         s.print_type_bounds(&bounds);
1363                     }
1364                     s.pclose()
1365                 });
1366
1367                 BadTypePlusSub::AddParen { sum_with_parens, span: sum_span }
1368             }
1369             TyKind::Ptr(..) | TyKind::BareFn(..) => BadTypePlusSub::ForgotParen { span: sum_span },
1370             _ => BadTypePlusSub::ExpectPath { span: sum_span },
1371         };
1372
1373         self.sess.emit_err(BadTypePlus { ty: pprust::ty_to_string(ty), span: sum_span, sub });
1374
1375         Ok(())
1376     }
1377
1378     pub(super) fn recover_from_prefix_increment(
1379         &mut self,
1380         operand_expr: P<Expr>,
1381         op_span: Span,
1382         prev_is_semi: bool,
1383     ) -> PResult<'a, P<Expr>> {
1384         let standalone =
1385             if prev_is_semi { IsStandalone::Standalone } else { IsStandalone::Subexpr };
1386         let kind = IncDecRecovery { standalone, op: IncOrDec::Inc, fixity: UnaryFixity::Pre };
1387
1388         self.recover_from_inc_dec(operand_expr, kind, op_span)
1389     }
1390
1391     pub(super) fn recover_from_postfix_increment(
1392         &mut self,
1393         operand_expr: P<Expr>,
1394         op_span: Span,
1395     ) -> PResult<'a, P<Expr>> {
1396         let kind = IncDecRecovery {
1397             standalone: IsStandalone::Maybe,
1398             op: IncOrDec::Inc,
1399             fixity: UnaryFixity::Post,
1400         };
1401
1402         self.recover_from_inc_dec(operand_expr, kind, op_span)
1403     }
1404
1405     fn recover_from_inc_dec(
1406         &mut self,
1407         base: P<Expr>,
1408         kind: IncDecRecovery,
1409         op_span: Span,
1410     ) -> PResult<'a, P<Expr>> {
1411         let mut err = self.struct_span_err(
1412             op_span,
1413             &format!("Rust has no {} {} operator", kind.fixity, kind.op.name()),
1414         );
1415         err.span_label(op_span, &format!("not a valid {} operator", kind.fixity));
1416
1417         let help_base_case = |mut err: DiagnosticBuilder<'_, _>, base| {
1418             err.help(&format!("use `{}= 1` instead", kind.op.chr()));
1419             err.emit();
1420             Ok(base)
1421         };
1422
1423         // (pre, post)
1424         let spans = match kind.fixity {
1425             UnaryFixity::Pre => (op_span, base.span.shrink_to_hi()),
1426             UnaryFixity::Post => (base.span.shrink_to_lo(), op_span),
1427         };
1428
1429         match kind.standalone {
1430             IsStandalone::Standalone => self.inc_dec_standalone_suggest(kind, spans).emit(&mut err),
1431             IsStandalone::Subexpr => {
1432                 let Ok(base_src) = self.span_to_snippet(base.span)
1433                     else { return help_base_case(err, base) };
1434                 match kind.fixity {
1435                     UnaryFixity::Pre => {
1436                         self.prefix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
1437                     }
1438                     UnaryFixity::Post => {
1439                         self.postfix_inc_dec_suggest(base_src, kind, spans).emit(&mut err)
1440                     }
1441                 }
1442             }
1443             IsStandalone::Maybe => {
1444                 let Ok(base_src) = self.span_to_snippet(base.span)
1445                     else { return help_base_case(err, base) };
1446                 let sugg1 = match kind.fixity {
1447                     UnaryFixity::Pre => self.prefix_inc_dec_suggest(base_src, kind, spans),
1448                     UnaryFixity::Post => self.postfix_inc_dec_suggest(base_src, kind, spans),
1449                 };
1450                 let sugg2 = self.inc_dec_standalone_suggest(kind, spans);
1451                 MultiSugg::emit_many(
1452                     &mut err,
1453                     "use `+= 1` instead",
1454                     Applicability::Unspecified,
1455                     [sugg1, sugg2].into_iter(),
1456                 )
1457             }
1458         }
1459         Err(err)
1460     }
1461
1462     fn prefix_inc_dec_suggest(
1463         &mut self,
1464         base_src: String,
1465         kind: IncDecRecovery,
1466         (pre_span, post_span): (Span, Span),
1467     ) -> MultiSugg {
1468         MultiSugg {
1469             msg: format!("use `{}= 1` instead", kind.op.chr()),
1470             patches: vec![
1471                 (pre_span, "{ ".to_string()),
1472                 (post_span, format!(" {}= 1; {} }}", kind.op.chr(), base_src)),
1473             ],
1474             applicability: Applicability::MachineApplicable,
1475         }
1476     }
1477
1478     fn postfix_inc_dec_suggest(
1479         &mut self,
1480         base_src: String,
1481         kind: IncDecRecovery,
1482         (pre_span, post_span): (Span, Span),
1483     ) -> MultiSugg {
1484         let tmp_var = if base_src.trim() == "tmp" { "tmp_" } else { "tmp" };
1485         MultiSugg {
1486             msg: format!("use `{}= 1` instead", kind.op.chr()),
1487             patches: vec![
1488                 (pre_span, format!("{{ let {} = ", tmp_var)),
1489                 (post_span, format!("; {} {}= 1; {} }}", base_src, kind.op.chr(), tmp_var)),
1490             ],
1491             applicability: Applicability::HasPlaceholders,
1492         }
1493     }
1494
1495     fn inc_dec_standalone_suggest(
1496         &mut self,
1497         kind: IncDecRecovery,
1498         (pre_span, post_span): (Span, Span),
1499     ) -> MultiSugg {
1500         MultiSugg {
1501             msg: format!("use `{}= 1` instead", kind.op.chr()),
1502             patches: vec![(pre_span, String::new()), (post_span, format!(" {}= 1", kind.op.chr()))],
1503             applicability: Applicability::MachineApplicable,
1504         }
1505     }
1506
1507     /// Tries to recover from associated item paths like `[T]::AssocItem` / `(T, U)::AssocItem`.
1508     /// Attempts to convert the base expression/pattern/type into a type, parses the `::AssocItem`
1509     /// tail, and combines them into a `<Ty>::AssocItem` expression/pattern/type.
1510     pub(super) fn maybe_recover_from_bad_qpath<T: RecoverQPath>(
1511         &mut self,
1512         base: P<T>,
1513     ) -> PResult<'a, P<T>> {
1514         // Do not add `::` to expected tokens.
1515         if self.token == token::ModSep {
1516             if let Some(ty) = base.to_ty() {
1517                 return self.maybe_recover_from_bad_qpath_stage_2(ty.span, ty);
1518             }
1519         }
1520         Ok(base)
1521     }
1522
1523     /// Given an already parsed `Ty`, parses the `::AssocItem` tail and
1524     /// combines them into a `<Ty>::AssocItem` expression/pattern/type.
1525     pub(super) fn maybe_recover_from_bad_qpath_stage_2<T: RecoverQPath>(
1526         &mut self,
1527         ty_span: Span,
1528         ty: P<Ty>,
1529     ) -> PResult<'a, P<T>> {
1530         self.expect(&token::ModSep)?;
1531
1532         let mut path = ast::Path { segments: Vec::new(), span: DUMMY_SP, tokens: None };
1533         self.parse_path_segments(&mut path.segments, T::PATH_STYLE, None)?;
1534         path.span = ty_span.to(self.prev_token.span);
1535
1536         let ty_str = self.span_to_snippet(ty_span).unwrap_or_else(|_| pprust::ty_to_string(&ty));
1537         self.sess.emit_err(BadQPathStage2 {
1538             span: path.span,
1539             ty: format!("<{}>::{}", ty_str, pprust::path_to_string(&path)),
1540         });
1541
1542         let path_span = ty_span.shrink_to_hi(); // Use an empty path since `position == 0`.
1543         Ok(P(T::recovered(Some(QSelf { ty, path_span, position: 0 }), path)))
1544     }
1545
1546     pub fn maybe_consume_incorrect_semicolon(&mut self, items: &[P<Item>]) -> bool {
1547         if self.token.kind == TokenKind::Semi {
1548             self.bump();
1549
1550             let mut err =
1551                 IncorrectSemicolon { span: self.prev_token.span, opt_help: None, name: "" };
1552
1553             if !items.is_empty() {
1554                 let previous_item = &items[items.len() - 1];
1555                 let previous_item_kind_name = match previous_item.kind {
1556                     // Say "braced struct" because tuple-structs and
1557                     // braceless-empty-struct declarations do take a semicolon.
1558                     ItemKind::Struct(..) => Some("braced struct"),
1559                     ItemKind::Enum(..) => Some("enum"),
1560                     ItemKind::Trait(..) => Some("trait"),
1561                     ItemKind::Union(..) => Some("union"),
1562                     _ => None,
1563                 };
1564                 if let Some(name) = previous_item_kind_name {
1565                     err.opt_help = Some(());
1566                     err.name = name;
1567                 }
1568             }
1569             self.sess.emit_err(err);
1570             true
1571         } else {
1572             false
1573         }
1574     }
1575
1576     /// Creates a `DiagnosticBuilder` for an unexpected token `t` and tries to recover if it is a
1577     /// closing delimiter.
1578     pub(super) fn unexpected_try_recover(
1579         &mut self,
1580         t: &TokenKind,
1581     ) -> PResult<'a, bool /* recovered */> {
1582         let token_str = pprust::token_kind_to_string(t);
1583         let this_token_str = super::token_descr(&self.token);
1584         let (prev_sp, sp) = match (&self.token.kind, self.subparser_name) {
1585             // Point at the end of the macro call when reaching end of macro arguments.
1586             (token::Eof, Some(_)) => {
1587                 let sp = self.sess.source_map().next_point(self.prev_token.span);
1588                 (sp, sp)
1589             }
1590             // We don't want to point at the following span after DUMMY_SP.
1591             // This happens when the parser finds an empty TokenStream.
1592             _ if self.prev_token.span == DUMMY_SP => (self.token.span, self.token.span),
1593             // EOF, don't want to point at the following char, but rather the last token.
1594             (token::Eof, None) => (self.prev_token.span, self.token.span),
1595             _ => (self.prev_token.span.shrink_to_hi(), self.token.span),
1596         };
1597         let msg = format!(
1598             "expected `{}`, found {}",
1599             token_str,
1600             match (&self.token.kind, self.subparser_name) {
1601                 (token::Eof, Some(origin)) => format!("end of {origin}"),
1602                 _ => this_token_str,
1603             },
1604         );
1605         let mut err = self.struct_span_err(sp, &msg);
1606         let label_exp = format!("expected `{token_str}`");
1607         match self.recover_closing_delimiter(&[t.clone()], err) {
1608             Err(e) => err = e,
1609             Ok(recovered) => {
1610                 return Ok(recovered);
1611             }
1612         }
1613         let sm = self.sess.source_map();
1614         if !sm.is_multiline(prev_sp.until(sp)) {
1615             // When the spans are in the same line, it means that the only content
1616             // between them is whitespace, point only at the found token.
1617             err.span_label(sp, label_exp);
1618         } else {
1619             err.span_label(prev_sp, label_exp);
1620             err.span_label(sp, "unexpected token");
1621         }
1622         Err(err)
1623     }
1624
1625     pub(super) fn expect_semi(&mut self) -> PResult<'a, ()> {
1626         if self.eat(&token::Semi) {
1627             return Ok(());
1628         }
1629         self.expect(&token::Semi).map(drop) // Error unconditionally
1630     }
1631
1632     /// Consumes alternative await syntaxes like `await!(<expr>)`, `await <expr>`,
1633     /// `await? <expr>`, `await(<expr>)`, and `await { <expr> }`.
1634     pub(super) fn recover_incorrect_await_syntax(
1635         &mut self,
1636         lo: Span,
1637         await_sp: Span,
1638         attrs: AttrVec,
1639     ) -> PResult<'a, P<Expr>> {
1640         let (hi, expr, is_question) = if self.token == token::Not {
1641             // Handle `await!(<expr>)`.
1642             self.recover_await_macro()?
1643         } else {
1644             self.recover_await_prefix(await_sp)?
1645         };
1646         let sp = self.error_on_incorrect_await(lo, hi, &expr, is_question);
1647         let kind = match expr.kind {
1648             // Avoid knock-down errors as we don't know whether to interpret this as `foo().await?`
1649             // or `foo()?.await` (the very reason we went with postfix syntax ðŸ˜…).
1650             ExprKind::Try(_) => ExprKind::Err,
1651             _ => ExprKind::Await(expr),
1652         };
1653         let expr = self.mk_expr(lo.to(sp), kind, attrs);
1654         self.maybe_recover_from_bad_qpath(expr)
1655     }
1656
1657     fn recover_await_macro(&mut self) -> PResult<'a, (Span, P<Expr>, bool)> {
1658         self.expect(&token::Not)?;
1659         self.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
1660         let expr = self.parse_expr()?;
1661         self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
1662         Ok((self.prev_token.span, expr, false))
1663     }
1664
1665     fn recover_await_prefix(&mut self, await_sp: Span) -> PResult<'a, (Span, P<Expr>, bool)> {
1666         let is_question = self.eat(&token::Question); // Handle `await? <expr>`.
1667         let expr = if self.token == token::OpenDelim(Delimiter::Brace) {
1668             // Handle `await { <expr> }`.
1669             // This needs to be handled separately from the next arm to avoid
1670             // interpreting `await { <expr> }?` as `<expr>?.await`.
1671             self.parse_block_expr(None, self.token.span, BlockCheckMode::Default, AttrVec::new())
1672         } else {
1673             self.parse_expr()
1674         }
1675         .map_err(|mut err| {
1676             err.span_label(await_sp, "while parsing this incorrect await expression");
1677             err
1678         })?;
1679         Ok((expr.span, expr, is_question))
1680     }
1681
1682     fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: bool) -> Span {
1683         let span = lo.to(hi);
1684         let applicability = match expr.kind {
1685             ExprKind::Try(_) => Applicability::MaybeIncorrect, // `await <expr>?`
1686             _ => Applicability::MachineApplicable,
1687         };
1688
1689         self.sess.emit_err(IncorrectAwait {
1690             span,
1691             sugg_span: (span, applicability),
1692             expr: self.span_to_snippet(expr.span).unwrap_or_else(|_| pprust::expr_to_string(&expr)),
1693             question_mark: if is_question { "?" } else { "" },
1694         });
1695
1696         span
1697     }
1698
1699     /// If encountering `future.await()`, consumes and emits an error.
1700     pub(super) fn recover_from_await_method_call(&mut self) {
1701         if self.token == token::OpenDelim(Delimiter::Parenthesis)
1702             && self.look_ahead(1, |t| t == &token::CloseDelim(Delimiter::Parenthesis))
1703         {
1704             // future.await()
1705             let lo = self.token.span;
1706             self.bump(); // (
1707             let span = lo.to(self.token.span);
1708             self.bump(); // )
1709
1710             self.sess.emit_err(IncorrectUseOfAwait { span });
1711         }
1712     }
1713
1714     pub(super) fn try_macro_suggestion(&mut self) -> PResult<'a, P<Expr>> {
1715         let is_try = self.token.is_keyword(kw::Try);
1716         let is_questionmark = self.look_ahead(1, |t| t == &token::Not); //check for !
1717         let is_open = self.look_ahead(2, |t| t == &token::OpenDelim(Delimiter::Parenthesis)); //check for (
1718
1719         if is_try && is_questionmark && is_open {
1720             let lo = self.token.span;
1721             self.bump(); //remove try
1722             self.bump(); //remove !
1723             let try_span = lo.to(self.token.span); //we take the try!( span
1724             self.bump(); //remove (
1725             let is_empty = self.token == token::CloseDelim(Delimiter::Parenthesis); //check if the block is empty
1726             self.consume_block(Delimiter::Parenthesis, ConsumeClosingDelim::No); //eat the block
1727             let hi = self.token.span;
1728             self.bump(); //remove )
1729             let mut err = self.struct_span_err(lo.to(hi), "use of deprecated `try` macro");
1730             err.note("in the 2018 edition `try` is a reserved keyword, and the `try!()` macro is deprecated");
1731             let prefix = if is_empty { "" } else { "alternatively, " };
1732             if !is_empty {
1733                 err.multipart_suggestion(
1734                     "you can use the `?` operator instead",
1735                     vec![(try_span, "".to_owned()), (hi, "?".to_owned())],
1736                     Applicability::MachineApplicable,
1737                 );
1738             }
1739             err.span_suggestion(lo.shrink_to_lo(), &format!("{prefix}you can still access the deprecated `try!()` macro using the \"raw identifier\" syntax"), "r#", Applicability::MachineApplicable);
1740             err.emit();
1741             Ok(self.mk_expr_err(lo.to(hi)))
1742         } else {
1743             Err(self.expected_expression_found()) // The user isn't trying to invoke the try! macro
1744         }
1745     }
1746
1747     /// Recovers a situation like `for ( $pat in $expr )`
1748     /// and suggest writing `for $pat in $expr` instead.
1749     ///
1750     /// This should be called before parsing the `$block`.
1751     pub(super) fn recover_parens_around_for_head(
1752         &mut self,
1753         pat: P<Pat>,
1754         begin_paren: Option<Span>,
1755     ) -> P<Pat> {
1756         match (&self.token.kind, begin_paren) {
1757             (token::CloseDelim(Delimiter::Parenthesis), Some(begin_par_sp)) => {
1758                 self.bump();
1759
1760                 self.struct_span_err(
1761                     MultiSpan::from_spans(vec![begin_par_sp, self.prev_token.span]),
1762                     "unexpected parentheses surrounding `for` loop head",
1763                 )
1764                 .multipart_suggestion(
1765                     "remove parentheses in `for` loop",
1766                     vec![(begin_par_sp, String::new()), (self.prev_token.span, String::new())],
1767                     // With e.g. `for (x) in y)` this would replace `(x) in y)`
1768                     // with `x) in y)` which is syntactically invalid.
1769                     // However, this is prevented before we get here.
1770                     Applicability::MachineApplicable,
1771                 )
1772                 .emit();
1773
1774                 // Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint.
1775                 pat.and_then(|pat| match pat.kind {
1776                     PatKind::Paren(pat) => pat,
1777                     _ => P(pat),
1778                 })
1779             }
1780             _ => pat,
1781         }
1782     }
1783
1784     pub(super) fn could_ascription_be_path(&self, node: &ast::ExprKind) -> bool {
1785         (self.token == token::Lt && // `foo:<bar`, likely a typoed turbofish.
1786             self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()))
1787             || self.token.is_ident() &&
1788             matches!(node, ast::ExprKind::Path(..) | ast::ExprKind::Field(..)) &&
1789             !self.token.is_reserved_ident() &&           // v `foo:bar(baz)`
1790             self.look_ahead(1, |t| t == &token::OpenDelim(Delimiter::Parenthesis))
1791             || self.look_ahead(1, |t| t == &token::OpenDelim(Delimiter::Brace)) // `foo:bar {`
1792             || self.look_ahead(1, |t| t == &token::Colon) &&     // `foo:bar::<baz`
1793             self.look_ahead(2, |t| t == &token::Lt) &&
1794             self.look_ahead(3, |t| t.is_ident())
1795             || self.look_ahead(1, |t| t == &token::Colon) &&  // `foo:bar:baz`
1796             self.look_ahead(2, |t| t.is_ident())
1797             || self.look_ahead(1, |t| t == &token::ModSep)
1798                 && (self.look_ahead(2, |t| t.is_ident()) ||   // `foo:bar::baz`
1799             self.look_ahead(2, |t| t == &token::Lt)) // `foo:bar::<baz>`
1800     }
1801
1802     pub(super) fn recover_seq_parse_error(
1803         &mut self,
1804         delim: Delimiter,
1805         lo: Span,
1806         result: PResult<'a, P<Expr>>,
1807     ) -> P<Expr> {
1808         match result {
1809             Ok(x) => x,
1810             Err(mut err) => {
1811                 err.emit();
1812                 // Recover from parse error, callers expect the closing delim to be consumed.
1813                 self.consume_block(delim, ConsumeClosingDelim::Yes);
1814                 self.mk_expr(lo.to(self.prev_token.span), ExprKind::Err, AttrVec::new())
1815             }
1816         }
1817     }
1818
1819     pub(super) fn recover_closing_delimiter(
1820         &mut self,
1821         tokens: &[TokenKind],
1822         mut err: DiagnosticBuilder<'a, ErrorGuaranteed>,
1823     ) -> PResult<'a, bool> {
1824         let mut pos = None;
1825         // We want to use the last closing delim that would apply.
1826         for (i, unmatched) in self.unclosed_delims.iter().enumerate().rev() {
1827             if tokens.contains(&token::CloseDelim(unmatched.expected_delim))
1828                 && Some(self.token.span) > unmatched.unclosed_span
1829             {
1830                 pos = Some(i);
1831             }
1832         }
1833         match pos {
1834             Some(pos) => {
1835                 // Recover and assume that the detected unclosed delimiter was meant for
1836                 // this location. Emit the diagnostic and act as if the delimiter was
1837                 // present for the parser's sake.
1838
1839                 // Don't attempt to recover from this unclosed delimiter more than once.
1840                 let unmatched = self.unclosed_delims.remove(pos);
1841                 let delim = TokenType::Token(token::CloseDelim(unmatched.expected_delim));
1842                 if unmatched.found_delim.is_none() {
1843                     // We encountered `Eof`, set this fact here to avoid complaining about missing
1844                     // `fn main()` when we found place to suggest the closing brace.
1845                     *self.sess.reached_eof.borrow_mut() = true;
1846                 }
1847
1848                 // We want to suggest the inclusion of the closing delimiter where it makes
1849                 // the most sense, which is immediately after the last token:
1850                 //
1851                 //  {foo(bar {}}
1852                 //      ^      ^
1853                 //      |      |
1854                 //      |      help: `)` may belong here
1855                 //      |
1856                 //      unclosed delimiter
1857                 if let Some(sp) = unmatched.unclosed_span {
1858                     let mut primary_span: Vec<Span> =
1859                         err.span.primary_spans().iter().cloned().collect();
1860                     primary_span.push(sp);
1861                     let mut primary_span: MultiSpan = primary_span.into();
1862                     for span_label in err.span.span_labels() {
1863                         if let Some(label) = span_label.label {
1864                             primary_span.push_span_label(span_label.span, label);
1865                         }
1866                     }
1867                     err.set_span(primary_span);
1868                     err.span_label(sp, "unclosed delimiter");
1869                 }
1870                 // Backticks should be removed to apply suggestions.
1871                 let mut delim = delim.to_string();
1872                 delim.retain(|c| c != '`');
1873                 err.span_suggestion_short(
1874                     self.prev_token.span.shrink_to_hi(),
1875                     &format!("`{delim}` may belong here"),
1876                     delim,
1877                     Applicability::MaybeIncorrect,
1878                 );
1879                 if unmatched.found_delim.is_none() {
1880                     // Encountered `Eof` when lexing blocks. Do not recover here to avoid knockdown
1881                     // errors which would be emitted elsewhere in the parser and let other error
1882                     // recovery consume the rest of the file.
1883                     Err(err)
1884                 } else {
1885                     err.emit();
1886                     self.expected_tokens.clear(); // Reduce the number of errors.
1887                     Ok(true)
1888                 }
1889             }
1890             _ => Err(err),
1891         }
1892     }
1893
1894     /// Eats tokens until we can be relatively sure we reached the end of the
1895     /// statement. This is something of a best-effort heuristic.
1896     ///
1897     /// We terminate when we find an unmatched `}` (without consuming it).
1898     pub(super) fn recover_stmt(&mut self) {
1899         self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore)
1900     }
1901
1902     /// If `break_on_semi` is `Break`, then we will stop consuming tokens after
1903     /// finding (and consuming) a `;` outside of `{}` or `[]` (note that this is
1904     /// approximate -- it can mean we break too early due to macros, but that
1905     /// should only lead to sub-optimal recovery, not inaccurate parsing).
1906     ///
1907     /// If `break_on_block` is `Break`, then we will stop consuming tokens
1908     /// after finding (and consuming) a brace-delimited block.
1909     pub(super) fn recover_stmt_(
1910         &mut self,
1911         break_on_semi: SemiColonMode,
1912         break_on_block: BlockMode,
1913     ) {
1914         let mut brace_depth = 0;
1915         let mut bracket_depth = 0;
1916         let mut in_block = false;
1917         debug!("recover_stmt_ enter loop (semi={:?}, block={:?})", break_on_semi, break_on_block);
1918         loop {
1919             debug!("recover_stmt_ loop {:?}", self.token);
1920             match self.token.kind {
1921                 token::OpenDelim(Delimiter::Brace) => {
1922                     brace_depth += 1;
1923                     self.bump();
1924                     if break_on_block == BlockMode::Break && brace_depth == 1 && bracket_depth == 0
1925                     {
1926                         in_block = true;
1927                     }
1928                 }
1929                 token::OpenDelim(Delimiter::Bracket) => {
1930                     bracket_depth += 1;
1931                     self.bump();
1932                 }
1933                 token::CloseDelim(Delimiter::Brace) => {
1934                     if brace_depth == 0 {
1935                         debug!("recover_stmt_ return - close delim {:?}", self.token);
1936                         break;
1937                     }
1938                     brace_depth -= 1;
1939                     self.bump();
1940                     if in_block && bracket_depth == 0 && brace_depth == 0 {
1941                         debug!("recover_stmt_ return - block end {:?}", self.token);
1942                         break;
1943                     }
1944                 }
1945                 token::CloseDelim(Delimiter::Bracket) => {
1946                     bracket_depth -= 1;
1947                     if bracket_depth < 0 {
1948                         bracket_depth = 0;
1949                     }
1950                     self.bump();
1951                 }
1952                 token::Eof => {
1953                     debug!("recover_stmt_ return - Eof");
1954                     break;
1955                 }
1956                 token::Semi => {
1957                     self.bump();
1958                     if break_on_semi == SemiColonMode::Break
1959                         && brace_depth == 0
1960                         && bracket_depth == 0
1961                     {
1962                         debug!("recover_stmt_ return - Semi");
1963                         break;
1964                     }
1965                 }
1966                 token::Comma
1967                     if break_on_semi == SemiColonMode::Comma
1968                         && brace_depth == 0
1969                         && bracket_depth == 0 =>
1970                 {
1971                     debug!("recover_stmt_ return - Semi");
1972                     break;
1973                 }
1974                 _ => self.bump(),
1975             }
1976         }
1977     }
1978
1979     pub(super) fn check_for_for_in_in_typo(&mut self, in_span: Span) {
1980         if self.eat_keyword(kw::In) {
1981             // a common typo: `for _ in in bar {}`
1982             self.sess.emit_err(InInTypo {
1983                 span: self.prev_token.span,
1984                 sugg_span: in_span.until(self.prev_token.span),
1985             });
1986         }
1987     }
1988
1989     pub(super) fn eat_incorrect_doc_comment_for_param_type(&mut self) {
1990         if let token::DocComment(..) = self.token.kind {
1991             self.struct_span_err(
1992                 self.token.span,
1993                 "documentation comments cannot be applied to a function parameter's type",
1994             )
1995             .span_label(self.token.span, "doc comments are not allowed here")
1996             .emit();
1997             self.bump();
1998         } else if self.token == token::Pound
1999             && self.look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Bracket))
2000         {
2001             let lo = self.token.span;
2002             // Skip every token until next possible arg.
2003             while self.token != token::CloseDelim(Delimiter::Bracket) {
2004                 self.bump();
2005             }
2006             let sp = lo.to(self.token.span);
2007             self.bump();
2008             self.struct_span_err(sp, "attributes cannot be applied to a function parameter's type")
2009                 .span_label(sp, "attributes are not allowed here")
2010                 .emit();
2011         }
2012     }
2013
2014     pub(super) fn parameter_without_type(
2015         &mut self,
2016         err: &mut Diagnostic,
2017         pat: P<ast::Pat>,
2018         require_name: bool,
2019         first_param: bool,
2020     ) -> Option<Ident> {
2021         // If we find a pattern followed by an identifier, it could be an (incorrect)
2022         // C-style parameter declaration.
2023         if self.check_ident()
2024             && self.look_ahead(1, |t| {
2025                 *t == token::Comma || *t == token::CloseDelim(Delimiter::Parenthesis)
2026             })
2027         {
2028             // `fn foo(String s) {}`
2029             let ident = self.parse_ident().unwrap();
2030             let span = pat.span.with_hi(ident.span.hi());
2031
2032             err.span_suggestion(
2033                 span,
2034                 "declare the type after the parameter binding",
2035                 "<identifier>: <type>",
2036                 Applicability::HasPlaceholders,
2037             );
2038             return Some(ident);
2039         } else if require_name
2040             && (self.token == token::Comma
2041                 || self.token == token::Lt
2042                 || self.token == token::CloseDelim(Delimiter::Parenthesis))
2043         {
2044             let rfc_note = "anonymous parameters are removed in the 2018 edition (see RFC 1685)";
2045
2046             let (ident, self_sugg, param_sugg, type_sugg, self_span, param_span, type_span) =
2047                 match pat.kind {
2048                     PatKind::Ident(_, ident, _) => (
2049                         ident,
2050                         "self: ",
2051                         ": TypeName".to_string(),
2052                         "_: ",
2053                         pat.span.shrink_to_lo(),
2054                         pat.span.shrink_to_hi(),
2055                         pat.span.shrink_to_lo(),
2056                     ),
2057                     // Also catches `fn foo(&a)`.
2058                     PatKind::Ref(ref inner_pat, mutab)
2059                         if matches!(inner_pat.clone().into_inner().kind, PatKind::Ident(..)) =>
2060                     {
2061                         match inner_pat.clone().into_inner().kind {
2062                             PatKind::Ident(_, ident, _) => {
2063                                 let mutab = mutab.prefix_str();
2064                                 (
2065                                     ident,
2066                                     "self: ",
2067                                     format!("{ident}: &{mutab}TypeName"),
2068                                     "_: ",
2069                                     pat.span.shrink_to_lo(),
2070                                     pat.span,
2071                                     pat.span.shrink_to_lo(),
2072                                 )
2073                             }
2074                             _ => unreachable!(),
2075                         }
2076                     }
2077                     _ => {
2078                         // Otherwise, try to get a type and emit a suggestion.
2079                         if let Some(ty) = pat.to_ty() {
2080                             err.span_suggestion_verbose(
2081                                 pat.span,
2082                                 "explicitly ignore the parameter name",
2083                                 format!("_: {}", pprust::ty_to_string(&ty)),
2084                                 Applicability::MachineApplicable,
2085                             );
2086                             err.note(rfc_note);
2087                         }
2088
2089                         return None;
2090                     }
2091                 };
2092
2093             // `fn foo(a, b) {}`, `fn foo(a<x>, b<y>) {}` or `fn foo(usize, usize) {}`
2094             if first_param {
2095                 err.span_suggestion(
2096                     self_span,
2097                     "if this is a `self` type, give it a parameter name",
2098                     self_sugg,
2099                     Applicability::MaybeIncorrect,
2100                 );
2101             }
2102             // Avoid suggesting that `fn foo(HashMap<u32>)` is fixed with a change to
2103             // `fn foo(HashMap: TypeName<u32>)`.
2104             if self.token != token::Lt {
2105                 err.span_suggestion(
2106                     param_span,
2107                     "if this is a parameter name, give it a type",
2108                     param_sugg,
2109                     Applicability::HasPlaceholders,
2110                 );
2111             }
2112             err.span_suggestion(
2113                 type_span,
2114                 "if this is a type, explicitly ignore the parameter name",
2115                 type_sugg,
2116                 Applicability::MachineApplicable,
2117             );
2118             err.note(rfc_note);
2119
2120             // Don't attempt to recover by using the `X` in `X<Y>` as the parameter name.
2121             return if self.token == token::Lt { None } else { Some(ident) };
2122         }
2123         None
2124     }
2125
2126     pub(super) fn recover_arg_parse(&mut self) -> PResult<'a, (P<ast::Pat>, P<ast::Ty>)> {
2127         let pat = self.parse_pat_no_top_alt(Some("argument name"))?;
2128         self.expect(&token::Colon)?;
2129         let ty = self.parse_ty()?;
2130
2131         struct_span_err!(
2132             self.diagnostic(),
2133             pat.span,
2134             E0642,
2135             "patterns aren't allowed in methods without bodies",
2136         )
2137         .span_suggestion_short(
2138             pat.span,
2139             "give this argument a name or use an underscore to ignore it",
2140             "_",
2141             Applicability::MachineApplicable,
2142         )
2143         .emit();
2144
2145         // Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
2146         let pat =
2147             P(Pat { kind: PatKind::Wild, span: pat.span, id: ast::DUMMY_NODE_ID, tokens: None });
2148         Ok((pat, ty))
2149     }
2150
2151     pub(super) fn recover_bad_self_param(&mut self, mut param: Param) -> PResult<'a, Param> {
2152         let sp = param.pat.span;
2153         param.ty.kind = TyKind::Err;
2154         self.struct_span_err(sp, "unexpected `self` parameter in function")
2155             .span_label(sp, "must be the first parameter of an associated function")
2156             .emit();
2157         Ok(param)
2158     }
2159
2160     pub(super) fn consume_block(&mut self, delim: Delimiter, consume_close: ConsumeClosingDelim) {
2161         let mut brace_depth = 0;
2162         loop {
2163             if self.eat(&token::OpenDelim(delim)) {
2164                 brace_depth += 1;
2165             } else if self.check(&token::CloseDelim(delim)) {
2166                 if brace_depth == 0 {
2167                     if let ConsumeClosingDelim::Yes = consume_close {
2168                         // Some of the callers of this method expect to be able to parse the
2169                         // closing delimiter themselves, so we leave it alone. Otherwise we advance
2170                         // the parser.
2171                         self.bump();
2172                     }
2173                     return;
2174                 } else {
2175                     self.bump();
2176                     brace_depth -= 1;
2177                     continue;
2178                 }
2179             } else if self.token == token::Eof {
2180                 return;
2181             } else {
2182                 self.bump();
2183             }
2184         }
2185     }
2186
2187     pub(super) fn expected_expression_found(&self) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
2188         let (span, msg) = match (&self.token.kind, self.subparser_name) {
2189             (&token::Eof, Some(origin)) => {
2190                 let sp = self.sess.source_map().next_point(self.prev_token.span);
2191                 (sp, format!("expected expression, found end of {origin}"))
2192             }
2193             _ => (
2194                 self.token.span,
2195                 format!("expected expression, found {}", super::token_descr(&self.token),),
2196             ),
2197         };
2198         let mut err = self.struct_span_err(span, &msg);
2199         let sp = self.sess.source_map().start_point(self.token.span);
2200         if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) {
2201             self.sess.expr_parentheses_needed(&mut err, *sp);
2202         }
2203         err.span_label(span, "expected expression");
2204         err
2205     }
2206
2207     fn consume_tts(
2208         &mut self,
2209         mut acc: i64, // `i64` because malformed code can have more closing delims than opening.
2210         // Not using `FxHashMap` due to `token::TokenKind: !Eq + !Hash`.
2211         modifier: &[(token::TokenKind, i64)],
2212     ) {
2213         while acc > 0 {
2214             if let Some((_, val)) = modifier.iter().find(|(t, _)| *t == self.token.kind) {
2215                 acc += *val;
2216             }
2217             if self.token.kind == token::Eof {
2218                 break;
2219             }
2220             self.bump();
2221         }
2222     }
2223
2224     /// Replace duplicated recovered parameters with `_` pattern to avoid unnecessary errors.
2225     ///
2226     /// This is necessary because at this point we don't know whether we parsed a function with
2227     /// anonymous parameters or a function with names but no types. In order to minimize
2228     /// unnecessary errors, we assume the parameters are in the shape of `fn foo(a, b, c)` where
2229     /// the parameters are *names* (so we don't emit errors about not being able to find `b` in
2230     /// the local scope), but if we find the same name multiple times, like in `fn foo(i8, i8)`,
2231     /// we deduplicate them to not complain about duplicated parameter names.
2232     pub(super) fn deduplicate_recovered_params_names(&self, fn_inputs: &mut Vec<Param>) {
2233         let mut seen_inputs = FxHashSet::default();
2234         for input in fn_inputs.iter_mut() {
2235             let opt_ident = if let (PatKind::Ident(_, ident, _), TyKind::Err) =
2236                 (&input.pat.kind, &input.ty.kind)
2237             {
2238                 Some(*ident)
2239             } else {
2240                 None
2241             };
2242             if let Some(ident) = opt_ident {
2243                 if seen_inputs.contains(&ident) {
2244                     input.pat.kind = PatKind::Wild;
2245                 }
2246                 seen_inputs.insert(ident);
2247             }
2248         }
2249     }
2250
2251     /// Handle encountering a symbol in a generic argument list that is not a `,` or `>`. In this
2252     /// case, we emit an error and try to suggest enclosing a const argument in braces if it looks
2253     /// like the user has forgotten them.
2254     pub fn handle_ambiguous_unbraced_const_arg(
2255         &mut self,
2256         args: &mut Vec<AngleBracketedArg>,
2257     ) -> PResult<'a, bool> {
2258         // If we haven't encountered a closing `>`, then the argument is malformed.
2259         // It's likely that the user has written a const expression without enclosing it
2260         // in braces, so we try to recover here.
2261         let arg = args.pop().unwrap();
2262         // FIXME: for some reason using `unexpected` or `expected_one_of_not_found` has
2263         // adverse side-effects to subsequent errors and seems to advance the parser.
2264         // We are causing this error here exclusively in case that a `const` expression
2265         // could be recovered from the current parser state, even if followed by more
2266         // arguments after a comma.
2267         let mut err = self.struct_span_err(
2268             self.token.span,
2269             &format!("expected one of `,` or `>`, found {}", super::token_descr(&self.token)),
2270         );
2271         err.span_label(self.token.span, "expected one of `,` or `>`");
2272         match self.recover_const_arg(arg.span(), err) {
2273             Ok(arg) => {
2274                 args.push(AngleBracketedArg::Arg(arg));
2275                 if self.eat(&token::Comma) {
2276                     return Ok(true); // Continue
2277                 }
2278             }
2279             Err(mut err) => {
2280                 args.push(arg);
2281                 // We will emit a more generic error later.
2282                 err.delay_as_bug();
2283             }
2284         }
2285         return Ok(false); // Don't continue.
2286     }
2287
2288     /// Attempt to parse a generic const argument that has not been enclosed in braces.
2289     /// There are a limited number of expressions that are permitted without being encoded
2290     /// in braces:
2291     /// - Literals.
2292     /// - Single-segment paths (i.e. standalone generic const parameters).
2293     /// All other expressions that can be parsed will emit an error suggesting the expression be
2294     /// wrapped in braces.
2295     pub fn handle_unambiguous_unbraced_const_arg(&mut self) -> PResult<'a, P<Expr>> {
2296         let start = self.token.span;
2297         let expr = self.parse_expr_res(Restrictions::CONST_EXPR, None).map_err(|mut err| {
2298             err.span_label(
2299                 start.shrink_to_lo(),
2300                 "while parsing a const generic argument starting here",
2301             );
2302             err
2303         })?;
2304         if !self.expr_is_valid_const_arg(&expr) {
2305             self.struct_span_err(
2306                 expr.span,
2307                 "expressions must be enclosed in braces to be used as const generic \
2308                     arguments",
2309             )
2310             .multipart_suggestion(
2311                 "enclose the `const` expression in braces",
2312                 vec![
2313                     (expr.span.shrink_to_lo(), "{ ".to_string()),
2314                     (expr.span.shrink_to_hi(), " }".to_string()),
2315                 ],
2316                 Applicability::MachineApplicable,
2317             )
2318             .emit();
2319         }
2320         Ok(expr)
2321     }
2322
2323     fn recover_const_param_decl(&mut self, ty_generics: Option<&Generics>) -> Option<GenericArg> {
2324         let snapshot = self.create_snapshot_for_diagnostic();
2325         let param = match self.parse_const_param(vec![]) {
2326             Ok(param) => param,
2327             Err(err) => {
2328                 err.cancel();
2329                 self.restore_snapshot(snapshot);
2330                 return None;
2331             }
2332         };
2333         let mut err =
2334             self.struct_span_err(param.span(), "unexpected `const` parameter declaration");
2335         err.span_label(param.span(), "expected a `const` expression, not a parameter declaration");
2336         if let (Some(generics), Ok(snippet)) =
2337             (ty_generics, self.sess.source_map().span_to_snippet(param.span()))
2338         {
2339             let (span, sugg) = match &generics.params[..] {
2340                 [] => (generics.span, format!("<{snippet}>")),
2341                 [.., generic] => (generic.span().shrink_to_hi(), format!(", {snippet}")),
2342             };
2343             err.multipart_suggestion(
2344                 "`const` parameters must be declared for the `impl`",
2345                 vec![(span, sugg), (param.span(), param.ident.to_string())],
2346                 Applicability::MachineApplicable,
2347             );
2348         }
2349         let value = self.mk_expr_err(param.span());
2350         err.emit();
2351         Some(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }))
2352     }
2353
2354     pub fn recover_const_param_declaration(
2355         &mut self,
2356         ty_generics: Option<&Generics>,
2357     ) -> PResult<'a, Option<GenericArg>> {
2358         // We have to check for a few different cases.
2359         if let Some(arg) = self.recover_const_param_decl(ty_generics) {
2360             return Ok(Some(arg));
2361         }
2362
2363         // We haven't consumed `const` yet.
2364         let start = self.token.span;
2365         self.bump(); // `const`
2366
2367         // Detect and recover from the old, pre-RFC2000 syntax for const generics.
2368         let mut err = self
2369             .struct_span_err(start, "expected lifetime, type, or constant, found keyword `const`");
2370         if self.check_const_arg() {
2371             err.span_suggestion_verbose(
2372                 start.until(self.token.span),
2373                 "the `const` keyword is only needed in the definition of the type",
2374                 "",
2375                 Applicability::MaybeIncorrect,
2376             );
2377             err.emit();
2378             Ok(Some(GenericArg::Const(self.parse_const_arg()?)))
2379         } else {
2380             let after_kw_const = self.token.span;
2381             self.recover_const_arg(after_kw_const, err).map(Some)
2382         }
2383     }
2384
2385     /// Try to recover from possible generic const argument without `{` and `}`.
2386     ///
2387     /// When encountering code like `foo::< bar + 3 >` or `foo::< bar - baz >` we suggest
2388     /// `foo::<{ bar + 3 }>` and `foo::<{ bar - baz }>`, respectively. We only provide a suggestion
2389     /// if we think that that the resulting expression would be well formed.
2390     pub fn recover_const_arg(
2391         &mut self,
2392         start: Span,
2393         mut err: DiagnosticBuilder<'a, ErrorGuaranteed>,
2394     ) -> PResult<'a, GenericArg> {
2395         let is_op_or_dot = AssocOp::from_token(&self.token)
2396             .and_then(|op| {
2397                 if let AssocOp::Greater
2398                 | AssocOp::Less
2399                 | AssocOp::ShiftRight
2400                 | AssocOp::GreaterEqual
2401                 // Don't recover from `foo::<bar = baz>`, because this could be an attempt to
2402                 // assign a value to a defaulted generic parameter.
2403                 | AssocOp::Assign
2404                 | AssocOp::AssignOp(_) = op
2405                 {
2406                     None
2407                 } else {
2408                     Some(op)
2409                 }
2410             })
2411             .is_some()
2412             || self.token.kind == TokenKind::Dot;
2413         // This will be true when a trait object type `Foo +` or a path which was a `const fn` with
2414         // type params has been parsed.
2415         let was_op =
2416             matches!(self.prev_token.kind, token::BinOp(token::Plus | token::Shr) | token::Gt);
2417         if !is_op_or_dot && !was_op {
2418             // We perform these checks and early return to avoid taking a snapshot unnecessarily.
2419             return Err(err);
2420         }
2421         let snapshot = self.create_snapshot_for_diagnostic();
2422         if is_op_or_dot {
2423             self.bump();
2424         }
2425         match self.parse_expr_res(Restrictions::CONST_EXPR, None) {
2426             Ok(expr) => {
2427                 // Find a mistake like `MyTrait<Assoc == S::Assoc>`.
2428                 if token::EqEq == snapshot.token.kind {
2429                     err.span_suggestion(
2430                         snapshot.token.span,
2431                         "if you meant to use an associated type binding, replace `==` with `=`",
2432                         "=",
2433                         Applicability::MaybeIncorrect,
2434                     );
2435                     let value = self.mk_expr_err(start.to(expr.span));
2436                     err.emit();
2437                     return Ok(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }));
2438                 } else if token::Colon == snapshot.token.kind
2439                     && expr.span.lo() == snapshot.token.span.hi()
2440                     && matches!(expr.kind, ExprKind::Path(..))
2441                 {
2442                     // Find a mistake like "foo::var:A".
2443                     err.span_suggestion(
2444                         snapshot.token.span,
2445                         "write a path separator here",
2446                         "::",
2447                         Applicability::MaybeIncorrect,
2448                     );
2449                     err.emit();
2450                     return Ok(GenericArg::Type(self.mk_ty(start.to(expr.span), TyKind::Err)));
2451                 } else if token::Comma == self.token.kind || self.token.kind.should_end_const_arg()
2452                 {
2453                     // Avoid the following output by checking that we consumed a full const arg:
2454                     // help: expressions must be enclosed in braces to be used as const generic
2455                     //       arguments
2456                     //    |
2457                     // LL |     let sr: Vec<{ (u32, _, _) = vec![] };
2458                     //    |                 ^                      ^
2459                     return Ok(self.dummy_const_arg_needs_braces(err, start.to(expr.span)));
2460                 }
2461             }
2462             Err(err) => {
2463                 err.cancel();
2464             }
2465         }
2466         self.restore_snapshot(snapshot);
2467         Err(err)
2468     }
2469
2470     /// Creates a dummy const argument, and reports that the expression must be enclosed in braces
2471     pub fn dummy_const_arg_needs_braces(
2472         &self,
2473         mut err: DiagnosticBuilder<'a, ErrorGuaranteed>,
2474         span: Span,
2475     ) -> GenericArg {
2476         err.multipart_suggestion(
2477             "expressions must be enclosed in braces to be used as const generic \
2478              arguments",
2479             vec![(span.shrink_to_lo(), "{ ".to_string()), (span.shrink_to_hi(), " }".to_string())],
2480             Applicability::MaybeIncorrect,
2481         );
2482         let value = self.mk_expr_err(span);
2483         err.emit();
2484         GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })
2485     }
2486
2487     /// Get the diagnostics for the cases where `move async` is found.
2488     ///
2489     /// `move_async_span` starts at the 'm' of the move keyword and ends with the 'c' of the async keyword
2490     pub(super) fn incorrect_move_async_order_found(
2491         &self,
2492         move_async_span: Span,
2493     ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
2494         let mut err =
2495             self.struct_span_err(move_async_span, "the order of `move` and `async` is incorrect");
2496         err.span_suggestion_verbose(
2497             move_async_span,
2498             "try switching the order",
2499             "async move",
2500             Applicability::MaybeIncorrect,
2501         );
2502         err
2503     }
2504
2505     /// Some special error handling for the "top-level" patterns in a match arm,
2506     /// `for` loop, `let`, &c. (in contrast to subpatterns within such).
2507     pub(crate) fn maybe_recover_colon_colon_in_pat_typo(
2508         &mut self,
2509         mut first_pat: P<Pat>,
2510         expected: Expected,
2511     ) -> P<Pat> {
2512         if token::Colon != self.token.kind {
2513             return first_pat;
2514         }
2515         if !matches!(first_pat.kind, PatKind::Ident(_, _, None) | PatKind::Path(..))
2516             || !self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident())
2517         {
2518             return first_pat;
2519         }
2520         // The pattern looks like it might be a path with a `::` -> `:` typo:
2521         // `match foo { bar:baz => {} }`
2522         let span = self.token.span;
2523         // We only emit "unexpected `:`" error here if we can successfully parse the
2524         // whole pattern correctly in that case.
2525         let snapshot = self.create_snapshot_for_diagnostic();
2526
2527         // Create error for "unexpected `:`".
2528         match self.expected_one_of_not_found(&[], &[]) {
2529             Err(mut err) => {
2530                 self.bump(); // Skip the `:`.
2531                 match self.parse_pat_no_top_alt(expected) {
2532                     Err(inner_err) => {
2533                         // Carry on as if we had not done anything, callers will emit a
2534                         // reasonable error.
2535                         inner_err.cancel();
2536                         err.cancel();
2537                         self.restore_snapshot(snapshot);
2538                     }
2539                     Ok(mut pat) => {
2540                         // We've parsed the rest of the pattern.
2541                         let new_span = first_pat.span.to(pat.span);
2542                         let mut show_sugg = false;
2543                         // Try to construct a recovered pattern.
2544                         match &mut pat.kind {
2545                             PatKind::Struct(qself @ None, path, ..)
2546                             | PatKind::TupleStruct(qself @ None, path, _)
2547                             | PatKind::Path(qself @ None, path) => match &first_pat.kind {
2548                                 PatKind::Ident(_, ident, _) => {
2549                                     path.segments.insert(0, PathSegment::from_ident(*ident));
2550                                     path.span = new_span;
2551                                     show_sugg = true;
2552                                     first_pat = pat;
2553                                 }
2554                                 PatKind::Path(old_qself, old_path) => {
2555                                     path.segments = old_path
2556                                         .segments
2557                                         .iter()
2558                                         .cloned()
2559                                         .chain(take(&mut path.segments))
2560                                         .collect();
2561                                     path.span = new_span;
2562                                     *qself = old_qself.clone();
2563                                     first_pat = pat;
2564                                     show_sugg = true;
2565                                 }
2566                                 _ => {}
2567                             },
2568                             PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None) => {
2569                                 match &first_pat.kind {
2570                                     PatKind::Ident(_, old_ident, _) => {
2571                                         let path = PatKind::Path(
2572                                             None,
2573                                             Path {
2574                                                 span: new_span,
2575                                                 segments: vec![
2576                                                     PathSegment::from_ident(*old_ident),
2577                                                     PathSegment::from_ident(*ident),
2578                                                 ],
2579                                                 tokens: None,
2580                                             },
2581                                         );
2582                                         first_pat = self.mk_pat(new_span, path);
2583                                         show_sugg = true;
2584                                     }
2585                                     PatKind::Path(old_qself, old_path) => {
2586                                         let mut segments = old_path.segments.clone();
2587                                         segments.push(PathSegment::from_ident(*ident));
2588                                         let path = PatKind::Path(
2589                                             old_qself.clone(),
2590                                             Path { span: new_span, segments, tokens: None },
2591                                         );
2592                                         first_pat = self.mk_pat(new_span, path);
2593                                         show_sugg = true;
2594                                     }
2595                                     _ => {}
2596                                 }
2597                             }
2598                             _ => {}
2599                         }
2600                         if show_sugg {
2601                             err.span_suggestion(
2602                                 span,
2603                                 "maybe write a path separator here",
2604                                 "::",
2605                                 Applicability::MaybeIncorrect,
2606                             );
2607                         } else {
2608                             first_pat = self.mk_pat(new_span, PatKind::Wild);
2609                         }
2610                         err.emit();
2611                     }
2612                 }
2613             }
2614             _ => {
2615                 // Carry on as if we had not done anything. This should be unreachable.
2616                 self.restore_snapshot(snapshot);
2617             }
2618         };
2619         first_pat
2620     }
2621
2622     pub(crate) fn maybe_recover_unexpected_block_label(&mut self) -> bool {
2623         let Some(label) = self.eat_label().filter(|_| {
2624             self.eat(&token::Colon) && self.token.kind == token::OpenDelim(Delimiter::Brace)
2625         }) else {
2626             return false;
2627         };
2628         let span = label.ident.span.to(self.prev_token.span);
2629         let mut err = self.struct_span_err(span, "block label not supported here");
2630         err.span_label(span, "not supported here");
2631         err.tool_only_span_suggestion(
2632             label.ident.span.until(self.token.span),
2633             "remove this block label",
2634             "",
2635             Applicability::MachineApplicable,
2636         );
2637         err.emit();
2638         true
2639     }
2640
2641     /// Some special error handling for the "top-level" patterns in a match arm,
2642     /// `for` loop, `let`, &c. (in contrast to subpatterns within such).
2643     pub(crate) fn maybe_recover_unexpected_comma(
2644         &mut self,
2645         lo: Span,
2646         rt: CommaRecoveryMode,
2647     ) -> PResult<'a, ()> {
2648         if self.token != token::Comma {
2649             return Ok(());
2650         }
2651
2652         // An unexpected comma after a top-level pattern is a clue that the
2653         // user (perhaps more accustomed to some other language) forgot the
2654         // parentheses in what should have been a tuple pattern; return a
2655         // suggestion-enhanced error here rather than choking on the comma later.
2656         let comma_span = self.token.span;
2657         self.bump();
2658         if let Err(err) = self.skip_pat_list() {
2659             // We didn't expect this to work anyway; we just wanted to advance to the
2660             // end of the comma-sequence so we know the span to suggest parenthesizing.
2661             err.cancel();
2662         }
2663         let seq_span = lo.to(self.prev_token.span);
2664         let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern");
2665         if let Ok(seq_snippet) = self.span_to_snippet(seq_span) {
2666             err.multipart_suggestion(
2667                 &format!(
2668                     "try adding parentheses to match on a tuple{}",
2669                     if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." },
2670                 ),
2671                 vec![
2672                     (seq_span.shrink_to_lo(), "(".to_string()),
2673                     (seq_span.shrink_to_hi(), ")".to_string()),
2674                 ],
2675                 Applicability::MachineApplicable,
2676             );
2677             if let CommaRecoveryMode::EitherTupleOrPipe = rt {
2678                 err.span_suggestion(
2679                     seq_span,
2680                     "...or a vertical bar to match on multiple alternatives",
2681                     seq_snippet.replace(',', " |"),
2682                     Applicability::MachineApplicable,
2683                 );
2684             }
2685         }
2686         Err(err)
2687     }
2688
2689     pub(crate) fn maybe_recover_bounds_doubled_colon(&mut self, ty: &Ty) -> PResult<'a, ()> {
2690         let TyKind::Path(qself, path) = &ty.kind else { return Ok(()) };
2691         let qself_position = qself.as_ref().map(|qself| qself.position);
2692         for (i, segments) in path.segments.windows(2).enumerate() {
2693             if qself_position.map(|pos| i < pos).unwrap_or(false) {
2694                 continue;
2695             }
2696             if let [a, b] = segments {
2697                 let (a_span, b_span) = (a.span(), b.span());
2698                 let between_span = a_span.shrink_to_hi().to(b_span.shrink_to_lo());
2699                 if self.span_to_snippet(between_span).as_ref().map(|a| &a[..]) == Ok(":: ") {
2700                     let mut err = self.struct_span_err(
2701                         path.span.shrink_to_hi(),
2702                         "expected `:` followed by trait or lifetime",
2703                     );
2704                     err.span_suggestion(
2705                         between_span,
2706                         "use single colon",
2707                         ": ",
2708                         Applicability::MachineApplicable,
2709                     );
2710                     return Err(err);
2711                 }
2712             }
2713         }
2714         Ok(())
2715     }
2716
2717     /// Parse and throw away a parenthesized comma separated
2718     /// sequence of patterns until `)` is reached.
2719     fn skip_pat_list(&mut self) -> PResult<'a, ()> {
2720         while !self.check(&token::CloseDelim(Delimiter::Parenthesis)) {
2721             self.parse_pat_no_top_alt(None)?;
2722             if !self.eat(&token::Comma) {
2723                 return Ok(());
2724             }
2725         }
2726         Ok(())
2727     }
2728 }