Skip to content

Commit 16c03a0

Browse files
Detect usage of (x + 1).ln() and suggest x.ln_1p() instead
1 parent 53ee2fb commit 16c03a0

File tree

3 files changed

+84
-24
lines changed

3 files changed

+84
-24
lines changed

clippy_lints/src/floating_point_arithmetic.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -94,24 +94,26 @@ fn check_log_base(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec<Expr>) {
9494
}
9595
}
9696

97-
// TODO: Lint expressions of the form `(x + 1).ln()` and `(x + y).ln()`
98-
// where y > 1 and suggest usage of `(x + (y - 1)).ln_1p()` instead
97+
// TODO: Lint expressions of the form `(x + y).ln()` where y > 1 and
98+
// suggest usage of `(x + (y - 1)).ln_1p()` instead
9999
fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr, args: &HirVec<Expr>) {
100100
if_chain! {
101101
if let ExprKind::Binary(op, ref lhs, ref rhs) = &args[0].kind;
102102
if op.node == BinOpKind::Add;
103-
if let Some((value, _)) = constant(cx, cx.tables, lhs);
104-
if F32(1.0) == value || F64(1.0) == value;
105103
then {
106-
let arg = sugg::Sugg::hir(cx, rhs, "..").maybe_par();
104+
let recv = match (constant(cx, cx.tables, lhs), constant(cx, cx.tables, rhs)) {
105+
(Some((value, _)), _) if F32(1.0) == value || F64(1.0) == value => rhs,
106+
(_, Some((value, _))) if F32(1.0) == value || F64(1.0) == value => lhs,
107+
_ => return,
108+
};
107109

108110
span_lint_and_sugg(
109111
cx,
110112
FLOATING_POINT_IMPROVEMENTS,
111113
expr.span,
112114
"ln(1 + x) can be computed more accurately",
113115
"consider using",
114-
format!("{}.ln_1p()", arg),
116+
format!("{}.ln_1p()", sugg::Sugg::hir(cx, recv, "..").maybe_par()),
115117
Applicability::MachineApplicable,
116118
);
117119
}

tests/ui/floating_point_log.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,28 @@ fn check_ln1p() {
2525
let _ = (1.0 + x.powi(2)).ln();
2626
let _ = (1.0 + x.powi(2) * 2.0).ln();
2727
let _ = (1.0 + (std::f32::consts::E - 1.0)).ln();
28-
// Cases where the lint shouldn't be applied
2928
let _ = (x + 1.0).ln();
29+
let _ = (x.powi(2) + 1.0).ln();
30+
let _ = (x + 2.0 + 1.0).ln();
31+
let _ = (x * 2.0 + 1.0).ln();
32+
// Cases where the lint shouldn't be applied
3033
let _ = (1.0 + x + 2.0).ln();
34+
let _ = (x + 1.0 + 2.0).ln();
35+
let _ = (x + 1.0 * 2.0).ln();
3136
let _ = (1.0 + x - 2.0).ln();
3237

3338
let x = 1f64;
3439
let _ = (1.0 + x).ln();
3540
let _ = (1.0 + x * 2.0).ln();
3641
let _ = (1.0 + x.powi(2)).ln();
37-
// Cases where the lint shouldn't be applied
3842
let _ = (x + 1.0).ln();
43+
let _ = (x.powi(2) + 1.0).ln();
44+
let _ = (x + 2.0 + 1.0).ln();
45+
let _ = (x * 2.0 + 1.0).ln();
46+
// Cases where the lint shouldn't be applied
3947
let _ = (1.0 + x + 2.0).ln();
48+
let _ = (x + 1.0 + 2.0).ln();
49+
let _ = (x + 1.0 * 2.0).ln();
4050
let _ = (1.0 + x - 2.0).ln();
4151
}
4252

tests/ui/floating_point_log.stderr

+64-16
Original file line numberDiff line numberDiff line change
@@ -79,94 +79,142 @@ LL | let _ = (1.0 + (std::f32::consts::E - 1.0)).ln();
7979
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `((std::f32::consts::E - 1.0)).ln_1p()`
8080

8181
error: ln(1 + x) can be computed more accurately
82-
--> $DIR/floating_point_log.rs:34:13
82+
--> $DIR/floating_point_log.rs:28:13
83+
|
84+
LL | let _ = (x + 1.0).ln();
85+
| ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()`
86+
87+
error: ln(1 + x) can be computed more accurately
88+
--> $DIR/floating_point_log.rs:29:13
89+
|
90+
LL | let _ = (x.powi(2) + 1.0).ln();
91+
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
92+
93+
error: ln(1 + x) can be computed more accurately
94+
--> $DIR/floating_point_log.rs:30:13
95+
|
96+
LL | let _ = (x + 2.0 + 1.0).ln();
97+
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x + 2.0).ln_1p()`
98+
99+
error: ln(1 + x) can be computed more accurately
100+
--> $DIR/floating_point_log.rs:31:13
101+
|
102+
LL | let _ = (x * 2.0 + 1.0).ln();
103+
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()`
104+
105+
error: ln(1 + x) can be computed more accurately
106+
--> $DIR/floating_point_log.rs:39:13
83107
|
84108
LL | let _ = (1.0 + x).ln();
85109
| ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()`
86110

87111
error: ln(1 + x) can be computed more accurately
88-
--> $DIR/floating_point_log.rs:35:13
112+
--> $DIR/floating_point_log.rs:40:13
89113
|
90114
LL | let _ = (1.0 + x * 2.0).ln();
91115
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()`
92116

93117
error: ln(1 + x) can be computed more accurately
94-
--> $DIR/floating_point_log.rs:36:13
118+
--> $DIR/floating_point_log.rs:41:13
95119
|
96120
LL | let _ = (1.0 + x.powi(2)).ln();
97121
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
98122

123+
error: ln(1 + x) can be computed more accurately
124+
--> $DIR/floating_point_log.rs:42:13
125+
|
126+
LL | let _ = (x + 1.0).ln();
127+
| ^^^^^^^^^^^^^^ help: consider using: `x.ln_1p()`
128+
129+
error: ln(1 + x) can be computed more accurately
130+
--> $DIR/floating_point_log.rs:43:13
131+
|
132+
LL | let _ = (x.powi(2) + 1.0).ln();
133+
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
134+
135+
error: ln(1 + x) can be computed more accurately
136+
--> $DIR/floating_point_log.rs:44:13
137+
|
138+
LL | let _ = (x + 2.0 + 1.0).ln();
139+
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x + 2.0).ln_1p()`
140+
141+
error: ln(1 + x) can be computed more accurately
142+
--> $DIR/floating_point_log.rs:45:13
143+
|
144+
LL | let _ = (x * 2.0 + 1.0).ln();
145+
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x * 2.0).ln_1p()`
146+
99147
error: x.log(b) / y.log(b) can be reduced to x.log(y)
100-
--> $DIR/floating_point_log.rs:48:13
148+
--> $DIR/floating_point_log.rs:58:13
101149
|
102150
LL | let _ = x.log2() / y.log2();
103151
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)`
104152

105153
error: x.log(b) / y.log(b) can be reduced to x.log(y)
106-
--> $DIR/floating_point_log.rs:49:13
154+
--> $DIR/floating_point_log.rs:59:13
107155
|
108156
LL | let _ = x.log10() / y.log10();
109157
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)`
110158

111159
error: x.log(b) / y.log(b) can be reduced to x.log(y)
112-
--> $DIR/floating_point_log.rs:50:13
160+
--> $DIR/floating_point_log.rs:60:13
113161
|
114162
LL | let _ = x.ln() / y.ln();
115163
| ^^^^^^^^^^^^^^^ help: consider using: `x.log(y)`
116164

117165
error: x.log(b) / y.log(b) can be reduced to x.log(y)
118-
--> $DIR/floating_point_log.rs:51:13
166+
--> $DIR/floating_point_log.rs:61:13
119167
|
120168
LL | let _ = x.log(4.0) / y.log(4.0);
121169
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)`
122170

123171
error: x.log(b) / y.log(b) can be reduced to x.log(y)
124-
--> $DIR/floating_point_log.rs:52:13
172+
--> $DIR/floating_point_log.rs:62:13
125173
|
126174
LL | let _ = x.log(b) / y.log(b);
127175
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)`
128176

129177
error: x.log(b) / y.log(b) can be reduced to x.log(y)
130-
--> $DIR/floating_point_log.rs:54:13
178+
--> $DIR/floating_point_log.rs:64:13
131179
|
132180
LL | let _ = x.log(b) / 2f32.log(b);
133181
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log2()`
134182

135183
error: x.log(b) / y.log(b) can be reduced to x.log(y)
136-
--> $DIR/floating_point_log.rs:60:13
184+
--> $DIR/floating_point_log.rs:70:13
137185
|
138186
LL | let _ = x.log2() / y.log2();
139187
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)`
140188

141189
error: x.log(b) / y.log(b) can be reduced to x.log(y)
142-
--> $DIR/floating_point_log.rs:61:13
190+
--> $DIR/floating_point_log.rs:71:13
143191
|
144192
LL | let _ = x.log10() / y.log10();
145193
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)`
146194

147195
error: x.log(b) / y.log(b) can be reduced to x.log(y)
148-
--> $DIR/floating_point_log.rs:62:13
196+
--> $DIR/floating_point_log.rs:72:13
149197
|
150198
LL | let _ = x.ln() / y.ln();
151199
| ^^^^^^^^^^^^^^^ help: consider using: `x.log(y)`
152200

153201
error: x.log(b) / y.log(b) can be reduced to x.log(y)
154-
--> $DIR/floating_point_log.rs:63:13
202+
--> $DIR/floating_point_log.rs:73:13
155203
|
156204
LL | let _ = x.log(4.0) / y.log(4.0);
157205
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)`
158206

159207
error: x.log(b) / y.log(b) can be reduced to x.log(y)
160-
--> $DIR/floating_point_log.rs:64:13
208+
--> $DIR/floating_point_log.rs:74:13
161209
|
162210
LL | let _ = x.log(b) / y.log(b);
163211
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)`
164212

165213
error: x.log(b) / y.log(b) can be reduced to x.log(y)
166-
--> $DIR/floating_point_log.rs:66:13
214+
--> $DIR/floating_point_log.rs:76:13
167215
|
168216
LL | let _ = x.log(b) / 2f64.log(b);
169217
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log2()`
170218

171-
error: aborting due to 28 previous errors
219+
error: aborting due to 36 previous errors
172220

0 commit comments

Comments
 (0)