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