fn attempt_chained_comparison_suggestion(
        &mut self,
        err: &mut DiagnosticBuilder<'_>,
        inner_op: &Expr,
        outer_op: &Spanned<AssocOp>,
    ) -> bool /* advanced the cursor */ {
        if let ExprKind::Binary(op, ref l1, ref r1) = inner_op.kind {
            if let ExprKind::Field(_, ident) = l1.kind {
                if ident.as_str().parse::<i32>().is_err() && !matches!(r1.kind, ExprKind::Lit(_)) {
                    // The parser has encountered `foo.bar<baz`, the likelihood of the turbofish
                    // suggestion being the only one to apply is high.
                    return false;
                }
            }
            let mut enclose = |left: Span, right: Span| {
                err.multipart_suggestion(
                    "parenthesize the comparison",
                    vec![
                        (left.shrink_to_lo(), "(".to_string()),
                        (right.shrink_to_hi(), ")".to_string()),
                    ],
                    Applicability::MaybeIncorrect,
                );
            };
            return match (op.node, &outer_op.node) {
                // `x == y == z`
                (BinOpKind::Eq, AssocOp::Equal) |
                // `x < y < z` and friends.
                (BinOpKind::Lt, AssocOp::Less | AssocOp::LessEqual) |
                (BinOpKind::Le, AssocOp::LessEqual | AssocOp::Less) |
                // `x > y > z` and friends.
                (BinOpKind::Gt, AssocOp::Greater | AssocOp::GreaterEqual) |
                (BinOpKind::Ge, AssocOp::GreaterEqual | AssocOp::Greater) => {
                    let expr_to_str = |e: &Expr| {
                        self.span_to_snippet(e.span)
                            .unwrap_or_else(|_| pprust::expr_to_string(&e))
                    };
                    err.span_suggestion_verbose(
                        inner_op.span.shrink_to_hi(),
                        "split the comparison into two",
                        format!(" && {}", expr_to_str(&r1)),
                        Applicability::MaybeIncorrect,
                    );
                    false // Keep the current parse behavior, where the AST is `(x < y) < z`.
                }
                // `x == y < z`
                (BinOpKind::Eq, AssocOp::Less | AssocOp::LessEqual | AssocOp::Greater | AssocOp::GreaterEqual) => {
                    // Consume `z`/outer-op-rhs.
                    let snapshot = self.clone();
                    match self.parse_expr() {
                        Ok(r2) => {
                            // We are sure that outer-op-rhs could be consumed, the suggestion is
                            // likely correct.
                            enclose(r1.span, r2.span);
                            true
                        }
                        Err(mut expr_err) => {
                            expr_err.cancel();
                            *self = snapshot;
                            false
                        }
                    }
                }
                // `x > y == z`
                (BinOpKind::Lt | BinOpKind::Le | BinOpKind::Gt | BinOpKind::Ge, AssocOp::Equal) => {
                    let snapshot = self.clone();
                    // At this point it is always valid to enclose the lhs in parentheses, no
                    // further checks are necessary.
                    match self.parse_expr() {
                        Ok(_) => {
                            enclose(l1.span, r1.span);
                            true
                        }
                        Err(mut expr_err) => {
                            expr_err.cancel();
                            *self = snapshot;
                            false
                        }
                    }
                }
                _ => false,
            };
        }
        false
    }
/// Check to see if a pair of chained operators looks like an attempt at chained comparison,
/// e.g. `1 < x <= 3`. If so, suggest either splitting the comparison into two, or
/// parenthesising the leftmost comparison.
Check to see if a pair of chained operators looks like an attempt at chained comparison,
e.g.
Check to see if a pair of chained operators looks like an attempt at chained comparison e . g .
fn attempt_chained_comparison_suggestion(
        &mut self,
        err: &mut DiagnosticBuilder<'_>,
        inner_op: &Expr,
        outer_op: &Spanned<AssocOp>,
    ) -> bool /* advanced the cursor */ {
        if let ExprKind::Binary(op, ref l1, ref r1) = inner_op.kind {
            if let ExprKind::Field(_, ident) = l1.kind {
                if ident.as_str().parse::<i32>().is_err() && !matches!(r1.kind, ExprKind::Lit(_)) {
                    // The parser has encountered `foo.bar<baz`, the likelihood of the turbofish
                    // suggestion being the only one to apply is high.
                    return false;
                }
            }
            let mut enclose = |left: Span, right: Span| {
                err.multipart_suggestion(
                    "parenthesize the comparison",
                    vec![
                        (left.shrink_to_lo(), "(".to_string()),
                        (right.shrink_to_hi(), ")".to_string()),
                    ],
                    Applicability::MaybeIncorrect,
                );
            };
            return match (op.node, &outer_op.node) {
                // `x == y == z`
                (BinOpKind::Eq, AssocOp::Equal) |
                // `x < y < z` and friends.
                (BinOpKind::Lt, AssocOp::Less | AssocOp::LessEqual) |
                (BinOpKind::Le, AssocOp::LessEqual | AssocOp::Less) |
                // `x > y > z` and friends.
                (BinOpKind::Gt, AssocOp::Greater | AssocOp::GreaterEqual) |
                (BinOpKind::Ge, AssocOp::GreaterEqual | AssocOp::Greater) => {
                    let expr_to_str = |e: &Expr| {
                        self.span_to_snippet(e.span)
                            .unwrap_or_else(|_| pprust::expr_to_string(&e))
                    };
                    err.span_suggestion_verbose(
                        inner_op.span.shrink_to_hi(),
                        "split the comparison into two",
                        format!(" && {}", expr_to_str(&r1)),
                        Applicability::MaybeIncorrect,
                    );
                    false // Keep the current parse behavior, where the AST is `(x < y) < z`.
                }
                // `x == y < z`
                (BinOpKind::Eq, AssocOp::Less | AssocOp::LessEqual | AssocOp::Greater | AssocOp::GreaterEqual) => {
                    // Consume `z`/outer-op-rhs.
                    let snapshot = self.clone();
                    match self.parse_expr() {
                        Ok(r2) => {
                            // We are sure that outer-op-rhs could be consumed, the suggestion is
                            // likely correct.
                            enclose(r1.span, r2.span);
                            true
                        }
                        Err(mut expr_err) => {
                            expr_err.cancel();
                            *self = snapshot;
                            false
                        }
                    }
                }
                // `x > y == z`
                (BinOpKind::Lt | BinOpKind::Le | BinOpKind::Gt | BinOpKind::Ge, AssocOp::Equal) => {
                    let snapshot = self.clone();
                    // At this point it is always valid to enclose the lhs in parentheses, no
                    // further checks are necessary.
                    match self.parse_expr() {
                        Ok(_) => {
                            enclose(l1.span, r1.span);
                            true
                        }
                        Err(mut expr_err) => {
                            expr_err.cancel();
                            *self = snapshot;
                            false
                        }
                    }
                }
                _ => false,
            };
        }
        false
    }
fn attempt_chained_comparison_suggestion ( & mut self , err : & mut DiagnosticBuilder < ' _ > , inner_op : & Expr , outer_op : & Spanned < AssocOp > , ) -> bool /* advanced the cursor */ { if let ExprKind :: Binary ( op , ref l1 , ref r1 ) = inner_op . kind { if let ExprKind :: Field ( _ , ident ) = l1 . kind { if ident . as_str ( ) . parse :: < i32 > ( ) . is_err ( ) && ! matches ! ( r1 kind ExprKind Lit ( ) ) { // The parser has encountered `foo.bar<baz`, the likelihood of the turbofish // suggestion being the only one to apply is high. return false ; } } let mut enclose = | left : Span , right : Span | { err . multipart_suggestion ( " " , vec ! [ ( left shrink_to_lo ( ) " " to_string ( ) ) ( right shrink_to_hi ( ) " " to_string ( ) ) ] , Applicability :: MaybeIncorrect , ) ; } ; return match ( op . node , & outer_op . node ) { // `x == y == z` ( BinOpKind :: Eq , AssocOp :: Equal ) | // `x < y < z` and friends. ( BinOpKind :: Lt , AssocOp :: Less | AssocOp :: LessEqual ) | ( BinOpKind :: Le , AssocOp :: LessEqual | AssocOp :: Less ) | // `x > y > z` and friends. ( BinOpKind :: Gt , AssocOp :: Greater | AssocOp :: GreaterEqual ) | ( BinOpKind :: Ge , AssocOp :: GreaterEqual | AssocOp :: Greater ) => { let expr_to_str = | e : & Expr | { self . span_to_snippet ( e . span ) . unwrap_or_else ( | _ | pprust :: expr_to_string ( & e ) ) } ; err . span_suggestion_verbose ( inner_op . span . shrink_to_hi ( ) , " " , format ! ( " " expr_to_str ( r1 ) ) , Applicability :: MaybeIncorrect , ) ; false // Keep the current parse behavior, where the AST is `(x < y) < z`. } // `x == y < z` ( BinOpKind :: Eq , AssocOp :: Less | AssocOp :: LessEqual | AssocOp :: Greater | AssocOp :: GreaterEqual ) => { // Consume `z`/outer-op-rhs. let snapshot = self . clone ( ) ; match self . parse_expr ( ) { Ok ( r2 ) => { // We are sure that outer-op-rhs could be consumed, the suggestion is // likely correct. enclose ( r1 . span , r2 . span ) ; true } Err ( mut expr_err ) => { expr_err . cancel ( ) ; * self = snapshot ; false } } } // `x > y == z` ( BinOpKind :: Lt | BinOpKind :: Le | BinOpKind :: Gt | BinOpKind :: Ge , AssocOp :: Equal ) => { let snapshot = self . clone ( ) ; // At this point it is always valid to enclose the lhs in parentheses, no // further checks are necessary. match self . parse_expr ( ) { Ok ( _ ) => { enclose ( l1 . span , r1 . span ) ; true } Err ( mut expr_err ) => { expr_err . cancel ( ) ; * self = snapshot ; false } } } _ => false , } ; } false }
Check to see if a pair of chained operators looks like an attempt at chained comparison,
e.g.
Check to see if a pair of chained operators looks like an attempt at chained comparison e . g .
&mut self
err
&mut DiagnosticBuilder<'_>
inner_op
&Expr
outer_op
&Spanned<AssocOp>
&mut self
err
&mut DiagnosticBuilder<'_>
inner_op
&Expr
outer_op
&Spanned<AssocOp>