Skip to main content

rustc_parse/parser/
function.rs

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