mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
conditionally wrap LHS of int_plus_one error to avoid parser ambiguity
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::sugg;
|
||||
use rustc_ast::ast::{BinOpKind, Expr, ExprKind, LitKind, UnOp};
|
||||
use rustc_ast::util::parser::AssocOp;
|
||||
use rustc_data_structures::packed::Pu128;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||
@@ -134,12 +135,19 @@ fn emit_warning(cx: &EarlyContext<'_>, expr: &Expr, new_lhs: &Expr, le_or_ge: Le
|
||||
|diag| {
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
let ctxt = expr.span.ctxt();
|
||||
let new_lhs = sugg::Sugg::ast(cx, new_lhs, "_", ctxt, &mut app);
|
||||
let mut new_lhs = sugg::Sugg::ast(cx, new_lhs, "_", ctxt, &mut app);
|
||||
let new_rhs = sugg::Sugg::ast(cx, new_rhs, "_", ctxt, &mut app);
|
||||
let new_binop = match le_or_ge {
|
||||
LeOrGe::Ge => BinOpKind::Gt,
|
||||
LeOrGe::Le => BinOpKind::Lt,
|
||||
};
|
||||
// When the replacement operator is `<`, an `as` cast on the LHS
|
||||
// must be parenthesized. Otherwise, the parser interprets the `<`
|
||||
// as the start of generic arguments on the cast type
|
||||
// (e.g., `x as usize < y` is parsed as `x as usize<y>`).
|
||||
if matches!(new_lhs, sugg::Sugg::BinOp(AssocOp::Cast, ..)) && new_binop == BinOpKind::Lt {
|
||||
new_lhs = new_lhs.maybe_paren();
|
||||
}
|
||||
let rec = sugg::make_binop(new_binop, &new_lhs, &new_rhs);
|
||||
diag.span_suggestion(expr.span, "change it to", rec, app);
|
||||
},
|
||||
|
||||
@@ -16,4 +16,18 @@ fn main() {
|
||||
|
||||
let _ = x > y; // should be ok
|
||||
let _ = y < x; // should be ok
|
||||
|
||||
// When the suggestion replaces `<=`/`>=` with `<`, an `as` cast on
|
||||
// the LHS must be parenthesized to avoid parser ambiguity
|
||||
// (e.g., `x as usize < y` is parsed as `x as usize<y>`).
|
||||
let z = 0usize;
|
||||
let _ = (x as usize) < z; //~ int_plus_one
|
||||
let _ = z > x as usize; //~ int_plus_one
|
||||
// No parentheses needed when the replacement operator is `>`.
|
||||
let _ = x as usize > z; //~ int_plus_one
|
||||
let _ = z < x as usize; //~ int_plus_one
|
||||
|
||||
// Nested and parenthesized casts on the LHS.
|
||||
let _ = ((x as usize) as u8) < 5u8; //~ int_plus_one
|
||||
let _ = (x as usize) < z; //~ int_plus_one
|
||||
}
|
||||
|
||||
@@ -16,4 +16,18 @@ fn main() {
|
||||
|
||||
let _ = x > y; // should be ok
|
||||
let _ = y < x; // should be ok
|
||||
|
||||
// When the suggestion replaces `<=`/`>=` with `<`, an `as` cast on
|
||||
// the LHS must be parenthesized to avoid parser ambiguity
|
||||
// (e.g., `x as usize < y` is parsed as `x as usize<y>`).
|
||||
let z = 0usize;
|
||||
let _ = x as usize + 1 <= z; //~ int_plus_one
|
||||
let _ = z >= x as usize + 1; //~ int_plus_one
|
||||
// No parentheses needed when the replacement operator is `>`.
|
||||
let _ = x as usize - 1 >= z; //~ int_plus_one
|
||||
let _ = z <= x as usize - 1; //~ int_plus_one
|
||||
|
||||
// Nested and parenthesized casts on the LHS.
|
||||
let _ = ((x as usize) as u8) + 1 <= 5u8; //~ int_plus_one
|
||||
let _ = (x as usize) + 1 <= z; //~ int_plus_one
|
||||
}
|
||||
|
||||
@@ -49,5 +49,41 @@ error: unnecessary `>= y + 1` or `x - 1 >=`
|
||||
LL | let _ = y <= -1 + x;
|
||||
| ^^^^^^^^^^^ help: change it to: `y < x`
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error: unnecessary `>= y + 1` or `x - 1 >=`
|
||||
--> tests/ui/int_plus_one.rs:24:13
|
||||
|
|
||||
LL | let _ = x as usize + 1 <= z;
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: change it to: `(x as usize) < z`
|
||||
|
||||
error: unnecessary `>= y + 1` or `x - 1 >=`
|
||||
--> tests/ui/int_plus_one.rs:25:13
|
||||
|
|
||||
LL | let _ = z >= x as usize + 1;
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: change it to: `z > x as usize`
|
||||
|
||||
error: unnecessary `>= y + 1` or `x - 1 >=`
|
||||
--> tests/ui/int_plus_one.rs:27:13
|
||||
|
|
||||
LL | let _ = x as usize - 1 >= z;
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: change it to: `x as usize > z`
|
||||
|
||||
error: unnecessary `>= y + 1` or `x - 1 >=`
|
||||
--> tests/ui/int_plus_one.rs:28:13
|
||||
|
|
||||
LL | let _ = z <= x as usize - 1;
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: change it to: `z < x as usize`
|
||||
|
||||
error: unnecessary `>= y + 1` or `x - 1 >=`
|
||||
--> tests/ui/int_plus_one.rs:31:13
|
||||
|
|
||||
LL | let _ = ((x as usize) as u8) + 1 <= 5u8;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: change it to: `((x as usize) as u8) < 5u8`
|
||||
|
||||
error: unnecessary `>= y + 1` or `x - 1 >=`
|
||||
--> tests/ui/int_plus_one.rs:32:13
|
||||
|
|
||||
LL | let _ = (x as usize) + 1 <= z;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: change it to: `(x as usize) < z`
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
|
||||
|
||||
Reference in New Issue
Block a user