Fix sliced_string_as_bytes FP with a RangeFull (#15873)
changelog: [`sliced_string_as_bytes`]: don't fire on `str[..].as_bytes()` So I ran into this in some codebase I was working on, where the lint fired on this line: ```rust let string: &str; string[..].as_bytes() ``` So I was trying to understand the rationale behind this lint, and it says: > It involves doing an unnecessary UTF-8 alignment check which is less efficient, and can cause a panic. This is obviously not true in the case where a `RangeFull` slice is being taken, since there is no UTF-8 boundary check, and no panic can be caused. So I created an exemption for `RangeFull`s. Two other notes: 1. I'm not sure the word "alignment" in the lint's description (quoted above) is really correct, should probably say "char boundary" instead? 2. I might be missing something, but isn't there a lint for doing superfluous slice indexing, and then calling a slice method? e.g. `str[..].len()` or `slice[..].len()`, where `str` and `slice` are `&str` and `&[T]`, respectively. If we had one, I would expect *it* to fire for the example code I quoted above.
This commit is contained in:
commit
cd61be7c56
3 changed files with 20 additions and 2 deletions
|
|
@ -1,15 +1,21 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::higher;
|
||||
use clippy_utils::res::MaybeDef;
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, ExprKind, LangItem, is_range_literal};
|
||||
use rustc_hir::{Expr, ExprKind, LangItem};
|
||||
use rustc_lint::LateContext;
|
||||
|
||||
use super::SLICED_STRING_AS_BYTES;
|
||||
|
||||
/// Checks if `index` is any type of range except `RangeFull` (i.e. `..`)
|
||||
fn is_bounded_range_literal(cx: &LateContext<'_>, index: &Expr<'_>) -> bool {
|
||||
higher::Range::hir(cx, index).is_some_and(|range| Option::or(range.start, range.end).is_some())
|
||||
}
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>) {
|
||||
if let ExprKind::Index(indexed, index, _) = recv.kind
|
||||
&& is_range_literal(index)
|
||||
&& is_bounded_range_literal(cx, index)
|
||||
&& let ty = cx.typeck_results().expr_ty(indexed).peel_refs()
|
||||
&& (ty.is_str() || ty.is_lang_item(cx, LangItem::String))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -32,6 +32,12 @@ fn main() {
|
|||
let bytes = &"consectetur adipiscing".as_bytes()[..=5];
|
||||
//~^ sliced_string_as_bytes
|
||||
|
||||
// this lint is a perf lint meant to catch utf-8 alignment checks.
|
||||
// while the slicing here *is* redundant, it's more like a needless borrow, and shouldn't affect
|
||||
// perf
|
||||
let bytes = s[..].as_bytes();
|
||||
let bytes = string[..].as_bytes();
|
||||
|
||||
let f = Foo;
|
||||
let bytes = f[0..4].as_bytes();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,12 @@ fn main() {
|
|||
let bytes = "consectetur adipiscing"[..=5].as_bytes();
|
||||
//~^ sliced_string_as_bytes
|
||||
|
||||
// this lint is a perf lint meant to catch utf-8 alignment checks.
|
||||
// while the slicing here *is* redundant, it's more like a needless borrow, and shouldn't affect
|
||||
// perf
|
||||
let bytes = s[..].as_bytes();
|
||||
let bytes = string[..].as_bytes();
|
||||
|
||||
let f = Foo;
|
||||
let bytes = f[0..4].as_bytes();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue