mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-24 07:44:10 +00:00
Auto merge of #5792 - flip1995:rollup-torc1we, r=flip1995
Rollup of 5 pull requests Successful merges: - #5443 (Some accuracy lints for floating point operations) - #5752 (Move range_minus_one to pedantic) - #5756 (unnecessary_sort_by: avoid linting if key borrows) - #5784 (Fix out of bounds access by checking length equality BEFORE accessing by index.) - #5786 (fix phrase in new_lint issue template) Failed merges: r? @ghost changelog: rollup
This commit is contained in:
commit
4b8700879c
2
.github/ISSUE_TEMPLATE/new_lint.md
vendored
2
.github/ISSUE_TEMPLATE/new_lint.md
vendored
@ -12,7 +12,7 @@ labels: L-lint
|
||||
|
||||
- Kind: *See <https://github.com/rust-lang/rust-clippy/blob/master/README.md#clippy> for list of lint kinds*
|
||||
|
||||
*What benefit of this lint over old code?*
|
||||
*What is the advantage of the recommended code over the original code*
|
||||
|
||||
For example:
|
||||
- Remove bounce checking inserted by ...
|
||||
|
@ -1,11 +1,11 @@
|
||||
use crate::consts::{
|
||||
constant, constant_simple, Constant,
|
||||
Constant::{F32, F64},
|
||||
Constant::{Int, F32, F64},
|
||||
};
|
||||
use crate::utils::{higher, numeric_literal, span_lint_and_sugg, sugg, SpanlessEq};
|
||||
use crate::utils::{get_parent_expr, higher, numeric_literal, span_lint_and_sugg, sugg, SpanlessEq};
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, UnOp};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
@ -293,6 +293,121 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
|
||||
if let Some((value, _)) = constant(cx, cx.tables(), &args[1]) {
|
||||
if value == Int(2) {
|
||||
if let Some(parent) = get_parent_expr(cx, expr) {
|
||||
if let Some(grandparent) = get_parent_expr(cx, parent) {
|
||||
if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, _, args, _) = grandparent.kind {
|
||||
if method_name.as_str() == "sqrt" && detect_hypot(cx, args).is_some() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let ExprKind::Binary(
|
||||
Spanned {
|
||||
node: BinOpKind::Add, ..
|
||||
},
|
||||
ref lhs,
|
||||
ref rhs,
|
||||
) = parent.kind
|
||||
{
|
||||
let other_addend = if lhs.hir_id == expr.hir_id { rhs } else { lhs };
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
SUBOPTIMAL_FLOPS,
|
||||
parent.span,
|
||||
"square can be computed more efficiently",
|
||||
"consider using",
|
||||
format!(
|
||||
"{}.mul_add({}, {})",
|
||||
Sugg::hir(cx, &args[0], ".."),
|
||||
Sugg::hir(cx, &args[0], ".."),
|
||||
Sugg::hir(cx, &other_addend, ".."),
|
||||
),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
SUBOPTIMAL_FLOPS,
|
||||
expr.span,
|
||||
"square can be computed more efficiently",
|
||||
"consider using",
|
||||
format!("{} * {}", Sugg::hir(cx, &args[0], ".."), Sugg::hir(cx, &args[0], "..")),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn detect_hypot(cx: &LateContext<'_>, args: &[Expr<'_>]) -> Option<String> {
|
||||
if let ExprKind::Binary(
|
||||
Spanned {
|
||||
node: BinOpKind::Add, ..
|
||||
},
|
||||
ref add_lhs,
|
||||
ref add_rhs,
|
||||
) = args[0].kind
|
||||
{
|
||||
// check if expression of the form x * x + y * y
|
||||
if_chain! {
|
||||
if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref lmul_lhs, ref lmul_rhs) = add_lhs.kind;
|
||||
if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref rmul_lhs, ref rmul_rhs) = add_rhs.kind;
|
||||
if are_exprs_equal(cx, lmul_lhs, lmul_rhs);
|
||||
if are_exprs_equal(cx, rmul_lhs, rmul_rhs);
|
||||
then {
|
||||
return Some(format!("{}.hypot({})", Sugg::hir(cx, &lmul_lhs, ".."), Sugg::hir(cx, &rmul_lhs, "..")));
|
||||
}
|
||||
}
|
||||
|
||||
// check if expression of the form x.powi(2) + y.powi(2)
|
||||
if_chain! {
|
||||
if let ExprKind::MethodCall(
|
||||
PathSegment { ident: lmethod_name, .. },
|
||||
ref _lspan,
|
||||
ref largs,
|
||||
_
|
||||
) = add_lhs.kind;
|
||||
if let ExprKind::MethodCall(
|
||||
PathSegment { ident: rmethod_name, .. },
|
||||
ref _rspan,
|
||||
ref rargs,
|
||||
_
|
||||
) = add_rhs.kind;
|
||||
if lmethod_name.as_str() == "powi" && rmethod_name.as_str() == "powi";
|
||||
if let Some((lvalue, _)) = constant(cx, cx.tables(), &largs[1]);
|
||||
if let Some((rvalue, _)) = constant(cx, cx.tables(), &rargs[1]);
|
||||
if Int(2) == lvalue && Int(2) == rvalue;
|
||||
then {
|
||||
return Some(format!("{}.hypot({})", Sugg::hir(cx, &largs[0], ".."), Sugg::hir(cx, &rargs[0], "..")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn check_hypot(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
|
||||
if let Some(message) = detect_hypot(cx, args) {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
IMPRECISE_FLOPS,
|
||||
expr.span,
|
||||
"hypotenuse can be computed more accurately",
|
||||
"consider using",
|
||||
message,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Lint expressions of the form `x.exp() - y` where y > 1
|
||||
// and suggest usage of `x.exp_m1() - (y - 1)` instead
|
||||
fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
@ -344,6 +459,14 @@ fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
rhs,
|
||||
) = &expr.kind
|
||||
{
|
||||
if let Some(parent) = get_parent_expr(cx, expr) {
|
||||
if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, _, args, _) = parent.kind {
|
||||
if method_name.as_str() == "sqrt" && detect_hypot(cx, args).is_some() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (recv, arg1, arg2) = if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, lhs) {
|
||||
(inner_lhs, inner_rhs, rhs)
|
||||
} else if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, rhs) {
|
||||
@ -479,6 +602,100 @@ fn check_custom_abs(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
}
|
||||
}
|
||||
|
||||
fn are_same_base_logs(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_>) -> bool {
|
||||
if_chain! {
|
||||
if let ExprKind::MethodCall(PathSegment { ident: method_name_a, .. }, _, ref args_a, _) = expr_a.kind;
|
||||
if let ExprKind::MethodCall(PathSegment { ident: method_name_b, .. }, _, ref args_b, _) = expr_b.kind;
|
||||
then {
|
||||
return method_name_a.as_str() == method_name_b.as_str() &&
|
||||
args_a.len() == args_b.len() &&
|
||||
(
|
||||
["ln", "log2", "log10"].contains(&&*method_name_a.as_str()) ||
|
||||
method_name_a.as_str() == "log" && args_a.len() == 2 && are_exprs_equal(cx, &args_a[1], &args_b[1])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
// check if expression of the form x.logN() / y.logN()
|
||||
if_chain! {
|
||||
if let ExprKind::Binary(
|
||||
Spanned {
|
||||
node: BinOpKind::Div, ..
|
||||
},
|
||||
lhs,
|
||||
rhs,
|
||||
) = &expr.kind;
|
||||
if are_same_base_logs(cx, lhs, rhs);
|
||||
if let ExprKind::MethodCall(_, _, ref largs, _) = lhs.kind;
|
||||
if let ExprKind::MethodCall(_, _, ref rargs, _) = rhs.kind;
|
||||
then {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
SUBOPTIMAL_FLOPS,
|
||||
expr.span,
|
||||
"log base can be expressed more clearly",
|
||||
"consider using",
|
||||
format!("{}.log({})", Sugg::hir(cx, &largs[0], ".."), Sugg::hir(cx, &rargs[0], ".."),),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
if_chain! {
|
||||
if let ExprKind::Binary(
|
||||
Spanned {
|
||||
node: BinOpKind::Div, ..
|
||||
},
|
||||
div_lhs,
|
||||
div_rhs,
|
||||
) = &expr.kind;
|
||||
if let ExprKind::Binary(
|
||||
Spanned {
|
||||
node: BinOpKind::Mul, ..
|
||||
},
|
||||
mul_lhs,
|
||||
mul_rhs,
|
||||
) = &div_lhs.kind;
|
||||
if let Some((rvalue, _)) = constant(cx, cx.tables(), div_rhs);
|
||||
if let Some((lvalue, _)) = constant(cx, cx.tables(), mul_rhs);
|
||||
then {
|
||||
// TODO: also check for constant values near PI/180 or 180/PI
|
||||
if (F32(f32_consts::PI) == rvalue || F64(f64_consts::PI) == rvalue) &&
|
||||
(F32(180_f32) == lvalue || F64(180_f64) == lvalue)
|
||||
{
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
SUBOPTIMAL_FLOPS,
|
||||
expr.span,
|
||||
"conversion to degrees can be done more accurately",
|
||||
"consider using",
|
||||
format!("{}.to_degrees()", Sugg::hir(cx, &mul_lhs, "..")),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else if
|
||||
(F32(180_f32) == rvalue || F64(180_f64) == rvalue) &&
|
||||
(F32(f32_consts::PI) == lvalue || F64(f64_consts::PI) == lvalue)
|
||||
{
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
SUBOPTIMAL_FLOPS,
|
||||
expr.span,
|
||||
"conversion to radians can be done more accurately",
|
||||
"consider using",
|
||||
format!("{}.to_radians()", Sugg::hir(cx, &mul_lhs, "..")),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if let ExprKind::MethodCall(ref path, _, args, _) = &expr.kind {
|
||||
@ -489,6 +706,8 @@ impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic {
|
||||
"ln" => check_ln1p(cx, expr, args),
|
||||
"log" => check_log_base(cx, expr, args),
|
||||
"powf" => check_powf(cx, expr, args),
|
||||
"powi" => check_powi(cx, expr, args),
|
||||
"sqrt" => check_hypot(cx, expr, args),
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
@ -496,6 +715,8 @@ impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic {
|
||||
check_expm1(cx, expr);
|
||||
check_mul_add(cx, expr);
|
||||
check_custom_abs(cx, expr);
|
||||
check_log_division(cx, expr);
|
||||
check_radians(cx, expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
|
||||
use rustc_hir::{Block, Expr, ExprKind, PatKind, StmtKind};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
@ -9,7 +8,7 @@ use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty::subst::GenericArgKind;
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
|
||||
use crate::utils::{in_macro, match_qpath, snippet_opt, span_lint_and_then};
|
||||
use crate::utils::{fn_def_id, in_macro, match_qpath, snippet_opt, span_lint_and_then};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for `let`-bindings, which are subsequently
|
||||
@ -97,22 +96,6 @@ struct BorrowVisitor<'a, 'tcx> {
|
||||
borrows: bool,
|
||||
}
|
||||
|
||||
impl BorrowVisitor<'_, '_> {
|
||||
fn fn_def_id(&self, expr: &Expr<'_>) -> Option<DefId> {
|
||||
match &expr.kind {
|
||||
ExprKind::MethodCall(..) => self.cx.tables().type_dependent_def_id(expr.hir_id),
|
||||
ExprKind::Call(
|
||||
Expr {
|
||||
kind: ExprKind::Path(qpath),
|
||||
..
|
||||
},
|
||||
..,
|
||||
) => self.cx.qpath_res(qpath, expr.hir_id).opt_def_id(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for BorrowVisitor<'_, 'tcx> {
|
||||
type Map = Map<'tcx>;
|
||||
|
||||
@ -121,7 +104,7 @@ impl<'tcx> Visitor<'tcx> for BorrowVisitor<'_, 'tcx> {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(def_id) = self.fn_def_id(expr) {
|
||||
if let Some(def_id) = fn_def_id(self.cx, expr) {
|
||||
self.borrows = self
|
||||
.cx
|
||||
.tcx
|
||||
|
@ -1161,6 +1161,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||
LintId::of(&needless_pass_by_value::NEEDLESS_PASS_BY_VALUE),
|
||||
LintId::of(&non_expressive_names::SIMILAR_NAMES),
|
||||
LintId::of(&option_if_let_else::OPTION_IF_LET_ELSE),
|
||||
LintId::of(&ranges::RANGE_MINUS_ONE),
|
||||
LintId::of(&ranges::RANGE_PLUS_ONE),
|
||||
LintId::of(&shadow::SHADOW_UNRELATED),
|
||||
LintId::of(&strings::STRING_ADD_ASSIGN),
|
||||
@ -1383,7 +1384,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||
LintId::of(&ptr::PTR_ARG),
|
||||
LintId::of(&ptr_offset_with_cast::PTR_OFFSET_WITH_CAST),
|
||||
LintId::of(&question_mark::QUESTION_MARK),
|
||||
LintId::of(&ranges::RANGE_MINUS_ONE),
|
||||
LintId::of(&ranges::RANGE_ZIP_WITH_LEN),
|
||||
LintId::of(&ranges::REVERSED_EMPTY_RANGES),
|
||||
LintId::of(&redundant_clone::REDUNDANT_CLONE),
|
||||
@ -1599,7 +1599,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||
LintId::of(&partialeq_ne_impl::PARTIALEQ_NE_IMPL),
|
||||
LintId::of(&precedence::PRECEDENCE),
|
||||
LintId::of(&ptr_offset_with_cast::PTR_OFFSET_WITH_CAST),
|
||||
LintId::of(&ranges::RANGE_MINUS_ONE),
|
||||
LintId::of(&ranges::RANGE_ZIP_WITH_LEN),
|
||||
LintId::of(&reference::DEREF_ADDROF),
|
||||
LintId::of(&reference::REF_IN_DEREF),
|
||||
|
@ -52,6 +52,11 @@ declare_clippy_lint! {
|
||||
/// exclusive ranges, because they essentially add an extra branch that
|
||||
/// LLVM may fail to hoist out of the loop.
|
||||
///
|
||||
/// This will cause a warning that cannot be fixed if the consumer of the
|
||||
/// range only accepts a specific range type, instead of the generic
|
||||
/// `RangeBounds` trait
|
||||
/// ([#3307](https://github.com/rust-lang/rust-clippy/issues/3307)).
|
||||
///
|
||||
/// **Example:**
|
||||
/// ```rust,ignore
|
||||
/// for x..(y+1) { .. }
|
||||
@ -72,7 +77,10 @@ declare_clippy_lint! {
|
||||
/// **Why is this bad?** The code is more readable with an exclusive range
|
||||
/// like `x..y`.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
/// **Known problems:** This will cause a warning that cannot be fixed if
|
||||
/// the consumer of the range only accepts a specific range type, instead of
|
||||
/// the generic `RangeBounds` trait
|
||||
/// ([#3307](https://github.com/rust-lang/rust-clippy/issues/3307)).
|
||||
///
|
||||
/// **Example:**
|
||||
/// ```rust,ignore
|
||||
@ -83,7 +91,7 @@ declare_clippy_lint! {
|
||||
/// for x..y { .. }
|
||||
/// ```
|
||||
pub RANGE_MINUS_ONE,
|
||||
complexity,
|
||||
pedantic,
|
||||
"`x..=(y-1)` reads better as `x..y`"
|
||||
}
|
||||
|
||||
|
@ -5,24 +5,23 @@ use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind, Mutability, Param, Pat, PatKind, Path, PathSegment, QPath};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::{self, subst::GenericArgKind};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::symbol::Ident;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:**
|
||||
/// Detects when people use `Vec::sort_by` and pass in a function
|
||||
/// Detects uses of `Vec::sort_by` passing in a closure
|
||||
/// which compares the two arguments, either directly or indirectly.
|
||||
///
|
||||
/// **Why is this bad?**
|
||||
/// It is more clear to use `Vec::sort_by_key` (or `Vec::sort` if
|
||||
/// possible) than to use `Vec::sort_by` and and a more complicated
|
||||
/// possible) than to use `Vec::sort_by` and a more complicated
|
||||
/// closure.
|
||||
///
|
||||
/// **Known problems:**
|
||||
/// If the suggested `Vec::sort_by_key` uses Reverse and it isn't
|
||||
/// imported by a use statement in the current frame, then a `use`
|
||||
/// statement that imports it will need to be added (which this lint
|
||||
/// can't do).
|
||||
/// If the suggested `Vec::sort_by_key` uses Reverse and it isn't already
|
||||
/// imported by a use statement, then it will need to be added manually.
|
||||
///
|
||||
/// **Example:**
|
||||
///
|
||||
@ -201,28 +200,41 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<LintTrigger> {
|
||||
};
|
||||
let vec_name = Sugg::hir(cx, &args[0], "..").to_string();
|
||||
let unstable = name == "sort_unstable_by";
|
||||
|
||||
if_chain! {
|
||||
if let ExprKind::Path(QPath::Resolved(_, Path {
|
||||
segments: [PathSegment { ident: left_name, .. }], ..
|
||||
})) = &left_expr.kind;
|
||||
if left_name == left_ident;
|
||||
then {
|
||||
Some(LintTrigger::Sort(SortDetection { vec_name, unstable }))
|
||||
}
|
||||
else {
|
||||
Some(LintTrigger::SortByKey(SortByKeyDetection {
|
||||
vec_name,
|
||||
unstable,
|
||||
closure_arg,
|
||||
closure_body,
|
||||
reverse
|
||||
}))
|
||||
return Some(LintTrigger::Sort(SortDetection { vec_name, unstable }))
|
||||
} else {
|
||||
if !key_returns_borrow(cx, left_expr) {
|
||||
return Some(LintTrigger::SortByKey(SortByKeyDetection {
|
||||
vec_name,
|
||||
unstable,
|
||||
closure_arg,
|
||||
closure_body,
|
||||
reverse
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn key_returns_borrow(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
if let Some(def_id) = utils::fn_def_id(cx, expr) {
|
||||
let output = cx.tcx.fn_sig(def_id).output();
|
||||
let ty = output.skip_binder();
|
||||
return matches!(ty.kind, ty::Ref(..))
|
||||
|| ty.walk().any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_)));
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
impl LateLintPass<'_> for UnnecessarySortBy {
|
||||
|
@ -400,8 +400,8 @@ fn extend_with_matching(
|
||||
|
||||
/// Are the patterns in `ps1` and `ps2` equal save for `ps1[idx]` compared to `ps2[idx]`?
|
||||
fn eq_pre_post(ps1: &[P<Pat>], ps2: &[P<Pat>], idx: usize) -> bool {
|
||||
ps1[idx].is_rest() == ps2[idx].is_rest() // Avoid `[x, ..] | [x, 0]` => `[x, .. | 0]`.
|
||||
&& ps1.len() == ps2.len()
|
||||
ps1.len() == ps2.len()
|
||||
&& ps1[idx].is_rest() == ps2[idx].is_rest() // Avoid `[x, ..] | [x, 0]` => `[x, .. | 0]`.
|
||||
&& over(&ps1[..idx], &ps2[..idx], |l, r| eq_pat(l, r))
|
||||
&& over(&ps1[idx + 1..], &ps2[idx + 1..], |l, r| eq_pat(l, r))
|
||||
}
|
||||
|
@ -1356,6 +1356,21 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool {
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the `DefId` of the callee if the given expression is a function or method call.
|
||||
pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<DefId> {
|
||||
match &expr.kind {
|
||||
ExprKind::MethodCall(..) => cx.tables().type_dependent_def_id(expr.hir_id),
|
||||
ExprKind::Call(
|
||||
Expr {
|
||||
kind: ExprKind::Path(qpath),
|
||||
..
|
||||
},
|
||||
..,
|
||||
) => cx.tables().qpath_res(qpath, expr.hir_id).opt_def_id(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_lints(cx: &LateContext<'_>, lints: &[&'static Lint], id: HirId) -> bool {
|
||||
lints.iter().any(|lint| {
|
||||
matches!(
|
||||
|
@ -1790,7 +1790,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![
|
||||
},
|
||||
Lint {
|
||||
name: "range_minus_one",
|
||||
group: "complexity",
|
||||
group: "pedantic",
|
||||
desc: "`x..=(y-1)` reads better as `x..y`",
|
||||
deprecation: None,
|
||||
module: "ranges",
|
||||
|
14
tests/ui/floating_point_hypot.fixed
Normal file
14
tests/ui/floating_point_hypot.fixed
Normal file
@ -0,0 +1,14 @@
|
||||
// run-rustfix
|
||||
#![warn(clippy::imprecise_flops)]
|
||||
|
||||
fn main() {
|
||||
let x = 3f32;
|
||||
let y = 4f32;
|
||||
let _ = x.hypot(y);
|
||||
let _ = (x + 1f32).hypot(y);
|
||||
let _ = x.hypot(y);
|
||||
// Cases where the lint shouldn't be applied
|
||||
// TODO: linting this adds some complexity, but could be done
|
||||
let _ = x.mul_add(x, y * y).sqrt();
|
||||
let _ = (x * 4f32 + y * y).sqrt();
|
||||
}
|
14
tests/ui/floating_point_hypot.rs
Normal file
14
tests/ui/floating_point_hypot.rs
Normal file
@ -0,0 +1,14 @@
|
||||
// run-rustfix
|
||||
#![warn(clippy::imprecise_flops)]
|
||||
|
||||
fn main() {
|
||||
let x = 3f32;
|
||||
let y = 4f32;
|
||||
let _ = (x * x + y * y).sqrt();
|
||||
let _ = ((x + 1f32) * (x + 1f32) + y * y).sqrt();
|
||||
let _ = (x.powi(2) + y.powi(2)).sqrt();
|
||||
// Cases where the lint shouldn't be applied
|
||||
// TODO: linting this adds some complexity, but could be done
|
||||
let _ = x.mul_add(x, y * y).sqrt();
|
||||
let _ = (x * 4f32 + y * y).sqrt();
|
||||
}
|
22
tests/ui/floating_point_hypot.stderr
Normal file
22
tests/ui/floating_point_hypot.stderr
Normal file
@ -0,0 +1,22 @@
|
||||
error: hypotenuse can be computed more accurately
|
||||
--> $DIR/floating_point_hypot.rs:7:13
|
||||
|
|
||||
LL | let _ = (x * x + y * y).sqrt();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.hypot(y)`
|
||||
|
|
||||
= note: `-D clippy::imprecise-flops` implied by `-D warnings`
|
||||
|
||||
error: hypotenuse can be computed more accurately
|
||||
--> $DIR/floating_point_hypot.rs:8:13
|
||||
|
|
||||
LL | let _ = ((x + 1f32) * (x + 1f32) + y * y).sqrt();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x + 1f32).hypot(y)`
|
||||
|
||||
error: hypotenuse can be computed more accurately
|
||||
--> $DIR/floating_point_hypot.rs:9:13
|
||||
|
|
||||
LL | let _ = (x.powi(2) + y.powi(2)).sqrt();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.hypot(y)`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
@ -25,11 +25,11 @@ fn check_ln1p() {
|
||||
let _ = 2.0f32.ln_1p();
|
||||
let _ = x.ln_1p();
|
||||
let _ = (x / 2.0).ln_1p();
|
||||
let _ = x.powi(2).ln_1p();
|
||||
let _ = (x.powi(2) / 2.0).ln_1p();
|
||||
let _ = x.powi(3).ln_1p();
|
||||
let _ = (x.powi(3) / 2.0).ln_1p();
|
||||
let _ = ((std::f32::consts::E - 1.0)).ln_1p();
|
||||
let _ = x.ln_1p();
|
||||
let _ = x.powi(2).ln_1p();
|
||||
let _ = x.powi(3).ln_1p();
|
||||
let _ = (x + 2.0).ln_1p();
|
||||
let _ = (x / 2.0).ln_1p();
|
||||
// Cases where the lint shouldn't be applied
|
||||
@ -43,9 +43,9 @@ fn check_ln1p() {
|
||||
let _ = 2.0f64.ln_1p();
|
||||
let _ = x.ln_1p();
|
||||
let _ = (x / 2.0).ln_1p();
|
||||
let _ = x.powi(2).ln_1p();
|
||||
let _ = x.powi(3).ln_1p();
|
||||
let _ = x.ln_1p();
|
||||
let _ = x.powi(2).ln_1p();
|
||||
let _ = x.powi(3).ln_1p();
|
||||
let _ = (x + 2.0).ln_1p();
|
||||
let _ = (x / 2.0).ln_1p();
|
||||
// Cases where the lint shouldn't be applied
|
||||
|
@ -25,11 +25,11 @@ fn check_ln1p() {
|
||||
let _ = (1f32 + 2.0).ln();
|
||||
let _ = (1.0 + x).ln();
|
||||
let _ = (1.0 + x / 2.0).ln();
|
||||
let _ = (1.0 + x.powi(2)).ln();
|
||||
let _ = (1.0 + x.powi(2) / 2.0).ln();
|
||||
let _ = (1.0 + x.powi(3)).ln();
|
||||
let _ = (1.0 + x.powi(3) / 2.0).ln();
|
||||
let _ = (1.0 + (std::f32::consts::E - 1.0)).ln();
|
||||
let _ = (x + 1.0).ln();
|
||||
let _ = (x.powi(2) + 1.0).ln();
|
||||
let _ = (x.powi(3) + 1.0).ln();
|
||||
let _ = (x + 2.0 + 1.0).ln();
|
||||
let _ = (x / 2.0 + 1.0).ln();
|
||||
// Cases where the lint shouldn't be applied
|
||||
@ -43,9 +43,9 @@ fn check_ln1p() {
|
||||
let _ = (1f64 + 2.0).ln();
|
||||
let _ = (1.0 + x).ln();
|
||||
let _ = (1.0 + x / 2.0).ln();
|
||||
let _ = (1.0 + x.powi(2)).ln();
|
||||
let _ = (1.0 + x.powi(3)).ln();
|
||||
let _ = (x + 1.0).ln();
|
||||
let _ = (x.powi(2) + 1.0).ln();
|
||||
let _ = (x.powi(3) + 1.0).ln();
|
||||
let _ = (x + 2.0 + 1.0).ln();
|
||||
let _ = (x / 2.0 + 1.0).ln();
|
||||
// Cases where the lint shouldn't be applied
|
||||
|
@ -77,14 +77,14 @@ LL | let _ = (1.0 + x / 2.0).ln();
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:28:13
|
||||
|
|
||||
LL | let _ = (1.0 + x.powi(2)).ln();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
|
||||
LL | let _ = (1.0 + x.powi(3)).ln();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()`
|
||||
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:29:13
|
||||
|
|
||||
LL | let _ = (1.0 + x.powi(2) / 2.0).ln();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x.powi(2) / 2.0).ln_1p()`
|
||||
LL | let _ = (1.0 + x.powi(3) / 2.0).ln();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x.powi(3) / 2.0).ln_1p()`
|
||||
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:30:13
|
||||
@ -101,8 +101,8 @@ LL | let _ = (x + 1.0).ln();
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:32:13
|
||||
|
|
||||
LL | let _ = (x.powi(2) + 1.0).ln();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
|
||||
LL | let _ = (x.powi(3) + 1.0).ln();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()`
|
||||
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:33:13
|
||||
@ -143,8 +143,8 @@ LL | let _ = (1.0 + x / 2.0).ln();
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:46:13
|
||||
|
|
||||
LL | let _ = (1.0 + x.powi(2)).ln();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
|
||||
LL | let _ = (1.0 + x.powi(3)).ln();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()`
|
||||
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:47:13
|
||||
@ -155,8 +155,8 @@ LL | let _ = (x + 1.0).ln();
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:48:13
|
||||
|
|
||||
LL | let _ = (x.powi(2) + 1.0).ln();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
|
||||
LL | let _ = (x.powi(3) + 1.0).ln();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()`
|
||||
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:49:13
|
||||
|
16
tests/ui/floating_point_logbase.fixed
Normal file
16
tests/ui/floating_point_logbase.fixed
Normal file
@ -0,0 +1,16 @@
|
||||
// run-rustfix
|
||||
#![warn(clippy::suboptimal_flops)]
|
||||
|
||||
fn main() {
|
||||
let x = 3f32;
|
||||
let y = 5f32;
|
||||
let _ = x.log(y);
|
||||
let _ = x.log(y);
|
||||
let _ = x.log(y);
|
||||
let _ = x.log(y);
|
||||
// Cases where the lint shouldn't be applied
|
||||
let _ = x.ln() / y.powf(3.2);
|
||||
let _ = x.powf(3.2) / y.powf(3.2);
|
||||
let _ = x.powf(3.2) / y.ln();
|
||||
let _ = x.log(5f32) / y.log(7f32);
|
||||
}
|
16
tests/ui/floating_point_logbase.rs
Normal file
16
tests/ui/floating_point_logbase.rs
Normal file
@ -0,0 +1,16 @@
|
||||
// run-rustfix
|
||||
#![warn(clippy::suboptimal_flops)]
|
||||
|
||||
fn main() {
|
||||
let x = 3f32;
|
||||
let y = 5f32;
|
||||
let _ = x.ln() / y.ln();
|
||||
let _ = x.log2() / y.log2();
|
||||
let _ = x.log10() / y.log10();
|
||||
let _ = x.log(5f32) / y.log(5f32);
|
||||
// Cases where the lint shouldn't be applied
|
||||
let _ = x.ln() / y.powf(3.2);
|
||||
let _ = x.powf(3.2) / y.powf(3.2);
|
||||
let _ = x.powf(3.2) / y.ln();
|
||||
let _ = x.log(5f32) / y.log(7f32);
|
||||
}
|
28
tests/ui/floating_point_logbase.stderr
Normal file
28
tests/ui/floating_point_logbase.stderr
Normal file
@ -0,0 +1,28 @@
|
||||
error: log base can be expressed more clearly
|
||||
--> $DIR/floating_point_logbase.rs:7:13
|
||||
|
|
||||
LL | let _ = x.ln() / y.ln();
|
||||
| ^^^^^^^^^^^^^^^ help: consider using: `x.log(y)`
|
||||
|
|
||||
= note: `-D clippy::suboptimal-flops` implied by `-D warnings`
|
||||
|
||||
error: log base can be expressed more clearly
|
||||
--> $DIR/floating_point_logbase.rs:8:13
|
||||
|
|
||||
LL | let _ = x.log2() / y.log2();
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)`
|
||||
|
||||
error: log base can be expressed more clearly
|
||||
--> $DIR/floating_point_logbase.rs:9:13
|
||||
|
|
||||
LL | let _ = x.log10() / y.log10();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)`
|
||||
|
||||
error: log base can be expressed more clearly
|
||||
--> $DIR/floating_point_logbase.rs:10:13
|
||||
|
|
||||
LL | let _ = x.log(5f32) / y.log(5f32);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
@ -18,4 +18,9 @@ fn main() {
|
||||
|
||||
let _ = a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c)) + c;
|
||||
let _ = 1234.567_f64.mul_add(45.67834_f64, 0.0004_f64);
|
||||
|
||||
let _ = a.mul_add(a, b).sqrt();
|
||||
|
||||
// Cases where the lint shouldn't be applied
|
||||
let _ = (a * a + b * b).sqrt();
|
||||
}
|
||||
|
@ -18,4 +18,9 @@ fn main() {
|
||||
|
||||
let _ = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c;
|
||||
let _ = 1234.567_f64 * 45.67834_f64 + 0.0004_f64;
|
||||
|
||||
let _ = (a * a + b).sqrt();
|
||||
|
||||
// Cases where the lint shouldn't be applied
|
||||
let _ = (a * a + b * b).sqrt();
|
||||
}
|
||||
|
@ -54,5 +54,11 @@ error: multiply and add expressions can be calculated more efficiently and accur
|
||||
LL | let _ = 1234.567_f64 * 45.67834_f64 + 0.0004_f64;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1234.567_f64.mul_add(45.67834_f64, 0.0004_f64)`
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
error: multiply and add expressions can be calculated more efficiently and accurately
|
||||
--> $DIR/floating_point_mul_add.rs:22:13
|
||||
|
|
||||
LL | let _ = (a * a + b).sqrt();
|
||||
| ^^^^^^^^^^^ help: consider using: `a.mul_add(a, b)`
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
|
@ -11,7 +11,7 @@ fn main() {
|
||||
let _ = (-3.1f32).exp();
|
||||
let _ = x.sqrt();
|
||||
let _ = x.cbrt();
|
||||
let _ = x.powi(2);
|
||||
let _ = x.powi(3);
|
||||
let _ = x.powi(-2);
|
||||
let _ = x.powi(16_777_215);
|
||||
let _ = x.powi(-16_777_215);
|
||||
@ -30,7 +30,7 @@ fn main() {
|
||||
let _ = (-3.1f64).exp();
|
||||
let _ = x.sqrt();
|
||||
let _ = x.cbrt();
|
||||
let _ = x.powi(2);
|
||||
let _ = x.powi(3);
|
||||
let _ = x.powi(-2);
|
||||
let _ = x.powi(-2_147_483_648);
|
||||
let _ = x.powi(2_147_483_647);
|
||||
|
@ -11,7 +11,7 @@ fn main() {
|
||||
let _ = std::f32::consts::E.powf(-3.1);
|
||||
let _ = x.powf(1.0 / 2.0);
|
||||
let _ = x.powf(1.0 / 3.0);
|
||||
let _ = x.powf(2.0);
|
||||
let _ = x.powf(3.0);
|
||||
let _ = x.powf(-2.0);
|
||||
let _ = x.powf(16_777_215.0);
|
||||
let _ = x.powf(-16_777_215.0);
|
||||
@ -30,7 +30,7 @@ fn main() {
|
||||
let _ = std::f64::consts::E.powf(-3.1);
|
||||
let _ = x.powf(1.0 / 2.0);
|
||||
let _ = x.powf(1.0 / 3.0);
|
||||
let _ = x.powf(2.0);
|
||||
let _ = x.powf(3.0);
|
||||
let _ = x.powf(-2.0);
|
||||
let _ = x.powf(-2_147_483_648.0);
|
||||
let _ = x.powf(2_147_483_647.0);
|
||||
|
@ -53,8 +53,8 @@ LL | let _ = x.powf(1.0 / 3.0);
|
||||
error: exponentiation with integer powers can be computed more efficiently
|
||||
--> $DIR/floating_point_powf.rs:14:13
|
||||
|
|
||||
LL | let _ = x.powf(2.0);
|
||||
| ^^^^^^^^^^^ help: consider using: `x.powi(2)`
|
||||
LL | let _ = x.powf(3.0);
|
||||
| ^^^^^^^^^^^ help: consider using: `x.powi(3)`
|
||||
|
||||
error: exponentiation with integer powers can be computed more efficiently
|
||||
--> $DIR/floating_point_powf.rs:15:13
|
||||
@ -125,8 +125,8 @@ LL | let _ = x.powf(1.0 / 3.0);
|
||||
error: exponentiation with integer powers can be computed more efficiently
|
||||
--> $DIR/floating_point_powf.rs:33:13
|
||||
|
|
||||
LL | let _ = x.powf(2.0);
|
||||
| ^^^^^^^^^^^ help: consider using: `x.powi(2)`
|
||||
LL | let _ = x.powf(3.0);
|
||||
| ^^^^^^^^^^^ help: consider using: `x.powi(3)`
|
||||
|
||||
error: exponentiation with integer powers can be computed more efficiently
|
||||
--> $DIR/floating_point_powf.rs:34:13
|
||||
|
19
tests/ui/floating_point_powi.fixed
Normal file
19
tests/ui/floating_point_powi.fixed
Normal file
@ -0,0 +1,19 @@
|
||||
// run-rustfix
|
||||
#![warn(clippy::suboptimal_flops)]
|
||||
|
||||
fn main() {
|
||||
let one = 1;
|
||||
let x = 3f32;
|
||||
let _ = x * x;
|
||||
let _ = x * x;
|
||||
|
||||
let y = 4f32;
|
||||
let _ = x.mul_add(x, y);
|
||||
let _ = y.mul_add(y, x);
|
||||
let _ = x.mul_add(x, y).sqrt();
|
||||
let _ = y.mul_add(y, x).sqrt();
|
||||
// Cases where the lint shouldn't be applied
|
||||
let _ = x.powi(3);
|
||||
let _ = x.powi(one + 1);
|
||||
let _ = (x.powi(2) + y.powi(2)).sqrt();
|
||||
}
|
19
tests/ui/floating_point_powi.rs
Normal file
19
tests/ui/floating_point_powi.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// run-rustfix
|
||||
#![warn(clippy::suboptimal_flops)]
|
||||
|
||||
fn main() {
|
||||
let one = 1;
|
||||
let x = 3f32;
|
||||
let _ = x.powi(2);
|
||||
let _ = x.powi(1 + 1);
|
||||
|
||||
let y = 4f32;
|
||||
let _ = x.powi(2) + y;
|
||||
let _ = x + y.powi(2);
|
||||
let _ = (x.powi(2) + y).sqrt();
|
||||
let _ = (x + y.powi(2)).sqrt();
|
||||
// Cases where the lint shouldn't be applied
|
||||
let _ = x.powi(3);
|
||||
let _ = x.powi(one + 1);
|
||||
let _ = (x.powi(2) + y.powi(2)).sqrt();
|
||||
}
|
40
tests/ui/floating_point_powi.stderr
Normal file
40
tests/ui/floating_point_powi.stderr
Normal file
@ -0,0 +1,40 @@
|
||||
error: square can be computed more efficiently
|
||||
--> $DIR/floating_point_powi.rs:7:13
|
||||
|
|
||||
LL | let _ = x.powi(2);
|
||||
| ^^^^^^^^^ help: consider using: `x * x`
|
||||
|
|
||||
= note: `-D clippy::suboptimal-flops` implied by `-D warnings`
|
||||
|
||||
error: square can be computed more efficiently
|
||||
--> $DIR/floating_point_powi.rs:8:13
|
||||
|
|
||||
LL | let _ = x.powi(1 + 1);
|
||||
| ^^^^^^^^^^^^^ help: consider using: `x * x`
|
||||
|
||||
error: square can be computed more efficiently
|
||||
--> $DIR/floating_point_powi.rs:11:13
|
||||
|
|
||||
LL | let _ = x.powi(2) + y;
|
||||
| ^^^^^^^^^^^^^ help: consider using: `x.mul_add(x, y)`
|
||||
|
||||
error: square can be computed more efficiently
|
||||
--> $DIR/floating_point_powi.rs:12:13
|
||||
|
|
||||
LL | let _ = x + y.powi(2);
|
||||
| ^^^^^^^^^^^^^ help: consider using: `y.mul_add(y, x)`
|
||||
|
||||
error: square can be computed more efficiently
|
||||
--> $DIR/floating_point_powi.rs:13:13
|
||||
|
|
||||
LL | let _ = (x.powi(2) + y).sqrt();
|
||||
| ^^^^^^^^^^^^^^^ help: consider using: `x.mul_add(x, y)`
|
||||
|
||||
error: square can be computed more efficiently
|
||||
--> $DIR/floating_point_powi.rs:14:13
|
||||
|
|
||||
LL | let _ = (x + y.powi(2)).sqrt();
|
||||
| ^^^^^^^^^^^^^^^ help: consider using: `y.mul_add(y, x)`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
13
tests/ui/floating_point_rad.fixed
Normal file
13
tests/ui/floating_point_rad.fixed
Normal file
@ -0,0 +1,13 @@
|
||||
// run-rustfix
|
||||
#![warn(clippy::suboptimal_flops)]
|
||||
|
||||
fn main() {
|
||||
let x = 3f32;
|
||||
let _ = x.to_degrees();
|
||||
let _ = x.to_radians();
|
||||
// Cases where the lint shouldn't be applied
|
||||
let _ = x * 90f32 / std::f32::consts::PI;
|
||||
let _ = x * std::f32::consts::PI / 90f32;
|
||||
let _ = x * 180f32 / std::f32::consts::E;
|
||||
let _ = x * std::f32::consts::E / 180f32;
|
||||
}
|
13
tests/ui/floating_point_rad.rs
Normal file
13
tests/ui/floating_point_rad.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// run-rustfix
|
||||
#![warn(clippy::suboptimal_flops)]
|
||||
|
||||
fn main() {
|
||||
let x = 3f32;
|
||||
let _ = x * 180f32 / std::f32::consts::PI;
|
||||
let _ = x * std::f32::consts::PI / 180f32;
|
||||
// Cases where the lint shouldn't be applied
|
||||
let _ = x * 90f32 / std::f32::consts::PI;
|
||||
let _ = x * std::f32::consts::PI / 90f32;
|
||||
let _ = x * 180f32 / std::f32::consts::E;
|
||||
let _ = x * std::f32::consts::E / 180f32;
|
||||
}
|
16
tests/ui/floating_point_rad.stderr
Normal file
16
tests/ui/floating_point_rad.stderr
Normal file
@ -0,0 +1,16 @@
|
||||
error: conversion to degrees can be done more accurately
|
||||
--> $DIR/floating_point_rad.rs:6:13
|
||||
|
|
||||
LL | let _ = x * 180f32 / std::f32::consts::PI;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_degrees()`
|
||||
|
|
||||
= note: `-D clippy::suboptimal-flops` implied by `-D warnings`
|
||||
|
||||
error: conversion to radians can be done more accurately
|
||||
--> $DIR/floating_point_rad.rs:7:13
|
||||
|
|
||||
LL | let _ = x * std::f32::consts::PI / 180f32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_radians()`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -7,6 +7,7 @@ fn f() -> usize {
|
||||
}
|
||||
|
||||
#[warn(clippy::range_plus_one)]
|
||||
#[warn(clippy::range_minus_one)]
|
||||
fn main() {
|
||||
for _ in 0..2 {}
|
||||
for _ in 0..=2 {}
|
||||
|
@ -7,6 +7,7 @@ fn f() -> usize {
|
||||
}
|
||||
|
||||
#[warn(clippy::range_plus_one)]
|
||||
#[warn(clippy::range_minus_one)]
|
||||
fn main() {
|
||||
for _ in 0..2 {}
|
||||
for _ in 0..=2 {}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: an inclusive range would be more readable
|
||||
--> $DIR/range_plus_minus_one.rs:14:14
|
||||
--> $DIR/range_plus_minus_one.rs:15:14
|
||||
|
|
||||
LL | for _ in 0..3 + 1 {}
|
||||
| ^^^^^^^^ help: use: `0..=3`
|
||||
@ -7,25 +7,25 @@ LL | for _ in 0..3 + 1 {}
|
||||
= note: `-D clippy::range-plus-one` implied by `-D warnings`
|
||||
|
||||
error: an inclusive range would be more readable
|
||||
--> $DIR/range_plus_minus_one.rs:17:14
|
||||
--> $DIR/range_plus_minus_one.rs:18:14
|
||||
|
|
||||
LL | for _ in 0..1 + 5 {}
|
||||
| ^^^^^^^^ help: use: `0..=5`
|
||||
|
||||
error: an inclusive range would be more readable
|
||||
--> $DIR/range_plus_minus_one.rs:20:14
|
||||
--> $DIR/range_plus_minus_one.rs:21:14
|
||||
|
|
||||
LL | for _ in 1..1 + 1 {}
|
||||
| ^^^^^^^^ help: use: `1..=1`
|
||||
|
||||
error: an inclusive range would be more readable
|
||||
--> $DIR/range_plus_minus_one.rs:26:14
|
||||
--> $DIR/range_plus_minus_one.rs:27:14
|
||||
|
|
||||
LL | for _ in 0..(1 + f()) {}
|
||||
| ^^^^^^^^^^^^ help: use: `0..=f()`
|
||||
|
||||
error: an exclusive range would be more readable
|
||||
--> $DIR/range_plus_minus_one.rs:30:13
|
||||
--> $DIR/range_plus_minus_one.rs:31:13
|
||||
|
|
||||
LL | let _ = ..=11 - 1;
|
||||
| ^^^^^^^^^ help: use: `..11`
|
||||
@ -33,25 +33,25 @@ LL | let _ = ..=11 - 1;
|
||||
= note: `-D clippy::range-minus-one` implied by `-D warnings`
|
||||
|
||||
error: an exclusive range would be more readable
|
||||
--> $DIR/range_plus_minus_one.rs:31:13
|
||||
--> $DIR/range_plus_minus_one.rs:32:13
|
||||
|
|
||||
LL | let _ = ..=(11 - 1);
|
||||
| ^^^^^^^^^^^ help: use: `..11`
|
||||
|
||||
error: an inclusive range would be more readable
|
||||
--> $DIR/range_plus_minus_one.rs:32:13
|
||||
--> $DIR/range_plus_minus_one.rs:33:13
|
||||
|
|
||||
LL | let _ = (1..11 + 1);
|
||||
| ^^^^^^^^^^^ help: use: `(1..=11)`
|
||||
|
||||
error: an inclusive range would be more readable
|
||||
--> $DIR/range_plus_minus_one.rs:33:13
|
||||
--> $DIR/range_plus_minus_one.rs:34:13
|
||||
|
|
||||
LL | let _ = (f() + 1)..(f() + 1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: use: `((f() + 1)..=f())`
|
||||
|
||||
error: an inclusive range would be more readable
|
||||
--> $DIR/range_plus_minus_one.rs:37:14
|
||||
--> $DIR/range_plus_minus_one.rs:38:14
|
||||
|
|
||||
LL | for _ in 1..ONE + ONE {}
|
||||
| ^^^^^^^^^^^^ help: use: `1..=ONE`
|
||||
|
@ -2,11 +2,11 @@
|
||||
|
||||
use std::cmp::Reverse;
|
||||
|
||||
fn id(x: isize) -> isize {
|
||||
x
|
||||
}
|
||||
fn unnecessary_sort_by() {
|
||||
fn id(x: isize) -> isize {
|
||||
x
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut vec: Vec<isize> = vec![3, 6, 1, 2, 5];
|
||||
// Forward examples
|
||||
vec.sort();
|
||||
@ -24,3 +24,41 @@ fn main() {
|
||||
vec.sort_by(|_, b| b.cmp(c));
|
||||
vec.sort_unstable_by(|a, _| a.cmp(c));
|
||||
}
|
||||
|
||||
// Should not be linted to avoid hitting https://github.com/rust-lang/rust/issues/34162
|
||||
mod issue_5754 {
|
||||
struct Test(String);
|
||||
|
||||
#[derive(PartialOrd, Ord, PartialEq, Eq)]
|
||||
struct Wrapper<'a>(&'a str);
|
||||
|
||||
impl Test {
|
||||
fn name(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
|
||||
fn wrapped(&self) -> Wrapper<'_> {
|
||||
Wrapper(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn test() {
|
||||
let mut args: Vec<Test> = vec![];
|
||||
|
||||
// Forward
|
||||
args.sort_by(|a, b| a.name().cmp(b.name()));
|
||||
args.sort_by(|a, b| a.wrapped().cmp(&b.wrapped()));
|
||||
args.sort_unstable_by(|a, b| a.name().cmp(b.name()));
|
||||
args.sort_unstable_by(|a, b| a.wrapped().cmp(&b.wrapped()));
|
||||
// Reverse
|
||||
args.sort_by(|a, b| b.name().cmp(a.name()));
|
||||
args.sort_by(|a, b| b.wrapped().cmp(&a.wrapped()));
|
||||
args.sort_unstable_by(|a, b| b.name().cmp(a.name()));
|
||||
args.sort_unstable_by(|a, b| b.wrapped().cmp(&a.wrapped()));
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unnecessary_sort_by();
|
||||
issue_5754::test();
|
||||
}
|
||||
|
@ -2,11 +2,11 @@
|
||||
|
||||
use std::cmp::Reverse;
|
||||
|
||||
fn id(x: isize) -> isize {
|
||||
x
|
||||
}
|
||||
fn unnecessary_sort_by() {
|
||||
fn id(x: isize) -> isize {
|
||||
x
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut vec: Vec<isize> = vec![3, 6, 1, 2, 5];
|
||||
// Forward examples
|
||||
vec.sort_by(|a, b| a.cmp(b));
|
||||
@ -24,3 +24,41 @@ fn main() {
|
||||
vec.sort_by(|_, b| b.cmp(c));
|
||||
vec.sort_unstable_by(|a, _| a.cmp(c));
|
||||
}
|
||||
|
||||
// Should not be linted to avoid hitting https://github.com/rust-lang/rust/issues/34162
|
||||
mod issue_5754 {
|
||||
struct Test(String);
|
||||
|
||||
#[derive(PartialOrd, Ord, PartialEq, Eq)]
|
||||
struct Wrapper<'a>(&'a str);
|
||||
|
||||
impl Test {
|
||||
fn name(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
|
||||
fn wrapped(&self) -> Wrapper<'_> {
|
||||
Wrapper(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn test() {
|
||||
let mut args: Vec<Test> = vec![];
|
||||
|
||||
// Forward
|
||||
args.sort_by(|a, b| a.name().cmp(b.name()));
|
||||
args.sort_by(|a, b| a.wrapped().cmp(&b.wrapped()));
|
||||
args.sort_unstable_by(|a, b| a.name().cmp(b.name()));
|
||||
args.sort_unstable_by(|a, b| a.wrapped().cmp(&b.wrapped()));
|
||||
// Reverse
|
||||
args.sort_by(|a, b| b.name().cmp(a.name()));
|
||||
args.sort_by(|a, b| b.wrapped().cmp(&a.wrapped()));
|
||||
args.sort_unstable_by(|a, b| b.name().cmp(a.name()));
|
||||
args.sort_unstable_by(|a, b| b.wrapped().cmp(&a.wrapped()));
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unnecessary_sort_by();
|
||||
issue_5754::test();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user