1 use clippy_utils
::consts
::{constant, Constant}
;
2 use clippy_utils
::diagnostics
::span_lint_and_sugg
;
3 use clippy_utils
::source
::snippet_with_applicability
;
4 use clippy_utils
::ty
::is_type_diagnostic_item
;
5 use if_chain
::if_chain
;
6 use rustc_errors
::Applicability
;
7 use rustc_hir
::{BinOpKind, Expr, ExprKind}
;
8 use rustc_lint
::{LateContext, LateLintPass}
;
9 use rustc_session
::{declare_lint_pass, declare_tool_lint}
;
10 use rustc_span
::source_map
::Spanned
;
13 declare_clippy_lint
! {
15 /// Checks for calculation of subsecond microseconds or milliseconds
16 /// from other `Duration` methods.
18 /// ### Why is this bad?
19 /// It's more concise to call `Duration::subsec_micros()` or
20 /// `Duration::subsec_millis()` than to calculate them.
24 /// # use std::time::Duration;
25 /// # let duration = Duration::new(5, 0);
26 /// let micros = duration.subsec_nanos() / 1_000;
27 /// let millis = duration.subsec_nanos() / 1_000_000;
32 /// # use std::time::Duration;
33 /// # let duration = Duration::new(5, 0);
34 /// let micros = duration.subsec_micros();
35 /// let millis = duration.subsec_millis();
37 #[clippy::version = "pre 1.29.0"]
40 "checks for calculation of subsecond microseconds or milliseconds"
43 declare_lint_pass
!(DurationSubsec
=> [DURATION_SUBSEC
]);
45 impl<'tcx
> LateLintPass
<'tcx
> for DurationSubsec
{
46 fn check_expr(&mut self, cx
: &LateContext
<'tcx
>, expr
: &'tcx Expr
<'_
>) {
48 if let ExprKind
::Binary(Spanned { node: BinOpKind::Div, .. }
, left
, right
) = expr
.kind
;
49 if let ExprKind
::MethodCall(method_path
, args
, _
) = left
.kind
;
50 if is_type_diagnostic_item(cx
, cx
.typeck_results().expr_ty(&args
[0]).peel_refs(), sym
::Duration
);
51 if let Some((Constant
::Int(divisor
), _
)) = constant(cx
, cx
.typeck_results(), right
);
53 let suggested_fn
= match (method_path
.ident
.as_str(), divisor
) {
54 ("subsec_micros", 1_000) | ("subsec_nanos", 1_000_000) => "subsec_millis",
55 ("subsec_nanos", 1_000) => "subsec_micros",
58 let mut applicability
= Applicability
::MachineApplicable
;
63 &format
!("calling `{}()` is more concise than this calculation", suggested_fn
),
67 snippet_with_applicability(cx
, args
[0].span
, "_", &mut applicability
),