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::{ExpTokenPair, 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_mut_or_const();

        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_mut_or_const().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()?;
        if self.token == TokenKind::Dot && self.look_ahead(1, |t| t.kind == TokenKind::OpenBrace) {
            // & [mut] <type> . { <fields> }
            //                ^
            //                we are here
            let view_start_span = self.token.span;
            self.bump();
            let fields = self
                .parse_delim_comma_seq(
                    ExpTokenPair { tok: TokenKind::OpenBrace, token_type: TokenType::OpenBrace },
                    ExpTokenPair { tok: TokenKind::CloseBrace, token_type: TokenType::CloseBrace },
                    |p| p.parse_ident(),
                )?
                .0;
            // FIXME(scrabsha): actually propagate field view in the AST.
            let _ = fields;
            let view_end_span = self.prev_token.span;
            let span = view_start_span.to(view_end_span);
            self.psess.gated_spans.gate(sym::view_types, span);
        }
        Ok(match pinned {
            Pinnedness::Not => TyKind::Ref(opt_lifetime, MutTy { ty, mutbl }),
            Pinnedness::Pinned => TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl }),
        })
    }

    /// Parse nothing, mutability or `pin` followed by "explicit" mutability.
    ///
    /// ```ebnf
    /// PinAndMut = "pin" MutOrConst | "mut"
    /// ```
    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_mut_or_const().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) && self.token.span.edition().at_least_rust_2018() {
                // 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 })
    }
}
