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, MgcaDisambiguation,
    MutTy, Mutability, Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers,
    TraitObjectSyntax, Ty, TyKind, UnsafeBinderTy,
};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{Applicability, Diag, E0516, 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, InvalidCVariadicType, 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,
}

/// Determine if the given token can begin a bound assuming it follows Rust 2015 identifier `dyn`.
///
/// In Rust 2015, `dyn` is a contextual keyword, not a full one.
fn can_begin_dyn_bound_in_edition_2015(t: Token) -> bool {
    if t.is_path_start() {
        // In `dyn::x`, `dyn<X>` and `dyn<<X>::Y>`, `dyn` should (continue to) denote a regular path
        // segment for backward compatibility. We make an exception for `dyn(X)` which used to be
        // interpreted as a path with parenthesized generic arguments which can be semantically
        // well-formed (consider: `use std::ops::Fn as dyn;`). Instead, we treat it as a trait
        // object type whose first bound is parenthesized.
        return t != token::PathSep && t != token::Lt && t != token::Shl;
    }

    // Contrary to `Parser::can_begin_bound`, `!`, `const`, `[` and `async` are deliberately not
    // part of this list to contain the number of potential regressions esp. in MBE code.
    // `const` and `[` would regress UI test `macro-dyn-const-2015.rs` and
    // `!` would regress `dyn!(...)` macro calls in Rust 2015 for example.
    t == token::OpenParen || t == token::Question || t.is_lifetime() || t.is_keyword(kw::For)
}

impl<'a> Parser<'a> {
    /// Parses a type.
    pub fn parse_ty(&mut self) -> PResult<'a, Box<Ty>> {
        if self.token == token::DotDotDot {
            // We special case this so that we don't talk about "nested C-variadics" in types.
            // We still pass in `AllowCVariadic::No` so that `parse_ty_common` can complain about
            // things like `Vec<...>`.
            let span = self.token.span;
            self.bump();
            let kind = TyKind::Err(self.dcx().emit_err(InvalidCVariadicType { span }));
            return Ok(self.mk_ty(span, kind));
        }
        // 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>> {
        let ty = self.parse_ty_common(
            AllowPlus::Yes,
            AllowCVariadic::Yes,
            RecoverQPath::Yes,
            RecoverReturnSign::Yes,
            None,
            RecoverQuestionMark::Yes,
        )?;

        // Recover a trailing `= EXPR` if present.
        if self.may_recover()
            && self.check_noexpect(&token::Eq)
            && self.look_ahead(1, |tok| tok.can_begin_expr())
        {
            let snapshot = self.create_snapshot_for_diagnostic();
            self.bump();
            let eq_span = self.prev_token.span;
            match self.parse_expr() {
                Ok(e) => {
                    self.dcx()
                        .struct_span_err(eq_span.to(e.span), "parameter defaults are not supported")
                        .emit();
                }
                Err(diag) => {
                    diag.cancel();
                    self.restore_snapshot(snapshot);
                }
            }
        }

        Ok(ty)
    }

    /// 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(lo)?
        } else if self.is_builtin() {
            self.parse_builtin_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.token.is_keyword(kw::Const) || self.token.is_keyword(kw::Mut))
            && self.look_ahead(1, |t| *t == token::Star)
        {
            self.parse_ty_c_style_pointer()?
        } 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 with a C-style typo
    fn parse_ty_c_style_pointer(&mut self) -> PResult<'a, TyKind> {
        let kw_span = self.token.span;
        let mutbl = self.parse_const_or_mut();

        if let Some(mutbl) = mutbl
            && self.eat(exp!(Star))
        {
            let star_span = self.prev_token.span;

            let mutability = match mutbl {
                Mutability::Not => "const",
                Mutability::Mut => "mut",
            };

            let ty = self.parse_ty_no_question_mark_recover()?;

            self.dcx()
                .struct_span_err(
                    kw_span,
                    format!("raw pointer types must be written as `*{mutability} T`"),
                )
                .with_multipart_suggestion(
                    format!("put the `*` before `{mutability}`"),
                    vec![(star_span, String::new()), (kw_span.shrink_to_lo(), "*".to_string())],
                    Applicability::MachineApplicable,
                )
                .emit();

            return Ok(TyKind::Ptr(MutTy { ty, mutbl }));
        }
        // This is unreachable because we always get into if above and return from it
        unreachable!("this could never happen")
    }

    /// 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(|_, _| MgcaDisambiguation::Direct)?;

            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 `]`");

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

        let snapshot = self.create_snapshot_for_diagnostic();

        // Consume common erroneous separators.
        let hi = self.prev_token.span.hi();
        _ = self.eat(exp!(Comma)) || self.eat(exp!(Colon)) || self.eat(exp!(Star));
        let suggestion_span = self.prev_token.span.with_lo(hi);

        // FIXME(mgca): recovery is broken for `const {` args
        // we first try to parse pattern like `[u8 5]`
        let length = match self.parse_expr_anon_const(|_, _| MgcaDisambiguation::Direct) {
            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) = self.parse_pin_and_mut();
        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, patterns, or borrow modifiers.
    ///
    /// It must be either `pin const`, `pin mut`, `mut`, or nothing (immutable).
    pub(crate) fn parse_pin_and_mut(&mut self) -> (Pinnedness, Mutability) {
        if self.token.is_ident_named(sym::pin) && self.look_ahead(1, Token::is_mutability) {
            self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
            assert!(self.eat_keyword(exp!(Pin)));
            let mutbl = self.parse_const_or_mut().unwrap();
            (Pinnedness::Pinned, mutbl)
        } else {
            (Pinnedness::Not, self.parse_mutability())
        }
    }

    /// Parses the `typeof(EXPR)` for better diagnostics before returning
    /// an error type.
    fn parse_typeof_ty(&mut self, lo: Span) -> PResult<'a, TyKind> {
        self.expect(exp!(OpenParen))?;
        let _expr = self.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst)?;
        self.expect(exp!(CloseParen))?;
        let span = lo.to(self.prev_token.span);
        let guar = self
            .dcx()
            .struct_span_err(span, "`typeof` is a reserved keyword but unimplemented")
            .with_note("consider replacing `typeof(...)` with an actual type")
            .with_code(E0516)
            .emit();
        Ok(TyKind::Err(guar))
    }

    fn parse_builtin_ty(&mut self) -> PResult<'a, TyKind> {
        self.parse_builtin(|this, lo, ident| {
            Ok(match ident.name {
                sym::field_of => Some(this.parse_ty_field_of(lo)?),
                _ => None,
            })
        })
    }

    pub(crate) fn parse_ty_field_of(&mut self, _lo: Span) -> PResult<'a, TyKind> {
        let container = self.parse_ty()?;
        self.expect(exp!(Comma))?;

        let fields = self.parse_floating_field_access()?;
        let trailing_comma = self.eat_noexpect(&TokenKind::Comma);

        if let Err(mut e) = self.expect_one_of(&[], &[exp!(CloseParen)]) {
            if trailing_comma {
                e.note("unexpected third argument to field_of");
            } else {
                e.note("field_of expects dot-separated field and variant names");
            }
            e.emit();
        }

        // Eat tokens until the macro call ends.
        if self.may_recover() {
            while !self.token.kind.is_close_delim_or_eof() {
                self.bump();
            }
        }

        match *fields {
            [] => Err(self.dcx().struct_span_err(
                self.token.span,
                "`field_of!` expects dot-separated field and variant names",
            )),
            [field] => Ok(TyKind::FieldOf(container, None, field)),
            [variant, field] => Ok(TyKind::FieldOf(container, Some(variant), field)),
            _ => Err(self.dcx().struct_span_err(
                fields.iter().map(|f| f.span).collect::<Vec<_>>(),
                "`field_of!` only supports a single field or a variant with a field",
            )),
        }
    }

    /// 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)))
    }

    /// 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`

        // 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, TraitObjectSyntax::Dyn))
    }

    /// 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.can_begin_maybe_const_bound()
            || self.check_keyword(exp!(Const))
            || self.check_keyword(exp!(Async))
            || self.check_keyword(exp!(Use))
    }

    fn can_begin_maybe_const_bound(&mut self) -> bool {
        self.check(exp!(OpenBracket))
            && self.look_ahead(1, |t| t.is_keyword(kw::Const))
            && self.look_ahead(2, |t| *t == token::CloseBracket)
    }

    /// 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.can_begin_maybe_const_bound() {
            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(());
        }

        let snapshot = if self.parsing_generics {
            // The snapshot is only relevant if we're parsing the generics of an `fn` to avoid
            // incorrect recovery.
            Some(self.create_snapshot_for_diagnostic())
        } else {
            None
        };
        // Parse `(T, U) -> R`.
        let inputs_lo = self.token.span;
        let mode =
            FnParseMode { req_name: |_, _| false, context: FnContext::Free, req_body: false };
        let params = match self.parse_fn_params(&mode) {
            Ok(params) => params,
            Err(err) => {
                if let Some(snapshot) = snapshot {
                    self.restore_snapshot(snapshot);
                    err.cancel();
                    return Ok(());
                } else {
                    return Err(err);
                }
            }
        };
        let inputs: ThinVec<_> = params.into_iter().map(|input| input.ty).collect();
        let inputs_span = inputs_lo.to(self.prev_token.span);
        let output = match self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)
        {
            Ok(output) => output,
            Err(err) => {
                if let Some(snapshot) = snapshot {
                    self.restore_snapshot(snapshot);
                    err.cancel();
                    return Ok(());
                } else {
                    return Err(err);
                }
            }
        };
        let args = ast::ParenthesizedArgs {
            span: fn_path_segment.span().to(self.prev_token.span),
            inputs,
            inputs_span,
            output,
        }
        .into();

        if let Some(snapshot) = snapshot
            && ![token::Comma, token::Gt, token::Plus].contains(&self.token.kind)
        {
            // We would expect another bound or the end of type params by now. Most likely we've
            // encountered a `(` *not* representing `Trait()`, but rather the start of the `fn`'s
            // argument list where the generic param list wasn't properly closed.
            self.restore_snapshot(snapshot);
            return Ok(());
        }

        *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 is_raw == IdentIsRaw::No && ident.without_first_quote().is_reserved_lifetime() {
                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 })
    }
}
