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