From 732d7162ab065c2b399d2a1aec7a8d5794f893d6 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Tue, 31 May 2022 22:48:17 -0400 Subject: [PATCH] Move `DurationSubsec` into `Operators` lint pass --- clippy_lints/src/duration_subsec.rs | 75 ------------------- clippy_lints/src/lib.register_all.rs | 2 +- clippy_lints/src/lib.register_complexity.rs | 2 +- clippy_lints/src/lib.register_lints.rs | 2 +- clippy_lints/src/lib.rs | 2 - clippy_lints/src/operators/duration_subsec.rs | 44 +++++++++++ clippy_lints/src/operators/mod.rs | 33 ++++++++ 7 files changed, 80 insertions(+), 80 deletions(-) delete mode 100644 clippy_lints/src/duration_subsec.rs create mode 100644 clippy_lints/src/operators/duration_subsec.rs diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs deleted file mode 100644 index d85ace3a2..000000000 --- a/clippy_lints/src/duration_subsec.rs +++ /dev/null @@ -1,75 +0,0 @@ -use clippy_utils::consts::{constant, Constant}; -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_with_applicability; -use clippy_utils::ty::is_type_diagnostic_item; -use if_chain::if_chain; -use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::source_map::Spanned; -use rustc_span::sym; - -declare_clippy_lint! { - /// ### What it does - /// Checks for calculation of subsecond microseconds or milliseconds - /// from other `Duration` methods. - /// - /// ### Why is this bad? - /// It's more concise to call `Duration::subsec_micros()` or - /// `Duration::subsec_millis()` than to calculate them. - /// - /// ### Example - /// ```rust - /// # use std::time::Duration; - /// # let duration = Duration::new(5, 0); - /// let micros = duration.subsec_nanos() / 1_000; - /// let millis = duration.subsec_nanos() / 1_000_000; - /// ``` - /// - /// Use instead: - /// ```rust - /// # use std::time::Duration; - /// # let duration = Duration::new(5, 0); - /// let micros = duration.subsec_micros(); - /// let millis = duration.subsec_millis(); - /// ``` - #[clippy::version = "pre 1.29.0"] - pub DURATION_SUBSEC, - complexity, - "checks for calculation of subsecond microseconds or milliseconds" -} - -declare_lint_pass!(DurationSubsec => [DURATION_SUBSEC]); - -impl<'tcx> LateLintPass<'tcx> for DurationSubsec { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if_chain! { - if let ExprKind::Binary(Spanned { node: BinOpKind::Div, .. }, left, right) = expr.kind; - if let ExprKind::MethodCall(method_path, args, _) = left.kind; - if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&args[0]).peel_refs(), sym::Duration); - if let Some((Constant::Int(divisor), _)) = constant(cx, cx.typeck_results(), right); - then { - let suggested_fn = match (method_path.ident.as_str(), divisor) { - ("subsec_micros", 1_000) | ("subsec_nanos", 1_000_000) => "subsec_millis", - ("subsec_nanos", 1_000) => "subsec_micros", - _ => return, - }; - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - DURATION_SUBSEC, - expr.span, - &format!("calling `{}()` is more concise than this calculation", suggested_fn), - "try", - format!( - "{}.{}()", - snippet_with_applicability(cx, args[0].span, "_", &mut applicability), - suggested_fn - ), - applicability, - ); - } - } - } -} diff --git a/clippy_lints/src/lib.register_all.rs b/clippy_lints/src/lib.register_all.rs index 22400f7b1..b64a56525 100644 --- a/clippy_lints/src/lib.register_all.rs +++ b/clippy_lints/src/lib.register_all.rs @@ -57,7 +57,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(drop_forget_ref::FORGET_REF), LintId::of(drop_forget_ref::UNDROPPED_MANUALLY_DROPS), LintId::of(duplicate_mod::DUPLICATE_MOD), - LintId::of(duration_subsec::DURATION_SUBSEC), LintId::of(entry::MAP_ENTRY), LintId::of(enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT), LintId::of(enum_variants::ENUM_VARIANT_NAMES), @@ -258,6 +257,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(operators::ASSIGN_OP_PATTERN), LintId::of(operators::BAD_BIT_MASK), LintId::of(operators::DOUBLE_COMPARISONS), + LintId::of(operators::DURATION_SUBSEC), LintId::of(operators::INEFFECTIVE_BIT_MASK), LintId::of(operators::MISREFACTORED_ASSIGN_OP), LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP), diff --git a/clippy_lints/src/lib.register_complexity.rs b/clippy_lints/src/lib.register_complexity.rs index 03bb67881..3a8a00d4e 100644 --- a/clippy_lints/src/lib.register_complexity.rs +++ b/clippy_lints/src/lib.register_complexity.rs @@ -11,7 +11,6 @@ store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec! LintId::of(casts::UNNECESSARY_CAST), LintId::of(derivable_impls::DERIVABLE_IMPLS), LintId::of(double_parens::DOUBLE_PARENS), - LintId::of(duration_subsec::DURATION_SUBSEC), LintId::of(explicit_write::EXPLICIT_WRITE), LintId::of(format::USELESS_FORMAT), LintId::of(functions::TOO_MANY_ARGUMENTS), @@ -71,6 +70,7 @@ store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec! LintId::of(no_effect::NO_EFFECT), LintId::of(no_effect::UNNECESSARY_OPERATION), LintId::of(operators::DOUBLE_COMPARISONS), + LintId::of(operators::DURATION_SUBSEC), LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL), LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL), LintId::of(precedence::PRECEDENCE), diff --git a/clippy_lints/src/lib.register_lints.rs b/clippy_lints/src/lib.register_lints.rs index a08ad4a31..d0b38522f 100644 --- a/clippy_lints/src/lib.register_lints.rs +++ b/clippy_lints/src/lib.register_lints.rs @@ -131,7 +131,6 @@ store.register_lints(&[ drop_forget_ref::FORGET_REF, drop_forget_ref::UNDROPPED_MANUALLY_DROPS, duplicate_mod::DUPLICATE_MOD, - duration_subsec::DURATION_SUBSEC, else_if_without_else::ELSE_IF_WITHOUT_ELSE, empty_drop::EMPTY_DROP, empty_enum::EMPTY_ENUM, @@ -432,6 +431,7 @@ store.register_lints(&[ operators::ASSIGN_OP_PATTERN, operators::BAD_BIT_MASK, operators::DOUBLE_COMPARISONS, + operators::DURATION_SUBSEC, operators::FLOAT_ARITHMETIC, operators::INEFFECTIVE_BIT_MASK, operators::INTEGER_ARITHMETIC, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 931039d8c..9b1b3afa2 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -212,7 +212,6 @@ mod doc_link_with_quotes; mod double_parens; mod drop_forget_ref; mod duplicate_mod; -mod duration_subsec; mod else_if_without_else; mod empty_drop; mod empty_enum; @@ -732,7 +731,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| Box::new(inherent_impl::MultipleInherentImpl)); store.register_late_pass(|| Box::new(neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd)); store.register_late_pass(|| Box::new(unwrap::Unwrap)); - store.register_late_pass(|| Box::new(duration_subsec::DurationSubsec)); store.register_late_pass(|| Box::new(indexing_slicing::IndexingSlicing)); store.register_late_pass(|| Box::new(non_copy_const::NonCopyConst)); store.register_late_pass(|| Box::new(ptr_offset_with_cast::PtrOffsetWithCast)); diff --git a/clippy_lints/src/operators/duration_subsec.rs b/clippy_lints/src/operators/duration_subsec.rs new file mode 100644 index 000000000..0d067d1e1 --- /dev/null +++ b/clippy_lints/src/operators/duration_subsec.rs @@ -0,0 +1,44 @@ +use clippy_utils::consts::{constant, Constant}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::is_type_diagnostic_item; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_span::sym; + +use super::DURATION_SUBSEC; + +pub(crate) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'_>, + op: BinOpKind, + left: &'tcx Expr<'_>, + right: &'tcx Expr<'_>, +) { + if op == BinOpKind::Div + && let ExprKind::MethodCall(method_path, [self_arg], _) = left.kind + && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_arg).peel_refs(), sym::Duration) + && let Some((Constant::Int(divisor), _)) = constant(cx, cx.typeck_results(), right) + { + let suggested_fn = match (method_path.ident.as_str(), divisor) { + ("subsec_micros", 1_000) | ("subsec_nanos", 1_000_000) => "subsec_millis", + ("subsec_nanos", 1_000) => "subsec_micros", + _ => return, + }; + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + DURATION_SUBSEC, + expr.span, + &format!("calling `{}()` is more concise than this calculation", suggested_fn), + "try", + format!( + "{}.{}()", + snippet_with_applicability(cx, self_arg.span, "_", &mut applicability), + suggested_fn + ), + applicability, + ); + } +} diff --git a/clippy_lints/src/operators/mod.rs b/clippy_lints/src/operators/mod.rs index b3ddab629..fb2c2bced 100644 --- a/clippy_lints/src/operators/mod.rs +++ b/clippy_lints/src/operators/mod.rs @@ -6,6 +6,7 @@ mod absurd_extreme_comparisons; mod assign_op_pattern; mod bit_mask; mod double_comparison; +mod duration_subsec; mod misrefactored_assign_op; mod numeric_arithmetic; mod verbose_bit_mask; @@ -271,6 +272,36 @@ declare_clippy_lint! { "unnecessary double comparisons that can be simplified" } +declare_clippy_lint! { + /// ### What it does + /// Checks for calculation of subsecond microseconds or milliseconds + /// from other `Duration` methods. + /// + /// ### Why is this bad? + /// It's more concise to call `Duration::subsec_micros()` or + /// `Duration::subsec_millis()` than to calculate them. + /// + /// ### Example + /// ```rust + /// # use std::time::Duration; + /// # let duration = Duration::new(5, 0); + /// let micros = duration.subsec_nanos() / 1_000; + /// let millis = duration.subsec_nanos() / 1_000_000; + /// ``` + /// + /// Use instead: + /// ```rust + /// # use std::time::Duration; + /// # let duration = Duration::new(5, 0); + /// let micros = duration.subsec_micros(); + /// let millis = duration.subsec_millis(); + /// ``` + #[clippy::version = "pre 1.29.0"] + pub DURATION_SUBSEC, + complexity, + "checks for calculation of subsecond microseconds or milliseconds" +} + pub struct Operators { arithmetic_context: numeric_arithmetic::Context, verbose_bit_mask_threshold: u64, @@ -285,6 +316,7 @@ impl_lint_pass!(Operators => [ INEFFECTIVE_BIT_MASK, VERBOSE_BIT_MASK, DOUBLE_COMPARISONS, + DURATION_SUBSEC, ]); impl Operators { pub fn new(verbose_bit_mask_threshold: u64) -> Self { @@ -305,6 +337,7 @@ impl<'tcx> LateLintPass<'tcx> for Operators { bit_mask::check(cx, e, op.node, lhs, rhs); verbose_bit_mask::check(cx, e, op.node, lhs, rhs, self.verbose_bit_mask_threshold); double_comparison::check(cx, op.node, lhs, rhs, e.span); + duration_subsec::check(cx, e, op.node, lhs, rhs); }, ExprKind::AssignOp(op, lhs, rhs) => { self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs);