From 7e53e27dfdb5ce4cda44912fcc6c288c34ac7d91 Mon Sep 17 00:00:00 2001 From: Krishna Sundarram Date: Thu, 16 Feb 2023 16:41:04 +0000 Subject: [PATCH] Stop bytes_nth from suggesting code that does not compile --- clippy_lints/src/methods/bytes_nth.rs | 42 ++++++++++++++++++--------- tests/ui/bytes_nth.fixed | 6 ++-- tests/ui/bytes_nth.rs | 2 +- tests/ui/bytes_nth.stderr | 10 +++---- 4 files changed, 38 insertions(+), 22 deletions(-) diff --git a/clippy_lints/src/methods/bytes_nth.rs b/clippy_lints/src/methods/bytes_nth.rs index d512cc4eeae..c5fc145b289 100644 --- a/clippy_lints/src/methods/bytes_nth.rs +++ b/clippy_lints/src/methods/bytes_nth.rs @@ -5,6 +5,8 @@ use rustc_errors::Applicability; use rustc_hir::{Expr, LangItem}; use rustc_lint::LateContext; +use crate::methods::method_call; + use super::BYTES_NTH; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx Expr<'tcx>, n_arg: &'tcx Expr<'tcx>) { @@ -16,18 +18,32 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx E } else { return; }; + let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - BYTES_NTH, - expr.span, - &format!("called `.bytes().nth()` on a `{caller_type}`"), - "try", - format!( - "{}.as_bytes().get({})", - snippet_with_applicability(cx, recv.span, "..", &mut applicability), - snippet_with_applicability(cx, n_arg.span, "..", &mut applicability) - ), - applicability, - ); + let receiver = snippet_with_applicability(cx, recv.span, "..", &mut applicability); + let n = snippet_with_applicability(cx, n_arg.span, "..", &mut applicability); + + if let Some(parent) = clippy_utils::get_parent_expr(cx, expr) + && let Some((name, _, _, _, _)) = method_call(parent) + && name == "unwrap" { + span_lint_and_sugg( + cx, + BYTES_NTH, + parent.span, + &format!("called `.bytes().nth().unwrap()` on a `{caller_type}`"), + "try", + format!("{receiver}.as_bytes()[{n}]",), + applicability + ); + } else { + span_lint_and_sugg( + cx, + BYTES_NTH, + expr.span, + &format!("called `.bytes().nth()` on a `{caller_type}`"), + "try", + format!("{receiver}.as_bytes().get({n}).copied()"), + applicability + ); + }; } diff --git a/tests/ui/bytes_nth.fixed b/tests/ui/bytes_nth.fixed index b1fb2e16bd5..a35c679afb7 100644 --- a/tests/ui/bytes_nth.fixed +++ b/tests/ui/bytes_nth.fixed @@ -5,7 +5,7 @@ fn main() { let s = String::from("String"); - let _ = s.as_bytes().get(3); - let _ = &s.as_bytes().get(3); - let _ = s[..].as_bytes().get(3); + let _ = s.as_bytes().get(3).copied(); + let _ = &s.as_bytes()[3]; + let _ = s[..].as_bytes().get(3).copied(); } diff --git a/tests/ui/bytes_nth.rs b/tests/ui/bytes_nth.rs index 034c54e6a42..1ecffea5303 100644 --- a/tests/ui/bytes_nth.rs +++ b/tests/ui/bytes_nth.rs @@ -6,6 +6,6 @@ fn main() { let s = String::from("String"); let _ = s.bytes().nth(3); - let _ = &s.bytes().nth(3); + let _ = &s.bytes().nth(3).unwrap(); let _ = s[..].bytes().nth(3); } diff --git a/tests/ui/bytes_nth.stderr b/tests/ui/bytes_nth.stderr index 9851d4791d8..e8b15027829 100644 --- a/tests/ui/bytes_nth.stderr +++ b/tests/ui/bytes_nth.stderr @@ -2,21 +2,21 @@ error: called `.bytes().nth()` on a `String` --> $DIR/bytes_nth.rs:8:13 | LL | let _ = s.bytes().nth(3); - | ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)` + | ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3).copied()` | = note: `-D clippy::bytes-nth` implied by `-D warnings` -error: called `.bytes().nth()` on a `String` +error: called `.bytes().nth().unwrap()` on a `String` --> $DIR/bytes_nth.rs:9:14 | -LL | let _ = &s.bytes().nth(3); - | ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)` +LL | let _ = &s.bytes().nth(3).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.as_bytes()[3]` error: called `.bytes().nth()` on a `str` --> $DIR/bytes_nth.rs:10:13 | LL | let _ = s[..].bytes().nth(3); - | ^^^^^^^^^^^^^^^^^^^^ help: try: `s[..].as_bytes().get(3)` + | ^^^^^^^^^^^^^^^^^^^^ help: try: `s[..].as_bytes().get(3).copied()` error: aborting due to 3 previous errors