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