use super::{Parser, PathStyle};
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
use rustc_errors::{PResult, Applicability, DiagnosticBuilder};
use syntax::ast::{self, Attribute, Pat, PatKind, FieldPat, RangeEnd, RangeSyntax, Mac};
use syntax::ast::{BindingMode, Ident, Mutability, Path, QSelf, Expr, ExprKind};
use syntax::mut_visit::{noop_visit_pat, noop_visit_mac, MutVisitor};
use syntax::ptr::P;
use syntax::print::pprust;
use syntax::ThinVec;
use syntax::token;
use syntax_pos::source_map::{respan, Span, Spanned};
use syntax_pos::symbol::{kw, sym};

type Expected = Option<&'static str>;

/// `Expected` for function and lambda parameter patterns.
pub(super) const PARAM_EXPECTED: Expected = Some("parameter name");

const WHILE_PARSING_OR_MSG: &str = "while parsing this or-pattern starting here";

/// Whether or not an or-pattern should be gated when occurring in the current context.
#[derive(PartialEq)]
pub(super) enum GateOr { Yes, No }

/// Whether or not to recover a `,` when parsing or-patterns.
#[derive(PartialEq, Copy, Clone)]
enum RecoverComma { Yes, No }

impl<'a> Parser<'a> {
    /// Parses a pattern.
    ///
    /// Corresponds to `pat<no_top_alt>` in RFC 2535 and does not admit or-patterns
    /// at the top level. Used when parsing the parameters of lambda expressions,
    /// functions, function pointers, and `pat` macro fragments.
    pub fn parse_pat(&mut self, expected: Expected) -> PResult<'a, P<Pat>> {
        self.parse_pat_with_range_pat(true, expected)
    }

    /// Entry point to the main pattern parser.
    /// Corresponds to `top_pat` in RFC 2535 and allows or-pattern at the top level.
    pub(super) fn parse_top_pat(&mut self, gate_or: GateOr) -> PResult<'a, P<Pat>> {
        // Allow a '|' before the pats (RFCs 1925, 2530, and 2535).
        let gated_leading_vert = self.eat_or_separator(None) && gate_or == GateOr::Yes;
        let leading_vert_span = self.prev_span;

        // Parse the possibly-or-pattern.
        let pat = self.parse_pat_with_or(None, gate_or, RecoverComma::Yes)?;

        // If we parsed a leading `|` which should be gated,
        // and no other gated or-pattern has been parsed thus far,
        // then we should really gate the leading `|`.
        // This complicated procedure is done purely for diagnostics UX.
        if gated_leading_vert && self.sess.gated_spans.is_ungated(sym::or_patterns) {
            self.sess.gated_spans.gate(sym::or_patterns, leading_vert_span);
        }

        Ok(pat)
    }

    /// Parse the pattern for a function or function pointer parameter.
    /// Special recovery is provided for or-patterns and leading `|`.
    pub(super) fn parse_fn_param_pat(&mut self) -> PResult<'a, P<Pat>> {
        self.recover_leading_vert(None, "not allowed in a parameter pattern");
        let pat = self.parse_pat_with_or(PARAM_EXPECTED, GateOr::No, RecoverComma::No)?;

        if let PatKind::Or(..) = &pat.kind {
            self.ban_illegal_fn_param_or_pat(&pat);
        }

        Ok(pat)
    }

    /// Ban `A | B` immediately in a parameter pattern and suggest wrapping in parens.
    fn ban_illegal_fn_param_or_pat(&self, pat: &Pat) {
        let msg = "wrap the pattern in parenthesis";
        let fix = format!("({})", pprust::pat_to_string(pat));
        self.struct_span_err(pat.span, "an or-pattern parameter must be wrapped in parenthesis")
            .span_suggestion(pat.span, msg, fix, Applicability::MachineApplicable)
            .emit();
    }

    /// Parses a pattern, that may be a or-pattern (e.g. `Foo | Bar` in `Some(Foo | Bar)`).
    /// Corresponds to `pat<allow_top_alt>` in RFC 2535.
    fn parse_pat_with_or(
        &mut self,
        expected: Expected,
        gate_or: GateOr,
        rc: RecoverComma,
    ) -> PResult<'a, P<Pat>> {
        // Parse the first pattern (`p_0`).
        let first_pat = self.parse_pat(expected)?;
        self.maybe_recover_unexpected_comma(first_pat.span, rc)?;

        // If the next token is not a `|`,
        // this is not an or-pattern and we should exit here.
        if !self.check(&token::BinOp(token::Or)) && self.token != token::OrOr {
            return Ok(first_pat)
        }

        // Parse the patterns `p_1 | ... | p_n` where `n > 0`.
        let lo = first_pat.span;
        let mut pats = vec![first_pat];
        while self.eat_or_separator(Some(lo)) {
            let pat = self.parse_pat(expected).map_err(|mut err| {
                err.span_label(lo, WHILE_PARSING_OR_MSG);
                err
            })?;
            self.maybe_recover_unexpected_comma(pat.span, rc)?;
            pats.push(pat);
        }
        let or_pattern_span = lo.to(self.prev_span);

        // Feature gate the or-pattern if instructed:
        if gate_or == GateOr::Yes {
            self.sess.gated_spans.gate(sym::or_patterns, or_pattern_span);
        }

        Ok(self.mk_pat(or_pattern_span, PatKind::Or(pats)))
    }

    /// Eat the or-pattern `|` separator.
    /// If instead a `||` token is encountered, recover and pretend we parsed `|`.
    fn eat_or_separator(&mut self, lo: Option<Span>) -> bool {
        if self.recover_trailing_vert(lo) {
            return false;
        }

        match self.token.kind {
            token::OrOr => {
                // Found `||`; Recover and pretend we parsed `|`.
                self.ban_unexpected_or_or(lo);
                self.bump();
                true
            }
            _ => self.eat(&token::BinOp(token::Or)),
        }
    }

    /// Recover if `|` or `||` is the current token and we have one of the
    /// tokens `=>`, `if`, `=`, `:`, `;`, `,`, `]`, `)`, or `}` ahead of us.
    ///
    /// These tokens all indicate that we reached the end of the or-pattern
    /// list and can now reliably say that the `|` was an illegal trailing vert.
    /// Note that there are more tokens such as `@` for which we know that the `|`
    /// is an illegal parse. However, the user's intent is less clear in that case.
    fn recover_trailing_vert(&mut self, lo: Option<Span>) -> bool {
        let is_end_ahead = self.look_ahead(1, |token| match &token.kind {
            token::FatArrow // e.g. `a | => 0,`.
            | token::Ident(kw::If, false) // e.g. `a | if expr`.
            | token::Eq // e.g. `let a | = 0`.
            | token::Semi // e.g. `let a |;`.
            | token::Colon // e.g. `let a | :`.
            | token::Comma // e.g. `let (a |,)`.
            | token::CloseDelim(token::Bracket) // e.g. `let [a | ]`.
            | token::CloseDelim(token::Paren) // e.g. `let (a | )`.
            | token::CloseDelim(token::Brace) => true, // e.g. `let A { f: a | }`.
            _ => false,
        });
        match (is_end_ahead, &self.token.kind) {
            (true, token::BinOp(token::Or)) | (true, token::OrOr) => {
                self.ban_illegal_vert(lo, "trailing", "not allowed in an or-pattern");
                self.bump();
                true
            }
            _ => false,
        }
    }

    /// We have parsed `||` instead of `|`. Error and suggest `|` instead.
    fn ban_unexpected_or_or(&mut self, lo: Option<Span>) {
        let mut err = self.struct_span_err(self.token.span, "unexpected token `||` after pattern");
        err.span_suggestion(
            self.token.span,
            "use a single `|` to separate multiple alternative patterns",
            "|".to_owned(),
            Applicability::MachineApplicable
        );
        if let Some(lo) = lo {
            err.span_label(lo, WHILE_PARSING_OR_MSG);
        }
        err.emit();
    }

    /// Some special error handling for the "top-level" patterns in a match arm,
    /// `for` loop, `let`, &c. (in contrast to subpatterns within such).
    fn maybe_recover_unexpected_comma(&mut self, lo: Span, rc: RecoverComma) -> PResult<'a, ()> {
        if rc == RecoverComma::No || self.token != token::Comma {
            return Ok(());
        }

        // An unexpected comma after a top-level pattern is a clue that the
        // user (perhaps more accustomed to some other language) forgot the
        // parentheses in what should have been a tuple pattern; return a
        // suggestion-enhanced error here rather than choking on the comma later.
        let comma_span = self.token.span;
        self.bump();
        if let Err(mut err) = self.skip_pat_list() {
            // We didn't expect this to work anyway; we just wanted to advance to the
            // end of the comma-sequence so we know the span to suggest parenthesizing.
            err.cancel();
        }
        let seq_span = lo.to(self.prev_span);
        let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern");
        if let Ok(seq_snippet) = self.span_to_snippet(seq_span) {
            err.span_suggestion(
                seq_span,
                "try adding parentheses to match on a tuple..",
                format!("({})", seq_snippet),
                Applicability::MachineApplicable
            )
            .span_suggestion(
                seq_span,
                "..or a vertical bar to match on multiple alternatives",
                format!("{}", seq_snippet.replace(",", " |")),
                Applicability::MachineApplicable
            );
        }
        Err(err)
    }

    /// Parse and throw away a parentesized comma separated
    /// sequence of patterns until `)` is reached.
    fn skip_pat_list(&mut self) -> PResult<'a, ()> {
        while !self.check(&token::CloseDelim(token::Paren)) {
            self.parse_pat(None)?;
            if !self.eat(&token::Comma) {
                return Ok(())
            }
        }
        Ok(())
    }

    /// Recursive possibly-or-pattern parser with recovery for an erroneous leading `|`.
    /// See `parse_pat_with_or` for details on parsing or-patterns.
    fn parse_pat_with_or_inner(&mut self) -> PResult<'a, P<Pat>> {
        self.recover_leading_vert(None, "only allowed in a top-level pattern");
        self.parse_pat_with_or(None, GateOr::Yes, RecoverComma::No)
    }

    /// Recover if `|` or `||` is here.
    /// The user is thinking that a leading `|` is allowed in this position.
    fn recover_leading_vert(&mut self, lo: Option<Span>, ctx: &str) {
        if let token::BinOp(token::Or) | token::OrOr = self.token.kind {
            self.ban_illegal_vert(lo, "leading", ctx);
            self.bump();
        }
    }

    /// A `|` or possibly `||` token shouldn't be here. Ban it.
    fn ban_illegal_vert(&mut self, lo: Option<Span>, pos: &str, ctx: &str) {
        let span = self.token.span;
        let mut err = self.struct_span_err(span, &format!("a {} `|` is {}", pos, ctx));
        err.span_suggestion(
            span,
            &format!("remove the `{}`", pprust::token_to_string(&self.token)),
            String::new(),
            Applicability::MachineApplicable,
        );
        if let Some(lo) = lo {
            err.span_label(lo, WHILE_PARSING_OR_MSG);
        }
        if let token::OrOr = self.token.kind {
            err.note("alternatives in or-patterns are separated with `|`, not `||`");
        }
        err.emit();
    }

    /// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are
    /// allowed).
    fn parse_pat_with_range_pat(
        &mut self,
        allow_range_pat: bool,
        expected: Expected,
    ) -> PResult<'a, P<Pat>> {
        maybe_recover_from_interpolated_ty_qpath!(self, true);
        maybe_whole!(self, NtPat, |x| x);

        let lo = self.token.span;
        let pat = match self.token.kind {
            token::BinOp(token::And) | token::AndAnd => self.parse_pat_deref(expected)?,
            token::OpenDelim(token::Paren) => self.parse_pat_tuple_or_parens()?,
            token::OpenDelim(token::Bracket) => {
                // Parse `[pat, pat,...]` as a slice pattern.
                let (pats, _) = self.parse_delim_comma_seq(
                    token::Bracket,
                    |p| p.parse_pat_with_or_inner(),
                )?;
                PatKind::Slice(pats)
            }
            token::DotDot => {
                self.bump();
                if self.is_pat_range_end_start() {
                    // Parse `..42` for recovery.
                    self.parse_pat_range_to(RangeEnd::Excluded, "..")?
                } else {
                    // A rest pattern `..`.
                    PatKind::Rest
                }
            }
            token::DotDotEq => {
                // Parse `..=42` for recovery.
                self.bump();
                self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotEq), "..=")?
            }
            token::DotDotDot => {
                // Parse `...42` for recovery.
                self.bump();
                self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotDot), "...")?
            }
            // At this point, token != `&`, `&&`, `(`, `[`, `..`, `..=`, or `...`.
            _ => if self.eat_keyword(kw::Underscore) {
                // Parse _
                PatKind::Wild
            } else if self.eat_keyword(kw::Mut) {
                self.parse_pat_ident_mut()?
            } else if self.eat_keyword(kw::Ref) {
                // Parse ref ident @ pat / ref mut ident @ pat
                let mutbl = self.parse_mutability();
                self.parse_pat_ident(BindingMode::ByRef(mutbl))?
            } else if self.eat_keyword(kw::Box) {
                // Parse `box pat`
                let pat = self.parse_pat_with_range_pat(false, None)?;
                self.sess.gated_spans.gate(sym::box_patterns, lo.to(self.prev_span));
                PatKind::Box(pat)
            } else if self.can_be_ident_pat() {
                // Parse `ident @ pat`
                // This can give false positives and parse nullary enums,
                // they are dealt with later in resolve.
                self.parse_pat_ident(BindingMode::ByValue(Mutability::Immutable))?
            } else if self.is_start_of_pat_with_path() {
                // Parse pattern starting with a path
                let (qself, path) = if self.eat_lt() {
                    // Parse a qualified path
                    let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
                    (Some(qself), path)
                } else {
                    // Parse an unqualified path
                    (None, self.parse_path(PathStyle::Expr)?)
                };
                match self.token.kind {
                    token::Not if qself.is_none() => self.parse_pat_mac_invoc(path)?,
                    token::DotDotDot | token::DotDotEq | token::DotDot => {
                        self.parse_pat_range_starting_with_path(lo, qself, path)?
                    }
                    token::OpenDelim(token::Brace) => self.parse_pat_struct(qself, path)?,
                    token::OpenDelim(token::Paren) => self.parse_pat_tuple_struct(qself, path)?,
                    _ => PatKind::Path(qself, path),
                }
            } else {
                // Try to parse everything else as literal with optional minus
                match self.parse_literal_maybe_minus() {
                    Ok(begin)
                        if self.check(&token::DotDot)
                            || self.check(&token::DotDotEq)
                            || self.check(&token::DotDotDot) =>
                    {
                        self.parse_pat_range_starting_with_lit(begin)?
                    }
                    Ok(begin) => PatKind::Lit(begin),
                    Err(err) => return self.fatal_unexpected_non_pat(err, expected),
                }
            }
        };

        let pat = self.mk_pat(lo.to(self.prev_span), pat);
        let pat = self.maybe_recover_from_bad_qpath(pat, true)?;
        let pat = self.recover_intersection_pat(pat)?;

        if !allow_range_pat {
            self.ban_pat_range_if_ambiguous(&pat)?
        }

        Ok(pat)
    }

    /// Try to recover the more general form `intersect ::= $pat_lhs @ $pat_rhs`.
    ///
    /// Allowed binding patterns generated by `binding ::= ref? mut? $ident @ $pat_rhs`
    /// should already have been parsed by now  at this point,
    /// if the next token is `@` then we can try to parse the more general form.
    ///
    /// Consult `parse_pat_ident` for the `binding` grammar.
    ///
    /// The notion of intersection patterns are found in
    /// e.g. [F#][and] where they are called AND-patterns.
    ///
    /// [and]: https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/pattern-matching
    fn recover_intersection_pat(&mut self, lhs: P<Pat>) -> PResult<'a, P<Pat>> {
        if self.token.kind != token::At {
            // Next token is not `@` so it's not going to be an intersection pattern.
            return Ok(lhs);
        }

        // At this point we attempt to parse `@ $pat_rhs` and emit an error.
        self.bump(); // `@`
        let mut rhs = self.parse_pat(None)?;
        let sp = lhs.span.to(rhs.span);

        if let PatKind::Ident(_, _, ref mut sub @ None) = rhs.kind {
            // The user inverted the order, so help them fix that.
            let mut applicability = Applicability::MachineApplicable;
            lhs.walk(&mut |p| match p.kind {
                // `check_match` is unhappy if the subpattern has a binding anywhere.
                PatKind::Ident(..) => {
                    applicability = Applicability::MaybeIncorrect;
                    false // Short-circuit.
                },
                _ => true,
            });

            let lhs_span = lhs.span;
            // Move the LHS into the RHS as a subpattern.
            // The RHS is now the full pattern.
            *sub = Some(lhs);

            self.struct_span_err(sp, "pattern on wrong side of `@`")
                .span_label(lhs_span, "pattern on the left, should be on the right")
                .span_label(rhs.span, "binding on the right, should be on the left")
                .span_suggestion(sp, "switch the order", pprust::pat_to_string(&rhs), applicability)
                .emit();
        } else {
            // The special case above doesn't apply so we may have e.g. `A(x) @ B(y)`.
            rhs.kind = PatKind::Wild;
            self.struct_span_err(sp, "left-hand side of `@` must be a binding")
                .span_label(lhs.span, "interpreted as a pattern, not a binding")
                .span_label(rhs.span, "also a pattern")
                .note("bindings are `x`, `mut x`, `ref x`, and `ref mut x`")
                .emit();
        }

        rhs.span = sp;
        Ok(rhs)
    }

    /// Ban a range pattern if it has an ambiguous interpretation.
    fn ban_pat_range_if_ambiguous(&self, pat: &Pat) -> PResult<'a, ()> {
        match pat.kind {
            PatKind::Range(
                .., Spanned { node: RangeEnd::Included(RangeSyntax::DotDotDot), .. }
            ) => return Ok(()),
            PatKind::Range(..) => {}
            _ => return Ok(()),
        }

        let mut err = self.struct_span_err(
            pat.span,
            "the range pattern here has ambiguous interpretation",
        );
        err.span_suggestion(
            pat.span,
            "add parentheses to clarify the precedence",
            format!("({})", pprust::pat_to_string(&pat)),
            // "ambiguous interpretation" implies that we have to be guessing
            Applicability::MaybeIncorrect
        );
        Err(err)
    }

    /// Parse `&pat` / `&mut pat`.
    fn parse_pat_deref(&mut self, expected: Expected) -> PResult<'a, PatKind> {
        self.expect_and()?;
        let mutbl = self.parse_mutability();

        if let token::Lifetime(name) = self.token.kind {
            let mut err = self.fatal(&format!("unexpected lifetime `{}` in pattern", name));
            err.span_label(self.token.span, "unexpected lifetime");
            return Err(err);
        }

        let subpat = self.parse_pat_with_range_pat(false, expected)?;
        Ok(PatKind::Ref(subpat, mutbl))
    }

    /// Parse a tuple or parenthesis pattern.
    fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> {
        let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or_inner())?;

        // Here, `(pat,)` is a tuple pattern.
        // For backward compatibility, `(..)` is a tuple pattern as well.
        Ok(if fields.len() == 1 && !(trailing_comma || fields[0].is_rest()) {
            PatKind::Paren(fields.into_iter().nth(0).unwrap())
        } else {
            PatKind::Tuple(fields)
        })
    }

    /// Parse a mutable binding with the `mut` token already eaten.
    fn parse_pat_ident_mut(&mut self) -> PResult<'a, PatKind> {
        let mut_span = self.prev_span;

        if self.eat_keyword(kw::Ref) {
            return self.recover_mut_ref_ident(mut_span)
        }

        self.recover_additional_muts();

        // Make sure we don't allow e.g. `let mut $p;` where `$p:pat`.
        if let token::Interpolated(ref nt) = self.token.kind {
             if let token::NtPat(_) = **nt {
                 self.expected_ident_found().emit();
             }
        }

        // Parse the pattern we hope to be an identifier.
        let mut pat = self.parse_pat(Some("identifier"))?;

        // Add `mut` to any binding in the parsed pattern.
        let changed_any_binding = Self::make_all_value_bindings_mutable(&mut pat);

        // Unwrap; If we don't have `mut $ident`, error.
        let pat = pat.into_inner();
        match &pat.kind {
            PatKind::Ident(..) => {}
            _ => self.ban_mut_general_pat(mut_span, &pat, changed_any_binding),
        }

        Ok(pat.kind)
    }

    /// Recover on `mut ref? ident @ pat` and suggest
    /// that the order of `mut` and `ref` is incorrect.
    fn recover_mut_ref_ident(&mut self, lo: Span) -> PResult<'a, PatKind> {
        let mutref_span = lo.to(self.prev_span);
        self.struct_span_err(mutref_span, "the order of `mut` and `ref` is incorrect")
            .span_suggestion(
                mutref_span,
                "try switching the order",
                "ref mut".into(),
                Applicability::MachineApplicable
            )
            .emit();

        self.parse_pat_ident(BindingMode::ByRef(Mutability::Mutable))
    }

    /// Turn all by-value immutable bindings in a pattern into mutable bindings.
    /// Returns `true` if any change was made.
    fn make_all_value_bindings_mutable(pat: &mut P<Pat>) -> bool {
        struct AddMut(bool);
        impl MutVisitor for AddMut {
            fn visit_mac(&mut self, mac: &mut Mac) {
                noop_visit_mac(mac, self);
            }

            fn visit_pat(&mut self, pat: &mut P<Pat>) {
                if let PatKind::Ident(BindingMode::ByValue(ref mut m @ Mutability::Immutable), ..)
                    = pat.kind
                {
                    *m = Mutability::Mutable;
                    self.0 = true;
                }
                noop_visit_pat(pat, self);
            }
        }

        let mut add_mut = AddMut(false);
        add_mut.visit_pat(pat);
        add_mut.0
    }

    /// Error on `mut $pat` where `$pat` is not an ident.
    fn ban_mut_general_pat(&self, lo: Span, pat: &Pat, changed_any_binding: bool) {
        let span = lo.to(pat.span);
        let fix = pprust::pat_to_string(&pat);
        let (problem, suggestion) = if changed_any_binding {
            ("`mut` must be attached to each individual binding", "add `mut` to each binding")
        } else {
            ("`mut` must be followed by a named binding", "remove the `mut` prefix")
        };
        self.struct_span_err(span, problem)
            .span_suggestion(span, suggestion, fix, Applicability::MachineApplicable)
            .note("`mut` may be followed by `variable` and `variable @ pattern`")
            .emit()
    }

    /// Eat any extraneous `mut`s and error + recover if we ate any.
    fn recover_additional_muts(&mut self) {
        let lo = self.token.span;
        while self.eat_keyword(kw::Mut) {}
        if lo == self.token.span {
            return;
        }

        let span = lo.to(self.prev_span);
        self.struct_span_err(span, "`mut` on a binding may not be repeated")
            .span_suggestion(
                span,
                "remove the additional `mut`s",
                String::new(),
                Applicability::MachineApplicable,
            )
            .emit();
    }

    /// Parse macro invocation
    fn parse_pat_mac_invoc(&mut self, path: Path) -> PResult<'a, PatKind> {
        self.bump();
        let args = self.parse_mac_args()?;
        let mac = Mac {
            path,
            args,
            prior_type_ascription: self.last_type_ascription,
        };
        Ok(PatKind::Mac(mac))
    }

    fn excluded_range_end(&self, span: Span) -> RangeEnd {
        self.sess.gated_spans.gate(sym::exclusive_range_pattern, span);
        RangeEnd::Excluded
    }

    /// Parse a range pattern `$path $form $end?` where `$form = ".." | "..." | "..=" ;`.
    /// The `$path` has already been parsed and the next token is the `$form`.
    fn parse_pat_range_starting_with_path(
        &mut self,
        lo: Span,
        qself: Option<QSelf>,
        path: Path
    ) -> PResult<'a, PatKind> {
        let (end_kind, form) = match self.token.kind {
            token::DotDot => (self.excluded_range_end(self.token.span), ".."),
            token::DotDotDot => (RangeEnd::Included(RangeSyntax::DotDotDot), "..."),
            token::DotDotEq => (RangeEnd::Included(RangeSyntax::DotDotEq), "..="),
            _ => panic!("can only parse `..`/`...`/`..=` for ranges (checked above)"),
        };
        let op_span = self.token.span;
        // Parse range
        let span = lo.to(self.prev_span);
        let begin = self.mk_expr(span, ExprKind::Path(qself, path), ThinVec::new());
        self.bump();
        let end = self.parse_pat_range_end_opt(&begin, form)?;
        Ok(PatKind::Range(begin, end, respan(op_span, end_kind)))
    }

    /// Parse a range pattern `$literal $form $end?` where `$form = ".." | "..." | "..=" ;`.
    /// The `$path` has already been parsed and the next token is the `$form`.
    fn parse_pat_range_starting_with_lit(&mut self, begin: P<Expr>) -> PResult<'a, PatKind> {
        let op_span = self.token.span;
        let (end_kind, form) = if self.eat(&token::DotDotDot) {
            (RangeEnd::Included(RangeSyntax::DotDotDot), "...")
        } else if self.eat(&token::DotDotEq) {
            (RangeEnd::Included(RangeSyntax::DotDotEq), "..=")
        } else if self.eat(&token::DotDot) {
            (self.excluded_range_end(op_span), "..")
        } else {
            panic!("impossible case: we already matched on a range-operator token")
        };
        let end = self.parse_pat_range_end_opt(&begin, form)?;
        Ok(PatKind::Range(begin, end, respan(op_span, end_kind)))
    }

    fn fatal_unexpected_non_pat(
        &mut self,
        mut err: DiagnosticBuilder<'a>,
        expected: Expected,
    ) -> PResult<'a, P<Pat>> {
        err.cancel();

        let expected = expected.unwrap_or("pattern");
        let msg = format!("expected {}, found {}", expected, self.this_token_descr());

        let mut err = self.fatal(&msg);
        err.span_label(self.token.span, format!("expected {}", expected));

        let sp = self.sess.source_map().start_point(self.token.span);
        if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) {
            self.sess.expr_parentheses_needed(&mut err, *sp, None);
        }

        Err(err)
    }

    /// Is the current token suitable as the start of a range patterns end?
    fn is_pat_range_end_start(&self) -> bool {
        self.token.is_path_start() // e.g. `MY_CONST`;
            || self.token == token::Dot // e.g. `.5` for recovery;
            || self.token.can_begin_literal_or_bool() // e.g. `42`.
            || self.token.is_whole_expr()
    }

    /// Parse a range-to pattern, e.g. `..X` and `..=X` for recovery.
    fn parse_pat_range_to(&mut self, re: RangeEnd, form: &str) -> PResult<'a, PatKind> {
        let lo = self.prev_span;
        let end = self.parse_pat_range_end()?;
        let range_span = lo.to(end.span);
        let begin = self.mk_expr(range_span, ExprKind::Err, ThinVec::new());

        self.diagnostic()
            .struct_span_err(range_span, &format!("`{}X` range patterns are not supported", form))
            .span_suggestion(
                range_span,
                "try using the minimum value for the type",
                format!("MIN{}{}", form, pprust::expr_to_string(&end)),
                Applicability::HasPlaceholders,
            )
            .emit();

        Ok(PatKind::Range(begin, end, respan(lo, re)))
    }

    /// Parse the end of a `X..Y`, `X..=Y`, or `X...Y` range pattern  or recover
    /// if that end is missing treating it as `X..`, `X..=`, or `X...` respectively.
    fn parse_pat_range_end_opt(&mut self, begin: &Expr, form: &str) -> PResult<'a, P<Expr>> {
        if self.is_pat_range_end_start() {
            // Parsing e.g. `X..=Y`.
            self.parse_pat_range_end()
        } else {
            // Parsing e.g. `X..`.
            let range_span = begin.span.to(self.prev_span);

            self.diagnostic()
                .struct_span_err(
                    range_span,
                    &format!("`X{}` range patterns are not supported", form),
                )
                .span_suggestion(
                    range_span,
                    "try using the maximum value for the type",
                    format!("{}{}MAX", pprust::expr_to_string(&begin), form),
                    Applicability::HasPlaceholders,
                )
                .emit();

            Ok(self.mk_expr(range_span, ExprKind::Err, ThinVec::new()))
        }
    }

    fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> {
        if self.token.is_path_start() {
            let lo = self.token.span;
            let (qself, path) = if self.eat_lt() {
                // Parse a qualified path
                let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
                (Some(qself), path)
            } else {
                // Parse an unqualified path
                (None, self.parse_path(PathStyle::Expr)?)
            };
            let hi = self.prev_span;
            Ok(self.mk_expr(lo.to(hi), ExprKind::Path(qself, path), ThinVec::new()))
        } else {
            self.parse_literal_maybe_minus()
        }
    }

    /// Is this the start of a pattern beginning with a path?
    fn is_start_of_pat_with_path(&mut self) -> bool {
        self.check_path()
        // Just for recovery (see `can_be_ident`).
        || self.token.is_ident() && !self.token.is_bool_lit() && !self.token.is_keyword(kw::In)
    }

    /// Would `parse_pat_ident` be appropriate here?
    fn can_be_ident_pat(&mut self) -> bool {
        self.check_ident()
        && !self.token.is_bool_lit() // Avoid `true` or `false` as a binding as it is a literal.
        && !self.token.is_path_segment_keyword() // Avoid e.g. `Self` as it is a path.
        // Avoid `in`. Due to recovery in the list parser this messes with `for ( $pat in $expr )`.
        && !self.token.is_keyword(kw::In)
        && self.look_ahead(1, |t| match t.kind { // Try to do something more complex?
            token::OpenDelim(token::Paren) // A tuple struct pattern.
            | token::OpenDelim(token::Brace) // A struct pattern.
            | token::DotDotDot | token::DotDotEq | token::DotDot // A range pattern.
            | token::ModSep // A tuple / struct variant pattern.
            | token::Not => false, // A macro expanding to a pattern.
            _ => true,
        })
    }

    /// Parses `ident` or `ident @ pat`.
    /// Used by the copy foo and ref foo patterns to give a good
    /// error message when parsing mistakes like `ref foo(a, b)`.
    fn parse_pat_ident(&mut self, binding_mode: BindingMode) -> PResult<'a, PatKind> {
        let ident = self.parse_ident()?;
        let sub = if self.eat(&token::At) {
            Some(self.parse_pat(Some("binding pattern"))?)
        } else {
            None
        };

        // Just to be friendly, if they write something like `ref Some(i)`,
        // we end up here with `(` as the current token.
        // This shortly leads to a parse error. Note that if there is no explicit
        // binding mode then we do not end up here, because the lookahead
        // will direct us over to `parse_enum_variant()`.
        if self.token == token::OpenDelim(token::Paren) {
            return Err(self.span_fatal(
                self.prev_span,
                "expected identifier, found enum pattern",
            ))
        }

        Ok(PatKind::Ident(binding_mode, ident, sub))
    }

    /// Parse a struct ("record") pattern (e.g. `Foo { ... }` or `Foo::Bar { ... }`).
    fn parse_pat_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
        if qself.is_some() {
            let msg = "unexpected `{` after qualified path";
            let mut err = self.fatal(msg);
            err.span_label(self.token.span, msg);
            return Err(err);
        }

        self.bump();
        let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| {
            e.emit();
            self.recover_stmt();
            (vec![], true)
        });
        self.bump();
        Ok(PatKind::Struct(path, fields, etc))
    }

    /// Parse tuple struct or tuple variant pattern (e.g. `Foo(...)` or `Foo::Bar(...)`).
    fn parse_pat_tuple_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
        if qself.is_some() {
            let msg = "unexpected `(` after qualified path";
            let mut err = self.fatal(msg);
            err.span_label(self.token.span, msg);
            return Err(err);
        }
        let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or_inner())?;
        Ok(PatKind::TupleStruct(path, fields))
    }

    /// Parses the fields of a struct-like pattern.
    fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<FieldPat>, bool)> {
        let mut fields = Vec::new();
        let mut etc = false;
        let mut ate_comma = true;
        let mut delayed_err: Option<DiagnosticBuilder<'a>> = None;
        let mut etc_span = None;

        while self.token != token::CloseDelim(token::Brace) {
            let attrs = match self.parse_outer_attributes() {
                Ok(attrs) => attrs,
                Err(err) => {
                    if let Some(mut delayed) = delayed_err {
                        delayed.emit();
                    }
                    return Err(err);
                },
            };
            let lo = self.token.span;

            // check that a comma comes after every field
            if !ate_comma {
                let err = self.struct_span_err(self.prev_span, "expected `,`");
                if let Some(mut delayed) = delayed_err {
                    delayed.emit();
                }
                return Err(err);
            }
            ate_comma = false;

            if self.check(&token::DotDot) || self.token == token::DotDotDot {
                etc = true;
                let mut etc_sp = self.token.span;

                self.recover_one_fewer_dotdot();
                self.bump();  // `..` || `...`

                if self.token == token::CloseDelim(token::Brace) {
                    etc_span = Some(etc_sp);
                    break;
                }
                let token_str = self.this_token_descr();
                let mut err = self.fatal(&format!("expected `}}`, found {}", token_str));

                err.span_label(self.token.span, "expected `}`");
                let mut comma_sp = None;
                if self.token == token::Comma { // Issue #49257
                    let nw_span = self.sess.source_map().span_until_non_whitespace(self.token.span);
                    etc_sp = etc_sp.to(nw_span);
                    err.span_label(etc_sp,
                                   "`..` must be at the end and cannot have a trailing comma");
                    comma_sp = Some(self.token.span);
                    self.bump();
                    ate_comma = true;
                }

                etc_span = Some(etc_sp.until(self.token.span));
                if self.token == token::CloseDelim(token::Brace) {
                    // If the struct looks otherwise well formed, recover and continue.
                    if let Some(sp) = comma_sp {
                        err.span_suggestion_short(
                            sp,
                            "remove this comma",
                            String::new(),
                            Applicability::MachineApplicable,
                        );
                    }
                    err.emit();
                    break;
                } else if self.token.is_ident() && ate_comma {
                    // Accept fields coming after `..,`.
                    // This way we avoid "pattern missing fields" errors afterwards.
                    // We delay this error until the end in order to have a span for a
                    // suggested fix.
                    if let Some(mut delayed_err) = delayed_err {
                        delayed_err.emit();
                        return Err(err);
                    } else {
                        delayed_err = Some(err);
                    }
                } else {
                    if let Some(mut err) = delayed_err {
                        err.emit();
                    }
                    return Err(err);
                }
            }

            fields.push(match self.parse_pat_field(lo, attrs) {
                Ok(field) => field,
                Err(err) => {
                    if let Some(mut delayed_err) = delayed_err {
                        delayed_err.emit();
                    }
                    return Err(err);
                }
            });
            ate_comma = self.eat(&token::Comma);
        }

        if let Some(mut err) = delayed_err {
            if let Some(etc_span) = etc_span {
                err.multipart_suggestion(
                    "move the `..` to the end of the field list",
                    vec![
                        (etc_span, String::new()),
                        (self.token.span, format!("{}.. }}", if ate_comma { "" } else { ", " })),
                    ],
                    Applicability::MachineApplicable,
                );
            }
            err.emit();
        }
        return Ok((fields, etc));
    }

    /// Recover on `...` as if it were `..` to avoid further errors.
    /// See issue #46718.
    fn recover_one_fewer_dotdot(&self) {
        if self.token != token::DotDotDot {
            return;
        }

        self.struct_span_err(self.token.span, "expected field pattern, found `...`")
            .span_suggestion(
                self.token.span,
                "to omit remaining fields, use one fewer `.`",
                "..".to_owned(),
                Applicability::MachineApplicable
            )
            .emit();
    }

    fn parse_pat_field(&mut self, lo: Span, attrs: Vec<Attribute>) -> PResult<'a, FieldPat> {
        // Check if a colon exists one ahead. This means we're parsing a fieldname.
        let hi;
        let (subpat, fieldname, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) {
            // Parsing a pattern of the form `fieldname: pat`.
            let fieldname = self.parse_field_name()?;
            self.bump();
            let pat = self.parse_pat_with_or_inner()?;
            hi = pat.span;
            (pat, fieldname, false)
        } else {
            // Parsing a pattern of the form `(box) (ref) (mut) fieldname`.
            let is_box = self.eat_keyword(kw::Box);
            let boxed_span = self.token.span;
            let is_ref = self.eat_keyword(kw::Ref);
            let is_mut = self.eat_keyword(kw::Mut);
            let fieldname = self.parse_ident()?;
            hi = self.prev_span;

            let bind_type = match (is_ref, is_mut) {
                (true, true) => BindingMode::ByRef(Mutability::Mutable),
                (true, false) => BindingMode::ByRef(Mutability::Immutable),
                (false, true) => BindingMode::ByValue(Mutability::Mutable),
                (false, false) => BindingMode::ByValue(Mutability::Immutable),
            };

            let fieldpat = self.mk_pat_ident(boxed_span.to(hi), bind_type, fieldname);
            let subpat = if is_box {
                self.mk_pat(lo.to(hi), PatKind::Box(fieldpat))
            } else {
                fieldpat
            };
            (subpat, fieldname, true)
        };

        Ok(FieldPat {
            ident: fieldname,
            pat: subpat,
            is_shorthand,
            attrs: attrs.into(),
            id: ast::DUMMY_NODE_ID,
            span: lo.to(hi),
            is_placeholder: false,
        })
    }

    pub(super) fn mk_pat_ident(&self, span: Span, bm: BindingMode, ident: Ident) -> P<Pat> {
        self.mk_pat(span, PatKind::Ident(bm, ident, None))
    }

    fn mk_pat(&self, span: Span, kind: PatKind) -> P<Pat> {
        P(Pat { kind, span, id: ast::DUMMY_NODE_ID })
    }
}
