Add new duration_suboptimal_units lint (#16250)
`Duration::from_mins` and `Duration::from_hours` where [recently stabilized](https://github.com/rust-lang/rust/issues/140881) in Rust 1.91.0. In our codebase we often times have things like ```rust Duration::from_secs(5 * 60); // Since Rust 1.91.0 one can use Duration::from_mins(5) ``` During the Rust 1.91.0 bump I noticed we can finally switch to `Duration::from_mins(5)`, but many users might not be aware of this. I started manually updating the places, but halfway through I figured "Can't a lint do this for me?", so I added exactly that in this PR. It does it for all stabilized `from_XXX` time units. changelog: Add new [`duration_suboptimal_units`] lint Closes rust-lang/rust-clippy#16335
This commit is contained in:
commit
331a474142
13 changed files with 633 additions and 4 deletions
|
|
@ -6406,6 +6406,7 @@ Released 2018-09-13
|
|||
[`duplicate_mod`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_mod
|
||||
[`duplicate_underscore_argument`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_underscore_argument
|
||||
[`duplicated_attributes`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicated_attributes
|
||||
[`duration_suboptimal_units`]: https://rust-lang.github.io/rust-clippy/master/index.html#duration_suboptimal_units
|
||||
[`duration_subsec`]: https://rust-lang.github.io/rust-clippy/master/index.html#duration_subsec
|
||||
[`eager_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#eager_transmute
|
||||
[`elidable_lifetime_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#elidable_lifetime_names
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ pub fn run(port: u16, lint: Option<String>) -> ! {
|
|||
}
|
||||
|
||||
// Delay to avoid updating the metadata too aggressively.
|
||||
thread::sleep(Duration::from_millis(1000));
|
||||
thread::sleep(Duration::from_secs(1));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[
|
|||
crate::drop_forget_ref::FORGET_NON_DROP_INFO,
|
||||
crate::drop_forget_ref::MEM_FORGET_INFO,
|
||||
crate::duplicate_mod::DUPLICATE_MOD_INFO,
|
||||
crate::duration_suboptimal_units::DURATION_SUBOPTIMAL_UNITS_INFO,
|
||||
crate::else_if_without_else::ELSE_IF_WITHOUT_ELSE_INFO,
|
||||
crate::empty_drop::EMPTY_DROP_INFO,
|
||||
crate::empty_enums::EMPTY_ENUMS_INFO,
|
||||
|
|
|
|||
204
clippy_lints/src/duration_suboptimal_units.rs
Normal file
204
clippy_lints/src/duration_suboptimal_units.rs
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
use std::ops::ControlFlow;
|
||||
|
||||
use clippy_config::Conf;
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::msrvs::{self, Msrv};
|
||||
use clippy_utils::res::MaybeDef;
|
||||
use clippy_utils::sym;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind, QPath, RustcVersion};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::Symbol;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
///
|
||||
/// Checks for instances where a `std::time::Duration` is constructed using a smaller time unit
|
||||
/// when the value could be expressed more clearly using a larger unit.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
///
|
||||
/// Using a smaller unit for a duration that is evenly divisible by a larger unit reduces
|
||||
/// readability. Readers have to mentally convert values, which can be error-prone and makes
|
||||
/// the code less clear.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let dur = Duration::from_millis(5_000);
|
||||
/// let dur = Duration::from_secs(180);
|
||||
/// let dur = Duration::from_mins(10 * 60);
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let dur = Duration::from_secs(5);
|
||||
/// let dur = Duration::from_mins(3);
|
||||
/// let dur = Duration::from_hours(10);
|
||||
/// ```
|
||||
#[clippy::version = "1.95.0"]
|
||||
pub DURATION_SUBOPTIMAL_UNITS,
|
||||
pedantic,
|
||||
"constructing a `Duration` using a smaller unit when a larger unit would be more readable"
|
||||
}
|
||||
|
||||
impl_lint_pass!(DurationSuboptimalUnits => [DURATION_SUBOPTIMAL_UNITS]);
|
||||
|
||||
pub struct DurationSuboptimalUnits {
|
||||
msrv: Msrv,
|
||||
units: Vec<Unit>,
|
||||
}
|
||||
|
||||
impl DurationSuboptimalUnits {
|
||||
pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self {
|
||||
// The order of the units matters, as they are walked top to bottom
|
||||
let mut units = UNITS.to_vec();
|
||||
if tcx.features().enabled(sym::duration_constructors) {
|
||||
units.extend(EXTENDED_UNITS);
|
||||
}
|
||||
Self { msrv: conf.msrv, units }
|
||||
}
|
||||
}
|
||||
|
||||
impl LateLintPass<'_> for DurationSuboptimalUnits {
|
||||
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) {
|
||||
if !expr.span.in_external_macro(cx.sess().source_map())
|
||||
// Check if a function on std::time::Duration is called
|
||||
&& let ExprKind::Call(func, [arg]) = expr.kind
|
||||
&& let ExprKind::Path(QPath::TypeRelative(func_ty, func_name)) = func.kind
|
||||
&& cx
|
||||
.typeck_results()
|
||||
.node_type(func_ty.hir_id)
|
||||
.is_diag_item(cx, sym::Duration)
|
||||
// We intentionally don't want to evaluate referenced constants, as we don't want to
|
||||
// recommend a literal value over using constants:
|
||||
//
|
||||
// let dur = Duration::from_secs(SIXTY);
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Duration::from_mins(1)`
|
||||
&& let Some(Constant::Int(value)) = ConstEvalCtxt::new(cx).eval_local(arg, expr.span.ctxt())
|
||||
&& let value = u64::try_from(value).expect("All Duration::from_<time-unit> constructors take a u64")
|
||||
// There is no need to promote e.g. 0 seconds to 0 hours
|
||||
&& value != 0
|
||||
&& let Some((promoted_constructor, promoted_value)) = self.promote(cx, func_name.ident.name, value)
|
||||
{
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
DURATION_SUBOPTIMAL_UNITS,
|
||||
expr.span,
|
||||
"constructing a `Duration` using a smaller unit when a larger unit would be more readable",
|
||||
|diag| {
|
||||
let suggestions = vec![
|
||||
(func_name.ident.span, promoted_constructor.to_string()),
|
||||
(arg.span, promoted_value.to_string()),
|
||||
];
|
||||
diag.multipart_suggestion_verbose(
|
||||
format!("try using {promoted_constructor}"),
|
||||
suggestions,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DurationSuboptimalUnits {
|
||||
/// Tries to promote the given constructor and value to a bigger time unit and returns the
|
||||
/// promoted constructor name and value.
|
||||
///
|
||||
/// Returns [`None`] in case no promotion could be done.
|
||||
fn promote(&self, cx: &LateContext<'_>, constructor_name: Symbol, value: u64) -> Option<(Symbol, u64)> {
|
||||
let (best_unit, best_value) = self
|
||||
.units
|
||||
.iter()
|
||||
.skip_while(|unit| unit.constructor_name != constructor_name)
|
||||
.skip(1)
|
||||
.try_fold(
|
||||
(constructor_name, value),
|
||||
|(current_unit, current_value), bigger_unit| {
|
||||
if let Some(bigger_value) = current_value.div_exact(u64::from(bigger_unit.factor))
|
||||
&& bigger_unit.stable_since.is_none_or(|v| self.msrv.meets(cx, v))
|
||||
{
|
||||
ControlFlow::Continue((bigger_unit.constructor_name, bigger_value))
|
||||
} else {
|
||||
// We have to break early, as we can't skip versions, as they are needed to
|
||||
// correctly calculate the promoted value.
|
||||
ControlFlow::Break((current_unit, current_value))
|
||||
}
|
||||
},
|
||||
)
|
||||
.into_value();
|
||||
(best_unit != constructor_name).then_some((best_unit, best_value))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Unit {
|
||||
/// Name of the constructor on [`Duration`](std::time::Duration) to construct it from the given
|
||||
/// unit, e.g. [`Duration::from_secs`](std::time::Duration::from_secs)
|
||||
constructor_name: Symbol,
|
||||
|
||||
/// The increase factor over the previous (smaller) unit
|
||||
factor: u16,
|
||||
|
||||
/// In what rustc version stable support for this constructor was added.
|
||||
/// We do not need to track the version stable support in const contexts was added, as the const
|
||||
/// stabilization was done in an ascending order of the time unites, so it's always valid to
|
||||
/// promote a const constructor.
|
||||
stable_since: Option<RustcVersion>,
|
||||
}
|
||||
|
||||
/// Time unit constructors available on stable. The order matters!
|
||||
const UNITS: [Unit; 6] = [
|
||||
Unit {
|
||||
constructor_name: sym::from_nanos,
|
||||
// The value doesn't matter, as there is no previous unit
|
||||
factor: 0,
|
||||
stable_since: Some(msrvs::DURATION_FROM_NANOS_MICROS),
|
||||
},
|
||||
Unit {
|
||||
constructor_name: sym::from_micros,
|
||||
factor: 1_000,
|
||||
stable_since: Some(msrvs::DURATION_FROM_NANOS_MICROS),
|
||||
},
|
||||
Unit {
|
||||
constructor_name: sym::from_millis,
|
||||
factor: 1_000,
|
||||
stable_since: Some(msrvs::DURATION_FROM_MILLIS_SECS),
|
||||
},
|
||||
Unit {
|
||||
constructor_name: sym::from_secs,
|
||||
factor: 1_000,
|
||||
stable_since: Some(msrvs::DURATION_FROM_MILLIS_SECS),
|
||||
},
|
||||
Unit {
|
||||
constructor_name: sym::from_mins,
|
||||
factor: 60,
|
||||
stable_since: Some(msrvs::DURATION_FROM_MINUTES_HOURS),
|
||||
},
|
||||
Unit {
|
||||
constructor_name: sym::from_hours,
|
||||
factor: 60,
|
||||
stable_since: Some(msrvs::DURATION_FROM_MINUTES_HOURS),
|
||||
},
|
||||
];
|
||||
|
||||
/// Time unit constructors behind the `duration_constructors` feature. The order matters!
|
||||
const EXTENDED_UNITS: [Unit; 2] = [
|
||||
Unit {
|
||||
constructor_name: sym::from_days,
|
||||
factor: 24,
|
||||
stable_since: None,
|
||||
},
|
||||
Unit {
|
||||
constructor_name: sym::from_weeks,
|
||||
factor: 7,
|
||||
stable_since: None,
|
||||
},
|
||||
];
|
||||
|
|
@ -1,11 +1,13 @@
|
|||
#![cfg_attr(bootstrap, feature(array_windows))]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(macro_metavar_expr_concat)]
|
||||
#![feature(control_flow_into_value)]
|
||||
#![feature(exact_div)]
|
||||
#![feature(f128)]
|
||||
#![feature(f16)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(iter_partition_in_place)]
|
||||
#![feature(macro_metavar_expr_concat)]
|
||||
#![feature(never_type)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
|
|
@ -113,6 +115,7 @@ mod doc;
|
|||
mod double_parens;
|
||||
mod drop_forget_ref;
|
||||
mod duplicate_mod;
|
||||
mod duration_suboptimal_units;
|
||||
mod else_if_without_else;
|
||||
mod empty_drop;
|
||||
mod empty_enums;
|
||||
|
|
@ -857,6 +860,7 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co
|
|||
Box::new(|_| Box::<replace_box::ReplaceBox>::default()),
|
||||
Box::new(move |_| Box::new(manual_ilog2::ManualIlog2::new(conf))),
|
||||
Box::new(|_| Box::new(same_length_and_capacity::SameLengthAndCapacity)),
|
||||
Box::new(move |tcx| Box::new(duration_suboptimal_units::DurationSuboptimalUnits::new(tcx, conf))),
|
||||
// add late passes here, used by `cargo dev new_lint`
|
||||
];
|
||||
store.late_passes.extend(late_lints);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ macro_rules! msrv_aliases {
|
|||
|
||||
// names may refer to stabilized feature flags or library items
|
||||
msrv_aliases! {
|
||||
1,91,0 { DURATION_FROM_MINUTES_HOURS }
|
||||
1,88,0 { LET_CHAINS }
|
||||
1,87,0 { OS_STR_DISPLAY, INT_MIDPOINT, CONST_CHAR_IS_DIGIT, UNSIGNED_IS_MULTIPLE_OF, INTEGER_SIGN_CAST }
|
||||
1,85,0 { UINT_FLOAT_MIDPOINT, CONST_SIZE_OF_VAL }
|
||||
|
|
@ -69,12 +70,12 @@ msrv_aliases! {
|
|||
1,35,0 { OPTION_COPIED, RANGE_CONTAINS }
|
||||
1,34,0 { TRY_FROM }
|
||||
1,33,0 { UNDERSCORE_IMPORTS }
|
||||
1,32,0 { CONST_IS_POWER_OF_TWO }
|
||||
1,32,0 { CONST_IS_POWER_OF_TWO, CONST_DURATION_FROM_NANOS_MICROS_MILLIS_SECS }
|
||||
1,31,0 { OPTION_REPLACE }
|
||||
1,30,0 { ITERATOR_FIND_MAP, TOOL_ATTRIBUTES }
|
||||
1,29,0 { ITER_FLATTEN }
|
||||
1,28,0 { FROM_BOOL, REPEAT_WITH, SLICE_FROM_REF }
|
||||
1,27,0 { ITERATOR_TRY_FOLD, DOUBLE_ENDED_ITERATOR_RFIND }
|
||||
1,27,0 { ITERATOR_TRY_FOLD, DOUBLE_ENDED_ITERATOR_RFIND, DURATION_FROM_NANOS_MICROS }
|
||||
1,26,0 { RANGE_INCLUSIVE, STRING_RETAIN, POINTER_ADD_SUB_METHODS }
|
||||
1,24,0 { IS_ASCII_DIGIT, PTR_NULL }
|
||||
1,18,0 { HASH_MAP_RETAIN, HASH_SET_RETAIN }
|
||||
|
|
@ -82,6 +83,7 @@ msrv_aliases! {
|
|||
1,16,0 { STR_REPEAT, RESULT_UNWRAP_OR_DEFAULT }
|
||||
1,15,0 { MAYBE_BOUND_IN_WHERE }
|
||||
1,13,0 { QUESTION_MARK_OPERATOR }
|
||||
1,3,0 { DURATION_FROM_MILLIS_SECS }
|
||||
}
|
||||
|
||||
/// `#[clippy::msrv]` attributes are rarely used outside of Clippy's test suite, as a basic
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ generate! {
|
|||
disallowed_types,
|
||||
drain,
|
||||
dump,
|
||||
duration_constructors,
|
||||
ends_with,
|
||||
enum_glob_use,
|
||||
enumerate,
|
||||
|
|
@ -164,12 +165,20 @@ generate! {
|
|||
from_be_bytes,
|
||||
from_bytes_with_nul,
|
||||
from_bytes_with_nul_unchecked,
|
||||
from_days,
|
||||
from_hours,
|
||||
from_le_bytes,
|
||||
from_micros,
|
||||
from_millis,
|
||||
from_mins,
|
||||
from_nanos,
|
||||
from_ne_bytes,
|
||||
from_ptr,
|
||||
from_raw,
|
||||
from_raw_parts,
|
||||
from_secs,
|
||||
from_str_radix,
|
||||
from_weeks,
|
||||
fs,
|
||||
fuse,
|
||||
futures_util,
|
||||
|
|
|
|||
91
tests/ui/duration_suboptimal_units.fixed
Normal file
91
tests/ui/duration_suboptimal_units.fixed
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
//@aux-build:proc_macros.rs
|
||||
#![warn(clippy::duration_suboptimal_units)]
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
const SIXTY: u64 = 60;
|
||||
|
||||
macro_rules! mac {
|
||||
(slow_rythm) => {
|
||||
3600
|
||||
};
|
||||
(duration) => {
|
||||
Duration::from_mins(5)
|
||||
//~^ duration_suboptimal_units
|
||||
};
|
||||
(arg => $e:expr) => {
|
||||
Duration::from_secs($e)
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let dur = Duration::from_secs(0);
|
||||
let dur = Duration::from_secs(42);
|
||||
let dur = Duration::from_hours(3);
|
||||
|
||||
let dur = Duration::from_mins(1);
|
||||
//~^ duration_suboptimal_units
|
||||
let dur = Duration::from_mins(3);
|
||||
//~^ duration_suboptimal_units
|
||||
let dur = Duration::from_mins(10);
|
||||
//~^ duration_suboptimal_units
|
||||
let dur = Duration::from_hours(24);
|
||||
//~^ duration_suboptimal_units
|
||||
let dur = Duration::from_secs(5);
|
||||
//~^ duration_suboptimal_units
|
||||
let dur = Duration::from_hours(13);
|
||||
//~^ duration_suboptimal_units
|
||||
|
||||
// Constants are intentionally not resolved, as we don't want to recommend a literal value over
|
||||
// using constants.
|
||||
let dur = Duration::from_secs(SIXTY);
|
||||
// Technically it would be nice to use Duration::from_mins(SIXTY) here, but that is a follow-up
|
||||
let dur = Duration::from_secs(SIXTY * 60);
|
||||
|
||||
const {
|
||||
let dur = Duration::from_secs(0);
|
||||
let dur = Duration::from_secs(5);
|
||||
//~^ duration_suboptimal_units
|
||||
let dur = Duration::from_mins(3);
|
||||
//~^ duration_suboptimal_units
|
||||
let dur = Duration::from_hours(24);
|
||||
//~^ duration_suboptimal_units
|
||||
|
||||
let dur = Duration::from_secs(SIXTY);
|
||||
}
|
||||
|
||||
// Qualified Durations must be kept
|
||||
std::time::Duration::from_mins(1);
|
||||
//~^ duration_suboptimal_units
|
||||
|
||||
// We lint in normal macros
|
||||
assert_eq!(Duration::from_hours(1), Duration::from_mins(6));
|
||||
//~^ duration_suboptimal_units
|
||||
|
||||
// We lint in normal macros (marker is in macro itself)
|
||||
let dur = mac!(duration);
|
||||
|
||||
// We don't lint in macros if duration comes from outside
|
||||
let dur = mac!(arg => 3600);
|
||||
|
||||
// We don't lint in external macros
|
||||
let dur = proc_macros::external! { Duration::from_secs(3_600) };
|
||||
|
||||
// We don't lint values coming from macros
|
||||
let dur = Duration::from_secs(mac!(slow_rythm));
|
||||
}
|
||||
|
||||
mod my_duration {
|
||||
struct Duration {}
|
||||
|
||||
impl Duration {
|
||||
pub const fn from_secs(_secs: u64) -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
fn test() {
|
||||
// Only suggest the change for std::time::Duration, not for other Duration structs
|
||||
let dur = Duration::from_secs(60);
|
||||
}
|
||||
}
|
||||
91
tests/ui/duration_suboptimal_units.rs
Normal file
91
tests/ui/duration_suboptimal_units.rs
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
//@aux-build:proc_macros.rs
|
||||
#![warn(clippy::duration_suboptimal_units)]
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
const SIXTY: u64 = 60;
|
||||
|
||||
macro_rules! mac {
|
||||
(slow_rythm) => {
|
||||
3600
|
||||
};
|
||||
(duration) => {
|
||||
Duration::from_secs(300)
|
||||
//~^ duration_suboptimal_units
|
||||
};
|
||||
(arg => $e:expr) => {
|
||||
Duration::from_secs($e)
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let dur = Duration::from_secs(0);
|
||||
let dur = Duration::from_secs(42);
|
||||
let dur = Duration::from_hours(3);
|
||||
|
||||
let dur = Duration::from_secs(60);
|
||||
//~^ duration_suboptimal_units
|
||||
let dur = Duration::from_secs(180);
|
||||
//~^ duration_suboptimal_units
|
||||
let dur = Duration::from_secs(10 * 60);
|
||||
//~^ duration_suboptimal_units
|
||||
let dur = Duration::from_mins(24 * 60);
|
||||
//~^ duration_suboptimal_units
|
||||
let dur = Duration::from_millis(5_000);
|
||||
//~^ duration_suboptimal_units
|
||||
let dur = Duration::from_nanos(13 * 60 * 60 * 1_000 * 1_000 * 1_000);
|
||||
//~^ duration_suboptimal_units
|
||||
|
||||
// Constants are intentionally not resolved, as we don't want to recommend a literal value over
|
||||
// using constants.
|
||||
let dur = Duration::from_secs(SIXTY);
|
||||
// Technically it would be nice to use Duration::from_mins(SIXTY) here, but that is a follow-up
|
||||
let dur = Duration::from_secs(SIXTY * 60);
|
||||
|
||||
const {
|
||||
let dur = Duration::from_secs(0);
|
||||
let dur = Duration::from_millis(5_000);
|
||||
//~^ duration_suboptimal_units
|
||||
let dur = Duration::from_secs(180);
|
||||
//~^ duration_suboptimal_units
|
||||
let dur = Duration::from_mins(24 * 60);
|
||||
//~^ duration_suboptimal_units
|
||||
|
||||
let dur = Duration::from_secs(SIXTY);
|
||||
}
|
||||
|
||||
// Qualified Durations must be kept
|
||||
std::time::Duration::from_secs(60);
|
||||
//~^ duration_suboptimal_units
|
||||
|
||||
// We lint in normal macros
|
||||
assert_eq!(Duration::from_secs(3_600), Duration::from_mins(6));
|
||||
//~^ duration_suboptimal_units
|
||||
|
||||
// We lint in normal macros (marker is in macro itself)
|
||||
let dur = mac!(duration);
|
||||
|
||||
// We don't lint in macros if duration comes from outside
|
||||
let dur = mac!(arg => 3600);
|
||||
|
||||
// We don't lint in external macros
|
||||
let dur = proc_macros::external! { Duration::from_secs(3_600) };
|
||||
|
||||
// We don't lint values coming from macros
|
||||
let dur = Duration::from_secs(mac!(slow_rythm));
|
||||
}
|
||||
|
||||
mod my_duration {
|
||||
struct Duration {}
|
||||
|
||||
impl Duration {
|
||||
pub const fn from_secs(_secs: u64) -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
fn test() {
|
||||
// Only suggest the change for std::time::Duration, not for other Duration structs
|
||||
let dur = Duration::from_secs(60);
|
||||
}
|
||||
}
|
||||
152
tests/ui/duration_suboptimal_units.stderr
Normal file
152
tests/ui/duration_suboptimal_units.stderr
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
error: constructing a `Duration` using a smaller unit when a larger unit would be more readable
|
||||
--> tests/ui/duration_suboptimal_units.rs:26:15
|
||||
|
|
||||
LL | let dur = Duration::from_secs(60);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::duration-suboptimal-units` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::duration_suboptimal_units)]`
|
||||
help: try using from_mins
|
||||
|
|
||||
LL - let dur = Duration::from_secs(60);
|
||||
LL + let dur = Duration::from_mins(1);
|
||||
|
|
||||
|
||||
error: constructing a `Duration` using a smaller unit when a larger unit would be more readable
|
||||
--> tests/ui/duration_suboptimal_units.rs:28:15
|
||||
|
|
||||
LL | let dur = Duration::from_secs(180);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: try using from_mins
|
||||
|
|
||||
LL - let dur = Duration::from_secs(180);
|
||||
LL + let dur = Duration::from_mins(3);
|
||||
|
|
||||
|
||||
error: constructing a `Duration` using a smaller unit when a larger unit would be more readable
|
||||
--> tests/ui/duration_suboptimal_units.rs:30:15
|
||||
|
|
||||
LL | let dur = Duration::from_secs(10 * 60);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: try using from_mins
|
||||
|
|
||||
LL - let dur = Duration::from_secs(10 * 60);
|
||||
LL + let dur = Duration::from_mins(10);
|
||||
|
|
||||
|
||||
error: constructing a `Duration` using a smaller unit when a larger unit would be more readable
|
||||
--> tests/ui/duration_suboptimal_units.rs:32:15
|
||||
|
|
||||
LL | let dur = Duration::from_mins(24 * 60);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: try using from_hours
|
||||
|
|
||||
LL - let dur = Duration::from_mins(24 * 60);
|
||||
LL + let dur = Duration::from_hours(24);
|
||||
|
|
||||
|
||||
error: constructing a `Duration` using a smaller unit when a larger unit would be more readable
|
||||
--> tests/ui/duration_suboptimal_units.rs:34:15
|
||||
|
|
||||
LL | let dur = Duration::from_millis(5_000);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: try using from_secs
|
||||
|
|
||||
LL - let dur = Duration::from_millis(5_000);
|
||||
LL + let dur = Duration::from_secs(5);
|
||||
|
|
||||
|
||||
error: constructing a `Duration` using a smaller unit when a larger unit would be more readable
|
||||
--> tests/ui/duration_suboptimal_units.rs:36:15
|
||||
|
|
||||
LL | let dur = Duration::from_nanos(13 * 60 * 60 * 1_000 * 1_000 * 1_000);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: try using from_hours
|
||||
|
|
||||
LL - let dur = Duration::from_nanos(13 * 60 * 60 * 1_000 * 1_000 * 1_000);
|
||||
LL + let dur = Duration::from_hours(13);
|
||||
|
|
||||
|
||||
error: constructing a `Duration` using a smaller unit when a larger unit would be more readable
|
||||
--> tests/ui/duration_suboptimal_units.rs:47:19
|
||||
|
|
||||
LL | let dur = Duration::from_millis(5_000);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: try using from_secs
|
||||
|
|
||||
LL - let dur = Duration::from_millis(5_000);
|
||||
LL + let dur = Duration::from_secs(5);
|
||||
|
|
||||
|
||||
error: constructing a `Duration` using a smaller unit when a larger unit would be more readable
|
||||
--> tests/ui/duration_suboptimal_units.rs:49:19
|
||||
|
|
||||
LL | let dur = Duration::from_secs(180);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: try using from_mins
|
||||
|
|
||||
LL - let dur = Duration::from_secs(180);
|
||||
LL + let dur = Duration::from_mins(3);
|
||||
|
|
||||
|
||||
error: constructing a `Duration` using a smaller unit when a larger unit would be more readable
|
||||
--> tests/ui/duration_suboptimal_units.rs:51:19
|
||||
|
|
||||
LL | let dur = Duration::from_mins(24 * 60);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: try using from_hours
|
||||
|
|
||||
LL - let dur = Duration::from_mins(24 * 60);
|
||||
LL + let dur = Duration::from_hours(24);
|
||||
|
|
||||
|
||||
error: constructing a `Duration` using a smaller unit when a larger unit would be more readable
|
||||
--> tests/ui/duration_suboptimal_units.rs:58:5
|
||||
|
|
||||
LL | std::time::Duration::from_secs(60);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: try using from_mins
|
||||
|
|
||||
LL - std::time::Duration::from_secs(60);
|
||||
LL + std::time::Duration::from_mins(1);
|
||||
|
|
||||
|
||||
error: constructing a `Duration` using a smaller unit when a larger unit would be more readable
|
||||
--> tests/ui/duration_suboptimal_units.rs:62:16
|
||||
|
|
||||
LL | assert_eq!(Duration::from_secs(3_600), Duration::from_mins(6));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: try using from_hours
|
||||
|
|
||||
LL - assert_eq!(Duration::from_secs(3_600), Duration::from_mins(6));
|
||||
LL + assert_eq!(Duration::from_hours(1), Duration::from_mins(6));
|
||||
|
|
||||
|
||||
error: constructing a `Duration` using a smaller unit when a larger unit would be more readable
|
||||
--> tests/ui/duration_suboptimal_units.rs:13:9
|
||||
|
|
||||
LL | Duration::from_secs(300)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | let dur = mac!(duration);
|
||||
| -------------- in this macro invocation
|
||||
|
|
||||
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: try using from_mins
|
||||
|
|
||||
LL - Duration::from_secs(300)
|
||||
LL + Duration::from_mins(5)
|
||||
|
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
|
||||
17
tests/ui/duration_suboptimal_units_days_weeks.fixed
Normal file
17
tests/ui/duration_suboptimal_units_days_weeks.fixed
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#![warn(clippy::duration_suboptimal_units)]
|
||||
// The duration_constructors feature enables `Duration::from_days` and `Duration::from_weeks`, so we
|
||||
// should suggest them
|
||||
#![feature(duration_constructors)]
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
fn main() {
|
||||
let dur = Duration::from_mins(1);
|
||||
//~^ duration_suboptimal_units
|
||||
|
||||
let dur = Duration::from_days(1);
|
||||
//~^ duration_suboptimal_units
|
||||
|
||||
let dur = Duration::from_weeks(13);
|
||||
//~^ duration_suboptimal_units
|
||||
}
|
||||
17
tests/ui/duration_suboptimal_units_days_weeks.rs
Normal file
17
tests/ui/duration_suboptimal_units_days_weeks.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#![warn(clippy::duration_suboptimal_units)]
|
||||
// The duration_constructors feature enables `Duration::from_days` and `Duration::from_weeks`, so we
|
||||
// should suggest them
|
||||
#![feature(duration_constructors)]
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
fn main() {
|
||||
let dur = Duration::from_secs(60);
|
||||
//~^ duration_suboptimal_units
|
||||
|
||||
let dur = Duration::from_hours(24);
|
||||
//~^ duration_suboptimal_units
|
||||
|
||||
let dur = Duration::from_nanos(13 * 7 * 24 * 60 * 60 * 1_000 * 1_000 * 1_000);
|
||||
//~^ duration_suboptimal_units
|
||||
}
|
||||
40
tests/ui/duration_suboptimal_units_days_weeks.stderr
Normal file
40
tests/ui/duration_suboptimal_units_days_weeks.stderr
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
error: constructing a `Duration` using a smaller unit when a larger unit would be more readable
|
||||
--> tests/ui/duration_suboptimal_units_days_weeks.rs:9:15
|
||||
|
|
||||
LL | let dur = Duration::from_secs(60);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::duration-suboptimal-units` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::duration_suboptimal_units)]`
|
||||
help: try using from_mins
|
||||
|
|
||||
LL - let dur = Duration::from_secs(60);
|
||||
LL + let dur = Duration::from_mins(1);
|
||||
|
|
||||
|
||||
error: constructing a `Duration` using a smaller unit when a larger unit would be more readable
|
||||
--> tests/ui/duration_suboptimal_units_days_weeks.rs:12:15
|
||||
|
|
||||
LL | let dur = Duration::from_hours(24);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: try using from_days
|
||||
|
|
||||
LL - let dur = Duration::from_hours(24);
|
||||
LL + let dur = Duration::from_days(1);
|
||||
|
|
||||
|
||||
error: constructing a `Duration` using a smaller unit when a larger unit would be more readable
|
||||
--> tests/ui/duration_suboptimal_units_days_weeks.rs:15:15
|
||||
|
|
||||
LL | let dur = Duration::from_nanos(13 * 7 * 24 * 60 * 60 * 1_000 * 1_000 * 1_000);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: try using from_weeks
|
||||
|
|
||||
LL - let dur = Duration::from_nanos(13 * 7 * 24 * 60 * 60 * 1_000 * 1_000 * 1_000);
|
||||
LL + let dur = Duration::from_weeks(13);
|
||||
|
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue