Skip to main content

rustc_parse/parser/
ty.rs

1use rustc_ast::token::{self, IdentIsRaw, MetaVarKind, Token, TokenKind};
2use rustc_ast::util::case::Case;
3use rustc_ast::{
4    self as ast, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnPtrTy, FnRetTy,
5    GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability,
6    Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty,
7    TyKind, UnsafeBinderTy,
8};
9use rustc_errors::{Applicability, Diag, E0516, PResult};
10use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym};
11use thin_vec::{ThinVec, thin_vec};
12
13use super::{Parser, PathStyle, SeqSep, TokenType, Trailing};
14use crate::diagnostics::{
15    self, AttributeOnEmptyType, AttributeOnType, DynAfterMut, ExpectedFnPathFoundFnKeyword,
16    ExpectedMutOrConstInRawPointerType, FnPtrWithGenerics, FnPtrWithGenericsSugg,
17    HelpUseLatestEdition, InvalidCVariadicType, InvalidDynKeyword, LifetimeAfterMut,
18    NeedPlusAfterTraitObjectLifetime, NestedCVariadicType, ReturnTypesUseThinArrow,
19};
20use crate::parser::{FnContext, FnParseMode, FrontMatterParsingMode};
21use crate::{exp, maybe_recover_from_interpolated_ty_qpath};
22
23/// Signals whether parsing a type should allow `+`.
24///
25/// For example, let T be the type `impl Default + 'static`
26/// With `AllowPlus::Yes`, T will be parsed successfully
27/// With `AllowPlus::No`, parsing T will return a parse error
28#[derive(#[automatically_derived]
impl ::core::marker::Copy for AllowPlus { }Copy, #[automatically_derived]
impl ::core::clone::Clone for AllowPlus {
    #[inline]
    fn clone(&self) -> AllowPlus { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for AllowPlus {
    #[inline]
    fn eq(&self, other: &AllowPlus) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq)]
29pub(super) enum AllowPlus {
30    Yes,
31    No,
32}
33
34#[derive(#[automatically_derived]
impl ::core::cmp::PartialEq for RecoverQPath {
    #[inline]
    fn eq(&self, other: &RecoverQPath) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq)]
35pub(super) enum RecoverQPath {
36    Yes,
37    No,
38}
39
40pub(super) enum RecoverQuestionMark {
41    Yes,
42    No,
43}
44
45/// Signals whether parsing a type should recover `->`.
46///
47/// More specifically, when parsing a function like:
48/// ```compile_fail
49/// fn foo() => u8 { 0 }
50/// fn bar(): u8 { 0 }
51/// ```
52/// The compiler will try to recover interpreting `foo() => u8` as `foo() -> u8` when calling
53/// `parse_ty` with anything except `RecoverReturnSign::No`, and it will try to recover `bar(): u8`
54/// as `bar() -> u8` when passing `RecoverReturnSign::Yes` to `parse_ty`
55#[derive(#[automatically_derived]
impl ::core::marker::Copy for RecoverReturnSign { }Copy, #[automatically_derived]
impl ::core::clone::Clone for RecoverReturnSign {
    #[inline]
    fn clone(&self) -> RecoverReturnSign { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for RecoverReturnSign {
    #[inline]
    fn eq(&self, other: &RecoverReturnSign) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq)]
56pub(super) enum RecoverReturnSign {
57    Yes,
58    OnlyFatArrow,
59    No,
60}
61
62impl RecoverReturnSign {
63    /// [RecoverReturnSign::Yes] allows for recovering `fn foo() => u8` and `fn foo(): u8`,
64    /// [RecoverReturnSign::OnlyFatArrow] allows for recovering only `fn foo() => u8` (recovering
65    /// colons can cause problems when parsing where clauses), and
66    /// [RecoverReturnSign::No] doesn't allow for any recovery of the return type arrow
67    fn can_recover(self, token: &TokenKind) -> bool {
68        match self {
69            Self::Yes => #[allow(non_exhaustive_omitted_patterns)] match token {
    token::FatArrow | token::Colon => true,
    _ => false,
}matches!(token, token::FatArrow | token::Colon),
70            Self::OnlyFatArrow => #[allow(non_exhaustive_omitted_patterns)] match token {
    token::FatArrow => true,
    _ => false,
}matches!(token, token::FatArrow),
71            Self::No => false,
72        }
73    }
74}
75
76// Is `...` (`CVarArgs`) legal at this level of type parsing?
77#[derive(#[automatically_derived]
impl ::core::cmp::PartialEq for AllowCVariadic {
    #[inline]
    fn eq(&self, other: &AllowCVariadic) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq)]
78enum AllowCVariadic {
79    Yes,
80    No,
81}
82
83/// Determine if the given token can begin a bound assuming it follows Rust 2015 identifier `dyn`.
84///
85/// In Rust 2015, `dyn` is a contextual keyword, not a full one.
86fn can_begin_dyn_bound_in_edition_2015(t: Token) -> bool {
87    if t.is_path_start() {
88        // In `dyn::x`, `dyn<X>` and `dyn<<X>::Y>`, `dyn` should (continue to) denote a regular path
89        // segment for backward compatibility. We make an exception for `dyn(X)` which used to be
90        // interpreted as a path with parenthesized generic arguments which can be semantically
91        // well-formed (consider: `use std::ops::Fn as dyn;`). Instead, we treat it as a trait
92        // object type whose first bound is parenthesized.
93        return t != token::PathSep && t != token::Lt && t != token::Shl;
94    }
95
96    // Contrary to `Parser::can_begin_bound`, `!`, `const`, `[` and `async` are deliberately not
97    // part of this list to contain the number of potential regressions esp. in MBE code.
98    // `const` and `[` would regress UI test `macro-dyn-const-2015.rs` and
99    // `!` would regress `dyn!(...)` macro calls in Rust 2015 for example.
100    t == token::OpenParen || t == token::Question || t.is_lifetime() || t.is_keyword(kw::For)
101}
102
103impl<'a> Parser<'a> {
104    /// Parses a type.
105    pub fn parse_ty(&mut self) -> PResult<'a, Box<Ty>> {
106        if self.token == token::DotDotDot {
107            // We special case this so that we don't talk about "nested C-variadics" in types.
108            // We still pass in `AllowCVariadic::No` so that `parse_ty_common` can complain about
109            // things like `Vec<...>`.
110            let span = self.token.span;
111            self.bump();
112            let kind = TyKind::Err(self.dcx().emit_err(InvalidCVariadicType { span }));
113            return Ok(self.mk_ty(span, kind));
114        }
115        // Make sure deeply nested types don't overflow the stack.
116        self.parse_ty_common(
117            AllowPlus::Yes,
118            AllowCVariadic::No,
119            RecoverQPath::Yes,
120            RecoverReturnSign::Yes,
121            None,
122            RecoverQuestionMark::Yes,
123        )
124    }
125
126    pub(super) fn parse_ty_with_generics_recovery(
127        &mut self,
128        ty_params: &Generics,
129    ) -> PResult<'a, Box<Ty>> {
130        self.parse_ty_common(
131            AllowPlus::Yes,
132            AllowCVariadic::No,
133            RecoverQPath::Yes,
134            RecoverReturnSign::Yes,
135            Some(ty_params),
136            RecoverQuestionMark::Yes,
137        )
138    }
139
140    /// Parse a type suitable for a function or function pointer parameter.
141    /// The difference from `parse_ty` is that this version allows `...`
142    /// (`CVarArgs`) at the top level of the type.
143    pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, Box<Ty>> {
144        let ty = self.parse_ty_common(
145            AllowPlus::Yes,
146            AllowCVariadic::Yes,
147            RecoverQPath::Yes,
148            RecoverReturnSign::Yes,
149            None,
150            RecoverQuestionMark::Yes,
151        )?;
152
153        // Recover a trailing `= EXPR` if present.
154        if self.may_recover()
155            && self.check_noexpect(&token::Eq)
156            && self.look_ahead(1, |tok| tok.can_begin_expr())
157        {
158            let snapshot = self.create_snapshot_for_diagnostic();
159            self.bump();
160            let eq_span = self.prev_token.span;
161            match self.parse_expr() {
162                Ok(e) => {
163                    self.dcx()
164                        .struct_span_err(eq_span.to(e.span), "parameter defaults are not supported")
165                        .emit();
166                }
167                Err(diag) => {
168                    diag.cancel();
169                    self.restore_snapshot(snapshot);
170                }
171            }
172        }
173
174        Ok(ty)
175    }
176
177    /// Parses a type in restricted contexts where `+` is not permitted.
178    ///
179    /// Example 1: `&'a TYPE`
180    ///     `+` is prohibited to maintain operator priority (P(+) < P(&)).
181    /// Example 2: `value1 as TYPE + value2`
182    ///     `+` is prohibited to avoid interactions with expression grammar.
183    pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, Box<Ty>> {
184        self.parse_ty_common(
185            AllowPlus::No,
186            AllowCVariadic::No,
187            RecoverQPath::Yes,
188            RecoverReturnSign::Yes,
189            None,
190            RecoverQuestionMark::Yes,
191        )
192    }
193
194    /// Parses a type following an `as` cast. Similar to `parse_ty_no_plus`, but signaling origin
195    /// for better diagnostics involving `?`.
196    pub(super) fn parse_as_cast_ty(&mut self) -> PResult<'a, Box<Ty>> {
197        self.parse_ty_common(
198            AllowPlus::No,
199            AllowCVariadic::No,
200            RecoverQPath::Yes,
201            RecoverReturnSign::Yes,
202            None,
203            RecoverQuestionMark::No,
204        )
205    }
206
207    pub(super) fn parse_ty_no_question_mark_recover(&mut self) -> PResult<'a, Box<Ty>> {
208        self.parse_ty_common(
209            AllowPlus::Yes,
210            AllowCVariadic::No,
211            RecoverQPath::Yes,
212            RecoverReturnSign::Yes,
213            None,
214            RecoverQuestionMark::No,
215        )
216    }
217
218    /// Parse a type without recovering `:` as `->` to avoid breaking code such
219    /// as `where fn() : for<'a>`.
220    pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, Box<Ty>> {
221        self.parse_ty_common(
222            AllowPlus::Yes,
223            AllowCVariadic::No,
224            RecoverQPath::Yes,
225            RecoverReturnSign::OnlyFatArrow,
226            None,
227            RecoverQuestionMark::Yes,
228        )
229    }
230
231    /// Parses an optional return type `[ -> TY ]` in a function declaration.
232    pub(super) fn parse_ret_ty(
233        &mut self,
234        allow_plus: AllowPlus,
235        recover_qpath: RecoverQPath,
236        recover_return_sign: RecoverReturnSign,
237    ) -> PResult<'a, FnRetTy> {
238        let lo = self.prev_token.span;
239        Ok(if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::RArrow,
    token_type: crate::parser::token_type::TokenType::RArrow,
}exp!(RArrow)) {
240            // FIXME(Centril): Can we unconditionally `allow_plus`?
241            let ty = self.parse_ty_common(
242                allow_plus,
243                AllowCVariadic::No,
244                recover_qpath,
245                recover_return_sign,
246                None,
247                RecoverQuestionMark::Yes,
248            )?;
249            FnRetTy::Ty(ty)
250        } else if recover_return_sign.can_recover(&self.token.kind) {
251            // Don't `eat` to prevent `=>` from being added as an expected token which isn't
252            // actually expected and could only confuse users
253            self.bump();
254            self.dcx().emit_err(ReturnTypesUseThinArrow {
255                span: self.prev_token.span,
256                suggestion: lo.between(self.token.span),
257            });
258            let ty = self.parse_ty_common(
259                allow_plus,
260                AllowCVariadic::No,
261                recover_qpath,
262                recover_return_sign,
263                None,
264                RecoverQuestionMark::Yes,
265            )?;
266            FnRetTy::Ty(ty)
267        } else {
268            FnRetTy::Default(self.prev_token.span.shrink_to_hi())
269        })
270    }
271
272    fn parse_ty_common(
273        &mut self,
274        allow_plus: AllowPlus,
275        allow_c_variadic: AllowCVariadic,
276        recover_qpath: RecoverQPath,
277        recover_return_sign: RecoverReturnSign,
278        ty_generics: Option<&Generics>,
279        recover_question_mark: RecoverQuestionMark,
280    ) -> PResult<'a, Box<Ty>> {
281        let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
282        if allow_qpath_recovery && self.may_recover() &&
                let Some(mv_kind) = self.token.is_metavar_seq() &&
            let token::MetaVarKind::Ty { .. } = mv_kind &&
        self.check_noexpect_past_close_delim(&token::PathSep) {
    let ty =
        self.eat_metavar_seq(mv_kind,
                |this|
                    this.parse_ty_no_question_mark_recover()).expect("metavar seq ty");
    return self.maybe_recover_from_bad_qpath_stage_2(self.prev_token.span,
            ty);
};maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
283        if self.token == token::Pound && self.look_ahead(1, |t| *t == token::OpenBracket) {
284            let attrs_wrapper = self.parse_outer_attributes()?;
285            let raw_attrs = attrs_wrapper.take_for_recovery(self.psess);
286            let attr_span = raw_attrs[0].span.to(raw_attrs.last().unwrap().span);
287            let (full_span, guar) = match self.parse_ty() {
288                Ok(ty) => {
289                    let full_span = attr_span.until(ty.span);
290                    let guar = self
291                        .dcx()
292                        .emit_err(AttributeOnType { span: attr_span, fix_span: full_span });
293                    (attr_span, guar)
294                }
295                Err(err) => {
296                    err.cancel();
297                    let guar = self.dcx().emit_err(AttributeOnEmptyType { span: attr_span });
298                    (attr_span, guar)
299                }
300            };
301
302            return Ok(self.mk_ty(full_span, TyKind::Err(guar)));
303        }
304        if let Some(ty) = self.eat_metavar_seq_with_matcher(
305            |mv_kind| #[allow(non_exhaustive_omitted_patterns)] match mv_kind {
    MetaVarKind::Ty { .. } => true,
    _ => false,
}matches!(mv_kind, MetaVarKind::Ty { .. }),
306            |this| this.parse_ty_no_question_mark_recover(),
307        ) {
308            return Ok(ty);
309        }
310
311        let lo = self.token.span;
312        let mut impl_dyn_multi = false;
313        let kind = if self.check(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::OpenParen,
    token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
314            self.parse_ty_tuple_or_parens(lo, allow_plus)?
315        } else if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Bang,
    token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) {
316            // Never type `!`
317            TyKind::Never
318        } else if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Star,
    token_type: crate::parser::token_type::TokenType::Star,
}exp!(Star)) {
319            self.parse_ty_ptr()?
320        } else if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::OpenBracket,
    token_type: crate::parser::token_type::TokenType::OpenBracket,
}exp!(OpenBracket)) {
321            self.parse_array_or_slice_ty()?
322        } else if self.check(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::And,
    token_type: crate::parser::token_type::TokenType::And,
}exp!(And)) || self.check(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::AndAnd,
    token_type: crate::parser::token_type::TokenType::AndAnd,
}exp!(AndAnd)) {
323            // Reference
324            self.expect_and()?;
325            self.parse_borrowed_pointee()?
326        } else if self.eat_keyword_noexpect(kw::Typeof) {
327            self.parse_typeof_ty(lo)?
328        } else if self.is_builtin() {
329            self.parse_builtin_ty()?
330        } else if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Underscore,
    token_type: crate::parser::token_type::TokenType::KwUnderscore,
}exp!(Underscore)) {
331            // A type to be inferred `_`
332            TyKind::Infer
333        } else if self.check_fn_front_matter(false, Case::Sensitive) {
334            // Function pointer type
335            self.parse_ty_fn_ptr(lo, ThinVec::new(), None, recover_return_sign)?
336        } else if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::For,
    token_type: crate::parser::token_type::TokenType::KwFor,
}exp!(For)) {
337            // Function pointer type or bound list (trait object type) starting with a poly-trait.
338            //   `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
339            //   `for<'lt> Trait1<'lt> + Trait2 + 'a`
340            let (bound_vars, _) = self.parse_higher_ranked_binder()?;
341            if self.check_fn_front_matter(false, Case::Sensitive) {
342                self.parse_ty_fn_ptr(
343                    lo,
344                    bound_vars,
345                    Some(self.prev_token.span.shrink_to_lo()),
346                    recover_return_sign,
347                )?
348            } else {
349                // Try to recover `for<'a> dyn Trait` or `for<'a> impl Trait`.
350                if self.may_recover()
351                    && (self.eat_keyword_noexpect(kw::Impl) || self.eat_keyword_noexpect(kw::Dyn))
352                {
353                    let kw = self.prev_token.ident().unwrap().0;
354                    let removal_span = kw.span.with_hi(self.token.span.lo());
355                    let path = self.parse_path(PathStyle::Type)?;
356                    let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
357                    let kind = self.parse_remaining_bounds_path(
358                        bound_vars,
359                        path,
360                        lo,
361                        parse_plus,
362                        ast::Parens::No,
363                    )?;
364                    let err = self.dcx().create_err(diagnostics::TransposeDynOrImpl {
365                        span: kw.span,
366                        kw: kw.name.as_str(),
367                        sugg: diagnostics::TransposeDynOrImplSugg {
368                            removal_span,
369                            insertion_span: lo.shrink_to_lo(),
370                            kw: kw.name.as_str(),
371                        },
372                    });
373
374                    // Take the parsed bare trait object and turn it either
375                    // into a `dyn` object or an `impl Trait`.
376                    let kind = match (kind, kw.name) {
377                        (TyKind::TraitObject(bounds, _), kw::Dyn) => {
378                            TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn)
379                        }
380                        (TyKind::TraitObject(bounds, _), kw::Impl) => {
381                            TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)
382                        }
383                        _ => return Err(err),
384                    };
385                    err.emit();
386                    kind
387                } else {
388                    let path = self.parse_path(PathStyle::Type)?;
389                    let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
390                    self.parse_remaining_bounds_path(
391                        bound_vars,
392                        path,
393                        lo,
394                        parse_plus,
395                        ast::Parens::No,
396                    )?
397                }
398            }
399        } else if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Impl,
    token_type: crate::parser::token_type::TokenType::KwImpl,
}exp!(Impl)) {
400            self.parse_impl_ty(&mut impl_dyn_multi)?
401        } else if self.is_explicit_dyn_type() {
402            self.parse_dyn_ty(&mut impl_dyn_multi)?
403        } else if self.eat_lt() {
404            // Qualified path
405            let (qself, path) = self.parse_qpath(PathStyle::Type)?;
406            TyKind::Path(Some(qself), path)
407        } else if (self.token.is_keyword(kw::Const) || self.token.is_keyword(kw::Mut))
408            && self.look_ahead(1, |t| *t == token::Star)
409        {
410            self.parse_ty_c_style_pointer()?
411        } else if self.check_path() {
412            self.parse_path_start_ty(lo, allow_plus, ty_generics)?
413        } else if self.can_begin_bound() {
414            self.parse_bare_trait_object(lo, allow_plus)?
415        } else if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::DotDotDot,
    token_type: crate::parser::token_type::TokenType::DotDotDot,
}exp!(DotDotDot)) {
416            match allow_c_variadic {
417                AllowCVariadic::Yes => TyKind::CVarArgs,
418                AllowCVariadic::No => {
419                    // FIXME(c_variadic): Should we just allow `...` syntactically
420                    // anywhere in a type and use semantic restrictions instead?
421                    // NOTE: This may regress certain MBE calls if done incorrectly.
422                    let guar = self.dcx().emit_err(NestedCVariadicType { span: lo });
423                    TyKind::Err(guar)
424                }
425            }
426        } 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))
427            && self.look_ahead(1, |tok| tok.kind == token::Lt)
428        {
429            self.parse_unsafe_binder_ty()?
430        } else {
431            let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("expected type, found {0}",
                super::token_descr(&self.token)))
    })format!("expected type, found {}", super::token_descr(&self.token));
432            let mut err = self.dcx().struct_span_err(lo, msg);
433            err.span_label(lo, "expected type");
434            return Err(err);
435        };
436
437        let span = lo.to(self.prev_token.span);
438        let mut ty = self.mk_ty(span, kind);
439
440        // Try to recover from use of `+` with incorrect priority.
441        match allow_plus {
442            AllowPlus::Yes => self.maybe_recover_from_bad_type_plus(&ty)?,
443            AllowPlus::No => self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty),
444        }
445        if let RecoverQuestionMark::Yes = recover_question_mark {
446            ty = self.maybe_recover_from_question_mark(ty);
447        }
448        if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) }
449    }
450
451    fn parse_unsafe_binder_ty(&mut self) -> PResult<'a, TyKind> {
452        let lo = self.token.span;
453        if !self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
                kw: rustc_span::symbol::kw::Unsafe,
                token_type: crate::parser::token_type::TokenType::KwUnsafe,
            }) {
    ::core::panicking::panic("assertion failed: self.eat_keyword(exp!(Unsafe))")
};assert!(self.eat_keyword(exp!(Unsafe)));
454        self.expect_lt()?;
455        let generic_params = self.parse_generic_params()?;
456        self.expect_gt()?;
457        let inner_ty = self.parse_ty()?;
458        let span = lo.to(self.prev_token.span);
459        self.psess.gated_spans.gate(sym::unsafe_binders, span);
460
461        Ok(TyKind::UnsafeBinder(Box::new(UnsafeBinderTy { generic_params, inner_ty })))
462    }
463
464    /// Parses either:
465    /// - `(TYPE)`, a parenthesized type.
466    /// - `(TYPE,)`, a tuple with a single field of type TYPE.
467    fn parse_ty_tuple_or_parens(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
468        let mut trailing_plus = false;
469        let (ts, trailing) = self.parse_paren_comma_seq(|p| {
470            let ty = p.parse_ty()?;
471            trailing_plus = p.prev_token == TokenKind::Plus;
472            Ok(ty)
473        })?;
474
475        if ts.len() == 1 && #[allow(non_exhaustive_omitted_patterns)] match trailing {
    Trailing::No => true,
    _ => false,
}matches!(trailing, Trailing::No) {
476            let ty = ts.into_iter().next().unwrap();
477            let maybe_bounds = allow_plus == AllowPlus::Yes && self.token.is_like_plus();
478            match ty.kind {
479                // `"(" BareTraitBound ")" "+" Bound "+" ...`.
480                TyKind::Path(None, path) if maybe_bounds => self.parse_remaining_bounds_path(
481                    ThinVec::new(),
482                    path,
483                    lo,
484                    true,
485                    ast::Parens::Yes,
486                ),
487                // For `('a) + …`, we know that `'a` in type position already lead to an error being
488                // emitted. To reduce output, let's indirectly suppress E0178 (bad `+` in type) and
489                // other irrelevant consequential errors.
490                TyKind::TraitObject(bounds, TraitObjectSyntax::None)
491                    if maybe_bounds && bounds.len() == 1 && !trailing_plus =>
492                {
493                    self.parse_remaining_bounds(bounds, true)
494                }
495                // `(TYPE)`
496                _ => Ok(TyKind::Paren(ty)),
497            }
498        } else {
499            Ok(TyKind::Tup(ts))
500        }
501    }
502
503    fn parse_bare_trait_object(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
504        // A lifetime only begins a bare trait object type if it is followed by `+`!
505        if self.token.is_lifetime() && !self.look_ahead(1, |t| t.is_like_plus()) {
506            // In Rust 2021 and beyond, we assume that the user didn't intend to write a bare trait
507            // object type with a leading lifetime bound since that seems very unlikely given the
508            // fact that `dyn`-less trait objects are *semantically* invalid.
509            if self.psess.edition.at_least_rust_2021() {
510                let lt = self.expect_lifetime();
511                let mut err = self.dcx().struct_span_err(lo, "expected type, found lifetime");
512                err.span_label(lo, "expected type");
513                return Ok(match self.maybe_recover_ref_ty_no_leading_ampersand(lt, lo, err) {
514                    Ok(ref_ty) => ref_ty,
515                    Err(err) => TyKind::Err(err.emit()),
516                });
517            }
518
519            self.dcx().emit_err(NeedPlusAfterTraitObjectLifetime {
520                span: lo,
521                suggestion: lo.shrink_to_hi(),
522            });
523        }
524        Ok(TyKind::TraitObject(
525            self.parse_generic_bounds_common(allow_plus)?,
526            TraitObjectSyntax::None,
527        ))
528    }
529
530    fn maybe_recover_ref_ty_no_leading_ampersand<'cx>(
531        &mut self,
532        lt: Lifetime,
533        lo: Span,
534        mut err: Diag<'cx>,
535    ) -> Result<TyKind, Diag<'cx>> {
536        if !self.may_recover() {
537            return Err(err);
538        }
539        let snapshot = self.create_snapshot_for_diagnostic();
540        let mutbl = self.parse_mutability();
541        match self.parse_ty_no_plus() {
542            Ok(ty) => {
543                err.span_suggestion_verbose(
544                    lo.shrink_to_lo(),
545                    "you might have meant to write a reference type here",
546                    "&",
547                    Applicability::MaybeIncorrect,
548                );
549                err.emit();
550                Ok(TyKind::Ref(Some(lt), MutTy { ty, mutbl }))
551            }
552            Err(diag) => {
553                diag.cancel();
554                self.restore_snapshot(snapshot);
555                Err(err)
556            }
557        }
558    }
559
560    fn parse_remaining_bounds_path(
561        &mut self,
562        generic_params: ThinVec<GenericParam>,
563        path: ast::Path,
564        lo: Span,
565        parse_plus: bool,
566        parens: ast::Parens,
567    ) -> PResult<'a, TyKind> {
568        let poly_trait_ref = PolyTraitRef::new(
569            generic_params,
570            path,
571            TraitBoundModifiers::NONE,
572            lo.to(self.prev_token.span),
573            parens,
574        );
575        let bounds = {
    let len = [()].len();
    let mut vec = ::thin_vec::ThinVec::with_capacity(len);
    vec.push(GenericBound::Trait(poly_trait_ref));
    vec
}thin_vec![GenericBound::Trait(poly_trait_ref)];
576        self.parse_remaining_bounds(bounds, parse_plus)
577    }
578
579    /// Parse the remainder of a bare trait object type given an already parsed list.
580    fn parse_remaining_bounds(
581        &mut self,
582        mut bounds: GenericBounds,
583        plus: bool,
584    ) -> PResult<'a, TyKind> {
585        if plus {
586            self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
587            bounds.append(&mut self.parse_generic_bounds()?);
588        }
589        Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
590    }
591
592    /// Parses a raw pointer with a C-style typo
593    fn parse_ty_c_style_pointer(&mut self) -> PResult<'a, TyKind> {
594        let kw_span = self.token.span;
595        let mutbl = self.parse_mut_or_const();
596
597        if let Some(mutbl) = mutbl
598            && self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Star,
    token_type: crate::parser::token_type::TokenType::Star,
}exp!(Star))
599        {
600            let star_span = self.prev_token.span;
601
602            let mutability = match mutbl {
603                Mutability::Not => "const",
604                Mutability::Mut => "mut",
605            };
606
607            let ty = self.parse_ty_no_question_mark_recover()?;
608
609            self.dcx()
610                .struct_span_err(
611                    kw_span,
612                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("raw pointer types must be written as `*{0} T`",
                mutability))
    })format!("raw pointer types must be written as `*{mutability} T`"),
613                )
614                .with_multipart_suggestion(
615                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("put the `*` before `{0}`",
                mutability))
    })format!("put the `*` before `{mutability}`"),
616                    ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(star_span, String::new()),
                (kw_span.shrink_to_lo(), "*".to_string())]))vec![(star_span, String::new()), (kw_span.shrink_to_lo(), "*".to_string())],
617                    Applicability::MachineApplicable,
618                )
619                .emit();
620
621            return Ok(TyKind::Ptr(MutTy { ty, mutbl }));
622        }
623        // This is unreachable because we always get into if above and return from it
624        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("this could never happen")));
}unreachable!("this could never happen")
625    }
626
627    /// Parses a raw pointer type: `*[const | mut] $type`.
628    fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {
629        let mutbl = self.parse_mut_or_const().unwrap_or_else(|| {
630            let span = self.prev_token.span;
631            self.dcx().emit_err(ExpectedMutOrConstInRawPointerType {
632                span,
633                after_asterisk: span.shrink_to_hi(),
634            });
635            Mutability::Not
636        });
637        let ty = self.parse_ty_no_plus()?;
638        Ok(TyKind::Ptr(MutTy { ty, mutbl }))
639    }
640
641    /// Parses an array (`[TYPE; EXPR]`) or slice (`[TYPE]`) type.
642    /// The opening `[` bracket is already eaten.
643    fn parse_array_or_slice_ty(&mut self) -> PResult<'a, TyKind> {
644        let elt_ty = match self.parse_ty() {
645            Ok(ty) => ty,
646            Err(err)
647                if self.look_ahead(1, |t| *t == token::CloseBracket)
648                    | self.look_ahead(1, |t| *t == token::Semi) =>
649            {
650                // Recover from `[LIT; EXPR]` and `[LIT]`
651                self.bump();
652                let guar = err.emit();
653                self.mk_ty(self.prev_token.span, TyKind::Err(guar))
654            }
655            Err(err) => return Err(err),
656        };
657
658        let ty = if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Semi,
    token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
659            let mut length = self.parse_expr_anon_const()?;
660
661            if let Err(e) = self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseBracket,
    token_type: crate::parser::token_type::TokenType::CloseBracket,
}exp!(CloseBracket)) {
662                // Try to recover from `X<Y, ...>` when `X::<Y, ...>` works
663                self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?;
664                self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseBracket,
    token_type: crate::parser::token_type::TokenType::CloseBracket,
}exp!(CloseBracket))?;
665            }
666            TyKind::Array(elt_ty, length)
667        } else if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseBracket,
    token_type: crate::parser::token_type::TokenType::CloseBracket,
}exp!(CloseBracket)) {
668            TyKind::Slice(elt_ty)
669        } else {
670            self.maybe_recover_array_ty_without_semi(elt_ty)?
671        };
672
673        Ok(ty)
674    }
675
676    /// Recover from malformed array type syntax.
677    ///
678    /// This method attempts to recover from cases like:
679    /// - `[u8, 5]` → suggests using `;`, return a Array type
680    /// - `[u8 5]` → suggests using `;`, return a Array type
681    /// Consider to add more cases in the future.
682    fn maybe_recover_array_ty_without_semi(&mut self, elt_ty: Box<Ty>) -> PResult<'a, TyKind> {
683        let span = self.token.span;
684        let token_descr = super::token_descr(&self.token);
685        let mut err =
686            self.dcx().struct_span_err(span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("expected `;` or `]`, found {0}",
                token_descr))
    })format!("expected `;` or `]`, found {}", token_descr));
687        err.span_label(span, "expected `;` or `]`");
688
689        // If we cannot recover, return the error immediately.
690        if !self.may_recover() {
691            return Err(err);
692        }
693
694        let snapshot = self.create_snapshot_for_diagnostic();
695
696        // Consume common erroneous separators.
697        let hi = self.prev_token.span.hi();
698        _ = self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Comma,
    token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma)) || self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Colon,
    token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)) || self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Star,
    token_type: crate::parser::token_type::TokenType::Star,
}exp!(Star));
699        let suggestion_span = self.prev_token.span.with_lo(hi);
700
701        // FIXME(mgca): recovery is broken for `const {` args
702        // we first try to parse pattern like `[u8 5]`
703        let length = match self.parse_expr_anon_const() {
704            Ok(length) => length,
705            Err(e) => {
706                e.cancel();
707                self.restore_snapshot(snapshot);
708                return Err(err);
709            }
710        };
711
712        if let Err(e) = self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseBracket,
    token_type: crate::parser::token_type::TokenType::CloseBracket,
}exp!(CloseBracket)) {
713            e.cancel();
714            self.restore_snapshot(snapshot);
715            return Err(err);
716        }
717
718        err.span_suggestion_verbose(
719            suggestion_span,
720            "you might have meant to use `;` as the separator",
721            ";",
722            Applicability::MaybeIncorrect,
723        );
724        err.emit();
725        Ok(TyKind::Array(elt_ty, length))
726    }
727
728    fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
729        let and_span = self.prev_token.span;
730        let mut opt_lifetime = self.check_lifetime().then(|| self.expect_lifetime());
731        let (pinned, mut mutbl) = self.parse_pin_and_mut();
732        if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
733            // A lifetime is invalid here: it would be part of a bare trait bound, which requires
734            // it to be followed by a plus, but we disallow plus in the pointee type.
735            // So we can handle this case as an error here, and suggest `'a mut`.
736            // If there *is* a plus next though, handling the error later provides better suggestions
737            // (like adding parentheses)
738            if !self.look_ahead(1, |t| t.is_like_plus()) {
739                let lifetime_span = self.token.span;
740                let span = and_span.to(lifetime_span);
741
742                let (suggest_lifetime, snippet) =
743                    if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
744                        (Some(span), lifetime_src)
745                    } else {
746                        (None, String::new())
747                    };
748                self.dcx().emit_err(LifetimeAfterMut { span, suggest_lifetime, snippet });
749
750                opt_lifetime = Some(self.expect_lifetime());
751            }
752        } else if self.token.is_keyword(kw::Dyn)
753            && mutbl == Mutability::Not
754            && self.look_ahead(1, |t| t.is_keyword(kw::Mut))
755        {
756            // We have `&dyn mut ...`, which is invalid and should be `&mut dyn ...`.
757            let span = and_span.to(self.look_ahead(1, |t| t.span));
758            self.dcx().emit_err(DynAfterMut { span });
759
760            // Recovery
761            mutbl = Mutability::Mut;
762            let (dyn_tok, dyn_tok_sp) = (self.token, self.token_spacing);
763            self.bump();
764            self.bump_with((dyn_tok, dyn_tok_sp));
765        }
766        let ty = self.parse_ty_no_plus()?;
767        Ok(match pinned {
768            Pinnedness::Not => TyKind::Ref(opt_lifetime, MutTy { ty, mutbl }),
769            Pinnedness::Pinned => TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl }),
770        })
771    }
772
773    /// Parse nothing, mutability or `pin` followed by "explicit" mutability.
774    ///
775    /// ```ebnf
776    /// PinAndMut = "pin" MutOrConst | "mut"
777    /// ```
778    pub(crate) fn parse_pin_and_mut(&mut self) -> (Pinnedness, Mutability) {
779        if self.token.is_ident_named(sym::pin) && self.look_ahead(1, Token::is_mutability) {
780            self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
781            if !self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
                kw: rustc_span::symbol::sym::pin,
                token_type: crate::parser::token_type::TokenType::SymPin,
            }) {
    ::core::panicking::panic("assertion failed: self.eat_keyword(exp!(Pin))")
};assert!(self.eat_keyword(exp!(Pin)));
782            let mutbl = self.parse_mut_or_const().unwrap();
783            (Pinnedness::Pinned, mutbl)
784        } else {
785            (Pinnedness::Not, self.parse_mutability())
786        }
787    }
788
789    /// Parses the `typeof(EXPR)` for better diagnostics before returning
790    /// an error type.
791    fn parse_typeof_ty(&mut self, lo: Span) -> PResult<'a, TyKind> {
792        self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::OpenParen,
    token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen))?;
793        let _expr = self.parse_expr_anon_const()?;
794        self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseParen,
    token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen))?;
795        let span = lo.to(self.prev_token.span);
796        let guar = self
797            .dcx()
798            .struct_span_err(span, "`typeof` is a reserved keyword but unimplemented")
799            .with_note("consider replacing `typeof(...)` with an actual type")
800            .with_code(E0516)
801            .emit();
802        Ok(TyKind::Err(guar))
803    }
804
805    fn parse_builtin_ty(&mut self) -> PResult<'a, TyKind> {
806        self.parse_builtin(|this, lo, ident| {
807            Ok(match ident.name {
808                sym::field_of => Some(this.parse_ty_field_of(lo)?),
809                _ => None,
810            })
811        })
812    }
813
814    pub(crate) fn parse_ty_field_of(&mut self, _lo: Span) -> PResult<'a, TyKind> {
815        let container = self.parse_ty()?;
816        self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Comma,
    token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma))?;
817
818        let fields = self.parse_floating_field_access()?;
819        let trailing_comma = self.eat_noexpect(&TokenKind::Comma);
820
821        if let Err(mut e) = self.expect_one_of(&[], &[crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseParen,
    token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]) {
822            if trailing_comma {
823                e.note("unexpected third argument to field_of");
824            } else {
825                e.note("field_of expects dot-separated field and variant names");
826            }
827            e.emit();
828        }
829
830        // Eat tokens until the macro call ends.
831        if self.may_recover() {
832            while !self.token.kind.is_close_delim_or_eof() {
833                self.bump();
834            }
835        }
836
837        match *fields {
838            [] => Err(self.dcx().struct_span_err(
839                self.token.span,
840                "`field_of!` expects dot-separated field and variant names",
841            )),
842            [field] => Ok(TyKind::FieldOf(container, None, field)),
843            [variant, field] => Ok(TyKind::FieldOf(container, Some(variant), field)),
844            _ => Err(self.dcx().struct_span_err(
845                fields.iter().map(|f| f.span).collect::<Vec<_>>(),
846                "`field_of!` only supports a single field or a variant with a field",
847            )),
848        }
849    }
850
851    /// Parses a function pointer type (`TyKind::FnPtr`).
852    /// ```ignore (illustrative)
853    ///    [unsafe] [extern "ABI"] fn (S) -> T
854    /// //  ^~~~~^          ^~~~^     ^~^    ^
855    /// //    |               |        |     |
856    /// //    |               |        |   Return type
857    /// // Function Style    ABI  Parameter types
858    /// ```
859    /// We actually parse `FnHeader FnDecl`, but we error on `const` and `async` qualifiers.
860    fn parse_ty_fn_ptr(
861        &mut self,
862        lo: Span,
863        mut params: ThinVec<GenericParam>,
864        param_insertion_point: Option<Span>,
865        recover_return_sign: RecoverReturnSign,
866    ) -> PResult<'a, TyKind> {
867        let inherited_vis = rustc_ast::Visibility {
868            span: rustc_span::DUMMY_SP,
869            kind: rustc_ast::VisibilityKind::Inherited,
870        };
871        let span_start = self.token.span;
872        let ast::FnHeader { ext, safety, .. } = self.parse_fn_front_matter(
873            &inherited_vis,
874            Case::Sensitive,
875            FrontMatterParsingMode::FunctionPtrType,
876        )?;
877        if self.may_recover() && self.token == TokenKind::Lt {
878            self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?;
879        }
880        let mode = crate::parser::FnParseMode {
881            req_name: |_, _| false,
882            context: FnContext::FunctionPtrType,
883            req_body: false,
884        };
885        let decl = self.parse_fn_decl(&mode, AllowPlus::No, recover_return_sign)?;
886
887        let decl_span = span_start.to(self.prev_token.span);
888        Ok(TyKind::FnPtr(Box::new(FnPtrTy {
889            ext,
890            safety,
891            generic_params: params,
892            decl,
893            decl_span,
894        })))
895    }
896
897    /// Recover from function pointer types with a generic parameter list (e.g. `fn<'a>(&'a str)`).
898    fn recover_fn_ptr_with_generics(
899        &mut self,
900        lo: Span,
901        params: &mut ThinVec<GenericParam>,
902        param_insertion_point: Option<Span>,
903    ) -> PResult<'a, ()> {
904        let generics = self.parse_generics()?;
905        let arity = generics.params.len();
906
907        let mut lifetimes: ThinVec<_> = generics
908            .params
909            .into_iter()
910            .filter(|param| #[allow(non_exhaustive_omitted_patterns)] match param.kind {
    ast::GenericParamKind::Lifetime => true,
    _ => false,
}matches!(param.kind, ast::GenericParamKind::Lifetime))
911            .collect();
912
913        let sugg = if !lifetimes.is_empty() {
914            let snippet =
915                lifetimes.iter().map(|param| param.ident.as_str()).intersperse(", ").collect();
916
917            let (left, snippet) = if let Some(span) = param_insertion_point {
918                (span, if params.is_empty() { snippet } else { ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(", {0}", snippet))
    })format!(", {snippet}") })
919            } else {
920                (lo.shrink_to_lo(), ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("for<{0}> ", snippet))
    })format!("for<{snippet}> "))
921            };
922
923            Some(FnPtrWithGenericsSugg {
924                left,
925                snippet,
926                right: generics.span,
927                arity,
928                for_param_list_exists: param_insertion_point.is_some(),
929            })
930        } else {
931            None
932        };
933
934        self.dcx().emit_err(FnPtrWithGenerics { span: generics.span, sugg });
935        params.append(&mut lifetimes);
936        Ok(())
937    }
938
939    /// Parses an `impl B0 + ... + Bn` type.
940    fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
941        if self.token.is_lifetime() {
942            self.look_ahead(1, |t| {
943                if let token::Ident(sym, _) = t.kind {
944                    // parse pattern with "'a Sized" we're supposed to give suggestion like
945                    // "'a + Sized"
946                    self.dcx().emit_err(diagnostics::MissingPlusBounds {
947                        span: self.token.span,
948                        hi: self.token.span.shrink_to_hi(),
949                        sym,
950                    });
951                }
952            })
953        }
954
955        // Always parse bounds greedily for better error recovery.
956        let bounds = self.parse_generic_bounds()?;
957
958        *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;
959
960        Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds))
961    }
962
963    /// Parse a use-bound aka precise capturing list.
964    ///
965    /// ```ebnf
966    /// UseBound = "use" "<" (PreciseCapture ("," PreciseCapture)* ","?)? ">"
967    /// PreciseCapture = "Self" | Ident | Lifetime
968    /// ```
969    fn parse_use_bound(&mut self, lo: Span, parens: ast::Parens) -> PResult<'a, GenericBound> {
970        self.expect_lt()?;
971        let (args, _, _) = self.parse_seq_to_before_tokens(
972            &[crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Gt,
    token_type: crate::parser::token_type::TokenType::Gt,
}exp!(Gt)],
973            &[&TokenKind::Ge, &TokenKind::Shr, &TokenKind::Shr],
974            SeqSep::trailing_allowed(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Comma,
    token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma)),
975            |self_| {
976                if self_.check_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::SelfUpper,
    token_type: crate::parser::token_type::TokenType::KwSelfUpper,
}exp!(SelfUpper)) {
977                    self_.bump();
978                    Ok(PreciseCapturingArg::Arg(
979                        ast::Path::from_ident(self_.prev_token.ident().unwrap().0),
980                        DUMMY_NODE_ID,
981                    ))
982                } else if self_.check_ident() {
983                    Ok(PreciseCapturingArg::Arg(
984                        ast::Path::from_ident(self_.parse_ident()?),
985                        DUMMY_NODE_ID,
986                    ))
987                } else if self_.check_lifetime() {
988                    Ok(PreciseCapturingArg::Lifetime(self_.expect_lifetime()))
989                } else {
990                    self_.unexpected_any()
991                }
992            },
993        )?;
994        self.expect_gt()?;
995
996        if let ast::Parens::Yes = parens {
997            self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseParen,
    token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen))?;
998            self.report_parenthesized_bound(lo, self.prev_token.span, "precise capturing lists");
999        }
1000
1001        Ok(GenericBound::Use(args, lo.to(self.prev_token.span)))
1002    }
1003
1004    /// Is a `dyn B0 + ... + Bn` type allowed here?
1005    fn is_explicit_dyn_type(&mut self) -> bool {
1006        self.check_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Dyn,
    token_type: crate::parser::token_type::TokenType::KwDyn,
}exp!(Dyn))
1007            && (self.token_uninterpolated_span().at_least_rust_2018()
1008                || self.look_ahead(1, |&t| can_begin_dyn_bound_in_edition_2015(t)))
1009    }
1010
1011    /// Parses a `dyn B0 + ... + Bn` type.
1012    ///
1013    /// Note that this does *not* parse bare trait objects.
1014    fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
1015        self.bump(); // `dyn`
1016
1017        // Always parse bounds greedily for better error recovery.
1018        let bounds = self.parse_generic_bounds()?;
1019        *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;
1020
1021        Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn))
1022    }
1023
1024    /// Parses a type starting with a path.
1025    ///
1026    /// This can be:
1027    /// 1. a type macro, `mac!(...)`,
1028    /// 2. a bare trait object, `B0 + ... + Bn`,
1029    /// 3. or a path, `path::to::MyType`.
1030    fn parse_path_start_ty(
1031        &mut self,
1032        lo: Span,
1033        allow_plus: AllowPlus,
1034        ty_generics: Option<&Generics>,
1035    ) -> PResult<'a, TyKind> {
1036        // Simple path
1037        let path = self.parse_path_inner(PathStyle::Type, ty_generics)?;
1038        if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Bang,
    token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) {
1039            // Macro invocation in type position
1040            Ok(TyKind::MacCall(Box::new(MacCall { path, args: self.parse_delim_args()? })))
1041        } else if allow_plus == AllowPlus::Yes && self.check_plus() {
1042            // `Trait1 + Trait2 + 'a`
1043            self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true, ast::Parens::No)
1044        } else {
1045            // Just a type path.
1046            Ok(TyKind::Path(None, path))
1047        }
1048    }
1049
1050    pub(super) fn parse_generic_bounds(&mut self) -> PResult<'a, GenericBounds> {
1051        self.parse_generic_bounds_common(AllowPlus::Yes)
1052    }
1053
1054    /// Parse generic bounds.
1055    ///
1056    /// Only if `allow_plus` this parses a `+`-separated list of bounds (trailing `+` is admitted).
1057    /// Otherwise, this only parses a single bound or none.
1058    fn parse_generic_bounds_common(&mut self, allow_plus: AllowPlus) -> PResult<'a, GenericBounds> {
1059        let mut bounds = ThinVec::new();
1060
1061        // In addition to looping while we find generic bounds:
1062        // We continue even if we find a keyword. This is necessary for error recovery on,
1063        // for example, `impl fn()`. The only keyword that can go after generic bounds is
1064        // `where`, so stop if it's it.
1065        // We also continue if we find types (not traits), again for error recovery.
1066        while self.can_begin_bound()
1067            || (self.may_recover()
1068                && (self.token.can_begin_type()
1069                    || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where))))
1070        {
1071            if self.token.is_keyword(kw::Dyn) && self.token.span.edition().at_least_rust_2018() {
1072                // Account for `&dyn Trait + dyn Other`.
1073                self.bump();
1074                self.dcx().emit_err(InvalidDynKeyword {
1075                    span: self.prev_token.span,
1076                    suggestion: self.prev_token.span.until(self.token.span),
1077                });
1078            }
1079            bounds.push(self.parse_generic_bound()?);
1080            if allow_plus == AllowPlus::No || !self.eat_plus() {
1081                break;
1082            }
1083        }
1084
1085        Ok(bounds)
1086    }
1087
1088    /// Can the current token begin a bound?
1089    fn can_begin_bound(&mut self) -> bool {
1090        self.check_path()
1091            || self.check_lifetime()
1092            || self.check(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Bang,
    token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang))
1093            || self.check(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Question,
    token_type: crate::parser::token_type::TokenType::Question,
}exp!(Question))
1094            || self.check(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Tilde,
    token_type: crate::parser::token_type::TokenType::Tilde,
}exp!(Tilde))
1095            || self.check_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::For,
    token_type: crate::parser::token_type::TokenType::KwFor,
}exp!(For))
1096            || self.check(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::OpenParen,
    token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen))
1097            || self.can_begin_maybe_const_bound()
1098            || self.check_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Const,
    token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const))
1099            || self.check_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Async,
    token_type: crate::parser::token_type::TokenType::KwAsync,
}exp!(Async))
1100            || self.check_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Use,
    token_type: crate::parser::token_type::TokenType::KwUse,
}exp!(Use))
1101    }
1102
1103    fn can_begin_maybe_const_bound(&mut self) -> bool {
1104        self.check(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::OpenBracket,
    token_type: crate::parser::token_type::TokenType::OpenBracket,
}exp!(OpenBracket))
1105            && self.look_ahead(1, |t| t.is_keyword(kw::Const))
1106            && self.look_ahead(2, |t| *t == token::CloseBracket)
1107    }
1108
1109    /// Parse a bound.
1110    ///
1111    /// ```ebnf
1112    /// Bound = LifetimeBound | UseBound | TraitBound
1113    /// ```
1114    fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> {
1115        let leading_token = self.prev_token;
1116        let lo = self.token.span;
1117
1118        // We only admit parenthesized *trait* bounds. However, we want to gracefully recover from
1119        // other kinds of parenthesized bounds, so parse the opening parenthesis *here*.
1120        //
1121        // In the future we might want to lift this syntactic restriction and
1122        // introduce "`GenericBound::Paren(Box<GenericBound>)`".
1123        let parens = if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::OpenParen,
    token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) { ast::Parens::Yes } else { ast::Parens::No };
1124
1125        if self.token.is_lifetime() {
1126            self.parse_lifetime_bound(lo, parens)
1127        } else if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Use,
    token_type: crate::parser::token_type::TokenType::KwUse,
}exp!(Use)) {
1128            self.parse_use_bound(lo, parens)
1129        } else {
1130            self.parse_trait_bound(lo, parens, &leading_token)
1131        }
1132    }
1133
1134    /// Parse a lifetime-bound aka outlives-bound.
1135    ///
1136    /// ```ebnf
1137    /// LifetimeBound = Lifetime
1138    /// ```
1139    fn parse_lifetime_bound(&mut self, lo: Span, parens: ast::Parens) -> PResult<'a, GenericBound> {
1140        let lt = self.expect_lifetime();
1141
1142        if let ast::Parens::Yes = parens {
1143            self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseParen,
    token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen))?;
1144            self.report_parenthesized_bound(lo, self.prev_token.span, "lifetime bounds");
1145        }
1146
1147        Ok(GenericBound::Outlives(lt))
1148    }
1149
1150    fn report_parenthesized_bound(&self, lo: Span, hi: Span, kind: &str) -> ErrorGuaranteed {
1151        let mut diag =
1152            self.dcx().struct_span_err(lo.to(hi), ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} may not be parenthesized",
                kind))
    })format!("{kind} may not be parenthesized"));
1153        diag.multipart_suggestion(
1154            "remove the parentheses",
1155            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(lo, String::new()), (hi, String::new())]))vec![(lo, String::new()), (hi, String::new())],
1156            Applicability::MachineApplicable,
1157        );
1158        diag.emit()
1159    }
1160
1161    /// Emits an error if any trait bound modifiers were present.
1162    fn error_lt_bound_with_modifiers(
1163        &self,
1164        modifiers: TraitBoundModifiers,
1165        binder_span: Option<Span>,
1166    ) -> ErrorGuaranteed {
1167        let TraitBoundModifiers { constness, asyncness, polarity } = modifiers;
1168
1169        match constness {
1170            BoundConstness::Never => {}
1171            BoundConstness::Always(span) | BoundConstness::Maybe(span) => {
1172                return self.dcx().emit_err(diagnostics::ModifierLifetime {
1173                    span,
1174                    modifier: constness.as_str(),
1175                });
1176            }
1177        }
1178
1179        match polarity {
1180            BoundPolarity::Positive => {}
1181            BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => {
1182                return self
1183                    .dcx()
1184                    .emit_err(diagnostics::ModifierLifetime { span, modifier: polarity.as_str() });
1185            }
1186        }
1187
1188        match asyncness {
1189            BoundAsyncness::Normal => {}
1190            BoundAsyncness::Async(span) => {
1191                return self.dcx().emit_err(diagnostics::ModifierLifetime {
1192                    span,
1193                    modifier: asyncness.as_str(),
1194                });
1195            }
1196        }
1197
1198        if let Some(span) = binder_span {
1199            return self
1200                .dcx()
1201                .emit_err(diagnostics::ModifierLifetime { span, modifier: "for<...>" });
1202        }
1203
1204        {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("lifetime bound intercepted in `parse_generic_ty_bound` but no modifiers?")));
}unreachable!("lifetime bound intercepted in `parse_generic_ty_bound` but no modifiers?")
1205    }
1206
1207    /// Parses the modifiers that may precede a trait in a bound, e.g. `?Trait` or `[const] Trait`.
1208    ///
1209    /// If no modifiers are present, this does not consume any tokens.
1210    ///
1211    /// ```ebnf
1212    /// Constness = ("const" | "[" "const" "]")?
1213    /// Asyncness = "async"?
1214    /// Polarity = ("?" | "!")?
1215    /// ```
1216    ///
1217    /// See `parse_trait_bound` for more context.
1218    fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> {
1219        let modifier_lo = self.token.span;
1220        let constness = self.parse_bound_constness()?;
1221
1222        let asyncness = if self.token_uninterpolated_span().at_least_rust_2018()
1223            && self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Async,
    token_type: crate::parser::token_type::TokenType::KwAsync,
}exp!(Async))
1224        {
1225            self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
1226            BoundAsyncness::Async(self.prev_token.span)
1227        } else if self.may_recover()
1228            && self.token_uninterpolated_span().is_rust_2015()
1229            && self.is_kw_followed_by_ident(kw::Async)
1230        {
1231            self.bump(); // eat `async`
1232            self.dcx().emit_err(diagnostics::AsyncBoundModifierIn2015 {
1233                span: self.prev_token.span,
1234                help: HelpUseLatestEdition::new(),
1235            });
1236            self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
1237            BoundAsyncness::Async(self.prev_token.span)
1238        } else {
1239            BoundAsyncness::Normal
1240        };
1241        let modifier_hi = self.prev_token.span;
1242
1243        let polarity = if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Question,
    token_type: crate::parser::token_type::TokenType::Question,
}exp!(Question)) {
1244            BoundPolarity::Maybe(self.prev_token.span)
1245        } else if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Bang,
    token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) {
1246            self.psess.gated_spans.gate(sym::negative_bounds, self.prev_token.span);
1247            BoundPolarity::Negative(self.prev_token.span)
1248        } else {
1249            BoundPolarity::Positive
1250        };
1251
1252        // Enforce the mutual-exclusivity of `const`/`async` and `?`/`!`.
1253        match polarity {
1254            BoundPolarity::Positive => {
1255                // All trait bound modifiers allowed to combine with positive polarity
1256            }
1257            BoundPolarity::Maybe(polarity_span) | BoundPolarity::Negative(polarity_span) => {
1258                match (asyncness, constness) {
1259                    (BoundAsyncness::Normal, BoundConstness::Never) => {
1260                        // Ok, no modifiers.
1261                    }
1262                    (_, _) => {
1263                        let constness = constness.as_str();
1264                        let asyncness = asyncness.as_str();
1265                        let glue =
1266                            if !constness.is_empty() && !asyncness.is_empty() { " " } else { "" };
1267                        let modifiers_concatenated = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}{1}{2}", constness, glue,
                asyncness))
    })format!("{constness}{glue}{asyncness}");
1268                        self.dcx().emit_err(diagnostics::PolarityAndModifiers {
1269                            polarity_span,
1270                            polarity: polarity.as_str(),
1271                            modifiers_span: modifier_lo.to(modifier_hi),
1272                            modifiers_concatenated,
1273                        });
1274                    }
1275                }
1276            }
1277        }
1278
1279        Ok(TraitBoundModifiers { constness, asyncness, polarity })
1280    }
1281
1282    pub fn parse_bound_constness(&mut self) -> PResult<'a, BoundConstness> {
1283        // FIXME(const_trait_impl): remove `~const` parser support once bootstrap has the new syntax
1284        // in rustfmt
1285        Ok(if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Tilde,
    token_type: crate::parser::token_type::TokenType::Tilde,
}exp!(Tilde)) {
1286            let tilde = self.prev_token.span;
1287            self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Const,
    token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const))?;
1288            let span = tilde.to(self.prev_token.span);
1289            self.psess.gated_spans.gate(sym::const_trait_impl, span);
1290            BoundConstness::Maybe(span)
1291        } else if self.can_begin_maybe_const_bound() {
1292            let start = self.token.span;
1293            self.bump();
1294            self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Const,
    token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const)).unwrap();
1295            self.bump();
1296            let span = start.to(self.prev_token.span);
1297            self.psess.gated_spans.gate(sym::const_trait_impl, span);
1298            BoundConstness::Maybe(span)
1299        } else if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Const,
    token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const)) {
1300            self.psess.gated_spans.gate(sym::const_trait_impl, self.prev_token.span);
1301            BoundConstness::Always(self.prev_token.span)
1302        } else {
1303            BoundConstness::Never
1304        })
1305    }
1306
1307    /// Parse a trait bound.
1308    ///
1309    /// ```ebnf
1310    /// TraitBound = BareTraitBound | "(" BareTraitBound ")"
1311    /// BareTraitBound =
1312    ///     (HigherRankedBinder Constness Asyncness | Polarity)
1313    ///     TypePath
1314    /// ```
1315    fn parse_trait_bound(
1316        &mut self,
1317        lo: Span,
1318        parens: ast::Parens,
1319        leading_token: &Token,
1320    ) -> PResult<'a, GenericBound> {
1321        let (mut bound_vars, binder_span) = self.parse_higher_ranked_binder()?;
1322
1323        let modifiers_lo = self.token.span;
1324        let modifiers = self.parse_trait_bound_modifiers()?;
1325        let modifiers_span = modifiers_lo.to(self.prev_token.span);
1326
1327        if let Some(binder_span) = binder_span {
1328            match modifiers.polarity {
1329                BoundPolarity::Negative(polarity_span) | BoundPolarity::Maybe(polarity_span) => {
1330                    self.dcx().emit_err(diagnostics::BinderAndPolarity {
1331                        binder_span,
1332                        polarity_span,
1333                        polarity: modifiers.polarity.as_str(),
1334                    });
1335                }
1336                BoundPolarity::Positive => {}
1337            }
1338        }
1339
1340        // Recover erroneous lifetime bound with modifiers or binder.
1341        // e.g. `T: for<'a> 'a` or `T: [const] 'a`.
1342        if self.token.is_lifetime() {
1343            let _: ErrorGuaranteed = self.error_lt_bound_with_modifiers(modifiers, binder_span);
1344            return self.parse_lifetime_bound(lo, parens);
1345        }
1346
1347        if let (more_bound_vars, Some(binder_span)) = self.parse_higher_ranked_binder()? {
1348            bound_vars.extend(more_bound_vars);
1349            self.dcx().emit_err(diagnostics::BinderBeforeModifiers { binder_span, modifiers_span });
1350        }
1351
1352        let mut path = if self.token.is_keyword(kw::Fn)
1353            && self.look_ahead(1, |t| *t == TokenKind::OpenParen)
1354            && let Some(path) = self.recover_path_from_fn()
1355        {
1356            path
1357        } else if !self.token.is_path_start() && self.token.can_begin_type() {
1358            let ty = self.parse_ty_no_plus()?;
1359            // Instead of finding a path (a trait), we found a type.
1360            let mut err = self.dcx().struct_span_err(ty.span, "expected a trait, found type");
1361
1362            // If we can recover, try to extract a path from the type. Note
1363            // that we do not use the try operator when parsing the type because
1364            // if it fails then we get a parser error which we don't want (we're trying
1365            // to recover from errors, not make more).
1366            let path = if self.may_recover() {
1367                let (span, message, sugg, path, applicability) = match &ty.kind {
1368                    TyKind::Ptr(..) | TyKind::Ref(..)
1369                        if let TyKind::Path(_, path) = &ty.peel_refs().kind =>
1370                    {
1371                        (
1372                            ty.span.until(path.span),
1373                            "consider removing the indirection",
1374                            "",
1375                            path,
1376                            Applicability::MaybeIncorrect,
1377                        )
1378                    }
1379                    TyKind::ImplTrait(_, bounds)
1380                        if let [GenericBound::Trait(tr, ..), ..] = bounds.as_slice() =>
1381                    {
1382                        (
1383                            ty.span.until(tr.span),
1384                            "use the trait bounds directly",
1385                            "",
1386                            &tr.trait_ref.path,
1387                            Applicability::MachineApplicable,
1388                        )
1389                    }
1390                    _ => return Err(err),
1391                };
1392
1393                err.span_suggestion_verbose(span, message, sugg, applicability);
1394
1395                path.clone()
1396            } else {
1397                return Err(err);
1398            };
1399
1400            err.emit();
1401
1402            path
1403        } else {
1404            self.parse_path(PathStyle::Type)?
1405        };
1406
1407        if self.may_recover() && self.token == TokenKind::OpenParen {
1408            self.recover_fn_trait_with_lifetime_params(&mut path, &mut bound_vars)?;
1409        }
1410
1411        if let ast::Parens::Yes = parens {
1412            // Someone has written something like `&dyn (Trait + Other)`. The correct code
1413            // would be `&(dyn Trait + Other)`
1414            if self.token.is_like_plus() && leading_token.is_keyword(kw::Dyn) {
1415                let bounds = ::thin_vec::ThinVec::new()thin_vec![];
1416                self.parse_remaining_bounds(bounds, true)?;
1417                self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseParen,
    token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen))?;
1418                self.dcx().emit_err(diagnostics::IncorrectParensTraitBounds {
1419                    span: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [lo, self.prev_token.span]))vec![lo, self.prev_token.span],
1420                    sugg: diagnostics::IncorrectParensTraitBoundsSugg {
1421                        wrong_span: leading_token.span.shrink_to_hi().to(lo),
1422                        new_span: leading_token.span.shrink_to_lo(),
1423                    },
1424                });
1425            } else {
1426                self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::CloseParen,
    token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen))?;
1427            }
1428        }
1429
1430        let poly_trait =
1431            PolyTraitRef::new(bound_vars, path, modifiers, lo.to(self.prev_token.span), parens);
1432        Ok(GenericBound::Trait(poly_trait))
1433    }
1434
1435    // recovers a `Fn(..)` parenthesized-style path from `fn(..)`
1436    fn recover_path_from_fn(&mut self) -> Option<ast::Path> {
1437        let fn_token_span = self.token.span;
1438        self.bump();
1439        let args_lo = self.token.span;
1440        let snapshot = self.create_snapshot_for_diagnostic();
1441        let mode =
1442            FnParseMode { req_name: |_, _| false, context: FnContext::Free, req_body: false };
1443        match self.parse_fn_decl(&mode, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) {
1444            Ok(decl) => {
1445                self.dcx().emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span });
1446                Some(ast::Path {
1447                    span: fn_token_span.to(self.prev_token.span),
1448                    segments: {
    let len = [()].len();
    let mut vec = ::thin_vec::ThinVec::with_capacity(len);
    vec.push(ast::PathSegment {
            ident: Ident::new(sym::Fn, fn_token_span),
            id: DUMMY_NODE_ID,
            args: Some(Box::new(ast::GenericArgs::Parenthesized(ast::ParenthesizedArgs {
                            span: args_lo.to(self.prev_token.span),
                            inputs: decl.inputs.iter().map(|a| a.clone()).collect(),
                            inputs_span: args_lo.until(decl.output.span()),
                            output: decl.output.clone(),
                        }))),
        });
    vec
}thin_vec![ast::PathSegment {
1449                        ident: Ident::new(sym::Fn, fn_token_span),
1450                        id: DUMMY_NODE_ID,
1451                        args: Some(Box::new(ast::GenericArgs::Parenthesized(
1452                            ast::ParenthesizedArgs {
1453                                span: args_lo.to(self.prev_token.span),
1454                                inputs: decl.inputs.iter().map(|a| a.clone()).collect(),
1455                                inputs_span: args_lo.until(decl.output.span()),
1456                                output: decl.output.clone(),
1457                            }
1458                        ))),
1459                    }],
1460                })
1461            }
1462            Err(diag) => {
1463                diag.cancel();
1464                self.restore_snapshot(snapshot);
1465                None
1466            }
1467        }
1468    }
1469
1470    /// Parse an optional higher-ranked binder.
1471    ///
1472    /// ```ebnf
1473    /// HigherRankedBinder = ("for" "<" GenericParams ">")?
1474    /// ```
1475    pub(super) fn parse_higher_ranked_binder(
1476        &mut self,
1477    ) -> PResult<'a, (ThinVec<GenericParam>, Option<Span>)> {
1478        if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::For,
    token_type: crate::parser::token_type::TokenType::KwFor,
}exp!(For)) {
1479            let lo = self.token.span;
1480            self.expect_lt()?;
1481            let params = self.parse_generic_params()?;
1482            self.expect_gt()?;
1483            // We rely on AST validation to rule out invalid cases: There must not be
1484            // type or const parameters, and parameters must not have bounds.
1485            Ok((params, Some(lo.to(self.prev_token.span))))
1486        } else {
1487            Ok((ThinVec::new(), None))
1488        }
1489    }
1490
1491    /// Recover from `Fn`-family traits (Fn, FnMut, FnOnce) with lifetime arguments
1492    /// (e.g. `FnOnce<'a>(&'a str) -> bool`). Up to generic arguments have already
1493    /// been eaten.
1494    fn recover_fn_trait_with_lifetime_params(
1495        &mut self,
1496        fn_path: &mut ast::Path,
1497        lifetime_defs: &mut ThinVec<GenericParam>,
1498    ) -> PResult<'a, ()> {
1499        let fn_path_segment = fn_path.segments.last_mut().unwrap();
1500        let generic_args = if let Some(p_args) = &fn_path_segment.args {
1501            *p_args.clone()
1502        } else {
1503            // Normally it wouldn't come here because the upstream should have parsed
1504            // generic parameters (otherwise it's impossible to call this function).
1505            return Ok(());
1506        };
1507        let lifetimes =
1508            if let ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { span: _, args }) =
1509                &generic_args
1510            {
1511                args.into_iter()
1512                    .filter_map(|arg| {
1513                        if let ast::AngleBracketedArg::Arg(generic_arg) = arg
1514                            && let ast::GenericArg::Lifetime(lifetime) = generic_arg
1515                        {
1516                            Some(lifetime)
1517                        } else {
1518                            None
1519                        }
1520                    })
1521                    .collect()
1522            } else {
1523                Vec::new()
1524            };
1525        // Only try to recover if the trait has lifetime params.
1526        if lifetimes.is_empty() {
1527            return Ok(());
1528        }
1529
1530        let snapshot = if self.parsing_generics {
1531            // The snapshot is only relevant if we're parsing the generics of an `fn` to avoid
1532            // incorrect recovery.
1533            Some(self.create_snapshot_for_diagnostic())
1534        } else {
1535            None
1536        };
1537        // Parse `(T, U) -> R`.
1538        let inputs_lo = self.token.span;
1539        let mode =
1540            FnParseMode { req_name: |_, _| false, context: FnContext::Free, req_body: false };
1541        let inputs = match self.parse_fn_params(&mode) {
1542            Ok(params) => params,
1543            Err(err) => {
1544                if let Some(snapshot) = snapshot {
1545                    self.restore_snapshot(snapshot);
1546                    err.cancel();
1547                    return Ok(());
1548                } else {
1549                    return Err(err);
1550                }
1551            }
1552        };
1553        let inputs_span = inputs_lo.to(self.prev_token.span);
1554        let output = match self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)
1555        {
1556            Ok(output) => output,
1557            Err(err) => {
1558                if let Some(snapshot) = snapshot {
1559                    self.restore_snapshot(snapshot);
1560                    err.cancel();
1561                    return Ok(());
1562                } else {
1563                    return Err(err);
1564                }
1565            }
1566        };
1567        let args = ast::ParenthesizedArgs {
1568            span: fn_path_segment.span().to(self.prev_token.span),
1569            inputs,
1570            inputs_span,
1571            output,
1572        }
1573        .into();
1574
1575        if let Some(snapshot) = snapshot
1576            && ![token::Comma, token::Gt, token::Plus].contains(&self.token.kind)
1577        {
1578            // We would expect another bound or the end of type params by now. Most likely we've
1579            // encountered a `(` *not* representing `Trait()`, but rather the start of the `fn`'s
1580            // argument list where the generic param list wasn't properly closed.
1581            self.restore_snapshot(snapshot);
1582            return Ok(());
1583        }
1584
1585        *fn_path_segment = ast::PathSegment {
1586            ident: fn_path_segment.ident,
1587            args: Some(args),
1588            id: ast::DUMMY_NODE_ID,
1589        };
1590
1591        // Convert parsed `<'a>` in `Fn<'a>` into `for<'a>`.
1592        let mut generic_params = lifetimes
1593            .iter()
1594            .map(|lt| GenericParam {
1595                id: lt.id,
1596                ident: lt.ident,
1597                attrs: ast::AttrVec::new(),
1598                bounds: ThinVec::new(),
1599                is_placeholder: false,
1600                kind: ast::GenericParamKind::Lifetime,
1601                colon_span: None,
1602            })
1603            .collect::<ThinVec<GenericParam>>();
1604        lifetime_defs.append(&mut generic_params);
1605
1606        let generic_args_span = generic_args.span();
1607        let snippet = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("for<{0}> ",
                lifetimes.iter().map(|lt|
                                lt.ident.as_str()).intersperse(", ").collect::<String>()))
    })format!(
1608            "for<{}> ",
1609            lifetimes.iter().map(|lt| lt.ident.as_str()).intersperse(", ").collect::<String>(),
1610        );
1611        let before_fn_path = fn_path.span.shrink_to_lo();
1612        self.dcx()
1613            .struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters")
1614            .with_multipart_suggestion(
1615                "consider using a higher-ranked trait bound instead",
1616                ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(generic_args_span, "".to_owned()), (before_fn_path, snippet)]))vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)],
1617                Applicability::MaybeIncorrect,
1618            )
1619            .emit();
1620        Ok(())
1621    }
1622
1623    pub(super) fn check_lifetime(&mut self) -> bool {
1624        self.expected_token_types.insert(TokenType::Lifetime);
1625        self.token.is_lifetime()
1626    }
1627
1628    /// Parses a single lifetime `'a` or panics.
1629    pub(super) fn expect_lifetime(&mut self) -> Lifetime {
1630        if let Some((ident, is_raw)) = self.token.lifetime() {
1631            if is_raw == IdentIsRaw::No && ident.without_first_quote().is_reserved_lifetime() {
1632                self.dcx().emit_err(diagnostics::KeywordLifetime { span: ident.span });
1633            }
1634
1635            self.bump();
1636            Lifetime { ident, id: ast::DUMMY_NODE_ID }
1637        } else {
1638            self.dcx().span_bug(self.token.span, "not a lifetime")
1639        }
1640    }
1641
1642    pub(super) fn mk_ty(&self, span: Span, kind: TyKind) -> Box<Ty> {
1643        Box::new(Ty { kind, span, id: ast::DUMMY_NODE_ID })
1644    }
1645}