Skip to content

Commit

Permalink
new lint
Browse files Browse the repository at this point in the history
  • Loading branch information
yawara committed Nov 13, 2024
1 parent f58088b commit 11c3cce
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5367,6 +5367,7 @@ Released 2018-09-13
[`box_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_vec
[`boxed_local`]: https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local
[`branches_sharing_code`]: https://rust-lang.github.io/rust-clippy/master/index.html#branches_sharing_code
[`bufreader_stdin`]: https://rust-lang.github.io/rust-clippy/master/index.html#bufreader_stdin
[`builtin_type_shadow`]: https://rust-lang.github.io/rust-clippy/master/index.html#builtin_type_shadow
[`byte_char_slices`]: https://rust-lang.github.io/rust-clippy/master/index.html#byte_char_slices
[`bytes_count_to_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#bytes_count_to_len
Expand Down
73 changes: 73 additions & 0 deletions clippy_lints/src/bufreader_stdin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::match_def_path;
use clippy_utils::source::snippet;
use rustc_errors::Applicability;
use rustc_hir::{ExprKind, QPath, TyKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
use rustc_span::sym;

declare_clippy_lint! {
/// ### What it does
/// Checks for usage of `BufReader::new` with `Stdin` or `StdinLock`.
///
/// ### Why is this bad?
/// `Stdin` is already buffered. Re-buffering it only increase the memcpy calls.
///
/// ### Example
/// ```no_run
/// let reader = std::io::BufReader::new(std::io::stdin());
/// ```
/// Use instead:
/// ```no_run
/// let stdin = std::io::stdin();
/// let reader = stdin.lock();
/// ```
#[clippy::version = "1.84.0"]
pub BUFREADER_STDIN,
perf,
"using `BufReader::new` with `Stdin` or `StdinLock` is unnecessary and less efficient"
}

declare_lint_pass!(BufreaderStdinlock => [BUFREADER_STDIN]);

impl<'tcx> LateLintPass<'tcx> for BufreaderStdinlock {
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &rustc_hir::Expr<'tcx>) {
if e.span.from_expansion() {
return;
}
if let ExprKind::Call(func, [arg]) = e.kind
&& let ExprKind::Path(QPath::TypeRelative(ty, seg)) = func.kind
&& seg.ident.name == sym::new
&& let TyKind::Path(ref qpath) = ty.kind
&& let Some(did) = cx.qpath_res(qpath, ty.hir_id).opt_def_id()
&& match_def_path(cx, did, &["std", "io", "buffered", "bufreader", "BufReader"])
&& let arg_ty = cx.typeck_results().expr_ty(arg)
&& let Some(arg_did) = arg_ty.ty_adt_def().map(|def| def.did())
{
if match_def_path(cx, arg_did, &["std", "io", "stdio", "Stdin"]) {
span_lint_and_sugg(
cx,
&BUFREADER_STDIN,
e.span,
"using `BufReader::new` with `Stdin`",
"instead of wrapping `Stdin` in `BufReader`, use the `lock` method directly",
format!("{}.lock()", snippet(cx, arg.span, "..")),
Applicability::MachineApplicable,
);
} else if match_def_path(cx, arg_did, &["std", "io", "stdio", "StdinLock"]) {
span_lint_and_sugg(
cx,
&BUFREADER_STDIN,
e.span,
"using `BufReader::new` with `Stdin`",
"instead of wrapping `StdinLock` in `BufReader`, use it self",
snippet(cx, arg.span, "..").to_string(),
Applicability::MachineApplicable,
);
} else {
return;
};
}
}
}
1 change: 1 addition & 0 deletions clippy_lints/src/declared_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
crate::booleans::OVERLY_COMPLEX_BOOL_EXPR_INFO,
crate::borrow_deref_ref::BORROW_DEREF_REF_INFO,
crate::box_default::BOX_DEFAULT_INFO,
crate::bufreader_stdin::BUFREADER_STDIN_INFO,
crate::byte_char_slices::BYTE_CHAR_SLICES_INFO,
crate::cargo::CARGO_COMMON_METADATA_INFO,
crate::cargo::LINT_GROUPS_PRIORITY_INFO,
Expand Down
2 changes: 2 additions & 0 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ mod bool_to_int_with_if;
mod booleans;
mod borrow_deref_ref;
mod box_default;
mod bufreader_stdin;
mod byte_char_slices;
mod cargo;
mod casts;
Expand Down Expand Up @@ -963,5 +964,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
store.register_late_pass(|_| Box::new(manual_ignore_case_cmp::ManualIgnoreCaseCmp));
store.register_late_pass(|_| Box::new(unnecessary_literal_bound::UnnecessaryLiteralBound));
store.register_late_pass(move |_| Box::new(arbitrary_source_item_ordering::ArbitrarySourceItemOrdering::new(conf)));
store.register_late_pass(|_| Box::new(bufreader_stdin::BufreaderStdinlock));
// add lints here, do not remove this comment, it's used in `new_lint`
}
10 changes: 10 additions & 0 deletions tests/ui/bufreader_stdin.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#![warn(clippy::bufreader_stdin)]
use std::io::{self, BufReader};

fn main() {
let a = io::stdin();
let reader = a.lock();

let b = io::stdin().lock();
let reader = b;
}
10 changes: 10 additions & 0 deletions tests/ui/bufreader_stdin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#![warn(clippy::BUFREADER_STDIN)]
use std::io::{self, BufReader};

fn main() {
let a = io::stdin();
let reader = BufReader::new(a);

let b = io::stdin().lock();
let reader = BufReader::new(b);
}
30 changes: 30 additions & 0 deletions tests/ui/bufreader_stdin.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
error: unknown lint: `clippy::BUFREADER_STDIN`
--> tests/ui/bufreader_stdin.rs:1:9
|
LL | #![warn(clippy::BUFREADER_STDIN)]
| ^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::bufreader_stdin`
|
= note: `-D unknown-lints` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(unknown_lints)]`

error: using `BufReader::new` with `Stdin`
--> tests/ui/bufreader_stdin.rs:6:18
|
LL | let reader = BufReader::new(a);
| ^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::bufreader-stdin` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::bufreader_stdin)]`
help: instead of wrapping `Stdin` in `BufReader`, use the `lock` method directly
|
LL | let reader = a.lock();
| ~~~~~~~~

error: using `BufReader::new` with `Stdin`
--> tests/ui/bufreader_stdin.rs:9:18
|
LL | let reader = BufReader::new(b);
| ^^^^^^^^^^^^^^^^^ help: instead of wrapping `StdinLock` in `BufReader`, use it self: `b`

error: aborting due to 3 previous errors

0 comments on commit 11c3cce

Please sign in to comment.