mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-27 15:11:30 +00:00
Auto merge of #4897 - krishna-veerareddy:issue-2040-accurate-float-functions, r=flip1995
Add lint to improve floating-point expressions Looks for floating-point expressions that can be expressed using built-in methods to improve accuracy, performance and/or succinctness. changelog: Add lint `floating_point_improvements`. Fixes #4726 Partly addresses [#2040](https://github.com/rust-lang/rust-clippy/issues/2040) Currently linted expressions: | Expression | Suggestion | |---------------------------------|------------| | x.log(2.0) | x.log2() | | x.log(10.0) | x.log10() | | x.log(std::f32::consts::E) | x.ln() | | (1 + x).ln() | x.ln_1p() | | (2.0).powf(x) | x.exp2() | | (std::f32::consts::E).powf(x) | x.exp() | | x.powf(1/2) | x.sqrt() | | x.powf(1/3) | x.cbrt() | | x.powf(y), where y is whole | x.powi(y) | | x.exp() - 1 | x.exp_m1() | |x * y + z|x.mul_add(y, z)|
This commit is contained in:
commit
2734e4e1f7
23 changed files with 1092 additions and 263 deletions
|
@ -1169,6 +1169,7 @@ Released 2018-09-13
|
|||
[`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond
|
||||
[`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher
|
||||
[`implicit_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_return
|
||||
[`imprecise_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#imprecise_flops
|
||||
[`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping
|
||||
[`indexing_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing
|
||||
[`ineffective_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_bit_mask
|
||||
|
@ -1210,7 +1211,6 @@ Released 2018-09-13
|
|||
[`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal
|
||||
[`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion
|
||||
[`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy
|
||||
[`manual_mul_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_mul_add
|
||||
[`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic
|
||||
[`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap
|
||||
[`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names
|
||||
|
@ -1349,6 +1349,7 @@ Released 2018-09-13
|
|||
[`string_lit_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_lit_as_bytes
|
||||
[`string_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_to_string
|
||||
[`struct_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools
|
||||
[`suboptimal_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#suboptimal_flops
|
||||
[`suspicious_arithmetic_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_arithmetic_impl
|
||||
[`suspicious_assignment_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_assignment_formatting
|
||||
[`suspicious_else_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_else_formatting
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
|
||||
|
||||
[There are 357 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
|
||||
[There are 358 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
|
||||
|
||||
We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:
|
||||
|
||||
|
|
380
clippy_lints/src/floating_point_arithmetic.rs
Normal file
380
clippy_lints/src/floating_point_arithmetic.rs
Normal file
|
@ -0,0 +1,380 @@
|
|||
use crate::consts::{
|
||||
constant, Constant,
|
||||
Constant::{F32, F64},
|
||||
};
|
||||
use crate::utils::{span_lint_and_sugg, sugg};
|
||||
use if_chain::if_chain;
|
||||
use rustc::ty;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::source_map::Spanned;
|
||||
|
||||
use std::f32::consts as f32_consts;
|
||||
use std::f64::consts as f64_consts;
|
||||
use sugg::{format_numeric_literal, Sugg};
|
||||
use syntax::ast;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Looks for floating-point expressions that
|
||||
/// can be expressed using built-in methods to improve accuracy
|
||||
/// at the cost of performance.
|
||||
///
|
||||
/// **Why is this bad?** Negatively impacts accuracy.
|
||||
///
|
||||
/// **Known problems:** None
|
||||
///
|
||||
/// **Example:**
|
||||
///
|
||||
/// ```rust
|
||||
///
|
||||
/// let a = 3f32;
|
||||
/// let _ = a.powf(1.0 / 3.0);
|
||||
/// let _ = (1.0 + a).ln();
|
||||
/// let _ = a.exp() - 1.0;
|
||||
/// ```
|
||||
///
|
||||
/// is better expressed as
|
||||
///
|
||||
/// ```rust
|
||||
///
|
||||
/// let a = 3f32;
|
||||
/// let _ = a.cbrt();
|
||||
/// let _ = a.ln_1p();
|
||||
/// let _ = a.exp_m1();
|
||||
/// ```
|
||||
pub IMPRECISE_FLOPS,
|
||||
nursery,
|
||||
"usage of imprecise floating point operations"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Looks for floating-point expressions that
|
||||
/// can be expressed using built-in methods to improve both
|
||||
/// accuracy and performance.
|
||||
///
|
||||
/// **Why is this bad?** Negatively impacts accuracy and performance.
|
||||
///
|
||||
/// **Known problems:** None
|
||||
///
|
||||
/// **Example:**
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::f32::consts::E;
|
||||
///
|
||||
/// let a = 3f32;
|
||||
/// let _ = (2f32).powf(a);
|
||||
/// let _ = E.powf(a);
|
||||
/// let _ = a.powf(1.0 / 2.0);
|
||||
/// let _ = a.log(2.0);
|
||||
/// let _ = a.log(10.0);
|
||||
/// let _ = a.log(E);
|
||||
/// let _ = a.powf(2.0);
|
||||
/// let _ = a * 2.0 + 4.0;
|
||||
/// ```
|
||||
///
|
||||
/// is better expressed as
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::f32::consts::E;
|
||||
///
|
||||
/// let a = 3f32;
|
||||
/// let _ = a.exp2();
|
||||
/// let _ = a.exp();
|
||||
/// let _ = a.sqrt();
|
||||
/// let _ = a.log2();
|
||||
/// let _ = a.log10();
|
||||
/// let _ = a.ln();
|
||||
/// let _ = a.powi(2);
|
||||
/// let _ = a.mul_add(2.0, 4.0);
|
||||
/// ```
|
||||
pub SUBOPTIMAL_FLOPS,
|
||||
nursery,
|
||||
"usage of sub-optimal floating point operations"
|
||||
}
|
||||
|
||||
declare_lint_pass!(FloatingPointArithmetic => [
|
||||
IMPRECISE_FLOPS,
|
||||
SUBOPTIMAL_FLOPS
|
||||
]);
|
||||
|
||||
// Returns the specialized log method for a given base if base is constant
|
||||
// and is one of 2, 10 and e
|
||||
fn get_specialized_log_method(cx: &LateContext<'_, '_>, base: &Expr<'_>) -> Option<&'static str> {
|
||||
if let Some((value, _)) = constant(cx, cx.tables, base) {
|
||||
if F32(2.0) == value || F64(2.0) == value {
|
||||
return Some("log2");
|
||||
} else if F32(10.0) == value || F64(10.0) == value {
|
||||
return Some("log10");
|
||||
} else if F32(f32_consts::E) == value || F64(f64_consts::E) == value {
|
||||
return Some("ln");
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
// Adds type suffixes and parenthesis to method receivers if necessary
|
||||
fn prepare_receiver_sugg<'a>(cx: &LateContext<'_, '_>, mut expr: &'a Expr<'a>) -> Sugg<'a> {
|
||||
let mut suggestion = Sugg::hir(cx, expr, "..");
|
||||
|
||||
if let ExprKind::Unary(UnOp::UnNeg, inner_expr) = &expr.kind {
|
||||
expr = &inner_expr;
|
||||
}
|
||||
|
||||
if_chain! {
|
||||
// if the expression is a float literal and it is unsuffixed then
|
||||
// add a suffix so the suggestion is valid and unambiguous
|
||||
if let ty::Float(float_ty) = cx.tables.expr_ty(expr).kind;
|
||||
if let ExprKind::Lit(lit) = &expr.kind;
|
||||
if let ast::LitKind::Float(sym, ast::LitFloatType::Unsuffixed) = lit.node;
|
||||
then {
|
||||
let op = format!(
|
||||
"{}{}{}",
|
||||
suggestion,
|
||||
// Check for float literals without numbers following the decimal
|
||||
// separator such as `2.` and adds a trailing zero
|
||||
if sym.as_str().ends_with('.') {
|
||||
"0"
|
||||
} else {
|
||||
""
|
||||
},
|
||||
float_ty.name_str()
|
||||
).into();
|
||||
|
||||
suggestion = match suggestion {
|
||||
Sugg::MaybeParen(_) => Sugg::MaybeParen(op),
|
||||
_ => Sugg::NonParen(op)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
suggestion.maybe_par()
|
||||
}
|
||||
|
||||
fn check_log_base(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
|
||||
if let Some(method) = get_specialized_log_method(cx, &args[1]) {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
SUBOPTIMAL_FLOPS,
|
||||
expr.span,
|
||||
"logarithm for bases 2, 10 and e can be computed more accurately",
|
||||
"consider using",
|
||||
format!("{}.{}()", Sugg::hir(cx, &args[0], ".."), method),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Lint expressions of the form `(x + y).ln()` where y > 1 and
|
||||
// suggest usage of `(x + (y - 1)).ln_1p()` instead
|
||||
fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
|
||||
if let ExprKind::Binary(
|
||||
Spanned {
|
||||
node: BinOpKind::Add, ..
|
||||
},
|
||||
lhs,
|
||||
rhs,
|
||||
) = &args[0].kind
|
||||
{
|
||||
let recv = match (constant(cx, cx.tables, lhs), constant(cx, cx.tables, rhs)) {
|
||||
(Some((value, _)), _) if F32(1.0) == value || F64(1.0) == value => rhs,
|
||||
(_, Some((value, _))) if F32(1.0) == value || F64(1.0) == value => lhs,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
IMPRECISE_FLOPS,
|
||||
expr.span,
|
||||
"ln(1 + x) can be computed more accurately",
|
||||
"consider using",
|
||||
format!("{}.ln_1p()", prepare_receiver_sugg(cx, recv)),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns an integer if the float constant is a whole number and it can be
|
||||
// converted to an integer without loss of precision. For now we only check
|
||||
// ranges [-16777215, 16777216) for type f32 as whole number floats outside
|
||||
// this range are lossy and ambiguous.
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
fn get_integer_from_float_constant(value: &Constant) -> Option<i32> {
|
||||
match value {
|
||||
F32(num) if num.fract() == 0.0 => {
|
||||
if (-16_777_215.0..16_777_216.0).contains(num) {
|
||||
Some(num.round() as i32)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
F64(num) if num.fract() == 0.0 => {
|
||||
if (-2_147_483_648.0..2_147_483_648.0).contains(num) {
|
||||
Some(num.round() as i32)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
|
||||
// Check receiver
|
||||
if let Some((value, _)) = constant(cx, cx.tables, &args[0]) {
|
||||
let method = if F32(f32_consts::E) == value || F64(f64_consts::E) == value {
|
||||
"exp"
|
||||
} else if F32(2.0) == value || F64(2.0) == value {
|
||||
"exp2"
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
SUBOPTIMAL_FLOPS,
|
||||
expr.span,
|
||||
"exponent for bases 2 and e can be computed more accurately",
|
||||
"consider using",
|
||||
format!("{}.{}()", prepare_receiver_sugg(cx, &args[1]), method),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
|
||||
// Check argument
|
||||
if let Some((value, _)) = constant(cx, cx.tables, &args[1]) {
|
||||
let (lint, help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value {
|
||||
(
|
||||
SUBOPTIMAL_FLOPS,
|
||||
"square-root of a number can be computed more efficiently and accurately",
|
||||
format!("{}.sqrt()", Sugg::hir(cx, &args[0], "..")),
|
||||
)
|
||||
} else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value {
|
||||
(
|
||||
IMPRECISE_FLOPS,
|
||||
"cube-root of a number can be computed more accurately",
|
||||
format!("{}.cbrt()", Sugg::hir(cx, &args[0], "..")),
|
||||
)
|
||||
} else if let Some(exponent) = get_integer_from_float_constant(&value) {
|
||||
(
|
||||
SUBOPTIMAL_FLOPS,
|
||||
"exponentiation with integer powers can be computed more efficiently",
|
||||
format!(
|
||||
"{}.powi({})",
|
||||
Sugg::hir(cx, &args[0], ".."),
|
||||
format_numeric_literal(&exponent.to_string(), None, false)
|
||||
),
|
||||
)
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
lint,
|
||||
expr.span,
|
||||
help,
|
||||
"consider using",
|
||||
suggestion,
|
||||
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<'_>) {
|
||||
if_chain! {
|
||||
if let ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, ref lhs, ref rhs) = expr.kind;
|
||||
if cx.tables.expr_ty(lhs).is_floating_point();
|
||||
if let Some((value, _)) = constant(cx, cx.tables, rhs);
|
||||
if F32(1.0) == value || F64(1.0) == value;
|
||||
if let ExprKind::MethodCall(ref path, _, ref method_args) = lhs.kind;
|
||||
if cx.tables.expr_ty(&method_args[0]).is_floating_point();
|
||||
if path.ident.name.as_str() == "exp";
|
||||
then {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
IMPRECISE_FLOPS,
|
||||
expr.span,
|
||||
"(e.pow(x) - 1) can be computed more accurately",
|
||||
"consider using",
|
||||
format!(
|
||||
"{}.exp_m1()",
|
||||
Sugg::hir(cx, &method_args[0], "..")
|
||||
),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_float_mul_expr<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr<'a>) -> Option<(&'a Expr<'a>, &'a Expr<'a>)> {
|
||||
if_chain! {
|
||||
if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref lhs, ref rhs) = &expr.kind;
|
||||
if cx.tables.expr_ty(lhs).is_floating_point();
|
||||
if cx.tables.expr_ty(rhs).is_floating_point();
|
||||
then {
|
||||
return Some((lhs, rhs));
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
// TODO: Fix rust-lang/rust-clippy#4735
|
||||
fn check_mul_add(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
|
||||
if let ExprKind::Binary(
|
||||
Spanned {
|
||||
node: BinOpKind::Add, ..
|
||||
},
|
||||
lhs,
|
||||
rhs,
|
||||
) = &expr.kind
|
||||
{
|
||||
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) {
|
||||
(inner_lhs, inner_rhs, lhs)
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
SUBOPTIMAL_FLOPS,
|
||||
expr.span,
|
||||
"multiply and add expressions can be calculated more efficiently and accurately",
|
||||
"consider using",
|
||||
format!(
|
||||
"{}.mul_add({}, {})",
|
||||
prepare_receiver_sugg(cx, recv),
|
||||
Sugg::hir(cx, arg1, ".."),
|
||||
Sugg::hir(cx, arg2, ".."),
|
||||
),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic {
|
||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if let ExprKind::MethodCall(ref path, _, args) = &expr.kind {
|
||||
let recv_ty = cx.tables.expr_ty(&args[0]);
|
||||
|
||||
if recv_ty.is_floating_point() {
|
||||
match &*path.ident.name.as_str() {
|
||||
"ln" => check_ln1p(cx, expr, args),
|
||||
"log" => check_log_base(cx, expr, args),
|
||||
"powf" => check_powf(cx, expr, args),
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
} else {
|
||||
check_expm1(cx, expr);
|
||||
check_mul_add(cx, expr);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -208,6 +208,7 @@ pub mod exit;
|
|||
pub mod explicit_write;
|
||||
pub mod fallible_impl_from;
|
||||
pub mod float_literal;
|
||||
pub mod floating_point_arithmetic;
|
||||
pub mod format;
|
||||
pub mod formatting;
|
||||
pub mod functions;
|
||||
|
@ -248,7 +249,6 @@ pub mod missing_const_for_fn;
|
|||
pub mod missing_doc;
|
||||
pub mod missing_inline;
|
||||
pub mod modulo_arithmetic;
|
||||
pub mod mul_add;
|
||||
pub mod multiple_crate_versions;
|
||||
pub mod mut_key;
|
||||
pub mod mut_mut;
|
||||
|
@ -538,6 +538,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
&fallible_impl_from::FALLIBLE_IMPL_FROM,
|
||||
&float_literal::EXCESSIVE_PRECISION,
|
||||
&float_literal::LOSSY_FLOAT_LITERAL,
|
||||
&floating_point_arithmetic::IMPRECISE_FLOPS,
|
||||
&floating_point_arithmetic::SUBOPTIMAL_FLOPS,
|
||||
&format::USELESS_FORMAT,
|
||||
&formatting::POSSIBLE_MISSING_COMMA,
|
||||
&formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING,
|
||||
|
@ -690,7 +692,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
&missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS,
|
||||
&missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS,
|
||||
&modulo_arithmetic::MODULO_ARITHMETIC,
|
||||
&mul_add::MANUAL_MUL_ADD,
|
||||
&multiple_crate_versions::MULTIPLE_CRATE_VERSIONS,
|
||||
&mut_key::MUTABLE_KEY_TYPE,
|
||||
&mut_mut::MUT_MUT,
|
||||
|
@ -966,7 +967,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
store.register_late_pass(|| box inherent_to_string::InherentToString);
|
||||
store.register_late_pass(|| box trait_bounds::TraitBounds);
|
||||
store.register_late_pass(|| box comparison_chain::ComparisonChain);
|
||||
store.register_late_pass(|| box mul_add::MulAddCheck);
|
||||
store.register_late_pass(|| box mut_key::MutableKeyType);
|
||||
store.register_late_pass(|| box modulo_arithmetic::ModuloArithmetic);
|
||||
store.register_early_pass(|| box reference::DerefAddrOf);
|
||||
|
@ -1000,6 +1000,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
store.register_late_pass(|| box to_digit_is_some::ToDigitIsSome);
|
||||
let array_size_threshold = conf.array_size_threshold;
|
||||
store.register_late_pass(move || box large_stack_arrays::LargeStackArrays::new(array_size_threshold));
|
||||
store.register_late_pass(move || box floating_point_arithmetic::FloatingPointArithmetic);
|
||||
store.register_early_pass(|| box as_conversions::AsConversions);
|
||||
store.register_early_pass(|| box utils::internal_lints::ProduceIce);
|
||||
store.register_late_pass(|| box let_underscore::LetUnderscore);
|
||||
|
@ -1648,8 +1649,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
|
||||
LintId::of(&attrs::EMPTY_LINE_AFTER_OUTER_ATTR),
|
||||
LintId::of(&fallible_impl_from::FALLIBLE_IMPL_FROM),
|
||||
LintId::of(&floating_point_arithmetic::IMPRECISE_FLOPS),
|
||||
LintId::of(&floating_point_arithmetic::SUBOPTIMAL_FLOPS),
|
||||
LintId::of(&missing_const_for_fn::MISSING_CONST_FOR_FN),
|
||||
LintId::of(&mul_add::MANUAL_MUL_ADD),
|
||||
LintId::of(&mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL),
|
||||
LintId::of(&mutex_atomic::MUTEX_INTEGER),
|
||||
LintId::of(&needless_borrow::NEEDLESS_BORROW),
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
|
||||
use crate::utils::{snippet, span_lint_and_sugg};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for expressions of the form `a * b + c`
|
||||
/// or `c + a * b` where `a`, `b`, `c` are floats and suggests using
|
||||
/// `a.mul_add(b, c)` instead.
|
||||
///
|
||||
/// **Why is this bad?** Calculating `a * b + c` may lead to slight
|
||||
/// numerical inaccuracies as `a * b` is rounded before being added to
|
||||
/// `c`. Depending on the target architecture, `mul_add()` may be more
|
||||
/// performant.
|
||||
///
|
||||
/// **Known problems:** This lint can emit semantic incorrect suggestions.
|
||||
/// For example, for `a * b * c + d` the suggestion `a * b.mul_add(c, d)`
|
||||
/// is emitted, which is equivalent to `a * (b * c + d)`. (#4735)
|
||||
///
|
||||
/// **Example:**
|
||||
///
|
||||
/// ```rust
|
||||
/// # let a = 0_f32;
|
||||
/// # let b = 0_f32;
|
||||
/// # let c = 0_f32;
|
||||
/// let foo = (a * b) + c;
|
||||
/// ```
|
||||
///
|
||||
/// can be written as
|
||||
///
|
||||
/// ```rust
|
||||
/// # let a = 0_f32;
|
||||
/// # let b = 0_f32;
|
||||
/// # let c = 0_f32;
|
||||
/// let foo = a.mul_add(b, c);
|
||||
/// ```
|
||||
pub MANUAL_MUL_ADD,
|
||||
nursery,
|
||||
"Using `a.mul_add(b, c)` for floating points has higher numerical precision than `a * b + c`"
|
||||
}
|
||||
|
||||
declare_lint_pass!(MulAddCheck => [MANUAL_MUL_ADD]);
|
||||
|
||||
fn is_float<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>) -> bool {
|
||||
cx.tables.expr_ty(expr).is_floating_point()
|
||||
}
|
||||
|
||||
// Checks whether expression is multiplication of two floats
|
||||
fn is_float_mult_expr<'a, 'tcx, 'b>(
|
||||
cx: &LateContext<'a, 'tcx>,
|
||||
expr: &'b Expr<'b>,
|
||||
) -> Option<(&'b Expr<'b>, &'b Expr<'b>)> {
|
||||
if let ExprKind::Binary(op, lhs, rhs) = &expr.kind {
|
||||
if let BinOpKind::Mul = op.node {
|
||||
if is_float(cx, &lhs) && is_float(cx, &rhs) {
|
||||
return Some((&lhs, &rhs));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MulAddCheck {
|
||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if let ExprKind::Binary(op, lhs, rhs) = &expr.kind {
|
||||
if let BinOpKind::Add = op.node {
|
||||
//Converts mult_lhs * mult_rhs + rhs to mult_lhs.mult_add(mult_rhs, rhs)
|
||||
if let Some((mult_lhs, mult_rhs)) = is_float_mult_expr(cx, lhs) {
|
||||
if is_float(cx, rhs) {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
MANUAL_MUL_ADD,
|
||||
expr.span,
|
||||
"consider using `mul_add()` for better numerical precision",
|
||||
"try",
|
||||
format!(
|
||||
"{}.mul_add({}, {})",
|
||||
snippet(cx, mult_lhs.span, "_"),
|
||||
snippet(cx, mult_rhs.span, "_"),
|
||||
snippet(cx, rhs.span, "_"),
|
||||
),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
//Converts lhs + mult_lhs * mult_rhs to mult_lhs.mult_add(mult_rhs, lhs)
|
||||
if let Some((mult_lhs, mult_rhs)) = is_float_mult_expr(cx, rhs) {
|
||||
if is_float(cx, lhs) {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
MANUAL_MUL_ADD,
|
||||
expr.span,
|
||||
"consider using `mul_add()` for better numerical precision",
|
||||
"try",
|
||||
format!(
|
||||
"{}.mul_add({}, {})",
|
||||
snippet(cx, mult_lhs.span, "_"),
|
||||
snippet(cx, mult_rhs.span, "_"),
|
||||
snippet(cx, lhs.span, "_"),
|
||||
),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ pub use lint::Lint;
|
|||
pub use lint::LINT_LEVELS;
|
||||
|
||||
// begin lint list, do not remove this comment, it’s used in `update_lints`
|
||||
pub const ALL_LINTS: [Lint; 357] = [
|
||||
pub const ALL_LINTS: [Lint; 358] = [
|
||||
Lint {
|
||||
name: "absurd_extreme_comparisons",
|
||||
group: "correctness",
|
||||
|
@ -749,6 +749,13 @@ pub const ALL_LINTS: [Lint; 357] = [
|
|||
deprecation: None,
|
||||
module: "implicit_return",
|
||||
},
|
||||
Lint {
|
||||
name: "imprecise_flops",
|
||||
group: "nursery",
|
||||
desc: "usage of imprecise floating point operations",
|
||||
deprecation: None,
|
||||
module: "floating_point_arithmetic",
|
||||
},
|
||||
Lint {
|
||||
name: "inconsistent_digit_grouping",
|
||||
group: "style",
|
||||
|
@ -1022,13 +1029,6 @@ pub const ALL_LINTS: [Lint; 357] = [
|
|||
deprecation: None,
|
||||
module: "loops",
|
||||
},
|
||||
Lint {
|
||||
name: "manual_mul_add",
|
||||
group: "nursery",
|
||||
desc: "Using `a.mul_add(b, c)` for floating points has higher numerical precision than `a * b + c`",
|
||||
deprecation: None,
|
||||
module: "mul_add",
|
||||
},
|
||||
Lint {
|
||||
name: "manual_saturating_arithmetic",
|
||||
group: "style",
|
||||
|
@ -1960,6 +1960,13 @@ pub const ALL_LINTS: [Lint; 357] = [
|
|||
deprecation: None,
|
||||
module: "excessive_bools",
|
||||
},
|
||||
Lint {
|
||||
name: "suboptimal_flops",
|
||||
group: "nursery",
|
||||
desc: "usage of sub-optimal floating point operations",
|
||||
deprecation: None,
|
||||
module: "floating_point_arithmetic",
|
||||
},
|
||||
Lint {
|
||||
name: "suspicious_arithmetic_impl",
|
||||
group: "correctness",
|
||||
|
|
18
tests/ui/floating_point_exp.fixed
Normal file
18
tests/ui/floating_point_exp.fixed
Normal file
|
@ -0,0 +1,18 @@
|
|||
// run-rustfix
|
||||
#![warn(clippy::imprecise_flops)]
|
||||
|
||||
fn main() {
|
||||
let x = 2f32;
|
||||
let _ = x.exp_m1();
|
||||
let _ = x.exp_m1() + 2.0;
|
||||
// Cases where the lint shouldn't be applied
|
||||
let _ = x.exp() - 2.0;
|
||||
let _ = x.exp() - 1.0 * 2.0;
|
||||
|
||||
let x = 2f64;
|
||||
let _ = x.exp_m1();
|
||||
let _ = x.exp_m1() + 2.0;
|
||||
// Cases where the lint shouldn't be applied
|
||||
let _ = x.exp() - 2.0;
|
||||
let _ = x.exp() - 1.0 * 2.0;
|
||||
}
|
18
tests/ui/floating_point_exp.rs
Normal file
18
tests/ui/floating_point_exp.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
// run-rustfix
|
||||
#![warn(clippy::imprecise_flops)]
|
||||
|
||||
fn main() {
|
||||
let x = 2f32;
|
||||
let _ = x.exp() - 1.0;
|
||||
let _ = x.exp() - 1.0 + 2.0;
|
||||
// Cases where the lint shouldn't be applied
|
||||
let _ = x.exp() - 2.0;
|
||||
let _ = x.exp() - 1.0 * 2.0;
|
||||
|
||||
let x = 2f64;
|
||||
let _ = x.exp() - 1.0;
|
||||
let _ = x.exp() - 1.0 + 2.0;
|
||||
// Cases where the lint shouldn't be applied
|
||||
let _ = x.exp() - 2.0;
|
||||
let _ = x.exp() - 1.0 * 2.0;
|
||||
}
|
28
tests/ui/floating_point_exp.stderr
Normal file
28
tests/ui/floating_point_exp.stderr
Normal file
|
@ -0,0 +1,28 @@
|
|||
error: (e.pow(x) - 1) can be computed more accurately
|
||||
--> $DIR/floating_point_exp.rs:6:13
|
||||
|
|
||||
LL | let _ = x.exp() - 1.0;
|
||||
| ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()`
|
||||
|
|
||||
= note: `-D clippy::imprecise-flops` implied by `-D warnings`
|
||||
|
||||
error: (e.pow(x) - 1) can be computed more accurately
|
||||
--> $DIR/floating_point_exp.rs:7:13
|
||||
|
|
||||
LL | let _ = x.exp() - 1.0 + 2.0;
|
||||
| ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()`
|
||||
|
||||
error: (e.pow(x) - 1) can be computed more accurately
|
||||
--> $DIR/floating_point_exp.rs:13:13
|
||||
|
|
||||
LL | let _ = x.exp() - 1.0;
|
||||
| ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()`
|
||||
|
||||
error: (e.pow(x) - 1) can be computed more accurately
|
||||
--> $DIR/floating_point_exp.rs:14:13
|
||||
|
|
||||
LL | let _ = x.exp() - 1.0 + 2.0;
|
||||
| ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
58
tests/ui/floating_point_log.fixed
Normal file
58
tests/ui/floating_point_log.fixed
Normal file
|
@ -0,0 +1,58 @@
|
|||
// run-rustfix
|
||||
#![allow(dead_code, clippy::double_parens)]
|
||||
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
|
||||
|
||||
const TWO: f32 = 2.0;
|
||||
const E: f32 = std::f32::consts::E;
|
||||
|
||||
fn check_log_base() {
|
||||
let x = 1f32;
|
||||
let _ = x.log2();
|
||||
let _ = x.log10();
|
||||
let _ = x.ln();
|
||||
let _ = x.log2();
|
||||
let _ = x.ln();
|
||||
|
||||
let x = 1f64;
|
||||
let _ = x.log2();
|
||||
let _ = x.log10();
|
||||
let _ = x.ln();
|
||||
}
|
||||
|
||||
fn check_ln1p() {
|
||||
let x = 1f32;
|
||||
let _ = 2.0f32.ln_1p();
|
||||
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 _ = ((std::f32::consts::E - 1.0)).ln_1p();
|
||||
let _ = x.ln_1p();
|
||||
let _ = x.powi(2).ln_1p();
|
||||
let _ = (x + 2.0).ln_1p();
|
||||
let _ = (x / 2.0).ln_1p();
|
||||
// Cases where the lint shouldn't be applied
|
||||
let _ = (1.0 + x + 2.0).ln();
|
||||
let _ = (x + 1.0 + 2.0).ln();
|
||||
let _ = (x + 1.0 / 2.0).ln();
|
||||
let _ = (1.0 + x - 2.0).ln();
|
||||
|
||||
let x = 1f64;
|
||||
let _ = 2.0f64.ln_1p();
|
||||
let _ = 2.0f64.ln_1p();
|
||||
let _ = x.ln_1p();
|
||||
let _ = (x / 2.0).ln_1p();
|
||||
let _ = x.powi(2).ln_1p();
|
||||
let _ = x.ln_1p();
|
||||
let _ = x.powi(2).ln_1p();
|
||||
let _ = (x + 2.0).ln_1p();
|
||||
let _ = (x / 2.0).ln_1p();
|
||||
// Cases where the lint shouldn't be applied
|
||||
let _ = (1.0 + x + 2.0).ln();
|
||||
let _ = (x + 1.0 + 2.0).ln();
|
||||
let _ = (x + 1.0 / 2.0).ln();
|
||||
let _ = (1.0 + x - 2.0).ln();
|
||||
}
|
||||
|
||||
fn main() {}
|
58
tests/ui/floating_point_log.rs
Normal file
58
tests/ui/floating_point_log.rs
Normal file
|
@ -0,0 +1,58 @@
|
|||
// run-rustfix
|
||||
#![allow(dead_code, clippy::double_parens)]
|
||||
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
|
||||
|
||||
const TWO: f32 = 2.0;
|
||||
const E: f32 = std::f32::consts::E;
|
||||
|
||||
fn check_log_base() {
|
||||
let x = 1f32;
|
||||
let _ = x.log(2f32);
|
||||
let _ = x.log(10f32);
|
||||
let _ = x.log(std::f32::consts::E);
|
||||
let _ = x.log(TWO);
|
||||
let _ = x.log(E);
|
||||
|
||||
let x = 1f64;
|
||||
let _ = x.log(2f64);
|
||||
let _ = x.log(10f64);
|
||||
let _ = x.log(std::f64::consts::E);
|
||||
}
|
||||
|
||||
fn check_ln1p() {
|
||||
let x = 1f32;
|
||||
let _ = (1f32 + 2.).ln();
|
||||
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 + (std::f32::consts::E - 1.0)).ln();
|
||||
let _ = (x + 1.0).ln();
|
||||
let _ = (x.powi(2) + 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
|
||||
let _ = (1.0 + x + 2.0).ln();
|
||||
let _ = (x + 1.0 + 2.0).ln();
|
||||
let _ = (x + 1.0 / 2.0).ln();
|
||||
let _ = (1.0 + x - 2.0).ln();
|
||||
|
||||
let x = 1f64;
|
||||
let _ = (1f64 + 2.).ln();
|
||||
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 _ = (x + 1.0).ln();
|
||||
let _ = (x.powi(2) + 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
|
||||
let _ = (1.0 + x + 2.0).ln();
|
||||
let _ = (x + 1.0 + 2.0).ln();
|
||||
let _ = (x + 1.0 / 2.0).ln();
|
||||
let _ = (1.0 + x - 2.0).ln();
|
||||
}
|
||||
|
||||
fn main() {}
|
174
tests/ui/floating_point_log.stderr
Normal file
174
tests/ui/floating_point_log.stderr
Normal file
|
@ -0,0 +1,174 @@
|
|||
error: logarithm for bases 2, 10 and e can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:10:13
|
||||
|
|
||||
LL | let _ = x.log(2f32);
|
||||
| ^^^^^^^^^^^ help: consider using: `x.log2()`
|
||||
|
|
||||
= note: `-D clippy::suboptimal-flops` implied by `-D warnings`
|
||||
|
||||
error: logarithm for bases 2, 10 and e can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:11:13
|
||||
|
|
||||
LL | let _ = x.log(10f32);
|
||||
| ^^^^^^^^^^^^ help: consider using: `x.log10()`
|
||||
|
||||
error: logarithm for bases 2, 10 and e can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:12:13
|
||||
|
|
||||
LL | let _ = x.log(std::f32::consts::E);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.ln()`
|
||||
|
||||
error: logarithm for bases 2, 10 and e can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:13:13
|
||||
|
|
||||
LL | let _ = x.log(TWO);
|
||||
| ^^^^^^^^^^ help: consider using: `x.log2()`
|
||||
|
||||
error: logarithm for bases 2, 10 and e can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:14:13
|
||||
|
|
||||
LL | let _ = x.log(E);
|
||||
| ^^^^^^^^ help: consider using: `x.ln()`
|
||||
|
||||
error: logarithm for bases 2, 10 and e can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:17:13
|
||||
|
|
||||
LL | let _ = x.log(2f64);
|
||||
| ^^^^^^^^^^^ help: consider using: `x.log2()`
|
||||
|
||||
error: logarithm for bases 2, 10 and e can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:18:13
|
||||
|
|
||||
LL | let _ = x.log(10f64);
|
||||
| ^^^^^^^^^^^^ help: consider using: `x.log10()`
|
||||
|
||||
error: logarithm for bases 2, 10 and e can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:19:13
|
||||
|
|
||||
LL | let _ = x.log(std::f64::consts::E);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.ln()`
|
||||
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:24:13
|
||||
|
|
||||
LL | let _ = (1f32 + 2.).ln();
|
||||
| ^^^^^^^^^^^^^^^^ help: consider using: `2.0f32.ln_1p()`
|
||||
|
|
||||
= note: `-D clippy::imprecise-flops` implied by `-D warnings`
|
||||
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:25:13
|
||||
|
|
||||
LL | let _ = (1f32 + 2.0).ln();
|
||||
| ^^^^^^^^^^^^^^^^^ help: consider using: `2.0f32.ln_1p()`
|
||||
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:26:13
|
||||
|
|
||||
LL | let _ = (1.0 + x).ln();
|
||||
| ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()`
|
||||
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:27:13
|
||||
|
|
||||
LL | let _ = (1.0 + x / 2.0).ln();
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x / 2.0).ln_1p()`
|
||||
|
||||
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()`
|
||||
|
||||
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()`
|
||||
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:30:13
|
||||
|
|
||||
LL | let _ = (1.0 + (std::f32::consts::E - 1.0)).ln();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `((std::f32::consts::E - 1.0)).ln_1p()`
|
||||
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:31:13
|
||||
|
|
||||
LL | let _ = (x + 1.0).ln();
|
||||
| ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()`
|
||||
|
||||
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()`
|
||||
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:33:13
|
||||
|
|
||||
LL | let _ = (x + 2.0 + 1.0).ln();
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x + 2.0).ln_1p()`
|
||||
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:34:13
|
||||
|
|
||||
LL | let _ = (x / 2.0 + 1.0).ln();
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x / 2.0).ln_1p()`
|
||||
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:42:13
|
||||
|
|
||||
LL | let _ = (1f64 + 2.).ln();
|
||||
| ^^^^^^^^^^^^^^^^ help: consider using: `2.0f64.ln_1p()`
|
||||
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:43:13
|
||||
|
|
||||
LL | let _ = (1f64 + 2.0).ln();
|
||||
| ^^^^^^^^^^^^^^^^^ help: consider using: `2.0f64.ln_1p()`
|
||||
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:44:13
|
||||
|
|
||||
LL | let _ = (1.0 + x).ln();
|
||||
| ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()`
|
||||
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:45:13
|
||||
|
|
||||
LL | let _ = (1.0 + x / 2.0).ln();
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x / 2.0).ln_1p()`
|
||||
|
||||
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()`
|
||||
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:47:13
|
||||
|
|
||||
LL | let _ = (x + 1.0).ln();
|
||||
| ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()`
|
||||
|
||||
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()`
|
||||
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:49:13
|
||||
|
|
||||
LL | let _ = (x + 2.0 + 1.0).ln();
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x + 2.0).ln_1p()`
|
||||
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:50:13
|
||||
|
|
||||
LL | let _ = (x / 2.0 + 1.0).ln();
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x / 2.0).ln_1p()`
|
||||
|
||||
error: aborting due to 28 previous errors
|
||||
|
21
tests/ui/floating_point_mul_add.fixed
Normal file
21
tests/ui/floating_point_mul_add.fixed
Normal file
|
@ -0,0 +1,21 @@
|
|||
// run-rustfix
|
||||
#![warn(clippy::suboptimal_flops)]
|
||||
|
||||
fn main() {
|
||||
let a: f64 = 1234.567;
|
||||
let b: f64 = 45.67834;
|
||||
let c: f64 = 0.0004;
|
||||
let d: f64 = 0.0001;
|
||||
|
||||
let _ = a.mul_add(b, c);
|
||||
let _ = a.mul_add(b, c);
|
||||
let _ = 2.0f64.mul_add(4.0, a);
|
||||
let _ = 2.0f64.mul_add(4., a);
|
||||
|
||||
let _ = a.mul_add(b, c);
|
||||
let _ = a.mul_add(b, c);
|
||||
let _ = (a * b).mul_add(c, d);
|
||||
|
||||
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);
|
||||
}
|
21
tests/ui/floating_point_mul_add.rs
Normal file
21
tests/ui/floating_point_mul_add.rs
Normal file
|
@ -0,0 +1,21 @@
|
|||
// run-rustfix
|
||||
#![warn(clippy::suboptimal_flops)]
|
||||
|
||||
fn main() {
|
||||
let a: f64 = 1234.567;
|
||||
let b: f64 = 45.67834;
|
||||
let c: f64 = 0.0004;
|
||||
let d: f64 = 0.0001;
|
||||
|
||||
let _ = a * b + c;
|
||||
let _ = c + a * b;
|
||||
let _ = a + 2.0 * 4.0;
|
||||
let _ = a + 2. * 4.;
|
||||
|
||||
let _ = (a * b) + c;
|
||||
let _ = c + (a * b);
|
||||
let _ = a * b * c + d;
|
||||
|
||||
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;
|
||||
}
|
58
tests/ui/floating_point_mul_add.stderr
Normal file
58
tests/ui/floating_point_mul_add.stderr
Normal file
|
@ -0,0 +1,58 @@
|
|||
error: multiply and add expressions can be calculated more efficiently and accurately
|
||||
--> $DIR/floating_point_mul_add.rs:10:13
|
||||
|
|
||||
LL | let _ = a * b + c;
|
||||
| ^^^^^^^^^ help: consider using: `a.mul_add(b, c)`
|
||||
|
|
||||
= note: `-D clippy::suboptimal-flops` implied by `-D warnings`
|
||||
|
||||
error: multiply and add expressions can be calculated more efficiently and accurately
|
||||
--> $DIR/floating_point_mul_add.rs:11:13
|
||||
|
|
||||
LL | let _ = c + a * b;
|
||||
| ^^^^^^^^^ help: consider using: `a.mul_add(b, c)`
|
||||
|
||||
error: multiply and add expressions can be calculated more efficiently and accurately
|
||||
--> $DIR/floating_point_mul_add.rs:12:13
|
||||
|
|
||||
LL | let _ = a + 2.0 * 4.0;
|
||||
| ^^^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4.0, a)`
|
||||
|
||||
error: multiply and add expressions can be calculated more efficiently and accurately
|
||||
--> $DIR/floating_point_mul_add.rs:13:13
|
||||
|
|
||||
LL | let _ = a + 2. * 4.;
|
||||
| ^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4., a)`
|
||||
|
||||
error: multiply and add expressions can be calculated more efficiently and accurately
|
||||
--> $DIR/floating_point_mul_add.rs:15:13
|
||||
|
|
||||
LL | let _ = (a * b) + c;
|
||||
| ^^^^^^^^^^^ help: consider using: `a.mul_add(b, c)`
|
||||
|
||||
error: multiply and add expressions can be calculated more efficiently and accurately
|
||||
--> $DIR/floating_point_mul_add.rs:16:13
|
||||
|
|
||||
LL | let _ = c + (a * b);
|
||||
| ^^^^^^^^^^^ help: consider using: `a.mul_add(b, c)`
|
||||
|
||||
error: multiply and add expressions can be calculated more efficiently and accurately
|
||||
--> $DIR/floating_point_mul_add.rs:17:13
|
||||
|
|
||||
LL | let _ = a * b * c + d;
|
||||
| ^^^^^^^^^^^^^ help: consider using: `(a * b).mul_add(c, d)`
|
||||
|
||||
error: multiply and add expressions can be calculated more efficiently and accurately
|
||||
--> $DIR/floating_point_mul_add.rs:19:13
|
||||
|
|
||||
LL | let _ = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c))`
|
||||
|
||||
error: multiply and add expressions can be calculated more efficiently and accurately
|
||||
--> $DIR/floating_point_mul_add.rs:20:13
|
||||
|
|
||||
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
|
||||
|
42
tests/ui/floating_point_powf.fixed
Normal file
42
tests/ui/floating_point_powf.fixed
Normal file
|
@ -0,0 +1,42 @@
|
|||
// run-rustfix
|
||||
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
|
||||
|
||||
fn main() {
|
||||
let x = 3f32;
|
||||
let _ = x.exp2();
|
||||
let _ = 3.1f32.exp2();
|
||||
let _ = (-3.1f32).exp2();
|
||||
let _ = x.exp();
|
||||
let _ = 3.1f32.exp();
|
||||
let _ = (-3.1f32).exp();
|
||||
let _ = x.sqrt();
|
||||
let _ = x.cbrt();
|
||||
let _ = x.powi(2);
|
||||
let _ = x.powi(-2);
|
||||
let _ = x.powi(16_777_215);
|
||||
let _ = x.powi(-16_777_215);
|
||||
// Cases where the lint shouldn't be applied
|
||||
let _ = x.powf(2.1);
|
||||
let _ = x.powf(-2.1);
|
||||
let _ = x.powf(16_777_216.0);
|
||||
let _ = x.powf(-16_777_216.0);
|
||||
|
||||
let x = 3f64;
|
||||
let _ = x.exp2();
|
||||
let _ = 3.1f64.exp2();
|
||||
let _ = (-3.1f64).exp2();
|
||||
let _ = x.exp();
|
||||
let _ = 3.1f64.exp();
|
||||
let _ = (-3.1f64).exp();
|
||||
let _ = x.sqrt();
|
||||
let _ = x.cbrt();
|
||||
let _ = x.powi(2);
|
||||
let _ = x.powi(-2);
|
||||
let _ = x.powi(-2_147_483_648);
|
||||
let _ = x.powi(2_147_483_647);
|
||||
// Cases where the lint shouldn't be applied
|
||||
let _ = x.powf(2.1);
|
||||
let _ = x.powf(-2.1);
|
||||
let _ = x.powf(-2_147_483_649.0);
|
||||
let _ = x.powf(2_147_483_648.0);
|
||||
}
|
42
tests/ui/floating_point_powf.rs
Normal file
42
tests/ui/floating_point_powf.rs
Normal file
|
@ -0,0 +1,42 @@
|
|||
// run-rustfix
|
||||
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
|
||||
|
||||
fn main() {
|
||||
let x = 3f32;
|
||||
let _ = 2f32.powf(x);
|
||||
let _ = 2f32.powf(3.1);
|
||||
let _ = 2f32.powf(-3.1);
|
||||
let _ = std::f32::consts::E.powf(x);
|
||||
let _ = std::f32::consts::E.powf(3.1);
|
||||
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(-2.0);
|
||||
let _ = x.powf(16_777_215.0);
|
||||
let _ = x.powf(-16_777_215.0);
|
||||
// Cases where the lint shouldn't be applied
|
||||
let _ = x.powf(2.1);
|
||||
let _ = x.powf(-2.1);
|
||||
let _ = x.powf(16_777_216.0);
|
||||
let _ = x.powf(-16_777_216.0);
|
||||
|
||||
let x = 3f64;
|
||||
let _ = 2f64.powf(x);
|
||||
let _ = 2f64.powf(3.1);
|
||||
let _ = 2f64.powf(-3.1);
|
||||
let _ = std::f64::consts::E.powf(x);
|
||||
let _ = std::f64::consts::E.powf(3.1);
|
||||
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(-2.0);
|
||||
let _ = x.powf(-2_147_483_648.0);
|
||||
let _ = x.powf(2_147_483_647.0);
|
||||
// Cases where the lint shouldn't be applied
|
||||
let _ = x.powf(2.1);
|
||||
let _ = x.powf(-2.1);
|
||||
let _ = x.powf(-2_147_483_649.0);
|
||||
let _ = x.powf(2_147_483_648.0);
|
||||
}
|
150
tests/ui/floating_point_powf.stderr
Normal file
150
tests/ui/floating_point_powf.stderr
Normal file
|
@ -0,0 +1,150 @@
|
|||
error: exponent for bases 2 and e can be computed more accurately
|
||||
--> $DIR/floating_point_powf.rs:6:13
|
||||
|
|
||||
LL | let _ = 2f32.powf(x);
|
||||
| ^^^^^^^^^^^^ help: consider using: `x.exp2()`
|
||||
|
|
||||
= note: `-D clippy::suboptimal-flops` implied by `-D warnings`
|
||||
|
||||
error: exponent for bases 2 and e can be computed more accurately
|
||||
--> $DIR/floating_point_powf.rs:7:13
|
||||
|
|
||||
LL | let _ = 2f32.powf(3.1);
|
||||
| ^^^^^^^^^^^^^^ help: consider using: `3.1f32.exp2()`
|
||||
|
||||
error: exponent for bases 2 and e can be computed more accurately
|
||||
--> $DIR/floating_point_powf.rs:8:13
|
||||
|
|
||||
LL | let _ = 2f32.powf(-3.1);
|
||||
| ^^^^^^^^^^^^^^^ help: consider using: `(-3.1f32).exp2()`
|
||||
|
||||
error: exponent for bases 2 and e can be computed more accurately
|
||||
--> $DIR/floating_point_powf.rs:9:13
|
||||
|
|
||||
LL | let _ = std::f32::consts::E.powf(x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()`
|
||||
|
||||
error: exponent for bases 2 and e can be computed more accurately
|
||||
--> $DIR/floating_point_powf.rs:10:13
|
||||
|
|
||||
LL | let _ = std::f32::consts::E.powf(3.1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `3.1f32.exp()`
|
||||
|
||||
error: exponent for bases 2 and e can be computed more accurately
|
||||
--> $DIR/floating_point_powf.rs:11:13
|
||||
|
|
||||
LL | let _ = std::f32::consts::E.powf(-3.1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-3.1f32).exp()`
|
||||
|
||||
error: square-root of a number can be computed more efficiently and accurately
|
||||
--> $DIR/floating_point_powf.rs:12:13
|
||||
|
|
||||
LL | let _ = x.powf(1.0 / 2.0);
|
||||
| ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()`
|
||||
|
||||
error: cube-root of a number can be computed more accurately
|
||||
--> $DIR/floating_point_powf.rs:13:13
|
||||
|
|
||||
LL | let _ = x.powf(1.0 / 3.0);
|
||||
| ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()`
|
||||
|
|
||||
= note: `-D clippy::imprecise-flops` implied by `-D warnings`
|
||||
|
||||
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)`
|
||||
|
||||
error: exponentiation with integer powers can be computed more efficiently
|
||||
--> $DIR/floating_point_powf.rs:15:13
|
||||
|
|
||||
LL | let _ = x.powf(-2.0);
|
||||
| ^^^^^^^^^^^^ help: consider using: `x.powi(-2)`
|
||||
|
||||
error: exponentiation with integer powers can be computed more efficiently
|
||||
--> $DIR/floating_point_powf.rs:16:13
|
||||
|
|
||||
LL | let _ = x.powf(16_777_215.0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(16_777_215)`
|
||||
|
||||
error: exponentiation with integer powers can be computed more efficiently
|
||||
--> $DIR/floating_point_powf.rs:17:13
|
||||
|
|
||||
LL | let _ = x.powf(-16_777_215.0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(-16_777_215)`
|
||||
|
||||
error: exponent for bases 2 and e can be computed more accurately
|
||||
--> $DIR/floating_point_powf.rs:25:13
|
||||
|
|
||||
LL | let _ = 2f64.powf(x);
|
||||
| ^^^^^^^^^^^^ help: consider using: `x.exp2()`
|
||||
|
||||
error: exponent for bases 2 and e can be computed more accurately
|
||||
--> $DIR/floating_point_powf.rs:26:13
|
||||
|
|
||||
LL | let _ = 2f64.powf(3.1);
|
||||
| ^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp2()`
|
||||
|
||||
error: exponent for bases 2 and e can be computed more accurately
|
||||
--> $DIR/floating_point_powf.rs:27:13
|
||||
|
|
||||
LL | let _ = 2f64.powf(-3.1);
|
||||
| ^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp2()`
|
||||
|
||||
error: exponent for bases 2 and e can be computed more accurately
|
||||
--> $DIR/floating_point_powf.rs:28:13
|
||||
|
|
||||
LL | let _ = std::f64::consts::E.powf(x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()`
|
||||
|
||||
error: exponent for bases 2 and e can be computed more accurately
|
||||
--> $DIR/floating_point_powf.rs:29:13
|
||||
|
|
||||
LL | let _ = std::f64::consts::E.powf(3.1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp()`
|
||||
|
||||
error: exponent for bases 2 and e can be computed more accurately
|
||||
--> $DIR/floating_point_powf.rs:30:13
|
||||
|
|
||||
LL | let _ = std::f64::consts::E.powf(-3.1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp()`
|
||||
|
||||
error: square-root of a number can be computed more efficiently and accurately
|
||||
--> $DIR/floating_point_powf.rs:31:13
|
||||
|
|
||||
LL | let _ = x.powf(1.0 / 2.0);
|
||||
| ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()`
|
||||
|
||||
error: cube-root of a number can be computed more accurately
|
||||
--> $DIR/floating_point_powf.rs:32:13
|
||||
|
|
||||
LL | let _ = x.powf(1.0 / 3.0);
|
||||
| ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()`
|
||||
|
||||
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)`
|
||||
|
||||
error: exponentiation with integer powers can be computed more efficiently
|
||||
--> $DIR/floating_point_powf.rs:34:13
|
||||
|
|
||||
LL | let _ = x.powf(-2.0);
|
||||
| ^^^^^^^^^^^^ help: consider using: `x.powi(-2)`
|
||||
|
||||
error: exponentiation with integer powers can be computed more efficiently
|
||||
--> $DIR/floating_point_powf.rs:35:13
|
||||
|
|
||||
LL | let _ = x.powf(-2_147_483_648.0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(-2_147_483_648)`
|
||||
|
||||
error: exponentiation with integer powers can be computed more efficiently
|
||||
--> $DIR/floating_point_powf.rs:36:13
|
||||
|
|
||||
LL | let _ = x.powf(2_147_483_647.0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2_147_483_647)`
|
||||
|
||||
error: aborting due to 24 previous errors
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
#![warn(clippy::manual_mul_add)]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
fn mul_add_test() {
|
||||
let a: f64 = 1234.567;
|
||||
let b: f64 = 45.67834;
|
||||
let c: f64 = 0.0004;
|
||||
|
||||
// Examples of not auto-fixable expressions
|
||||
let test1 = (a * b + c) * (c + a * b) + (c + (a * b) + c);
|
||||
let test2 = 1234.567 * 45.67834 + 0.0004;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
mul_add_test();
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
error: consider using `mul_add()` for better numerical precision
|
||||
--> $DIR/mul_add.rs:10:17
|
||||
|
|
||||
LL | let test1 = (a * b + c) * (c + a * b) + (c + (a * b) + c);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(a * b + c).mul_add((c + a * b), (c + (a * b) + c))`
|
||||
|
|
||||
= note: `-D clippy::manual-mul-add` implied by `-D warnings`
|
||||
|
||||
error: consider using `mul_add()` for better numerical precision
|
||||
--> $DIR/mul_add.rs:10:17
|
||||
|
|
||||
LL | let test1 = (a * b + c) * (c + a * b) + (c + (a * b) + c);
|
||||
| ^^^^^^^^^^^ help: try: `a.mul_add(b, c)`
|
||||
|
||||
error: consider using `mul_add()` for better numerical precision
|
||||
--> $DIR/mul_add.rs:10:31
|
||||
|
|
||||
LL | let test1 = (a * b + c) * (c + a * b) + (c + (a * b) + c);
|
||||
| ^^^^^^^^^^^ help: try: `a.mul_add(b, c)`
|
||||
|
||||
error: consider using `mul_add()` for better numerical precision
|
||||
--> $DIR/mul_add.rs:10:46
|
||||
|
|
||||
LL | let test1 = (a * b + c) * (c + a * b) + (c + (a * b) + c);
|
||||
| ^^^^^^^^^^^ help: try: `a.mul_add(b, c)`
|
||||
|
||||
error: consider using `mul_add()` for better numerical precision
|
||||
--> $DIR/mul_add.rs:11:17
|
||||
|
|
||||
LL | let test2 = 1234.567 * 45.67834 + 0.0004;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1234.567.mul_add(45.67834, 0.0004)`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
// run-rustfix
|
||||
|
||||
#![warn(clippy::manual_mul_add)]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
fn mul_add_test() {
|
||||
let a: f64 = 1234.567;
|
||||
let b: f64 = 45.67834;
|
||||
let c: f64 = 0.0004;
|
||||
|
||||
// Auto-fixable examples
|
||||
let test1 = a.mul_add(b, c);
|
||||
let test2 = a.mul_add(b, c);
|
||||
|
||||
let test3 = a.mul_add(b, c);
|
||||
let test4 = a.mul_add(b, c);
|
||||
|
||||
let test5 = a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c)) + c;
|
||||
let test6 = 1234.567_f64.mul_add(45.67834_f64, 0.0004_f64);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
mul_add_test();
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
// run-rustfix
|
||||
|
||||
#![warn(clippy::manual_mul_add)]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
fn mul_add_test() {
|
||||
let a: f64 = 1234.567;
|
||||
let b: f64 = 45.67834;
|
||||
let c: f64 = 0.0004;
|
||||
|
||||
// Auto-fixable examples
|
||||
let test1 = a * b + c;
|
||||
let test2 = c + a * b;
|
||||
|
||||
let test3 = (a * b) + c;
|
||||
let test4 = c + (a * b);
|
||||
|
||||
let test5 = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c;
|
||||
let test6 = 1234.567_f64 * 45.67834_f64 + 0.0004_f64;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
mul_add_test();
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
error: consider using `mul_add()` for better numerical precision
|
||||
--> $DIR/mul_add_fixable.rs:12:17
|
||||
|
|
||||
LL | let test1 = a * b + c;
|
||||
| ^^^^^^^^^ help: try: `a.mul_add(b, c)`
|
||||
|
|
||||
= note: `-D clippy::manual-mul-add` implied by `-D warnings`
|
||||
|
||||
error: consider using `mul_add()` for better numerical precision
|
||||
--> $DIR/mul_add_fixable.rs:13:17
|
||||
|
|
||||
LL | let test2 = c + a * b;
|
||||
| ^^^^^^^^^ help: try: `a.mul_add(b, c)`
|
||||
|
||||
error: consider using `mul_add()` for better numerical precision
|
||||
--> $DIR/mul_add_fixable.rs:15:17
|
||||
|
|
||||
LL | let test3 = (a * b) + c;
|
||||
| ^^^^^^^^^^^ help: try: `a.mul_add(b, c)`
|
||||
|
||||
error: consider using `mul_add()` for better numerical precision
|
||||
--> $DIR/mul_add_fixable.rs:16:17
|
||||
|
|
||||
LL | let test4 = c + (a * b);
|
||||
| ^^^^^^^^^^^ help: try: `a.mul_add(b, c)`
|
||||
|
||||
error: consider using `mul_add()` for better numerical precision
|
||||
--> $DIR/mul_add_fixable.rs:18:17
|
||||
|
|
||||
LL | let test5 = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c))`
|
||||
|
||||
error: consider using `mul_add()` for better numerical precision
|
||||
--> $DIR/mul_add_fixable.rs:19:17
|
||||
|
|
||||
LL | let test6 = 1234.567_f64 * 45.67834_f64 + 0.0004_f64;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1234.567_f64.mul_add(45.67834_f64, 0.0004_f64)`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
Loading…
Reference in a new issue