Skip to content

Commit

Permalink
Auto merge of #6695 - TaKO8Ki:add-bytes-nth, r=phansch
Browse files Browse the repository at this point in the history
New lint: `bytes_nth`

This pull request adds a new lint named `bytes_nth`.

---
closes: #6391

changelog: Added a new lint: `bytes_nth`
  • Loading branch information
bors committed Feb 10, 2021
2 parents 9c0ae2a + 5996ae1 commit b5e4389
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -1877,6 +1877,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
[`builtin_type_shadow`]: https://rust-lang.github.io/rust-clippy/master/index.html#builtin_type_shadow
[`bytes_nth`]: https://rust-lang.github.io/rust-clippy/master/index.html#bytes_nth
[`cargo_common_metadata`]: https://rust-lang.github.io/rust-clippy/master/index.html#cargo_common_metadata
[`case_sensitive_file_extension_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#case_sensitive_file_extension_comparisons
[`cast_lossless`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_lossless
Expand Down
3 changes: 3 additions & 0 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
&mem_replace::MEM_REPLACE_WITH_DEFAULT,
&mem_replace::MEM_REPLACE_WITH_UNINIT,
&methods::BIND_INSTEAD_OF_MAP,
&methods::BYTES_NTH,
&methods::CHARS_LAST_CMP,
&methods::CHARS_NEXT_CMP,
&methods::CLONE_DOUBLE_REF,
Expand Down Expand Up @@ -1531,6 +1532,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&mem_replace::MEM_REPLACE_WITH_DEFAULT),
LintId::of(&mem_replace::MEM_REPLACE_WITH_UNINIT),
LintId::of(&methods::BIND_INSTEAD_OF_MAP),
LintId::of(&methods::BYTES_NTH),
LintId::of(&methods::CHARS_LAST_CMP),
LintId::of(&methods::CHARS_NEXT_CMP),
LintId::of(&methods::CLONE_DOUBLE_REF),
Expand Down Expand Up @@ -1748,6 +1750,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&matches::SINGLE_MATCH),
LintId::of(&mem_replace::MEM_REPLACE_OPTION_WITH_NONE),
LintId::of(&mem_replace::MEM_REPLACE_WITH_DEFAULT),
LintId::of(&methods::BYTES_NTH),
LintId::of(&methods::CHARS_LAST_CMP),
LintId::of(&methods::CHARS_NEXT_CMP),
LintId::of(&methods::FROM_ITER_INSTEAD_OF_COLLECT),
Expand Down
39 changes: 39 additions & 0 deletions clippy_lints/src/methods/bytes_nth.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use crate::utils::{is_type_diagnostic_item, snippet_with_applicability, span_lint_and_sugg};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_span::sym;

use super::BYTES_NTH;

pub(super) fn lints<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, iter_args: &'tcx [Expr<'tcx>]) {
if_chain! {
if let ExprKind::MethodCall(_, _, ref args, _) = expr.kind;
let ty = cx.typeck_results().expr_ty(&iter_args[0]).peel_refs();
let caller_type = if is_type_diagnostic_item(cx, ty, sym::string_type) {
Some("String")
} else if ty.is_str() {
Some("str")
} else {
None
};
if let Some(caller_type) = caller_type;
then {
let mut applicability = Applicability::MachineApplicable;
span_lint_and_sugg(
cx,
BYTES_NTH,
expr.span,
&format!("called `.byte().nth()` on a `{}`", caller_type),
"try",
format!(
"{}.as_bytes().get({})",
snippet_with_applicability(cx, iter_args[0].span, "..", &mut applicability),
snippet_with_applicability(cx, args[1].span, "..", &mut applicability)
),
applicability,
);
}
}
}
25 changes: 25 additions & 0 deletions clippy_lints/src/methods/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod bind_instead_of_map;
mod bytes_nth;
mod filter_map_identity;
mod inefficient_to_string;
mod inspect_for_each;
Expand Down Expand Up @@ -1490,6 +1491,28 @@ declare_clippy_lint! {
"call to `filter_map` where `flatten` is sufficient"
}

declare_clippy_lint! {
/// **What it does:** Checks for the use of `.bytes().nth()`.
///
/// **Why is this bad?** `.as_bytes().get()` is more efficient and more
/// readable.
///
/// **Known problems:** None.
///
/// **Example:**
///
/// ```rust
/// // Bad
/// let _ = "Hello".bytes().nth(3);;
///
/// // Good
/// let _ = "Hello".as_bytes().get(3);
/// ```
pub BYTES_NTH,
style,
"replace `.bytes().nth()` with `.as_bytes().get()`"
}

pub struct Methods {
msrv: Option<RustcVersion>,
}
Expand Down Expand Up @@ -1537,6 +1560,7 @@ impl_lint_pass!(Methods => [
ITER_NEXT_SLICE,
ITER_NTH,
ITER_NTH_ZERO,
BYTES_NTH,
ITER_SKIP_NEXT,
GET_UNWRAP,
STRING_EXTEND_CHARS,
Expand Down Expand Up @@ -1614,6 +1638,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
["extend", ..] => lint_extend(cx, expr, arg_lists[0]),
["nth", "iter"] => lint_iter_nth(cx, expr, &arg_lists, false),
["nth", "iter_mut"] => lint_iter_nth(cx, expr, &arg_lists, true),
["nth", "bytes"] => bytes_nth::lints(cx, expr, &arg_lists[1]),
["nth", ..] => lint_iter_nth_zero(cx, expr, arg_lists[0]),
["step_by", ..] => lint_step_by(cx, expr, arg_lists[0]),
["next", "skip"] => lint_iter_skip_next(cx, expr, arg_lists[1]),
Expand Down
11 changes: 11 additions & 0 deletions tests/ui/bytes_nth.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// run-rustfix

#![allow(clippy::unnecessary_operation)]
#![warn(clippy::bytes_nth)]

fn main() {
let s = String::from("String");
s.as_bytes().get(3);
&s.as_bytes().get(3);
s[..].as_bytes().get(3);
}
11 changes: 11 additions & 0 deletions tests/ui/bytes_nth.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// run-rustfix

#![allow(clippy::unnecessary_operation)]
#![warn(clippy::bytes_nth)]

fn main() {
let s = String::from("String");
s.bytes().nth(3);
&s.bytes().nth(3);
s[..].bytes().nth(3);
}
22 changes: 22 additions & 0 deletions tests/ui/bytes_nth.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
error: called `.byte().nth()` on a `String`
--> $DIR/bytes_nth.rs:8:5
|
LL | s.bytes().nth(3);
| ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)`
|
= note: `-D clippy::bytes-nth` implied by `-D warnings`

error: called `.byte().nth()` on a `String`
--> $DIR/bytes_nth.rs:9:6
|
LL | &s.bytes().nth(3);
| ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)`

error: called `.byte().nth()` on a `str`
--> $DIR/bytes_nth.rs:10:5
|
LL | s[..].bytes().nth(3);
| ^^^^^^^^^^^^^^^^^^^^ help: try: `s[..].as_bytes().get(3)`

error: aborting due to 3 previous errors

0 comments on commit b5e4389

Please sign in to comment.