mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-03 05:27:36 +00:00
72 lines
2.4 KiB
Rust
72 lines
2.4 KiB
Rust
use rustc_ast::token::LitKind;
|
|
use rustc_ast::{Expr, ExprKind, MethodCall, UnOp};
|
|
use rustc_session::{declare_lint, declare_lint_pass};
|
|
|
|
use crate::lints::{
|
|
AmbiguousNegativeLiteralsCurrentBehaviorSuggestion, AmbiguousNegativeLiteralsDiag,
|
|
AmbiguousNegativeLiteralsNegativeLiteralSuggestion,
|
|
};
|
|
use crate::{EarlyContext, EarlyLintPass, LintContext};
|
|
|
|
declare_lint! {
|
|
/// The `ambiguous_negative_literals` lint checks for cases that are
|
|
/// confusing between a negative literal and a negation that's not part
|
|
/// of the literal.
|
|
///
|
|
/// ### Example
|
|
///
|
|
/// ```rust,compile_fail
|
|
/// # #![deny(ambiguous_negative_literals)]
|
|
/// # #![allow(unused)]
|
|
/// -1i32.abs(); // equals -1, while `(-1i32).abs()` equals 1
|
|
/// ```
|
|
///
|
|
/// {{produces}}
|
|
///
|
|
/// ### Explanation
|
|
///
|
|
/// Method calls take precedence over unary precedence. Setting the
|
|
/// precedence explicitly makes the code clearer and avoid potential bugs.
|
|
pub AMBIGUOUS_NEGATIVE_LITERALS,
|
|
Allow,
|
|
"ambiguous negative literals operations",
|
|
report_in_external_macro
|
|
}
|
|
|
|
declare_lint_pass!(Precedence => [AMBIGUOUS_NEGATIVE_LITERALS]);
|
|
|
|
impl EarlyLintPass for Precedence {
|
|
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
|
|
let ExprKind::Unary(UnOp::Neg, operand) = &expr.kind else {
|
|
return;
|
|
};
|
|
|
|
let mut arg = operand;
|
|
let mut at_least_one = false;
|
|
while let ExprKind::MethodCall(box MethodCall { receiver, .. }) = &arg.kind {
|
|
at_least_one = true;
|
|
arg = receiver;
|
|
}
|
|
|
|
if at_least_one
|
|
&& let ExprKind::Lit(lit) = &arg.kind
|
|
&& let LitKind::Integer | LitKind::Float = &lit.kind
|
|
{
|
|
cx.emit_span_lint(
|
|
AMBIGUOUS_NEGATIVE_LITERALS,
|
|
expr.span,
|
|
AmbiguousNegativeLiteralsDiag {
|
|
negative_literal: AmbiguousNegativeLiteralsNegativeLiteralSuggestion {
|
|
start_span: expr.span.shrink_to_lo(),
|
|
end_span: arg.span.shrink_to_hi(),
|
|
},
|
|
current_behavior: AmbiguousNegativeLiteralsCurrentBehaviorSuggestion {
|
|
start_span: operand.span.shrink_to_lo(),
|
|
end_span: operand.span.shrink_to_hi(),
|
|
},
|
|
},
|
|
);
|
|
}
|
|
}
|
|
}
|