mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 06:22:00 +00:00
Add elapsed_instant
lint
Closes #8603 Signed-off-by: Federico Guerinoni <guerinoni.federico@gmail.com>
This commit is contained in:
parent
a0ed68776e
commit
0696624ba7
@ -3686,6 +3686,7 @@ Released 2018-09-13
|
||||
[`manual_find`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find
|
||||
[`manual_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find_map
|
||||
[`manual_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_flatten
|
||||
[`manual_instant_elapsed`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_instant_elapsed
|
||||
[`manual_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_map
|
||||
[`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy
|
||||
[`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive
|
||||
|
@ -244,6 +244,7 @@ store.register_lints(&[
|
||||
manual_assert::MANUAL_ASSERT,
|
||||
manual_async_fn::MANUAL_ASYNC_FN,
|
||||
manual_bits::MANUAL_BITS,
|
||||
manual_instant_elapsed::MANUAL_INSTANT_ELAPSED,
|
||||
manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE,
|
||||
manual_ok_or::MANUAL_OK_OR,
|
||||
manual_rem_euclid::MANUAL_REM_EUCLID,
|
||||
|
@ -49,6 +49,7 @@ store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![
|
||||
LintId::of(loops::EXPLICIT_ITER_LOOP),
|
||||
LintId::of(macro_use::MACRO_USE_IMPORTS),
|
||||
LintId::of(manual_assert::MANUAL_ASSERT),
|
||||
LintId::of(manual_instant_elapsed::MANUAL_INSTANT_ELAPSED),
|
||||
LintId::of(manual_ok_or::MANUAL_OK_OR),
|
||||
LintId::of(matches::MATCH_BOOL),
|
||||
LintId::of(matches::MATCH_ON_VEC_ITEMS),
|
||||
|
@ -273,6 +273,7 @@ mod main_recursion;
|
||||
mod manual_assert;
|
||||
mod manual_async_fn;
|
||||
mod manual_bits;
|
||||
mod manual_instant_elapsed;
|
||||
mod manual_non_exhaustive;
|
||||
mod manual_ok_or;
|
||||
mod manual_rem_euclid;
|
||||
@ -929,6 +930,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||
store.register_late_pass(move || Box::new(operators::Operators::new(verbose_bit_mask_threshold)));
|
||||
store.register_late_pass(|| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked));
|
||||
store.register_late_pass(|| Box::new(std_instead_of_core::StdReexports::default()));
|
||||
store.register_late_pass(|| Box::new(manual_instant_elapsed::ManualInstantElapsed));
|
||||
// add lints here, do not remove this comment, it's used in `new_lint`
|
||||
}
|
||||
|
||||
|
69
clippy_lints/src/manual_instant_elapsed.rs
Normal file
69
clippy_lints/src/manual_instant_elapsed.rs
Normal file
@ -0,0 +1,69 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
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;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Lints subtraction between `Instant::now()` and another `Instant`.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// It is easy to accidentally write `prev_instant - Instant::now()`, which will always be 0ns
|
||||
/// as `Instant` subtraction saturates.
|
||||
///
|
||||
/// `prev_instant.elapsed()` also more clearly signals intention.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust
|
||||
/// use std::time::Instant;
|
||||
/// let prev_instant = Instant::now();
|
||||
/// let duration = Instant::now() - prev_instant;
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
/// use std::time::Instant;
|
||||
/// let prev_instant = Instant::now();
|
||||
/// let duration = prev_instant.elapsed();
|
||||
/// ```
|
||||
#[clippy::version = "1.64.0"]
|
||||
pub MANUAL_INSTANT_ELAPSED,
|
||||
pedantic,
|
||||
"subtraction between `Instant::now()` and previous `Instant`"
|
||||
}
|
||||
|
||||
declare_lint_pass!(ManualInstantElapsed => [MANUAL_INSTANT_ELAPSED]);
|
||||
|
||||
impl LateLintPass<'_> for ManualInstantElapsed {
|
||||
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) {
|
||||
if let ExprKind::Binary(Spanned {node: BinOpKind::Sub, ..}, lhs, rhs) = expr.kind
|
||||
&& check_instant_now_call(cx, lhs)
|
||||
&& let ty_resolved = cx.typeck_results().expr_ty(rhs)
|
||||
&& let rustc_middle::ty::Adt(def, _) = ty_resolved.kind()
|
||||
&& clippy_utils::match_def_path(cx, def.did(), &clippy_utils::paths::INSTANT)
|
||||
&& let Some(sugg) = clippy_utils::sugg::Sugg::hir_opt(cx, rhs)
|
||||
{
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
MANUAL_INSTANT_ELAPSED,
|
||||
expr.span,
|
||||
"manual implementation of `Instant::elapsed`",
|
||||
"try",
|
||||
format!("{}.elapsed()", sugg.maybe_par()),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_instant_now_call(cx: &LateContext<'_>, expr_block: &'_ Expr<'_>) -> bool {
|
||||
if let ExprKind::Call(fn_expr, []) = expr_block.kind
|
||||
&& let Some(fn_id) = clippy_utils::path_def_id(cx, fn_expr)
|
||||
&& clippy_utils::match_def_path(cx, fn_id, &clippy_utils::paths::INSTANT_NOW)
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
@ -194,3 +194,5 @@ pub const VEC_RESIZE: [&str; 4] = ["alloc", "vec", "Vec", "resize"];
|
||||
pub const WEAK_ARC: [&str; 3] = ["alloc", "sync", "Weak"];
|
||||
pub const WEAK_RC: [&str; 3] = ["alloc", "rc", "Weak"];
|
||||
pub const PTR_NON_NULL: [&str; 4] = ["core", "ptr", "non_null", "NonNull"];
|
||||
pub const INSTANT_NOW: [&str; 4] = ["std", "time", "Instant", "now"];
|
||||
pub const INSTANT: [&str; 3] = ["std", "time", "Instant"];
|
||||
|
27
tests/ui/manual_instant_elapsed.fixed
Normal file
27
tests/ui/manual_instant_elapsed.fixed
Normal file
@ -0,0 +1,27 @@
|
||||
// run-rustfix
|
||||
#![warn(clippy::manual_instant_elapsed)]
|
||||
#![allow(clippy::unnecessary_operation)]
|
||||
#![allow(unused_variables)]
|
||||
#![allow(unused_must_use)]
|
||||
|
||||
use std::time::Instant;
|
||||
|
||||
fn main() {
|
||||
let prev_instant = Instant::now();
|
||||
|
||||
{
|
||||
// don't influence
|
||||
let another_instant = Instant::now();
|
||||
}
|
||||
|
||||
let duration = prev_instant.elapsed();
|
||||
|
||||
// don't catch
|
||||
let duration = prev_instant.elapsed();
|
||||
|
||||
Instant::now() - duration;
|
||||
|
||||
let ref_to_instant = &Instant::now();
|
||||
|
||||
(*ref_to_instant).elapsed(); // to ensure parens are added correctly
|
||||
}
|
27
tests/ui/manual_instant_elapsed.rs
Normal file
27
tests/ui/manual_instant_elapsed.rs
Normal file
@ -0,0 +1,27 @@
|
||||
// run-rustfix
|
||||
#![warn(clippy::manual_instant_elapsed)]
|
||||
#![allow(clippy::unnecessary_operation)]
|
||||
#![allow(unused_variables)]
|
||||
#![allow(unused_must_use)]
|
||||
|
||||
use std::time::Instant;
|
||||
|
||||
fn main() {
|
||||
let prev_instant = Instant::now();
|
||||
|
||||
{
|
||||
// don't influence
|
||||
let another_instant = Instant::now();
|
||||
}
|
||||
|
||||
let duration = Instant::now() - prev_instant;
|
||||
|
||||
// don't catch
|
||||
let duration = prev_instant.elapsed();
|
||||
|
||||
Instant::now() - duration;
|
||||
|
||||
let ref_to_instant = &Instant::now();
|
||||
|
||||
Instant::now() - *ref_to_instant; // to ensure parens are added correctly
|
||||
}
|
16
tests/ui/manual_instant_elapsed.stderr
Normal file
16
tests/ui/manual_instant_elapsed.stderr
Normal file
@ -0,0 +1,16 @@
|
||||
error: manual implementation of `Instant::elapsed`
|
||||
--> $DIR/manual_instant_elapsed.rs:17:20
|
||||
|
|
||||
LL | let duration = Instant::now() - prev_instant;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `prev_instant.elapsed()`
|
||||
|
|
||||
= note: `-D clippy::manual-instant-elapsed` implied by `-D warnings`
|
||||
|
||||
error: manual implementation of `Instant::elapsed`
|
||||
--> $DIR/manual_instant_elapsed.rs:26:5
|
||||
|
|
||||
LL | Instant::now() - *ref_to_instant; // to ensure parens are added correctly
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(*ref_to_instant).elapsed()`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
Loading…
Reference in New Issue
Block a user