Skip to content

Commit b6744db

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

File tree

4 files changed

+77
-29
lines changed

4 files changed

+77
-29
lines changed

clippy_lints/src/time_subtraction.rs

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -84,43 +84,57 @@ impl_lint_pass!(UncheckedTimeSubtraction => [MANUAL_INSTANT_ELAPSED, UNCHECKED_T
8484

8585
impl LateLintPass<'_> for UncheckedTimeSubtraction {
8686
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) {
87-
if let ExprKind::Binary(
88-
Spanned {
89-
node: BinOpKind::Sub, ..
87+
match expr.kind {
88+
ExprKind::Binary(
89+
Spanned {
90+
node: BinOpKind::Sub, ..
91+
},
92+
lhs,
93+
rhs,
94+
) => {
95+
self.check_unchecked_time_subtraction(cx, expr, lhs, rhs);
9096
},
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);
97+
ExprKind::MethodCall(fn_name, lhs, [rhs], _)
98+
if let Some(fn_impl_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
99+
&& let Some(sym::sub) = cx.tcx.get_diagnostic_name(fn_impl_id) =>
100+
{
101+
self.check_unchecked_time_subtraction(cx, expr, lhs, rhs);
102+
},
103+
_ => {},
104+
}
105+
}
106+
}
98107

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-
}
108+
impl UncheckedTimeSubtraction {
109+
fn check_unchecked_time_subtraction(&self, cx: &LateContext<'_>, expr: &Expr<'_>, lhs: &Expr<'_>, rhs: &Expr<'_>) {
110+
let typeck = cx.typeck_results();
111+
let lhs_ty = typeck.expr_ty(lhs);
112+
let rhs_ty = typeck.expr_ty(rhs);
113+
114+
if lhs_ty.is_diag_item(cx, sym::Instant) {
115+
// Instant::now() - instant
116+
if is_instant_now_call(cx, lhs)
117+
&& rhs_ty.is_diag_item(cx, sym::Instant)
118+
&& let Some(sugg) = Sugg::hir_opt(cx, rhs)
119+
{
120+
print_manual_instant_elapsed_sugg(cx, expr, sugg);
114121
}
115-
// duration - duration
116-
else if lhs_ty.is_diag_item(cx, sym::Duration)
117-
&& rhs_ty.is_diag_item(cx, sym::Duration)
122+
// instant - duration
123+
else if rhs_ty.is_diag_item(cx, sym::Duration)
118124
&& !expr.span.from_expansion()
119125
&& self.msrv.meets(cx, msrvs::TRY_FROM)
120126
{
121127
print_unchecked_duration_subtraction_sugg(cx, lhs, rhs, expr);
122128
}
123129
}
130+
// duration - duration
131+
else if lhs_ty.is_diag_item(cx, sym::Duration)
132+
&& rhs_ty.is_diag_item(cx, sym::Duration)
133+
&& !expr.span.from_expansion()
134+
&& self.msrv.meets(cx, msrvs::TRY_FROM)
135+
{
136+
print_unchecked_duration_subtraction_sugg(cx, lhs, rhs, expr);
137+
}
124138
}
125139
}
126140

tests/ui/unchecked_time_subtraction.fixed

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,14 @@ 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+
use std::time::Duration;
42+
43+
Duration::ZERO.checked_sub(Duration::MAX).unwrap();
44+
//~^ unchecked_time_subtraction
45+
46+
let _ = Duration::ZERO.checked_sub(Duration::MAX).unwrap();
47+
//~^ unchecked_time_subtraction
48+
}

tests/ui/unchecked_time_subtraction.rs

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

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:43: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:46: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)