Skip to content

Commit 075548e

Browse files
committed
fix: unchecked_time_subtraction FN on Ops::sub method call
1 parent 5a37f7b commit 075548e

File tree

4 files changed

+59
-30
lines changed

4 files changed

+59
-30
lines changed

clippy_lints/src/time_subtraction.rs

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use rustc_hir::{BinOpKind, Expr, ExprKind};
88
use rustc_lint::{LateContext, LateLintPass};
99
use rustc_middle::ty::Ty;
1010
use rustc_session::impl_lint_pass;
11-
use rustc_span::source_map::Spanned;
1211
use rustc_span::sym;
1312

1413
declare_clippy_lint! {
@@ -84,43 +83,41 @@ impl_lint_pass!(UncheckedTimeSubtraction => [MANUAL_INSTANT_ELAPSED, UNCHECKED_T
8483

8584
impl LateLintPass<'_> for UncheckedTimeSubtraction {
8685
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) {
87-
if let ExprKind::Binary(
88-
Spanned {
89-
node: BinOpKind::Sub, ..
86+
let (lhs, rhs) = match expr.kind {
87+
ExprKind::Binary(op, lhs, rhs) if matches!(op.node, BinOpKind::Sub,) => (lhs, rhs),
88+
ExprKind::MethodCall(fn_name, lhs, [rhs], _) if cx.ty_based_def(expr).is_diag_item(cx, sym::sub) => {
89+
(lhs, rhs)
9090
},
91-
lhs,
92-
rhs,
93-
) = expr.kind
94-
{
95-
let typeck = cx.typeck_results();
96-
let lhs_ty = typeck.expr_ty(lhs);
97-
let rhs_ty = typeck.expr_ty(rhs);
91+
_ => return,
92+
};
93+
let typeck = cx.typeck_results();
94+
let lhs_ty = typeck.expr_ty(lhs);
95+
let rhs_ty = typeck.expr_ty(rhs);
9896

99-
if lhs_ty.is_diag_item(cx, sym::Instant) {
100-
// Instant::now() - instant
101-
if is_instant_now_call(cx, lhs)
102-
&& rhs_ty.is_diag_item(cx, sym::Instant)
103-
&& let Some(sugg) = Sugg::hir_opt(cx, rhs)
104-
{
105-
print_manual_instant_elapsed_sugg(cx, expr, sugg);
106-
}
107-
// instant - duration
108-
else if rhs_ty.is_diag_item(cx, sym::Duration)
109-
&& !expr.span.from_expansion()
110-
&& self.msrv.meets(cx, msrvs::TRY_FROM)
111-
{
112-
print_unchecked_duration_subtraction_sugg(cx, lhs, rhs, expr);
113-
}
97+
if lhs_ty.is_diag_item(cx, sym::Instant) {
98+
// Instant::now() - instant
99+
if is_instant_now_call(cx, lhs)
100+
&& rhs_ty.is_diag_item(cx, sym::Instant)
101+
&& let Some(sugg) = Sugg::hir_opt(cx, rhs)
102+
{
103+
print_manual_instant_elapsed_sugg(cx, expr, sugg);
114104
}
115-
// duration - duration
116-
else if lhs_ty.is_diag_item(cx, sym::Duration)
117-
&& rhs_ty.is_diag_item(cx, sym::Duration)
105+
// instant - duration
106+
else if rhs_ty.is_diag_item(cx, sym::Duration)
118107
&& !expr.span.from_expansion()
119108
&& self.msrv.meets(cx, msrvs::TRY_FROM)
120109
{
121110
print_unchecked_duration_subtraction_sugg(cx, lhs, rhs, expr);
122111
}
123112
}
113+
// duration - duration
114+
else if lhs_ty.is_diag_item(cx, sym::Duration)
115+
&& rhs_ty.is_diag_item(cx, sym::Duration)
116+
&& !expr.span.from_expansion()
117+
&& self.msrv.meets(cx, msrvs::TRY_FROM)
118+
{
119+
print_unchecked_duration_subtraction_sugg(cx, lhs, rhs, expr);
120+
}
124121
}
125122
}
126123

tests/ui/unchecked_time_subtraction.fixed

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,13 @@ fn main() {
3535
let _ = (2 * dur1).checked_sub(dur2).unwrap();
3636
//~^ unchecked_time_subtraction
3737
}
38+
39+
fn issue16230() {
40+
use std::ops::Sub as _;
41+
42+
Duration::ZERO.checked_sub(Duration::MAX).unwrap();
43+
//~^ unchecked_time_subtraction
44+
45+
let _ = Duration::ZERO.checked_sub(Duration::MAX).unwrap();
46+
//~^ unchecked_time_subtraction
47+
}

tests/ui/unchecked_time_subtraction.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,13 @@ fn main() {
3535
let _ = 2 * dur1 - dur2;
3636
//~^ unchecked_time_subtraction
3737
}
38+
39+
fn issue16230() {
40+
use std::ops::Sub as _;
41+
42+
Duration::ZERO.sub(Duration::MAX);
43+
//~^ unchecked_time_subtraction
44+
45+
let _ = Duration::ZERO - Duration::MAX;
46+
//~^ unchecked_time_subtraction
47+
}

tests/ui/unchecked_time_subtraction.stderr

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,17 @@ error: unchecked subtraction of a `Duration`
4949
LL | let _ = 2 * dur1 - dur2;
5050
| ^^^^^^^^^^^^^^^ help: try: `(2 * dur1).checked_sub(dur2).unwrap()`
5151

52-
error: aborting due to 8 previous errors
52+
error: unchecked subtraction of a `Duration`
53+
--> tests/ui/unchecked_time_subtraction.rs:42:5
54+
|
55+
LL | Duration::ZERO.sub(Duration::MAX);
56+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Duration::ZERO.checked_sub(Duration::MAX).unwrap()`
57+
58+
error: unchecked subtraction of a `Duration`
59+
--> tests/ui/unchecked_time_subtraction.rs:45:13
60+
|
61+
LL | let _ = Duration::ZERO - Duration::MAX;
62+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Duration::ZERO.checked_sub(Duration::MAX).unwrap()`
63+
64+
error: aborting due to 10 previous errors
5365

0 commit comments

Comments
 (0)