@@ -41,7 +41,7 @@ declare_clippy_lint! {
4141
4242declare_clippy_lint ! {
4343 /// ### What it does
44- /// Lints subtraction between an `Instant` and a `Duration`.
44+ /// Lints subtraction between an `Instant` or `Duration` and a `Duration`.
4545 ///
4646 /// ### Why is this bad?
4747 /// Unchecked subtraction could cause underflow on certain platforms, leading to
@@ -51,17 +51,19 @@ declare_clippy_lint! {
5151 /// ```no_run
5252 /// # use std::time::{Instant, Duration};
5353 /// let time_passed = Instant::now() - Duration::from_secs(5);
54+ /// let time_delta = Duration::from_secs(1) - Duration::from_secs(5);
5455 /// ```
5556 ///
5657 /// Use instead:
5758 /// ```no_run
5859 /// # use std::time::{Instant, Duration};
5960 /// let time_passed = Instant::now().checked_sub(Duration::from_secs(5));
61+ /// let time_delta = Duration::from_secs(1).checked_sub(Duration::from_secs(5));
6062 /// ```
6163 #[ clippy:: version = "1.67.0" ]
6264 pub UNCHECKED_DURATION_SUBTRACTION ,
6365 pedantic,
64- "finds unchecked subtraction of a 'Duration' from an 'Instant'"
66+ "finds unchecked subtraction of a 'Duration' from an 'Instant' or 'Duration' "
6567}
6668
6769pub struct InstantSubtraction {
@@ -88,7 +90,8 @@ impl LateLintPass<'_> for InstantSubtraction {
8890 rhs,
8991 ) = expr. kind
9092 && let typeck = cx. typeck_results ( )
91- && ty:: is_type_diagnostic_item ( cx, typeck. expr_ty ( lhs) , sym:: Instant )
93+ && ( ty:: is_type_diagnostic_item ( cx, typeck. expr_ty ( lhs) , sym:: Instant )
94+ || ty:: is_type_diagnostic_item ( cx, typeck. expr_ty ( lhs) , sym:: Duration ) )
9295 {
9396 let rhs_ty = typeck. expr_ty ( rhs) ;
9497
@@ -139,16 +142,23 @@ fn print_unchecked_duration_subtraction_sugg(
139142 expr : & Expr < ' _ > ,
140143) {
141144 let mut applicability = Applicability :: MachineApplicable ;
145+ let ty = cx. typeck_results ( ) . expr_ty ( expr) . peel_refs ( ) ;
146+ let ( left_default, left_ty) = match ty:: get_type_diagnostic_name ( cx, ty) {
147+ Some ( v) => ( format ! ( "<{}>" , v. as_str( ) . to_lowercase( ) ) , v. as_str ( ) . to_string ( ) ) ,
148+ None => {
149+ return ;
150+ } ,
151+ } ;
142152
143153 let ctxt = expr. span . ctxt ( ) ;
144- let left_expr = snippet_with_context ( cx, left_expr. span , ctxt, "<instant>" , & mut applicability) . 0 ;
154+ let left_expr = snippet_with_context ( cx, left_expr. span , ctxt, & left_default , & mut applicability) . 0 ;
145155 let right_expr = snippet_with_context ( cx, right_expr. span , ctxt, "<duration>" , & mut applicability) . 0 ;
146156
147157 span_lint_and_sugg (
148158 cx,
149159 UNCHECKED_DURATION_SUBTRACTION ,
150160 expr. span ,
151- "unchecked subtraction of a 'Duration' from an 'Instant'" ,
161+ format ! ( "unchecked subtraction of 'Duration' from '{left_ty}'" ) ,
152162 "try" ,
153163 format ! ( "{left_expr}.checked_sub({right_expr}).unwrap()" ) ,
154164 applicability,
0 commit comments