Skip to main content

rustc_parse/parser/
function.rs

1use rustc_ast as ast;
2use rustc_ast::ast::*;
3use rustc_ast::token::{self, InvisibleOrigin, MetaVarKind, TokenKind};
4use rustc_ast::tokenstream::TokenTree;
5use rustc_ast::util::case::Case;
6use rustc_ast_pretty::pprust;
7use rustc_errors::{Applicability, PResult};
8use rustc_lint_defs::builtin::VARARGS_WITHOUT_PATTERN;
9use rustc_span::edition::Edition;
10use rustc_span::{ErrorGuaranteed, Ident, Span, kw, respan, sym};
11use thin_vec::ThinVec;
12use tracing::debug;
13
14use super::diagnostics::dummy_arg;
15use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
16use super::{
17    ExpKeywordPair, FollowedByType, ForceCollect, Parser, Recovered, Trailing, UsePreAttrPos,
18};
19use crate::diagnostics::{self, FnPointerCannotBeAsync, FnPointerCannotBeConst};
20use crate::exp;
21
22/// The parsing configuration used to parse a parameter list (see `parse_fn_params`).
23///
24/// The function decides if, per-parameter `p`, `p` must have a pattern or just a type.
25///
26/// This function pointer accepts an edition, because in edition 2015, trait declarations
27/// were allowed to omit parameter names. In 2018, they became required. It also accepts an
28/// `IsDotDotDot` parameter, as `extern` function declarations and function pointer types are
29/// allowed to omit the name of the `...` but regular function items are not.
30type ReqName = fn(Edition, IsDotDotDot) -> bool;
31
32#[derive(#[automatically_derived]
impl ::core::marker::Copy for IsDotDotDot { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for IsDotDotDot { }
#[automatically_derived]
impl ::core::clone::Clone for IsDotDotDot {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for IsDotDotDot { }
#[automatically_derived]
impl ::core::cmp::PartialEq for IsDotDotDot {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq)]
33pub(crate) enum IsDotDotDot {
34    Yes,
35    No,
36}
37
38/// Parsing configuration for functions.
39///
40/// The syntax of function items is slightly different within trait definitions,
41/// impl blocks, and modules. It is still parsed using the same code, just with
42/// different flags set, so that even when the input is wrong and produces a parse
43/// error, it still gets into the AST and the rest of the parser and
44/// type checker can run.
45#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for FnParseMode { }
#[automatically_derived]
impl ::core::clone::Clone for FnParseMode {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<ReqName>;
        let _: ::core::clone::AssertParamIsClone<FnContext>;
        let _: ::core::clone::AssertParamIsClone<bool>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for FnParseMode { }Copy)]
46pub(crate) struct FnParseMode {
47    /// A function pointer that decides if, per-parameter `p`, `p` must have a
48    /// pattern or just a type. This field affects parsing of the parameters list.
49    ///
50    /// ```text
51    /// fn foo(alef: A) -> X { X::new() }
52    ///        -----^^ affects parsing this part of the function signature
53    ///        |
54    ///        if req_name returns false, then this name is optional
55    ///
56    /// fn bar(A) -> X;
57    ///        ^
58    ///        |
59    ///        if req_name returns true, this is an error
60    /// ```
61    ///
62    /// Calling this function pointer should only return false if:
63    ///
64    ///   * The item is being parsed inside of a trait definition.
65    ///     Within an impl block or a module, it should always evaluate
66    ///     to true.
67    ///   * The span is from Edition 2015. In particular, you can get a
68    ///     2015 span inside a 2021 crate using macros.
69    ///
70    /// Or if `IsDotDotDot::Yes`, this function will also return `false` if the item being parsed
71    /// is inside an `extern` block.
72    pub(super) req_name: ReqName,
73    /// The context in which this function is parsed, used for diagnostics.
74    /// This indicates the fn is a free function or method and so on.
75    pub(super) context: FnContext,
76    /// If this flag is set to `true`, then plain, semicolon-terminated function
77    /// prototypes are not allowed here.
78    ///
79    /// ```text
80    /// fn foo(alef: A) -> X { X::new() }
81    ///                      ^^^^^^^^^^^^
82    ///                      |
83    ///                      this is always allowed
84    ///
85    /// fn bar(alef: A, bet: B) -> X;
86    ///                             ^
87    ///                             |
88    ///                             if req_body is set to true, this is an error
89    /// ```
90    ///
91    /// This field should only be set to false if the item is inside of a trait
92    /// definition or extern block. Within an impl block or a module, it should
93    /// always be set to true.
94    pub(super) req_body: bool,
95}
96
97/// The context in which a function is parsed.
98/// FIXME(estebank, xizheyin): Use more variants.
99#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for FnContext { }
#[automatically_derived]
impl ::core::clone::Clone for FnContext {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for FnContext { }Copy, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for FnContext { }
#[automatically_derived]
impl ::core::cmp::PartialEq for FnContext {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for FnContext { }Eq)]
100pub(crate) enum FnContext {
101    /// Free context.
102    Free,
103    /// A Function Pointer Type `fn(..)`.
104    FunctionPtrType,
105    /// A Parenthesized Argument List `impl Fn(...)`
106    ParenthesizedArgumentList,
107    /// A Trait context.
108    Trait,
109    /// An Impl block.
110    Impl,
111}
112
113/// Parsing of functions and methods.
114impl<'a> Parser<'a> {
115    /// Parse a function starting from the front matter (`const ...`) to the body `{ ... }` or `;`.
116    pub(super) fn parse_fn(
117        &mut self,
118        attrs: &mut AttrVec,
119        fn_parse_mode: FnParseMode,
120        sig_lo: Span,
121        vis: &Visibility,
122        case: Case,
123    ) -> PResult<'a, (Ident, FnSig, Generics, Option<Box<FnContract>>, Option<Box<Block>>)> {
124        let fn_span = self.token.span;
125        let header = self.parse_fn_front_matter(vis, case, FrontMatterParsingMode::Function)?; // `const ... fn`
126        let ident = self.parse_ident()?; // `foo`
127        let mut generics = self.parse_generics()?; // `<'a, T, ...>`
128        let decl = match self.parse_fn_decl(&fn_parse_mode, AllowPlus::Yes, RecoverReturnSign::Yes)
129        {
130            Ok(decl) => decl,
131            Err(old_err) => {
132                // If we see `for Ty ...` then user probably meant `impl` item.
133                if self.token.is_keyword(kw::For) {
134                    old_err.cancel();
135                    return Err(self.dcx().create_err(diagnostics::FnTypoWithImpl { fn_span }));
136                } else {
137                    return Err(old_err);
138                }
139            }
140        };
141
142        // Store the end of function parameters to give better diagnostics
143        // inside `parse_fn_body()`.
144        let fn_params_end = self.prev_token.span.shrink_to_hi();
145
146        let contract = self.parse_contract()?;
147
148        generics.where_clause = self.parse_where_clause()?; // `where T: Ord`
149
150        // `fn_params_end` is needed only when it's followed by a where clause.
151        let fn_params_end =
152            if generics.where_clause.has_where_token { Some(fn_params_end) } else { None };
153
154        let mut sig_hi = self.prev_token.span;
155        // Either `;` or `{ ... }`.
156        let body =
157            self.parse_fn_body(attrs, &ident, &mut sig_hi, fn_parse_mode.req_body, fn_params_end)?;
158        let fn_sig_span = sig_lo.to(sig_hi);
159        Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, contract, body))
160    }
161
162    /// Provide diagnostics when function body is not found
163    fn error_fn_body_not_found(
164        &mut self,
165        ident_span: Span,
166        req_body: bool,
167        fn_params_end: Option<Span>,
168    ) -> PResult<'a, ErrorGuaranteed> {
169        let expected: &[_] =
170            if req_body { &[crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::OpenBrace,
    token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)] } else { &[crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Semi,
    token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi), crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::OpenBrace,
    token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)] };
171        match self.expected_one_of_not_found(&[], expected) {
172            Ok(error_guaranteed) => Ok(error_guaranteed),
173            Err(mut err) => {
174                if self.token == token::CloseBrace {
175                    // The enclosing `mod`, `trait` or `impl` is being closed, so keep the `fn` in
176                    // the AST for typechecking.
177                    err.span_label(ident_span, "while parsing this `fn`");
178                    Ok(err.emit_err())
179                } else if self.token == token::RArrow
180                    && let Some(fn_params_end) = fn_params_end
181                {
182                    // Instead of a function body, the parser has encountered a right arrow
183                    // preceded by a where clause.
184
185                    // Find whether token behind the right arrow is a function trait and
186                    // store its span.
187                    let fn_trait_span =
188                        [sym::FnOnce, sym::FnMut, sym::Fn].into_iter().find_map(|symbol| {
189                            if self.prev_token.is_ident_named(symbol) {
190                                Some(self.prev_token.span)
191                            } else {
192                                None
193                            }
194                        });
195
196                    // Parse the return type (along with the right arrow) and store its span.
197                    // If there's a parse error, cancel it and return the existing error
198                    // as we are primarily concerned with the
199                    // expected-function-body-but-found-something-else error here.
200                    let arrow_span = self.token.span;
201                    let ty_span = match self.parse_ret_ty(
202                        AllowPlus::Yes,
203                        RecoverQPath::Yes,
204                        RecoverReturnSign::Yes,
205                    ) {
206                        Ok(ty_span) => ty_span.span().shrink_to_hi(),
207                        Err(parse_error) => {
208                            parse_error.cancel();
209                            return Err(err);
210                        }
211                    };
212                    let ret_ty_span = arrow_span.to(ty_span);
213
214                    if let Some(fn_trait_span) = fn_trait_span {
215                        // Typo'd Fn* trait bounds such as
216                        // fn foo<F>() where F: FnOnce -> () {}
217                        err.subdiagnostic(diagnostics::FnTraitMissingParen { span: fn_trait_span });
218                    } else if let Ok(snippet) = self.psess.source_map().span_to_snippet(ret_ty_span)
219                    {
220                        // If token behind right arrow is not a Fn* trait, the programmer
221                        // probably misplaced the return type after the where clause like
222                        // `fn foo<T>() where T: Default -> u8 {}`
223                        err.primary_message(
224                            "return type should be specified after the function parameters",
225                        );
226                        err.subdiagnostic(diagnostics::MisplacedReturnType {
227                            fn_params_end,
228                            snippet,
229                            ret_ty_span,
230                        });
231                    }
232                    Err(err)
233                } else {
234                    Err(err)
235                }
236            }
237        }
238    }
239
240    /// Parse the "body" of a function.
241    /// This can either be `;` when there's no body,
242    /// or e.g. a block when the function is a provided one.
243    fn parse_fn_body(
244        &mut self,
245        attrs: &mut AttrVec,
246        ident: &Ident,
247        sig_hi: &mut Span,
248        req_body: bool,
249        fn_params_end: Option<Span>,
250    ) -> PResult<'a, Option<Box<Block>>> {
251        let has_semi = if req_body {
252            self.token == TokenKind::Semi
253        } else {
254            // Only include `;` in list of expected tokens if body is not required
255            self.check(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Semi,
    token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi))
256        };
257        let (inner_attrs, body) = if has_semi {
258            // Include the trailing semicolon in the span of the signature
259            self.expect_semi()?;
260            *sig_hi = self.prev_token.span;
261            (AttrVec::new(), None)
262        } else if self.check(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::OpenBrace,
    token_type: crate::parser::token_type::TokenType::OpenBrace,
}exp!(OpenBrace)) || self.token.is_metavar_block() {
263            let prev_in_fn_body = self.in_fn_body;
264            self.in_fn_body = true;
265            let res = self.parse_block_common(self.token.span, BlockCheckMode::Default, None).map(
266                |(attrs, mut body)| {
267                    if let Some(guar) = self.fn_body_missing_semi_guar.take() {
268                        body.stmts.push(self.mk_stmt(
269                            body.span,
270                            StmtKind::Expr(self.mk_expr(body.span, ExprKind::Err(guar))),
271                        ));
272                    }
273                    (attrs, Some(body))
274                },
275            );
276            self.in_fn_body = prev_in_fn_body;
277            res?
278        } else if self.token == token::Eq {
279            // Recover `fn foo() = $expr;`.
280            self.bump(); // `=`
281            let eq_sp = self.prev_token.span;
282            let _ = self.parse_expr()?;
283            self.expect_semi()?; // `;`
284            let span = eq_sp.to(self.prev_token.span);
285            let guar = self.dcx().emit_err(diagnostics::FunctionBodyEqualsExpr {
286                span,
287                sugg: diagnostics::FunctionBodyEqualsExprSugg {
288                    eq: eq_sp,
289                    semi: self.prev_token.span,
290                },
291            });
292            (AttrVec::new(), Some(self.mk_block_err(span, guar)))
293        } else {
294            self.error_fn_body_not_found(ident.span, req_body, fn_params_end)?;
295            (AttrVec::new(), None)
296        };
297        attrs.extend(inner_attrs);
298        Ok(body)
299    }
300
301    /// Is the current token the start of an `FnHeader` / not a valid parse?
302    ///
303    /// `check_pub` adds additional `pub` to the checks in case users place it
304    /// wrongly, can be used to ensure `pub` never comes after `default`.
305    pub(super) fn check_fn_front_matter(&mut self, check_pub: bool, case: Case) -> bool {
306        const ALL_QUALS: &[ExpKeywordPair] = &[
307            crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Pub,
    token_type: crate::parser::token_type::TokenType::KwPub,
}exp!(Pub),
308            crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Gen,
    token_type: crate::parser::token_type::TokenType::KwGen,
}exp!(Gen),
309            crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Const,
    token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const),
310            crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Async,
    token_type: crate::parser::token_type::TokenType::KwAsync,
}exp!(Async),
311            crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Unsafe,
    token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe),
312            crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Safe,
    token_type: crate::parser::token_type::TokenType::KwSafe,
}exp!(Safe),
313            crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Extern,
    token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern),
314        ];
315
316        // We use an over-approximation here.
317        // `const const`, `fn const` won't parse, but we're not stepping over other syntax either.
318        // `pub` is added in case users got confused with the ordering like `async pub fn`,
319        // only if it wasn't preceded by `default` as `default pub` is invalid.
320        let quals: &[_] = if check_pub {
321            ALL_QUALS
322        } else {
323            &[crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Gen,
    token_type: crate::parser::token_type::TokenType::KwGen,
}exp!(Gen), crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Const,
    token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const), crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Async,
    token_type: crate::parser::token_type::TokenType::KwAsync,
}exp!(Async), crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Unsafe,
    token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe), crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Safe,
    token_type: crate::parser::token_type::TokenType::KwSafe,
}exp!(Safe), crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Extern,
    token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern)]
324        };
325        self.check_keyword_case(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Fn,
    token_type: crate::parser::token_type::TokenType::KwFn,
}exp!(Fn), case) // Definitely an `fn`.
326            // `$qual fn` or `$qual $qual`:
327            || quals.iter().any(|&exp| self.check_keyword_case(exp, case))
328                && self.look_ahead(1, |t| {
329                    // `$qual fn`, e.g. `const fn` or `async fn`.
330                    t.is_keyword_case(kw::Fn, case)
331                    // Two qualifiers `$qual $qual` is enough, e.g. `async unsafe`.
332                    || (
333                        (
334                            t.non_raw_ident().is_some_and(|i|
335                                quals.iter().any(|exp| exp.kw == i.name)
336                                    // Rule out 2015 `const async: T = val`.
337                                    && i.is_reserved()
338                            )
339                            || case == Case::Insensitive
340                                && t.non_raw_ident().is_some_and(|i| quals.iter().any(|exp| {
341                                    exp.kw.as_str() == i.name.as_str().to_lowercase()
342                                }))
343                        )
344                        // Rule out `unsafe extern {`.
345                        && !self.is_unsafe_foreign_mod()
346                        // Rule out `async gen {` and `async gen move {`
347                        && !self.is_async_gen_block()
348                        // Rule out `const unsafe auto` and `const unsafe trait` and `const unsafe impl`
349                        && !self.is_keyword_ahead(2, &[kw::Auto, kw::Trait, kw::Impl])
350                    )
351                })
352            // `extern ABI fn`
353            || self.check_keyword_case(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Extern,
    token_type: crate::parser::token_type::TokenType::KwExtern,
}exp!(Extern), case)
354                // Use `tree_look_ahead` because `ABI` might be a metavariable,
355                // i.e. an invisible-delimited sequence, and `tree_look_ahead`
356                // will consider that a single element when looking ahead.
357                && self.look_ahead(1, |t| t.can_begin_string_literal())
358                && (self.tree_look_ahead(2, |tt| {
359                    match tt {
360                        TokenTree::Token(t, _) => t.is_keyword_case(kw::Fn, case),
361                        TokenTree::Delimited(..) => false,
362                    }
363                }) == Some(true) ||
364                    // This branch is only for better diagnostics; `pub`, `unsafe`, etc. are not
365                    // allowed here.
366                    // This branch also follows `$qual fn` or `$qual $qual` rule
367                    // above since a valid `fn` can be after `extern`.
368                    (self.may_recover()
369                        && self.tree_look_ahead(2, |tt| {
370                            match tt {
371                                TokenTree::Token(t, _) =>
372                                    ALL_QUALS.iter().any(|exp| {
373                                        t.is_keyword(exp.kw)
374                                    }),
375                                TokenTree::Delimited(..) => false,
376                            }
377                        }) == Some(true)
378                        && self.tree_look_ahead(3, |tt| {
379                            match tt {
380                                TokenTree::Token(t, _) => {
381                                    t.is_keyword_case(kw::Fn, case) ||
382                                    ALL_QUALS.iter().any(|exp| {
383                                        t.is_keyword(exp.kw)
384                                    })
385                                },
386                                TokenTree::Delimited(..) => false,
387                            }
388                        }) == Some(true)
389                    )
390                )
391    }
392
393    /// Parses all the "front matter" (or "qualifiers") for a `fn` declaration,
394    /// up to and including the `fn` keyword. The formal grammar is:
395    ///
396    /// ```text
397    /// Extern = "extern" StringLit? ;
398    /// FnQual = "const"? "async"? "unsafe"? Extern? ;
399    /// FnFrontMatter = FnQual "fn" ;
400    /// ```
401    ///
402    /// `vis` represents the visibility that was already parsed, if any. Use
403    /// `Visibility::Inherited` when no visibility is known.
404    ///
405    /// If `parsing_mode` is `FrontMatterParsingMode::FunctionPtrType`, we error on `const` and `async` qualifiers,
406    /// which are not allowed in function pointer types.
407    pub(super) fn parse_fn_front_matter(
408        &mut self,
409        orig_vis: &Visibility,
410        case: Case,
411        parsing_mode: FrontMatterParsingMode,
412    ) -> PResult<'a, FnHeader> {
413        let sp_start = self.token.span;
414        let constness = self.parse_constness(case);
415        if parsing_mode == FrontMatterParsingMode::FunctionPtrType
416            && let Const::Yes(const_span) = constness
417        {
418            self.dcx().emit_err(FnPointerCannotBeConst {
419                span: const_span,
420                suggestion: const_span.until(self.token.span),
421            });
422        }
423
424        let async_start_sp = self.token.span;
425        let coroutine_marker = self.parse_coroutine_marker(case);
426        if parsing_mode == FrontMatterParsingMode::FunctionPtrType
427            && let Some(coroutine_marker) = coroutine_marker
428            && coroutine_marker.kind == CoroutineKind::Async
429        {
430            self.dcx().emit_err(FnPointerCannotBeAsync {
431                span: coroutine_marker.span,
432                suggestion: coroutine_marker.span.until(self.token.span),
433            });
434        }
435        // FIXME(gen_blocks): emit a similar error for `gen fn()`
436
437        let unsafe_start_sp = self.token.span;
438        let safety = self.parse_safety(case);
439
440        let ext_start_sp = self.token.span;
441        let ext = self.parse_extern(case);
442
443        if let Some(coroutine_marker) = coroutine_marker
444            && let CoroutineKind::Async = coroutine_marker.kind
445            && coroutine_marker.span.is_rust_2015()
446        {
447            self.dcx().emit_err(diagnostics::AsyncFnIn2015 {
448                span: coroutine_marker.span,
449                help: diagnostics::HelpUseLatestEdition::new(),
450            });
451        }
452
453        if let Some(coroutine_marker) = coroutine_marker
454            && coroutine_marker.kind.is_gen()
455        {
456            self.psess.gated_spans.gate(sym::gen_blocks, coroutine_marker.span);
457        }
458
459        if !self.eat_keyword_case(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Fn,
    token_type: crate::parser::token_type::TokenType::KwFn,
}exp!(Fn), case) {
460            // It is possible for `expect_one_of` to recover given the contents of
461            // `self.expected_token_types`, therefore, do not use `self.unexpected()` which doesn't
462            // account for this.
463            match self.expect_one_of(&[], &[]) {
464                Ok(Recovered::Yes(_)) => {}
465                Ok(Recovered::No) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
466                Err(mut err) => {
467                    // Qualifier keywords ordering check
468                    enum WrongKw {
469                        Duplicated(Span),
470                        Misplaced(Span),
471                        /// `MisplacedDisallowedQualifier` is only used instead of `Misplaced`,
472                        /// when the misplaced keyword is disallowed by the current `FrontMatterParsingMode`.
473                        /// In this case, we avoid generating the suggestion to swap around the keywords,
474                        /// as we already generated a suggestion to remove the keyword earlier.
475                        MisplacedDisallowedQualifier,
476                    }
477
478                    // We may be able to recover
479                    let mut recover_constness = constness;
480                    let mut recover_coroutine_marker = coroutine_marker;
481                    let mut recover_safety = safety;
482                    // This will allow the machine fix to directly place the keyword in the correct place or to indicate
483                    // that the keyword is already present and the second instance should be removed.
484                    let wrong_kw = if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Const,
    token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const)) {
485                        match constness {
486                            Const::Yes(sp) => Some(WrongKw::Duplicated(sp)),
487                            Const::No => {
488                                recover_constness = Const::Yes(self.token.span);
489                                match parsing_mode {
490                                    FrontMatterParsingMode::Function => {
491                                        Some(WrongKw::Misplaced(async_start_sp))
492                                    }
493                                    FrontMatterParsingMode::FunctionPtrType => {
494                                        self.dcx().emit_err(FnPointerCannotBeConst {
495                                            span: self.token.span,
496                                            suggestion: self
497                                                .token
498                                                .span
499                                                .with_lo(self.prev_token.span.hi()),
500                                        });
501                                        Some(WrongKw::MisplacedDisallowedQualifier)
502                                    }
503                                }
504                            }
505                        }
506                    } else if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Async,
    token_type: crate::parser::token_type::TokenType::KwAsync,
}exp!(Async)) {
507                        match coroutine_marker {
508                            Some(CoroutineMarker {
509                                kind: CoroutineKind::Async | CoroutineKind::AsyncGen,
510                                span,
511                                ..
512                            }) => Some(WrongKw::Duplicated(span)),
513                            Some(CoroutineMarker { kind: CoroutineKind::Gen, .. }) => {
514                                recover_coroutine_marker = Some(CoroutineMarker::new(
515                                    CoroutineKind::AsyncGen,
516                                    self.token.span,
517                                ));
518                                // FIXME(gen_blocks): This span is wrong, didn't want to think about it.
519                                Some(WrongKw::Misplaced(unsafe_start_sp))
520                            }
521                            None => {
522                                recover_coroutine_marker = Some(CoroutineMarker::new(
523                                    CoroutineKind::Async,
524                                    self.token.span,
525                                ));
526                                match parsing_mode {
527                                    FrontMatterParsingMode::Function => {
528                                        Some(WrongKw::Misplaced(async_start_sp))
529                                    }
530                                    FrontMatterParsingMode::FunctionPtrType => {
531                                        self.dcx().emit_err(FnPointerCannotBeAsync {
532                                            span: self.token.span,
533                                            suggestion: self
534                                                .token
535                                                .span
536                                                .with_lo(self.prev_token.span.hi()),
537                                        });
538                                        Some(WrongKw::MisplacedDisallowedQualifier)
539                                    }
540                                }
541                            }
542                        }
543                    } else if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Unsafe,
    token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe)) {
544                        match safety {
545                            Safety::Unsafe(sp) => Some(WrongKw::Duplicated(sp)),
546                            Safety::Safe(sp) => {
547                                recover_safety = Safety::Unsafe(self.token.span);
548                                Some(WrongKw::Misplaced(sp))
549                            }
550                            Safety::Default => {
551                                recover_safety = Safety::Unsafe(self.token.span);
552                                Some(WrongKw::Misplaced(ext_start_sp))
553                            }
554                        }
555                    } else if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Safe,
    token_type: crate::parser::token_type::TokenType::KwSafe,
}exp!(Safe)) {
556                        match safety {
557                            Safety::Safe(sp) => Some(WrongKw::Duplicated(sp)),
558                            Safety::Unsafe(sp) => {
559                                recover_safety = Safety::Safe(self.token.span);
560                                Some(WrongKw::Misplaced(sp))
561                            }
562                            Safety::Default => {
563                                recover_safety = Safety::Safe(self.token.span);
564                                Some(WrongKw::Misplaced(ext_start_sp))
565                            }
566                        }
567                    } else {
568                        None
569                    };
570
571                    // The keyword is already present, suggest removal of the second instance
572                    if let Some(WrongKw::Duplicated(original_sp)) = wrong_kw {
573                        let original_kw = self
574                            .span_to_snippet(original_sp)
575                            .expect("Span extracted directly from keyword should always work");
576
577                        err.span_suggestion_verbose(
578                            self.token_uninterpolated_span(),
579                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` already used earlier, remove this one",
                original_kw))
    })format!("`{original_kw}` already used earlier, remove this one"),
580                            "",
581                            Applicability::MachineApplicable,
582                        )
583                        .span_note(original_sp, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` first seen here",
                original_kw))
    })format!("`{original_kw}` first seen here"));
584                    }
585                    // The keyword has not been seen yet, suggest correct placement in the function front matter
586                    else if let Some(WrongKw::Misplaced(correct_pos_sp)) = wrong_kw {
587                        let correct_pos_sp = correct_pos_sp.to(self.prev_token.span);
588                        if let Ok(current_qual) = self.span_to_snippet(correct_pos_sp) {
589                            let misplaced_qual_sp = self.token_uninterpolated_span();
590                            let misplaced_qual = self.span_to_snippet(misplaced_qual_sp).unwrap();
591
592                            err.span_suggestion_verbose(
593                                    correct_pos_sp.to(misplaced_qual_sp),
594                                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` must come before `{1}`",
                misplaced_qual, current_qual))
    })format!("`{misplaced_qual}` must come before `{current_qual}`"),
595                                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} {1}", misplaced_qual,
                current_qual))
    })format!("{misplaced_qual} {current_qual}"),
596                                    Applicability::MachineApplicable,
597                                ).note("keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`");
598                        }
599                    }
600                    // Recover incorrect visibility order such as `async pub`
601                    else if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Pub,
    token_type: crate::parser::token_type::TokenType::KwPub,
}exp!(Pub)) {
602                        let sp = sp_start.to(self.prev_token.span);
603                        if let Ok(snippet) = self.span_to_snippet(sp) {
604                            let current_vis = match self.parse_visibility(FollowedByType::No) {
605                                Ok(v) => v,
606                                Err(d) => {
607                                    d.cancel();
608                                    return Err(err);
609                                }
610                            };
611                            let vs = pprust::vis_to_string(&current_vis);
612                            let vs = vs.trim_end();
613
614                            // There was no explicit visibility
615                            if #[allow(non_exhaustive_omitted_patterns)] match orig_vis.kind {
    VisibilityKind::Inherited => true,
    _ => false,
}matches!(orig_vis.kind, VisibilityKind::Inherited) {
616                                err.span_suggestion_verbose(
617                                    sp_start.to(self.prev_token.span),
618                                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("visibility `{0}` must come before `{1}`",
                vs, snippet))
    })format!("visibility `{vs}` must come before `{snippet}`"),
619                                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} {1}", vs, snippet))
    })format!("{vs} {snippet}"),
620                                    Applicability::MachineApplicable,
621                                );
622                            }
623                            // There was an explicit visibility
624                            else {
625                                err.span_suggestion_verbose(
626                                    current_vis.span,
627                                    "there is already a visibility modifier, remove one",
628                                    "",
629                                    Applicability::MachineApplicable,
630                                )
631                                .span_note(orig_vis.span, "explicit visibility first seen here");
632                            }
633                        }
634                    }
635
636                    // FIXME(gen_blocks): add keyword recovery logic for genness
637
638                    if let Some(wrong_kw) = wrong_kw
639                        && self.may_recover()
640                        && self.look_ahead(1, |tok| tok.is_keyword_case(kw::Fn, case))
641                    {
642                        // Advance past the misplaced keyword and `fn`
643                        self.bump();
644                        self.bump();
645                        // When we recover from a `MisplacedDisallowedQualifier`, we already emitted an error for the disallowed qualifier
646                        // So we don't emit another error that the qualifier is unexpected.
647                        if #[allow(non_exhaustive_omitted_patterns)] match wrong_kw {
    WrongKw::MisplacedDisallowedQualifier => true,
    _ => false,
}matches!(wrong_kw, WrongKw::MisplacedDisallowedQualifier) {
648                            err.cancel();
649                        } else {
650                            err.emit();
651                        }
652                        return Ok(FnHeader {
653                            constness: recover_constness,
654                            safety: recover_safety,
655                            coroutine_marker: recover_coroutine_marker,
656                            ext,
657                        });
658                    }
659
660                    return Err(err);
661                }
662            }
663        }
664
665        Ok(FnHeader { constness, safety, coroutine_marker, ext })
666    }
667
668    /// Parses the parameter list and result type of a function declaration.
669    pub(super) fn parse_fn_decl(
670        &mut self,
671        fn_parse_mode: &FnParseMode,
672        ret_allow_plus: AllowPlus,
673        recover_return_sign: RecoverReturnSign,
674    ) -> PResult<'a, Box<FnDecl>> {
675        Ok(Box::new(FnDecl {
676            inputs: self.parse_fn_params(fn_parse_mode)?,
677            output: self.parse_ret_ty(ret_allow_plus, RecoverQPath::Yes, recover_return_sign)?,
678        }))
679    }
680
681    /// Parses the parameter list of a function, including the `(` and `)` delimiters.
682    pub(super) fn parse_fn_params(
683        &mut self,
684        fn_parse_mode: &FnParseMode,
685    ) -> PResult<'a, ThinVec<Param>> {
686        let mut first_param = true;
687        // Parse the arguments, starting out with `self` being allowed...
688        if self.token != TokenKind::OpenParen
689        // might be typo'd trait impl, handled elsewhere
690        && !self.token.is_keyword(kw::For)
691        {
692            // recover from missing argument list, e.g. `fn main -> () {}`
693            self.dcx().emit_err(diagnostics::MissingFnParams {
694                span: self.prev_token.span.shrink_to_hi(),
695            });
696            return Ok(ThinVec::new());
697        }
698
699        let (mut params, _) = self.parse_paren_comma_seq(|p| {
700            p.recover_vcs_conflict_marker();
701            let snapshot = p.create_snapshot_for_diagnostic();
702            let param = p.parse_param_general(fn_parse_mode, first_param).or_else(|e| {
703                let guar = e.emit_err();
704                // When parsing a param failed, we should check to make the span of the param
705                // not contain '(' before it.
706                // For example when parsing `*mut Self` in function `fn oof(*mut Self)`.
707                let lo = if let TokenKind::OpenParen = p.prev_token.kind {
708                    p.prev_token.span.shrink_to_hi()
709                } else {
710                    p.prev_token.span
711                };
712                p.restore_snapshot(snapshot);
713                // Skip every token until next possible arg or end.
714                p.eat_to_tokens(&[crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Comma,
    token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma), crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseParen,
    token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]);
715                // Create a placeholder argument for proper arg count (issue #34264).
716                Ok(dummy_arg(Ident::new(sym::dummy, lo.to(p.prev_token.span)), guar))
717            });
718            // ...now that we've parsed the first argument, `self` is no longer allowed.
719            first_param = false;
720            param
721        })?;
722        // Replace duplicated recovered params with `_` pattern to avoid unnecessary errors.
723        self.deduplicate_recovered_params_names(&mut params);
724        Ok(params)
725    }
726
727    /// Parses a single function parameter.
728    ///
729    /// - `self` is syntactically allowed when `first_param` holds.
730    /// - `recover_arg_parse` is used to recover from a failed argument parse.
731    pub(super) fn parse_param_general(
732        &mut self,
733        fn_parse_mode: &FnParseMode,
734        first_param: bool,
735    ) -> PResult<'a, Param> {
736        let lo = self.token.span;
737        let attrs = self.parse_outer_attributes()?;
738        self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
739            // Possibly parse `self`. Recover if we parsed it and it wasn't allowed here.
740            if let Some(mut param) = this.parse_self_param()? {
741                param.attrs = attrs;
742                let res = if first_param { Ok(param) } else { this.recover_bad_self_param(param) };
743                return Ok((res?, Trailing::No, UsePreAttrPos::No));
744            }
745
746            let is_dot_dot_dot = if this.token.kind == token::DotDotDot {
747                IsDotDotDot::Yes
748            } else {
749                IsDotDotDot::No
750            };
751            let is_name_required = (fn_parse_mode.req_name)(
752                this.token.span.with_neighbor(this.prev_token.span).edition(),
753                is_dot_dot_dot,
754            );
755            let is_name_required = if is_name_required && is_dot_dot_dot == IsDotDotDot::Yes {
756                this.psess.buffer_lint(
757                    VARARGS_WITHOUT_PATTERN,
758                    this.token.span,
759                    ast::CRATE_NODE_ID,
760                    diagnostics::VarargsWithoutPattern { span: this.token.span },
761                );
762                false
763            } else {
764                is_name_required
765            };
766            let (pat, ty) = if is_name_required || this.is_named_param() {
767                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/1303417c416e1595173d9689e7394c31e136ae95/compiler/rustc_parse/src/parser/function.rs:767",
                        "rustc_parse::parser::function", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/1303417c416e1595173d9689e7394c31e136ae95/compiler/rustc_parse/src/parser/function.rs"),
                        ::tracing_core::__macro_support::Option::Some(767u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_parse::parser::function"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("parse_param_general parse_pat (is_name_required:{0})",
                                                    is_name_required) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
768                let (pat, colon) = this.parse_fn_param_pat_colon()?;
769                if !colon {
770                    let mut err = this.unexpected().unwrap_err();
771                    let pat_span = pat.span;
772                    return if let Some(ident) = this.parameter_without_type(
773                        &mut err,
774                        pat,
775                        is_name_required,
776                        first_param,
777                        fn_parse_mode,
778                    ) {
779                        let guar = err.emit_err();
780                        let mut arg = dummy_arg(ident, guar);
781                        arg.span = pat_span;
782                        Ok((arg, Trailing::No, UsePreAttrPos::No))
783                    } else {
784                        Err(err)
785                    };
786                }
787
788                (pat, this.parse_ty_for_param()?)
789            } else {
790                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/1303417c416e1595173d9689e7394c31e136ae95/compiler/rustc_parse/src/parser/function.rs:790",
                        "rustc_parse::parser::function", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/1303417c416e1595173d9689e7394c31e136ae95/compiler/rustc_parse/src/parser/function.rs"),
                        ::tracing_core::__macro_support::Option::Some(790u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_parse::parser::function"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("parse_param_general ident_to_pat")
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("parse_param_general ident_to_pat");
791                let parser_snapshot_before_ty = this.create_snapshot_for_diagnostic();
792                let mut ty = this.parse_ty_for_param();
793
794                if let Ok(t) = &ty {
795                    // Check for trailing angle brackets
796                    if let TyKind::Path(_, Path { segments, .. }) = &t.kind
797                        && let Some(segment) = segments.last()
798                        && let Some(guar) =
799                            this.check_trailing_angle_brackets(segment, &[crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseParen,
    token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)])
800                    {
801                        return Ok((
802                            dummy_arg(segment.ident, guar),
803                            Trailing::No,
804                            UsePreAttrPos::No,
805                        ));
806                    }
807
808                    if this.token != token::Comma && this.token != token::CloseParen {
809                        // This wasn't actually a type, but a pattern looking like a type,
810                        // so we are going to rollback and re-parse for recovery.
811                        ty = this.unexpected_any();
812                    }
813                }
814                match ty {
815                    Ok(ty) => {
816                        let pat = this.mk_pat(ty.span, PatKind::Missing);
817                        (Box::new(pat), ty)
818                    }
819                    // If this is a C-variadic argument and we hit an error, return the error.
820                    Err(err) if this.token == token::DotDotDot => return Err(err),
821                    Err(err) if this.unmatched_angle_bracket_count > 0 => return Err(err),
822                    Err(err) => {
823                        // Recover from attempting to parse the argument as a type without pattern.
824                        this.restore_snapshot(parser_snapshot_before_ty);
825                        match this.recover_arg_parse(fn_parse_mode.context) {
826                            Ok(res) => {
827                                // We managed to parse the argument as a pattern, cancel the original error and emit a better one
828                                err.cancel();
829                                res
830                            }
831                            Err(new_err) => {
832                                // We did not manage to parse the argument as a pattern, avoid suggesting a pattern and emit the original error
833                                new_err.cancel();
834                                return Err(err);
835                            }
836                        }
837                    }
838                }
839            };
840
841            let span = lo.to(this.prev_token.span);
842
843            Ok((
844                Param { attrs, id: ast::DUMMY_NODE_ID, is_placeholder: false, pat, span, ty },
845                Trailing::No,
846                UsePreAttrPos::No,
847            ))
848        })
849    }
850
851    /// Returns the parsed optional self parameter and whether a self shortcut was used.
852    fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> {
853        // Extract an identifier *after* having confirmed that the token is one.
854        let expect_self_ident = |this: &mut Self| {
855            let ident = this.token.non_raw_ident().unwrap();
856            this.bump();
857            ident
858        };
859        // is lifetime `n` tokens ahead?
860        let is_lifetime = |this: &Self, n| this.look_ahead(n, |t| t.is_lifetime());
861        // Is `self` `n` tokens ahead?
862        let is_isolated_self = |this: &Self, n| {
863            this.is_keyword_ahead(n, &[kw::SelfLower])
864                && this.look_ahead(n + 1, |t| t != &token::PathSep)
865        };
866        // Is `pin const self` `n` tokens ahead?
867        let is_isolated_pin_const_self = |this: &Self, n| {
868            this.is_keyword_ahead(n, &[kw::Pin])
869                && this.is_keyword_ahead(n + 1, &[kw::Const])
870                && is_isolated_self(this, n + 2)
871        };
872        // Is `mut self` `n` tokens ahead?
873        let is_isolated_mut_self =
874            |this: &Self, n| this.is_keyword_ahead(n, &[kw::Mut]) && is_isolated_self(this, n + 1);
875        // Is `pin mut self` `n` tokens ahead?
876        let is_isolated_pin_mut_self = |this: &Self, n| {
877            this.is_keyword_ahead(n, &[kw::Pin]) && is_isolated_mut_self(this, n + 1)
878        };
879        // Parse `self` or `self: TYPE`. We already know the current token is `self`.
880        let parse_self_possibly_typed = |this: &mut Self, m| {
881            let eself_ident = expect_self_ident(this);
882            let eself_hi = this.prev_token.span;
883            let eself = if this.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Colon,
    token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)) {
884                SelfKind::Explicit(this.parse_ty()?, m)
885            } else {
886                SelfKind::Value(m)
887            };
888            Ok((eself, eself_ident, eself_hi))
889        };
890        let expect_self_ident_not_typed =
891            |this: &mut Self, modifier: &SelfKind, modifier_span: Span| {
892                let eself_ident = expect_self_ident(this);
893
894                // Recover `: Type` after a qualified self
895                if this.may_recover() && this.eat_noexpect(&token::Colon) {
896                    let snap = this.create_snapshot_for_diagnostic();
897                    match this.parse_ty() {
898                        Ok(ty) => {
899                            this.dcx().emit_err(diagnostics::IncorrectTypeOnSelf {
900                                span: ty.span,
901                                move_self_modifier: diagnostics::MoveSelfModifier {
902                                    removal_span: modifier_span,
903                                    insertion_span: ty.span.shrink_to_lo(),
904                                    modifier: modifier.to_ref_suggestion(),
905                                },
906                            });
907                        }
908                        Err(diag) => {
909                            diag.cancel();
910                            this.restore_snapshot(snap);
911                        }
912                    }
913                }
914                eself_ident
915            };
916        // Recover for the grammar `*self`, `*const self`, and `*mut self`.
917        let recover_self_ptr = |this: &mut Self| {
918            this.dcx().emit_err(diagnostics::SelfArgumentPointer { span: this.token.span });
919
920            Ok((SelfKind::Value(Mutability::Not), expect_self_ident(this), this.prev_token.span))
921        };
922
923        // Parse optional `self` parameter of a method.
924        // Only a limited set of initial token sequences is considered `self` parameters; anything
925        // else is parsed as a normal function parameter list, so some lookahead is required.
926        let eself_lo = self.token.span;
927        let (eself, eself_ident, eself_hi) = match self.token.uninterpolate().kind {
928            token::And => {
929                let has_lifetime = is_lifetime(self, 1);
930                let skip_lifetime_count = has_lifetime as usize;
931                let eself = if is_isolated_self(self, skip_lifetime_count + 1) {
932                    // `&{'lt} self`
933                    self.bump(); // &
934                    let lifetime = has_lifetime.then(|| self.expect_lifetime());
935                    SelfKind::Region(lifetime, Mutability::Not)
936                } else if is_isolated_mut_self(self, skip_lifetime_count + 1) {
937                    // `&{'lt} mut self`
938                    self.bump(); // &
939                    let lifetime = has_lifetime.then(|| self.expect_lifetime());
940                    self.bump(); // mut
941                    SelfKind::Region(lifetime, Mutability::Mut)
942                } else if is_isolated_pin_const_self(self, skip_lifetime_count + 1) {
943                    // `&{'lt} pin const self`
944                    self.bump(); // &
945                    let lifetime = has_lifetime.then(|| self.expect_lifetime());
946                    self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
947                    self.bump(); // pin
948                    self.bump(); // const
949                    SelfKind::Pinned(lifetime, Mutability::Not)
950                } else if is_isolated_pin_mut_self(self, skip_lifetime_count + 1) {
951                    // `&{'lt} pin mut self`
952                    self.bump(); // &
953                    let lifetime = has_lifetime.then(|| self.expect_lifetime());
954                    self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
955                    self.bump(); // pin
956                    self.bump(); // mut
957                    SelfKind::Pinned(lifetime, Mutability::Mut)
958                } else {
959                    // `&not_self`
960                    return Ok(None);
961                };
962                let hi = self.token.span;
963                let self_ident = expect_self_ident_not_typed(self, &eself, eself_lo.until(hi));
964                (eself, self_ident, hi)
965            }
966            // `*self`
967            token::Star if is_isolated_self(self, 1) => {
968                self.bump();
969                recover_self_ptr(self)?
970            }
971            // `*mut self` and `*const self`
972            token::Star
973                if self.look_ahead(1, |t| t.is_mutability()) && is_isolated_self(self, 2) =>
974            {
975                self.bump();
976                self.bump();
977                recover_self_ptr(self)?
978            }
979            // `self` and `self: TYPE`
980            token::Ident(..) if is_isolated_self(self, 0) => {
981                parse_self_possibly_typed(self, Mutability::Not)?
982            }
983            // `mut self` and `mut self: TYPE`
984            token::Ident(..) if is_isolated_mut_self(self, 0) => {
985                self.bump();
986                parse_self_possibly_typed(self, Mutability::Mut)?
987            }
988            _ => return Ok(None),
989        };
990
991        let eself = respan(eself_lo.to(eself_hi), eself);
992        Ok(Some(Param::from_self(AttrVec::default(), eself, eself_ident)))
993    }
994
995    fn is_named_param(&self) -> bool {
996        let offset = match &self.token.kind {
997            token::OpenInvisible(origin) => match origin {
998                InvisibleOrigin::MetaVar(MetaVarKind::Pat(_)) => {
999                    return self.check_noexpect_past_close_delim(&token::Colon);
1000                }
1001                _ => 0,
1002            },
1003            token::And | token::AndAnd => 1,
1004            _ if self.token.is_keyword(kw::Mut) => 1,
1005            _ => 0,
1006        };
1007
1008        self.look_ahead(offset, |t| t.is_ident())
1009            && self.look_ahead(offset + 1, |t| t == &token::Colon)
1010    }
1011
1012    pub(super) fn recover_self_param(&mut self) -> bool {
1013        #[allow(non_exhaustive_omitted_patterns)] match self.parse_outer_attributes().and_then(|_|
                self.parse_self_param()).map_err(|e| e.cancel()) {
    Ok(Some(_)) => true,
    _ => false,
}matches!(
1014            self.parse_outer_attributes()
1015                .and_then(|_| self.parse_self_param())
1016                .map_err(|e| e.cancel()),
1017            Ok(Some(_))
1018        )
1019    }
1020}
1021
1022#[derive(#[automatically_derived]
impl ::core::marker::Copy for FrontMatterParsingMode { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for FrontMatterParsingMode { }
#[automatically_derived]
impl ::core::clone::Clone for FrontMatterParsingMode {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for FrontMatterParsingMode { }
#[automatically_derived]
impl ::core::cmp::PartialEq for FrontMatterParsingMode {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for FrontMatterParsingMode { }Eq)]
1023pub(crate) enum FrontMatterParsingMode {
1024    /// Parse the front matter of a function declaration
1025    Function,
1026    /// Parse the front matter of a function pointet type.
1027    /// For function pointer types, the `const` and `async` keywords are not permitted.
1028    FunctionPtrType,
1029}