use rustc_ast::token::{self, IdentIsRaw, MetaVarKind, Token, TokenKind};
use rustc_ast::util::case::Case;
use rustc_ast::{
    self as ast, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnPtrTy, FnRetTy,
    GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability,
    Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty,
    TyKind, UnsafeBinderTy,
};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{Applicability, Diag, PResult};
use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym};
use thin_vec::{ThinVec, thin_vec};

use super::{Parser, PathStyle, SeqSep, TokenType, Trailing};
use crate::errors::{
    self, AttributeOnEmptyType, AttributeOnType, DynAfterMut, ExpectedFnPathFoundFnKeyword,
    ExpectedMutOrConstInRawPointerType, FnPtrWithGenerics, FnPtrWithGenericsSugg,
    HelpUseLatestEdition, InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
    NestedCVariadicType, ReturnTypesUseThinArrow,
};
use crate::parser::item::FrontMatterParsingMode;
use crate::parser::{FnContext, FnParseMode};
use crate::{exp, maybe_recover_from_interpolated_ty_qpath};

/// Signals whether parsing a type should allow `+`.
///
/// For example, let T be the type `impl Default + 'static`
/// With `AllowPlus::Yes`, T will be parsed successfully
/// With `AllowPlus::No`, parsing T will return a parse error
#[derive(Copy, Clone, PartialEq)]
pub(super) enum AllowPlus {
    Yes,
    No,
}

#[derive(PartialEq)]
pub(super) enum RecoverQPath {
    Yes,
    No,
}

pub(super) enum RecoverQuestionMark {
    Yes,
    No,
}

/// Signals whether parsing a type should recover `->`.
///
/// More specifically, when parsing a function like:
/// ```compile_fail
/// fn foo() => u8 { 0 }
/// fn bar(): u8 { 0 }
/// ```
/// The compiler will try to recover interpreting `foo() => u8` as `foo() -> u8` when calling
/// `parse_ty` with anything except `RecoverReturnSign::No`, and it will try to recover `bar(): u8`
/// as `bar() -> u8` when passing `RecoverReturnSign::Yes` to `parse_ty`
#[derive(Copy, Clone, PartialEq)]
pub(super) enum RecoverReturnSign {
    Yes,
    OnlyFatArrow,
    No,
}

impl RecoverReturnSign {
    /// [RecoverReturnSign::Yes] allows for recovering `fn foo() => u8` and `fn foo(): u8`,
    /// [RecoverReturnSign::OnlyFatArrow] allows for recovering only `fn foo() => u8` (recovering
    /// colons can cause problems when parsing where clauses), and
    /// [RecoverReturnSign::No] doesn't allow for any recovery of the return type arrow
    fn can_recover(self, token: &TokenKind) -> bool {
        match self {
            Self::Yes => matches!(token, token::FatArrow | token::Colon),
            Self::OnlyFatArrow => matches!(token, token::FatArrow),
            Self::No => false,
        }
    }
}

// Is `...` (`CVarArgs`) legal at this level of type parsing?
#[derive(PartialEq)]
enum AllowCVariadic {
    Yes,
    No,
}

/// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT<u8, u8>`,
/// `IDENT<<u8 as Trait>::AssocTy>`.
///
/// Types can also be of the form `IDENT(u8, u8) -> u8`, however this assumes
/// that `IDENT` is not the ident of a fn trait.
fn can_continue_type_after_non_fn_ident(t: &Token) -> bool {
    t == &token::PathSep || t == &token::Lt || t == &token::Shl
}

fn can_begin_dyn_bound_in_edition_2015(t: &Token) -> bool {
    // `Not`, `Tilde` & `Const` are deliberately not part of this list to
    // contain the number of potential regressions esp. in MBE code.
    // `Const` would regress `rfc-2632-const-trait-impl/mbe-dyn-const-2015.rs`.
    // `Not` would regress `dyn!(...)` macro calls in Rust 2015.
    t.is_path_start()
        || t.is_lifetime()
        || t == &TokenKind::Question
        || t.is_keyword(kw::For)
        || t == &TokenKind::OpenParen
}

impl<'a> Parser<'a> {
    /// Parses a type.
    pub fn parse_ty(&mut self) -> PResult<'a, Box<Ty>> {
        // Make sure deeply nested types don't overflow the stack.
        ensure_sufficient_stack(|| {
            self.parse_ty_common(
                AllowPlus::Yes,
                AllowCVariadic::No,
                RecoverQPath::Yes,
                RecoverReturnSign::Yes,
                None,
                RecoverQuestionMark::Yes,
            )
        })
    }

    pub(super) fn parse_ty_with_generics_recovery(
        &mut self,
        ty_params: &Generics,
    ) -> PResult<'a, Box<Ty>> {
        self.parse_ty_common(
            AllowPlus::Yes,
            AllowCVariadic::No,
            RecoverQPath::Yes,
            RecoverReturnSign::Yes,
            Some(ty_params),
            RecoverQuestionMark::Yes,
        )
    }

    /// Parse a type suitable for a function or function pointer parameter.
    /// The difference from `parse_ty` is that this version allows `...`
    /// (`CVarArgs`) at the top level of the type.
    pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, Box<Ty>> {
        self.parse_ty_common(
            AllowPlus::Yes,
            AllowCVariadic::Yes,
            RecoverQPath::Yes,
            RecoverReturnSign::Yes,
            None,
            RecoverQuestionMark::Yes,
        )
    }

    /// Parses a type in restricted contexts where `+` is not permitted.
    ///
    /// Example 1: `&'a TYPE`
    ///     `+` is prohibited to maintain operator priority (P(+) < P(&)).
    /// Example 2: `value1 as TYPE + value2`
    ///     `+` is prohibited to avoid interactions with expression grammar.
    pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, Box<Ty>> {
        self.parse_ty_common(
            AllowPlus::No,
            AllowCVariadic::No,
            RecoverQPath::Yes,
            RecoverReturnSign::Yes,
            None,
            RecoverQuestionMark::Yes,
        )
    }

    /// Parses a type following an `as` cast. Similar to `parse_ty_no_plus`, but signaling origin
    /// for better diagnostics involving `?`.
    pub(super) fn parse_as_cast_ty(&mut self) -> PResult<'a, Box<Ty>> {
        self.parse_ty_common(
            AllowPlus::No,
            AllowCVariadic::No,
            RecoverQPath::Yes,
            RecoverReturnSign::Yes,
            None,
            RecoverQuestionMark::No,
        )
    }

    pub(super) fn parse_ty_no_question_mark_recover(&mut self) -> PResult<'a, Box<Ty>> {
        self.parse_ty_common(
            AllowPlus::Yes,
            AllowCVariadic::No,
            RecoverQPath::Yes,
            RecoverReturnSign::Yes,
            None,
            RecoverQuestionMark::No,
        )
    }

    /// Parse a type without recovering `:` as `->` to avoid breaking code such
    /// as `where fn() : for<'a>`.
    pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, Box<Ty>> {
        self.parse_ty_common(
            AllowPlus::Yes,
            AllowCVariadic::No,
            RecoverQPath::Yes,
            RecoverReturnSign::OnlyFatArrow,
            None,
            RecoverQuestionMark::Yes,
        )
    }

    /// Parses an optional return type `[ -> TY ]` in a function declaration.
    pub(super) fn parse_ret_ty(
        &mut self,
        allow_plus: AllowPlus,
        recover_qpath: RecoverQPath,
        recover_return_sign: RecoverReturnSign,
    ) -> PResult<'a, FnRetTy> {
        let lo = self.prev_token.span;
        Ok(if self.eat(exp!(RArrow)) {
            // FIXME(Centril): Can we unconditionally `allow_plus`?
            let ty = self.parse_ty_common(
                allow_plus,
                AllowCVariadic::No,
                recover_qpath,
                recover_return_sign,
                None,
                RecoverQuestionMark::Yes,
            )?;
            FnRetTy::Ty(ty)
        } else if recover_return_sign.can_recover(&self.token.kind) {
            // Don't `eat` to prevent `=>` from being added as an expected token which isn't
            // actually expected and could only confuse users
            self.bump();
            self.dcx().emit_err(ReturnTypesUseThinArrow {
                span: self.prev_token.span,
                suggestion: lo.between(self.token.span),
            });
            let ty = self.parse_ty_common(
                allow_plus,
                AllowCVariadic::No,
                recover_qpath,
                recover_return_sign,
                None,
                RecoverQuestionMark::Yes,
            )?;
            FnRetTy::Ty(ty)
        } else {
            FnRetTy::Default(self.prev_token.span.shrink_to_hi())
        })
    }

    fn parse_ty_common(
        &mut self,
        allow_plus: AllowPlus,
        allow_c_variadic: AllowCVariadic,
        recover_qpath: RecoverQPath,
        recover_return_sign: RecoverReturnSign,
        ty_generics: Option<&Generics>,
        recover_question_mark: RecoverQuestionMark,
    ) -> PResult<'a, Box<Ty>> {
        let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
        maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
        if self.token == token::Pound && self.look_ahead(1, |t| *t == token::OpenBracket) {
            let attrs_wrapper = self.parse_outer_attributes()?;
            let raw_attrs = attrs_wrapper.take_for_recovery(self.psess);
            let attr_span = raw_attrs[0].span.to(raw_attrs.last().unwrap().span);
            let (full_span, guar) = match self.parse_ty() {
                Ok(ty) => {
                    let full_span = attr_span.until(ty.span);
                    let guar = self
                        .dcx()
                        .emit_err(AttributeOnType { span: attr_span, fix_span: full_span });
                    (attr_span, guar)
                }
                Err(err) => {
                    err.cancel();
                    let guar = self.dcx().emit_err(AttributeOnEmptyType { span: attr_span });
                    (attr_span, guar)
                }
            };

            return Ok(self.mk_ty(full_span, TyKind::Err(guar)));
        }
        if let Some(ty) = self.eat_metavar_seq_with_matcher(
            |mv_kind| matches!(mv_kind, MetaVarKind::Ty { .. }),
            |this| this.parse_ty_no_question_mark_recover(),
        ) {
            return Ok(ty);
        }

        let lo = self.token.span;
        let mut impl_dyn_multi = false;
        let kind = if self.check(exp!(OpenParen)) {
            self.parse_ty_tuple_or_parens(lo, allow_plus)?
        } else if self.eat(exp!(Bang)) {
            // Never type `!`
            TyKind::Never
        } else if self.eat(exp!(Star)) {
            self.parse_ty_ptr()?
        } else if self.eat(exp!(OpenBracket)) {
            self.parse_array_or_slice_ty()?
        } else if self.check(exp!(And)) || self.check(exp!(AndAnd)) {
            // Reference
            self.expect_and()?;
            self.parse_borrowed_pointee()?
        } else if self.eat_keyword_noexpect(kw::Typeof) {
            self.parse_typeof_ty()?
        } else if self.eat_keyword(exp!(Underscore)) {
            // A type to be inferred `_`
            TyKind::Infer
        } else if self.check_fn_front_matter(false, Case::Sensitive) {
            // Function pointer type
            self.parse_ty_fn_ptr(lo, ThinVec::new(), None, recover_return_sign)?
        } else if self.check_keyword(exp!(For)) {
            // Function pointer type or bound list (trait object type) starting with a poly-trait.
            //   `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
            //   `for<'lt> Trait1<'lt> + Trait2 + 'a`
            let (bound_vars, _) = self.parse_higher_ranked_binder()?;
            if self.check_fn_front_matter(false, Case::Sensitive) {
                self.parse_ty_fn_ptr(
                    lo,
                    bound_vars,
                    Some(self.prev_token.span.shrink_to_lo()),
                    recover_return_sign,
                )?
            } else {
                // Try to recover `for<'a> dyn Trait` or `for<'a> impl Trait`.
                if self.may_recover()
                    && (self.eat_keyword_noexpect(kw::Impl) || self.eat_keyword_noexpect(kw::Dyn))
                {
                    let kw = self.prev_token.ident().unwrap().0;
                    let removal_span = kw.span.with_hi(self.token.span.lo());
                    let path = self.parse_path(PathStyle::Type)?;
                    let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
                    let kind = self.parse_remaining_bounds_path(
                        bound_vars,
                        path,
                        lo,
                        parse_plus,
                        ast::Parens::No,
                    )?;
                    let err = self.dcx().create_err(errors::TransposeDynOrImpl {
                        span: kw.span,
                        kw: kw.name.as_str(),
                        sugg: errors::TransposeDynOrImplSugg {
                            removal_span,
                            insertion_span: lo.shrink_to_lo(),
                            kw: kw.name.as_str(),
                        },
                    });

                    // Take the parsed bare trait object and turn it either
                    // into a `dyn` object or an `impl Trait`.
                    let kind = match (kind, kw.name) {
                        (TyKind::TraitObject(bounds, _), kw::Dyn) => {
                            TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn)
                        }
                        (TyKind::TraitObject(bounds, _), kw::Impl) => {
                            TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)
                        }
                        _ => return Err(err),
                    };
                    err.emit();
                    kind
                } else {
                    let path = self.parse_path(PathStyle::Type)?;
                    let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
                    self.parse_remaining_bounds_path(
                        bound_vars,
                        path,
                        lo,
                        parse_plus,
                        ast::Parens::No,
                    )?
                }
            }
        } else if self.eat_keyword(exp!(Impl)) {
            self.parse_impl_ty(&mut impl_dyn_multi)?
        } else if self.is_explicit_dyn_type() {
            self.parse_dyn_ty(&mut impl_dyn_multi)?
        } else if self.eat_lt() {
            // Qualified path
            let (qself, path) = self.parse_qpath(PathStyle::Type)?;
            TyKind::Path(Some(qself), path)
        } else if self.check_path() {
            self.parse_path_start_ty(lo, allow_plus, ty_generics)?
        } else if self.can_begin_bound() {
            self.parse_bare_trait_object(lo, allow_plus)?
        } else if self.eat(exp!(DotDotDot)) {
            match allow_c_variadic {
                AllowCVariadic::Yes => TyKind::CVarArgs,
                AllowCVariadic::No => {
                    // FIXME(c_variadic): Should we just allow `...` syntactically
                    // anywhere in a type and use semantic restrictions instead?
                    // NOTE: This may regress certain MBE calls if done incorrectly.
                    let guar = self.dcx().emit_err(NestedCVariadicType { span: lo });
                    TyKind::Err(guar)
                }
            }
        } else if self.check_keyword(exp!(Unsafe))
            && self.look_ahead(1, |tok| tok.kind == token::Lt)
        {
            self.parse_unsafe_binder_ty()?
        } else {
            let msg = format!("expected type, found {}", super::token_descr(&self.token));
            let mut err = self.dcx().struct_span_err(lo, msg);
            err.span_label(lo, "expected type");
            return Err(err);
        };

        let span = lo.to(self.prev_token.span);
        let mut ty = self.mk_ty(span, kind);

        // Try to recover from use of `+` with incorrect priority.
        match allow_plus {
            AllowPlus::Yes => self.maybe_recover_from_bad_type_plus(&ty)?,
            AllowPlus::No => self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty),
        }
        if let RecoverQuestionMark::Yes = recover_question_mark {
            ty = self.maybe_recover_from_question_mark(ty);
        }
        if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) }
    }

    fn parse_unsafe_binder_ty(&mut self) -> PResult<'a, TyKind> {
        let lo = self.token.span;
        assert!(self.eat_keyword(exp!(Unsafe)));
        self.expect_lt()?;
        let generic_params = self.parse_generic_params()?;
        self.expect_gt()?;
        let inner_ty = self.parse_ty()?;
        let span = lo.to(self.prev_token.span);
        self.psess.gated_spans.gate(sym::unsafe_binders, span);

        Ok(TyKind::UnsafeBinder(Box::new(UnsafeBinderTy { generic_params, inner_ty })))
    }

    /// Parses either:
    /// - `(TYPE)`, a parenthesized type.
    /// - `(TYPE,)`, a tuple with a single field of type TYPE.
    fn parse_ty_tuple_or_parens(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
        let mut trailing_plus = false;
        let (ts, trailing) = self.parse_paren_comma_seq(|p| {
            let ty = p.parse_ty()?;
            trailing_plus = p.prev_token == TokenKind::Plus;
            Ok(ty)
        })?;

        if ts.len() == 1 && matches!(trailing, Trailing::No) {
            let ty = ts.into_iter().next().unwrap();
            let maybe_bounds = allow_plus == AllowPlus::Yes && self.token.is_like_plus();
            match ty.kind {
                // `"(" BareTraitBound ")" "+" Bound "+" ...`.
                TyKind::Path(None, path) if maybe_bounds => self.parse_remaining_bounds_path(
                    ThinVec::new(),
                    path,
                    lo,
                    true,
                    ast::Parens::Yes,
                ),
                // For `('a) + …`, we know that `'a` in type position already lead to an error being
                // emitted. To reduce output, let's indirectly suppress E0178 (bad `+` in type) and
                // other irrelevant consequential errors.
                TyKind::TraitObject(bounds, TraitObjectSyntax::None)
                    if maybe_bounds && bounds.len() == 1 && !trailing_plus =>
                {
                    self.parse_remaining_bounds(bounds, true)
                }
                // `(TYPE)`
                _ => Ok(TyKind::Paren(ty)),
            }
        } else {
            Ok(TyKind::Tup(ts))
        }
    }

    fn parse_bare_trait_object(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
        // A lifetime only begins a bare trait object type if it is followed by `+`!
        if self.token.is_lifetime() && !self.look_ahead(1, |t| t.is_like_plus()) {
            // In Rust 2021 and beyond, we assume that the user didn't intend to write a bare trait
            // object type with a leading lifetime bound since that seems very unlikely given the
            // fact that `dyn`-less trait objects are *semantically* invalid.
            if self.psess.edition.at_least_rust_2021() {
                let lt = self.expect_lifetime();
                let mut err = self.dcx().struct_span_err(lo, "expected type, found lifetime");
                err.span_label(lo, "expected type");
                return Ok(match self.maybe_recover_ref_ty_no_leading_ampersand(lt, lo, err) {
                    Ok(ref_ty) => ref_ty,
                    Err(err) => TyKind::Err(err.emit()),
                });
            }

            self.dcx().emit_err(NeedPlusAfterTraitObjectLifetime {
                span: lo,
                suggestion: lo.shrink_to_hi(),
            });
        }
        Ok(TyKind::TraitObject(
            self.parse_generic_bounds_common(allow_plus)?,
            TraitObjectSyntax::None,
        ))
    }

    fn maybe_recover_ref_ty_no_leading_ampersand<'cx>(
        &mut self,
        lt: Lifetime,
        lo: Span,
        mut err: Diag<'cx>,
    ) -> Result<TyKind, Diag<'cx>> {
        if !self.may_recover() {
            return Err(err);
        }
        let snapshot = self.create_snapshot_for_diagnostic();
        let mutbl = self.parse_mutability();
        match self.parse_ty_no_plus() {
            Ok(ty) => {
                err.span_suggestion_verbose(
                    lo.shrink_to_lo(),
                    "you might have meant to write a reference type here",
                    "&",
                    Applicability::MaybeIncorrect,
                );
                err.emit();
                Ok(TyKind::Ref(Some(lt), MutTy { ty, mutbl }))
            }
            Err(diag) => {
                diag.cancel();
                self.restore_snapshot(snapshot);
                Err(err)
            }
        }
    }

    fn parse_remaining_bounds_path(
        &mut self,
        generic_params: ThinVec<GenericParam>,
        path: ast::Path,
        lo: Span,
        parse_plus: bool,
        parens: ast::Parens,
    ) -> PResult<'a, TyKind> {
        let poly_trait_ref = PolyTraitRef::new(
            generic_params,
            path,
            TraitBoundModifiers::NONE,
            lo.to(self.prev_token.span),
            parens,
        );
        let bounds = vec![GenericBound::Trait(poly_trait_ref)];
        self.parse_remaining_bounds(bounds, parse_plus)
    }

    /// Parse the remainder of a bare trait object type given an already parsed list.
    fn parse_remaining_bounds(
        &mut self,
        mut bounds: GenericBounds,
        plus: bool,
    ) -> PResult<'a, TyKind> {
        if plus {
            self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
            bounds.append(&mut self.parse_generic_bounds()?);
        }
        Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
    }

    /// Parses a raw pointer type: `*[const | mut] $type`.
    fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {
        let mutbl = self.parse_const_or_mut().unwrap_or_else(|| {
            let span = self.prev_token.span;
            self.dcx().emit_err(ExpectedMutOrConstInRawPointerType {
                span,
                after_asterisk: span.shrink_to_hi(),
            });
            Mutability::Not
        });
        let ty = self.parse_ty_no_plus()?;
        Ok(TyKind::Ptr(MutTy { ty, mutbl }))
    }

    /// Parses an array (`[TYPE; EXPR]`) or slice (`[TYPE]`) type.
    /// The opening `[` bracket is already eaten.
    fn parse_array_or_slice_ty(&mut self) -> PResult<'a, TyKind> {
        let elt_ty = match self.parse_ty() {
            Ok(ty) => ty,
            Err(err)
                if self.look_ahead(1, |t| *t == token::CloseBracket)
                    | self.look_ahead(1, |t| *t == token::Semi) =>
            {
                // Recover from `[LIT; EXPR]` and `[LIT]`
                self.bump();
                let guar = err.emit();
                self.mk_ty(self.prev_token.span, TyKind::Err(guar))
            }
            Err(err) => return Err(err),
        };

        let ty = if self.eat(exp!(Semi)) {
            let mut length = self.parse_expr_anon_const()?;
            if let Err(e) = self.expect(exp!(CloseBracket)) {
                // Try to recover from `X<Y, ...>` when `X::<Y, ...>` works
                self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?;
                self.expect(exp!(CloseBracket))?;
            }
            TyKind::Array(elt_ty, length)
        } else if self.eat(exp!(CloseBracket)) {
            TyKind::Slice(elt_ty)
        } else {
            self.maybe_recover_array_ty_without_semi(elt_ty)?
        };

        Ok(ty)
    }

    /// Recover from malformed array type syntax.
    ///
    /// This method attempts to recover from cases like:
    /// - `[u8, 5]` → suggests using `;`, return a Array type
    /// - `[u8 5]` → suggests using `;`, return a Array type
    /// Consider to add more cases in the future.
    fn maybe_recover_array_ty_without_semi(&mut self, elt_ty: Box<Ty>) -> PResult<'a, TyKind> {
        let span = self.token.span;
        let token_descr = super::token_descr(&self.token);
        let mut err =
            self.dcx().struct_span_err(span, format!("expected `;` or `]`, found {}", token_descr));
        err.span_label(span, "expected `;` or `]`");
        err.note("you might have meant to write a slice or array type");

        // If we cannot recover, return the error immediately.
        if !self.may_recover() {
            return Err(err);
        }

        let snapshot = self.create_snapshot_for_diagnostic();

        let suggestion_span = if self.eat(exp!(Comma)) || self.eat(exp!(Star)) {
            // Consume common erroneous separators.
            self.prev_token.span
        } else {
            self.token.span.shrink_to_lo()
        };

        // we first try to parse pattern like `[u8 5]`
        let length = match self.parse_expr_anon_const() {
            Ok(length) => length,
            Err(e) => {
                e.cancel();
                self.restore_snapshot(snapshot);
                return Err(err);
            }
        };

        if let Err(e) = self.expect(exp!(CloseBracket)) {
            e.cancel();
            self.restore_snapshot(snapshot);
            return Err(err);
        }

        err.span_suggestion_verbose(
            suggestion_span,
            "you might have meant to use `;` as the separator",
            ";",
            Applicability::MaybeIncorrect,
        );
        err.emit();
        Ok(TyKind::Array(elt_ty, length))
    }

    fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
        let and_span = self.prev_token.span;
        let mut opt_lifetime = self.check_lifetime().then(|| self.expect_lifetime());
        let (pinned, mut mutbl) = match self.parse_pin_and_mut() {
            Some(pin_mut) => pin_mut,
            None => (Pinnedness::Not, self.parse_mutability()),
        };
        if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
            // A lifetime is invalid here: it would be part of a bare trait bound, which requires
            // it to be followed by a plus, but we disallow plus in the pointee type.
            // So we can handle this case as an error here, and suggest `'a mut`.
            // If there *is* a plus next though, handling the error later provides better suggestions
            // (like adding parentheses)
            if !self.look_ahead(1, |t| t.is_like_plus()) {
                let lifetime_span = self.token.span;
                let span = and_span.to(lifetime_span);

                let (suggest_lifetime, snippet) =
                    if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
                        (Some(span), lifetime_src)
                    } else {
                        (None, String::new())
                    };
                self.dcx().emit_err(LifetimeAfterMut { span, suggest_lifetime, snippet });

                opt_lifetime = Some(self.expect_lifetime());
            }
        } else if self.token.is_keyword(kw::Dyn)
            && mutbl == Mutability::Not
            && self.look_ahead(1, |t| t.is_keyword(kw::Mut))
        {
            // We have `&dyn mut ...`, which is invalid and should be `&mut dyn ...`.
            let span = and_span.to(self.look_ahead(1, |t| t.span));
            self.dcx().emit_err(DynAfterMut { span });

            // Recovery
            mutbl = Mutability::Mut;
            let (dyn_tok, dyn_tok_sp) = (self.token, self.token_spacing);
            self.bump();
            self.bump_with((dyn_tok, dyn_tok_sp));
        }
        let ty = self.parse_ty_no_plus()?;
        Ok(match pinned {
            Pinnedness::Not => TyKind::Ref(opt_lifetime, MutTy { ty, mutbl }),
            Pinnedness::Pinned => TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl }),
        })
    }

    /// Parses `pin` and `mut` annotations on references.
    ///
    /// It must be either `pin const` or `pin mut`.
    pub(crate) fn parse_pin_and_mut(&mut self) -> Option<(Pinnedness, Mutability)> {
        if self.token.is_ident_named(sym::pin) {
            let result = self.look_ahead(1, |token| {
                if token.is_keyword(kw::Const) {
                    Some((Pinnedness::Pinned, Mutability::Not))
                } else if token.is_keyword(kw::Mut) {
                    Some((Pinnedness::Pinned, Mutability::Mut))
                } else {
                    None
                }
            });
            if result.is_some() {
                self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
                self.bump();
                self.bump();
            }
            result
        } else {
            None
        }
    }

    // Parses the `typeof(EXPR)`.
    // To avoid ambiguity, the type is surrounded by parentheses.
    fn parse_typeof_ty(&mut self) -> PResult<'a, TyKind> {
        self.expect(exp!(OpenParen))?;
        let expr = self.parse_expr_anon_const()?;
        self.expect(exp!(CloseParen))?;
        Ok(TyKind::Typeof(expr))
    }

    /// Parses a function pointer type (`TyKind::FnPtr`).
    /// ```ignore (illustrative)
    ///    [unsafe] [extern "ABI"] fn (S) -> T
    /// //  ^~~~~^          ^~~~^     ^~^    ^
    /// //    |               |        |     |
    /// //    |               |        |   Return type
    /// // Function Style    ABI  Parameter types
    /// ```
    /// We actually parse `FnHeader FnDecl`, but we error on `const` and `async` qualifiers.
    fn parse_ty_fn_ptr(
        &mut self,
        lo: Span,
        mut params: ThinVec<GenericParam>,
        param_insertion_point: Option<Span>,
        recover_return_sign: RecoverReturnSign,
    ) -> PResult<'a, TyKind> {
        let inherited_vis = rustc_ast::Visibility {
            span: rustc_span::DUMMY_SP,
            kind: rustc_ast::VisibilityKind::Inherited,
            tokens: None,
        };
        let span_start = self.token.span;
        let ast::FnHeader { ext, safety, .. } = self.parse_fn_front_matter(
            &inherited_vis,
            Case::Sensitive,
            FrontMatterParsingMode::FunctionPtrType,
        )?;
        if self.may_recover() && self.token == TokenKind::Lt {
            self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?;
        }
        let mode = crate::parser::item::FnParseMode {
            req_name: |_| false,
            context: FnContext::Free,
            req_body: false,
        };
        let decl = self.parse_fn_decl(&mode, AllowPlus::No, recover_return_sign)?;

        let decl_span = span_start.to(self.prev_token.span);
        Ok(TyKind::FnPtr(Box::new(FnPtrTy {
            ext,
            safety,
            generic_params: params,
            decl,
            decl_span,
        })))
    }

    /// Recover from function pointer types with a generic parameter list (e.g. `fn<'a>(&'a str)`).
    fn recover_fn_ptr_with_generics(
        &mut self,
        lo: Span,
        params: &mut ThinVec<GenericParam>,
        param_insertion_point: Option<Span>,
    ) -> PResult<'a, ()> {
        let generics = self.parse_generics()?;
        let arity = generics.params.len();

        let mut lifetimes: ThinVec<_> = generics
            .params
            .into_iter()
            .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime))
            .collect();

        let sugg = if !lifetimes.is_empty() {
            let snippet =
                lifetimes.iter().map(|param| param.ident.as_str()).intersperse(", ").collect();

            let (left, snippet) = if let Some(span) = param_insertion_point {
                (span, if params.is_empty() { snippet } else { format!(", {snippet}") })
            } else {
                (lo.shrink_to_lo(), format!("for<{snippet}> "))
            };

            Some(FnPtrWithGenericsSugg {
                left,
                snippet,
                right: generics.span,
                arity,
                for_param_list_exists: param_insertion_point.is_some(),
            })
        } else {
            None
        };

        self.dcx().emit_err(FnPtrWithGenerics { span: generics.span, sugg });
        params.append(&mut lifetimes);
        Ok(())
    }

    /// Parses an `impl B0 + ... + Bn` type.
    fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
        if self.token.is_lifetime() {
            self.look_ahead(1, |t| {
                if let token::Ident(sym, _) = t.kind {
                    // parse pattern with "'a Sized" we're supposed to give suggestion like
                    // "'a + Sized"
                    self.dcx().emit_err(errors::MissingPlusBounds {
                        span: self.token.span,
                        hi: self.token.span.shrink_to_hi(),
                        sym,
                    });
                }
            })
        }

        // Always parse bounds greedily for better error recovery.
        let bounds = self.parse_generic_bounds()?;

        *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;

        Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds))
    }

    /// Parse a use-bound aka precise capturing list.
    ///
    /// ```ebnf
    /// UseBound = "use" "<" (PreciseCapture ("," PreciseCapture)* ","?)? ">"
    /// PreciseCapture = "Self" | Ident | Lifetime
    /// ```
    fn parse_use_bound(&mut self, lo: Span, parens: ast::Parens) -> PResult<'a, GenericBound> {
        self.expect_lt()?;
        let (args, _, _) = self.parse_seq_to_before_tokens(
            &[exp!(Gt)],
            &[&TokenKind::Ge, &TokenKind::Shr, &TokenKind::Shr],
            SeqSep::trailing_allowed(exp!(Comma)),
            |self_| {
                if self_.check_keyword(exp!(SelfUpper)) {
                    self_.bump();
                    Ok(PreciseCapturingArg::Arg(
                        ast::Path::from_ident(self_.prev_token.ident().unwrap().0),
                        DUMMY_NODE_ID,
                    ))
                } else if self_.check_ident() {
                    Ok(PreciseCapturingArg::Arg(
                        ast::Path::from_ident(self_.parse_ident()?),
                        DUMMY_NODE_ID,
                    ))
                } else if self_.check_lifetime() {
                    Ok(PreciseCapturingArg::Lifetime(self_.expect_lifetime()))
                } else {
                    self_.unexpected_any()
                }
            },
        )?;
        self.expect_gt()?;

        if let ast::Parens::Yes = parens {
            self.expect(exp!(CloseParen))?;
            self.report_parenthesized_bound(lo, self.prev_token.span, "precise capturing lists");
        }

        Ok(GenericBound::Use(args, lo.to(self.prev_token.span)))
    }

    /// Is a `dyn B0 + ... + Bn` type allowed here?
    fn is_explicit_dyn_type(&mut self) -> bool {
        self.check_keyword(exp!(Dyn))
            && (self.token_uninterpolated_span().at_least_rust_2018()
                || self.look_ahead(1, |t| {
                    (can_begin_dyn_bound_in_edition_2015(t) || *t == TokenKind::Star)
                        && !can_continue_type_after_non_fn_ident(t)
                }))
    }

    /// Parses a `dyn B0 + ... + Bn` type.
    ///
    /// Note that this does *not* parse bare trait objects.
    fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
        self.bump(); // `dyn`

        // We used to parse `*` for `dyn*` here.
        let syntax = TraitObjectSyntax::Dyn;

        // Always parse bounds greedily for better error recovery.
        let bounds = self.parse_generic_bounds()?;
        *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;
        Ok(TyKind::TraitObject(bounds, syntax))
    }

    /// Parses a type starting with a path.
    ///
    /// This can be:
    /// 1. a type macro, `mac!(...)`,
    /// 2. a bare trait object, `B0 + ... + Bn`,
    /// 3. or a path, `path::to::MyType`.
    fn parse_path_start_ty(
        &mut self,
        lo: Span,
        allow_plus: AllowPlus,
        ty_generics: Option<&Generics>,
    ) -> PResult<'a, TyKind> {
        // Simple path
        let path = self.parse_path_inner(PathStyle::Type, ty_generics)?;
        if self.eat(exp!(Bang)) {
            // Macro invocation in type position
            Ok(TyKind::MacCall(Box::new(MacCall { path, args: self.parse_delim_args()? })))
        } else if allow_plus == AllowPlus::Yes && self.check_plus() {
            // `Trait1 + Trait2 + 'a`
            self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true, ast::Parens::No)
        } else {
            // Just a type path.
            Ok(TyKind::Path(None, path))
        }
    }

    pub(super) fn parse_generic_bounds(&mut self) -> PResult<'a, GenericBounds> {
        self.parse_generic_bounds_common(AllowPlus::Yes)
    }

    /// Parse generic bounds.
    ///
    /// Only if `allow_plus` this parses a `+`-separated list of bounds (trailing `+` is admitted).
    /// Otherwise, this only parses a single bound or none.
    fn parse_generic_bounds_common(&mut self, allow_plus: AllowPlus) -> PResult<'a, GenericBounds> {
        let mut bounds = Vec::new();

        // In addition to looping while we find generic bounds:
        // We continue even if we find a keyword. This is necessary for error recovery on,
        // for example, `impl fn()`. The only keyword that can go after generic bounds is
        // `where`, so stop if it's it.
        // We also continue if we find types (not traits), again for error recovery.
        while self.can_begin_bound()
            || (self.may_recover()
                && (self.token.can_begin_type()
                    || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where))))
        {
            if self.token.is_keyword(kw::Dyn) {
                // Account for `&dyn Trait + dyn Other`.
                self.bump();
                self.dcx().emit_err(InvalidDynKeyword {
                    span: self.prev_token.span,
                    suggestion: self.prev_token.span.until(self.token.span),
                });
            }
            bounds.push(self.parse_generic_bound()?);
            if allow_plus == AllowPlus::No || !self.eat_plus() {
                break;
            }
        }

        Ok(bounds)
    }

    /// Can the current token begin a bound?
    fn can_begin_bound(&mut self) -> bool {
        self.check_path()
            || self.check_lifetime()
            || self.check(exp!(Bang))
            || self.check(exp!(Question))
            || self.check(exp!(Tilde))
            || self.check_keyword(exp!(For))
            || self.check(exp!(OpenParen))
            || self.check(exp!(OpenBracket))
            || self.check_keyword(exp!(Const))
            || self.check_keyword(exp!(Async))
            || self.check_keyword(exp!(Use))
    }

    /// Parse a bound.
    ///
    /// ```ebnf
    /// Bound = LifetimeBound | UseBound | TraitBound
    /// ```
    fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> {
        let leading_token = self.prev_token;
        let lo = self.token.span;

        // We only admit parenthesized *trait* bounds. However, we want to gracefully recover from
        // other kinds of parenthesized bounds, so parse the opening parenthesis *here*.
        //
        // In the future we might want to lift this syntactic restriction and
        // introduce "`GenericBound::Paren(Box<GenericBound>)`".
        let parens = if self.eat(exp!(OpenParen)) { ast::Parens::Yes } else { ast::Parens::No };

        if self.token.is_lifetime() {
            self.parse_lifetime_bound(lo, parens)
        } else if self.eat_keyword(exp!(Use)) {
            self.parse_use_bound(lo, parens)
        } else {
            self.parse_trait_bound(lo, parens, &leading_token)
        }
    }

    /// Parse a lifetime-bound aka outlives-bound.
    ///
    /// ```ebnf
    /// LifetimeBound = Lifetime
    /// ```
    fn parse_lifetime_bound(&mut self, lo: Span, parens: ast::Parens) -> PResult<'a, GenericBound> {
        let lt = self.expect_lifetime();

        if let ast::Parens::Yes = parens {
            self.expect(exp!(CloseParen))?;
            self.report_parenthesized_bound(lo, self.prev_token.span, "lifetime bounds");
        }

        Ok(GenericBound::Outlives(lt))
    }

    fn report_parenthesized_bound(&self, lo: Span, hi: Span, kind: &str) -> ErrorGuaranteed {
        let mut diag =
            self.dcx().struct_span_err(lo.to(hi), format!("{kind} may not be parenthesized"));
        diag.multipart_suggestion(
            "remove the parentheses",
            vec![(lo, String::new()), (hi, String::new())],
            Applicability::MachineApplicable,
        );
        diag.emit()
    }

    /// Emits an error if any trait bound modifiers were present.
    fn error_lt_bound_with_modifiers(
        &self,
        modifiers: TraitBoundModifiers,
        binder_span: Option<Span>,
    ) -> ErrorGuaranteed {
        let TraitBoundModifiers { constness, asyncness, polarity } = modifiers;

        match constness {
            BoundConstness::Never => {}
            BoundConstness::Always(span) | BoundConstness::Maybe(span) => {
                return self
                    .dcx()
                    .emit_err(errors::ModifierLifetime { span, modifier: constness.as_str() });
            }
        }

        match polarity {
            BoundPolarity::Positive => {}
            BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => {
                return self
                    .dcx()
                    .emit_err(errors::ModifierLifetime { span, modifier: polarity.as_str() });
            }
        }

        match asyncness {
            BoundAsyncness::Normal => {}
            BoundAsyncness::Async(span) => {
                return self
                    .dcx()
                    .emit_err(errors::ModifierLifetime { span, modifier: asyncness.as_str() });
            }
        }

        if let Some(span) = binder_span {
            return self.dcx().emit_err(errors::ModifierLifetime { span, modifier: "for<...>" });
        }

        unreachable!("lifetime bound intercepted in `parse_generic_ty_bound` but no modifiers?")
    }

    /// Parses the modifiers that may precede a trait in a bound, e.g. `?Trait` or `[const] Trait`.
    ///
    /// If no modifiers are present, this does not consume any tokens.
    ///
    /// ```ebnf
    /// Constness = ("const" | "[" "const" "]")?
    /// Asyncness = "async"?
    /// Polarity = ("?" | "!")?
    /// ```
    ///
    /// See `parse_trait_bound` for more context.
    fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> {
        let modifier_lo = self.token.span;
        let constness = self.parse_bound_constness()?;

        let asyncness = if self.token_uninterpolated_span().at_least_rust_2018()
            && self.eat_keyword(exp!(Async))
        {
            self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
            BoundAsyncness::Async(self.prev_token.span)
        } else if self.may_recover()
            && self.token_uninterpolated_span().is_rust_2015()
            && self.is_kw_followed_by_ident(kw::Async)
        {
            self.bump(); // eat `async`
            self.dcx().emit_err(errors::AsyncBoundModifierIn2015 {
                span: self.prev_token.span,
                help: HelpUseLatestEdition::new(),
            });
            self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
            BoundAsyncness::Async(self.prev_token.span)
        } else {
            BoundAsyncness::Normal
        };
        let modifier_hi = self.prev_token.span;

        let polarity = if self.eat(exp!(Question)) {
            BoundPolarity::Maybe(self.prev_token.span)
        } else if self.eat(exp!(Bang)) {
            self.psess.gated_spans.gate(sym::negative_bounds, self.prev_token.span);
            BoundPolarity::Negative(self.prev_token.span)
        } else {
            BoundPolarity::Positive
        };

        // Enforce the mutual-exclusivity of `const`/`async` and `?`/`!`.
        match polarity {
            BoundPolarity::Positive => {
                // All trait bound modifiers allowed to combine with positive polarity
            }
            BoundPolarity::Maybe(polarity_span) | BoundPolarity::Negative(polarity_span) => {
                match (asyncness, constness) {
                    (BoundAsyncness::Normal, BoundConstness::Never) => {
                        // Ok, no modifiers.
                    }
                    (_, _) => {
                        let constness = constness.as_str();
                        let asyncness = asyncness.as_str();
                        let glue =
                            if !constness.is_empty() && !asyncness.is_empty() { " " } else { "" };
                        let modifiers_concatenated = format!("{constness}{glue}{asyncness}");
                        self.dcx().emit_err(errors::PolarityAndModifiers {
                            polarity_span,
                            polarity: polarity.as_str(),
                            modifiers_span: modifier_lo.to(modifier_hi),
                            modifiers_concatenated,
                        });
                    }
                }
            }
        }

        Ok(TraitBoundModifiers { constness, asyncness, polarity })
    }

    pub fn parse_bound_constness(&mut self) -> PResult<'a, BoundConstness> {
        // FIXME(const_trait_impl): remove `~const` parser support once bootstrap has the new syntax
        // in rustfmt
        Ok(if self.eat(exp!(Tilde)) {
            let tilde = self.prev_token.span;
            self.expect_keyword(exp!(Const))?;
            let span = tilde.to(self.prev_token.span);
            self.psess.gated_spans.gate(sym::const_trait_impl, span);
            BoundConstness::Maybe(span)
        } else if self.check(exp!(OpenBracket))
            && self.look_ahead(1, |t| t.is_keyword(kw::Const))
            && self.look_ahead(2, |t| *t == token::CloseBracket)
        {
            let start = self.token.span;
            self.bump();
            self.expect_keyword(exp!(Const)).unwrap();
            self.bump();
            let span = start.to(self.prev_token.span);
            self.psess.gated_spans.gate(sym::const_trait_impl, span);
            BoundConstness::Maybe(span)
        } else if self.eat_keyword(exp!(Const)) {
            self.psess.gated_spans.gate(sym::const_trait_impl, self.prev_token.span);
            BoundConstness::Always(self.prev_token.span)
        } else {
            BoundConstness::Never
        })
    }

    /// Parse a trait bound.
    ///
    /// ```ebnf
    /// TraitBound = BareTraitBound | "(" BareTraitBound ")"
    /// BareTraitBound =
    ///     (HigherRankedBinder Constness Asyncness | Polarity)
    ///     TypePath
    /// ```
    fn parse_trait_bound(
        &mut self,
        lo: Span,
        parens: ast::Parens,
        leading_token: &Token,
    ) -> PResult<'a, GenericBound> {
        let (mut bound_vars, binder_span) = self.parse_higher_ranked_binder()?;

        let modifiers_lo = self.token.span;
        let modifiers = self.parse_trait_bound_modifiers()?;
        let modifiers_span = modifiers_lo.to(self.prev_token.span);

        if let Some(binder_span) = binder_span {
            match modifiers.polarity {
                BoundPolarity::Negative(polarity_span) | BoundPolarity::Maybe(polarity_span) => {
                    self.dcx().emit_err(errors::BinderAndPolarity {
                        binder_span,
                        polarity_span,
                        polarity: modifiers.polarity.as_str(),
                    });
                }
                BoundPolarity::Positive => {}
            }
        }

        // Recover erroneous lifetime bound with modifiers or binder.
        // e.g. `T: for<'a> 'a` or `T: [const] 'a`.
        if self.token.is_lifetime() {
            let _: ErrorGuaranteed = self.error_lt_bound_with_modifiers(modifiers, binder_span);
            return self.parse_lifetime_bound(lo, parens);
        }

        if let (more_bound_vars, Some(binder_span)) = self.parse_higher_ranked_binder()? {
            bound_vars.extend(more_bound_vars);
            self.dcx().emit_err(errors::BinderBeforeModifiers { binder_span, modifiers_span });
        }

        let mut path = if self.token.is_keyword(kw::Fn)
            && self.look_ahead(1, |t| *t == TokenKind::OpenParen)
            && let Some(path) = self.recover_path_from_fn()
        {
            path
        } else if !self.token.is_path_start() && self.token.can_begin_type() {
            let ty = self.parse_ty_no_plus()?;
            // Instead of finding a path (a trait), we found a type.
            let mut err = self.dcx().struct_span_err(ty.span, "expected a trait, found type");

            // If we can recover, try to extract a path from the type. Note
            // that we do not use the try operator when parsing the type because
            // if it fails then we get a parser error which we don't want (we're trying
            // to recover from errors, not make more).
            let path = if self.may_recover() {
                let (span, message, sugg, path, applicability) = match &ty.kind {
                    TyKind::Ptr(..) | TyKind::Ref(..)
                        if let TyKind::Path(_, path) = &ty.peel_refs().kind =>
                    {
                        (
                            ty.span.until(path.span),
                            "consider removing the indirection",
                            "",
                            path,
                            Applicability::MaybeIncorrect,
                        )
                    }
                    TyKind::ImplTrait(_, bounds)
                        if let [GenericBound::Trait(tr, ..), ..] = bounds.as_slice() =>
                    {
                        (
                            ty.span.until(tr.span),
                            "use the trait bounds directly",
                            "",
                            &tr.trait_ref.path,
                            Applicability::MachineApplicable,
                        )
                    }
                    _ => return Err(err),
                };

                err.span_suggestion_verbose(span, message, sugg, applicability);

                path.clone()
            } else {
                return Err(err);
            };

            err.emit();

            path
        } else {
            self.parse_path(PathStyle::Type)?
        };

        if self.may_recover() && self.token == TokenKind::OpenParen {
            self.recover_fn_trait_with_lifetime_params(&mut path, &mut bound_vars)?;
        }

        if let ast::Parens::Yes = parens {
            // Someone has written something like `&dyn (Trait + Other)`. The correct code
            // would be `&(dyn Trait + Other)`
            if self.token.is_like_plus() && leading_token.is_keyword(kw::Dyn) {
                let bounds = vec![];
                self.parse_remaining_bounds(bounds, true)?;
                self.expect(exp!(CloseParen))?;
                self.dcx().emit_err(errors::IncorrectParensTraitBounds {
                    span: vec![lo, self.prev_token.span],
                    sugg: errors::IncorrectParensTraitBoundsSugg {
                        wrong_span: leading_token.span.shrink_to_hi().to(lo),
                        new_span: leading_token.span.shrink_to_lo(),
                    },
                });
            } else {
                self.expect(exp!(CloseParen))?;
            }
        }

        let poly_trait =
            PolyTraitRef::new(bound_vars, path, modifiers, lo.to(self.prev_token.span), parens);
        Ok(GenericBound::Trait(poly_trait))
    }

    // recovers a `Fn(..)` parenthesized-style path from `fn(..)`
    fn recover_path_from_fn(&mut self) -> Option<ast::Path> {
        let fn_token_span = self.token.span;
        self.bump();
        let args_lo = self.token.span;
        let snapshot = self.create_snapshot_for_diagnostic();
        let mode = FnParseMode { req_name: |_| false, context: FnContext::Free, req_body: false };
        match self.parse_fn_decl(&mode, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) {
            Ok(decl) => {
                self.dcx().emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span });
                Some(ast::Path {
                    span: fn_token_span.to(self.prev_token.span),
                    segments: thin_vec![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(),
                            }
                        ))),
                    }],
                    tokens: None,
                })
            }
            Err(diag) => {
                diag.cancel();
                self.restore_snapshot(snapshot);
                None
            }
        }
    }

    /// Parse an optional higher-ranked binder.
    ///
    /// ```ebnf
    /// HigherRankedBinder = ("for" "<" GenericParams ">")?
    /// ```
    pub(super) fn parse_higher_ranked_binder(
        &mut self,
    ) -> PResult<'a, (ThinVec<GenericParam>, Option<Span>)> {
        if self.eat_keyword(exp!(For)) {
            let lo = self.token.span;
            self.expect_lt()?;
            let params = self.parse_generic_params()?;
            self.expect_gt()?;
            // We rely on AST validation to rule out invalid cases: There must not be
            // type or const parameters, and parameters must not have bounds.
            Ok((params, Some(lo.to(self.prev_token.span))))
        } else {
            Ok((ThinVec::new(), None))
        }
    }

    /// Recover from `Fn`-family traits (Fn, FnMut, FnOnce) with lifetime arguments
    /// (e.g. `FnOnce<'a>(&'a str) -> bool`). Up to generic arguments have already
    /// been eaten.
    fn recover_fn_trait_with_lifetime_params(
        &mut self,
        fn_path: &mut ast::Path,
        lifetime_defs: &mut ThinVec<GenericParam>,
    ) -> PResult<'a, ()> {
        let fn_path_segment = fn_path.segments.last_mut().unwrap();
        let generic_args = if let Some(p_args) = &fn_path_segment.args {
            *p_args.clone()
        } else {
            // Normally it wouldn't come here because the upstream should have parsed
            // generic parameters (otherwise it's impossible to call this function).
            return Ok(());
        };
        let lifetimes =
            if let ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { span: _, args }) =
                &generic_args
            {
                args.into_iter()
                    .filter_map(|arg| {
                        if let ast::AngleBracketedArg::Arg(generic_arg) = arg
                            && let ast::GenericArg::Lifetime(lifetime) = generic_arg
                        {
                            Some(lifetime)
                        } else {
                            None
                        }
                    })
                    .collect()
            } else {
                Vec::new()
            };
        // Only try to recover if the trait has lifetime params.
        if lifetimes.is_empty() {
            return Ok(());
        }

        // Parse `(T, U) -> R`.
        let inputs_lo = self.token.span;
        let mode = FnParseMode { req_name: |_| false, context: FnContext::Free, req_body: false };
        let inputs: ThinVec<_> =
            self.parse_fn_params(&mode)?.into_iter().map(|input| input.ty).collect();
        let inputs_span = inputs_lo.to(self.prev_token.span);
        let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
        let args = ast::ParenthesizedArgs {
            span: fn_path_segment.span().to(self.prev_token.span),
            inputs,
            inputs_span,
            output,
        }
        .into();
        *fn_path_segment = ast::PathSegment {
            ident: fn_path_segment.ident,
            args: Some(args),
            id: ast::DUMMY_NODE_ID,
        };

        // Convert parsed `<'a>` in `Fn<'a>` into `for<'a>`.
        let mut generic_params = lifetimes
            .iter()
            .map(|lt| GenericParam {
                id: lt.id,
                ident: lt.ident,
                attrs: ast::AttrVec::new(),
                bounds: Vec::new(),
                is_placeholder: false,
                kind: ast::GenericParamKind::Lifetime,
                colon_span: None,
            })
            .collect::<ThinVec<GenericParam>>();
        lifetime_defs.append(&mut generic_params);

        let generic_args_span = generic_args.span();
        let snippet = format!(
            "for<{}> ",
            lifetimes.iter().map(|lt| lt.ident.as_str()).intersperse(", ").collect::<String>(),
        );
        let before_fn_path = fn_path.span.shrink_to_lo();
        self.dcx()
            .struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters")
            .with_multipart_suggestion(
                "consider using a higher-ranked trait bound instead",
                vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)],
                Applicability::MaybeIncorrect,
            )
            .emit();
        Ok(())
    }

    pub(super) fn check_lifetime(&mut self) -> bool {
        self.expected_token_types.insert(TokenType::Lifetime);
        self.token.is_lifetime()
    }

    /// Parses a single lifetime `'a` or panics.
    pub(super) fn expect_lifetime(&mut self) -> Lifetime {
        if let Some((ident, is_raw)) = self.token.lifetime() {
            if matches!(is_raw, IdentIsRaw::No)
                && ident.without_first_quote().is_reserved()
                && ![kw::UnderscoreLifetime, kw::StaticLifetime].contains(&ident.name)
            {
                self.dcx().emit_err(errors::KeywordLifetime { span: ident.span });
            }

            self.bump();
            Lifetime { ident, id: ast::DUMMY_NODE_ID }
        } else {
            self.dcx().span_bug(self.token.span, "not a lifetime")
        }
    }

    pub(super) fn mk_ty(&self, span: Span, kind: TyKind) -> Box<Ty> {
        Box::new(Ty { kind, span, id: ast::DUMMY_NODE_ID, tokens: None })
    }
}
