-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Closes #8603 Signed-off-by: Federico Guerinoni <[email protected]>
- Loading branch information
Showing
9 changed files
with
146 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
|