Skip to content

Commit 58c53e8

Browse files
committed
reduce single_char_pattern to only lint on ascii chars
1 parent 6b1c828 commit 58c53e8

File tree

7 files changed

+28
-17
lines changed

7 files changed

+28
-17
lines changed

clippy_lints/src/methods/mod.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,11 +1145,14 @@ declare_clippy_lint! {
11451145
/// `str` as an argument, e.g., `_.split("x")`.
11461146
///
11471147
/// ### Why is this bad?
1148-
/// Performing these methods using a `char` is faster than
1149-
/// using a `str`.
1148+
/// Performing these methods using a `char` can be faster than
1149+
/// using a `str` because it needs one less indirection.
11501150
///
11511151
/// ### Known problems
1152-
/// Does not catch multi-byte unicode characters.
1152+
/// Does not catch multi-byte unicode characters. This is by
1153+
/// design, on many machines, splitting by a non-ascii char is
1154+
/// actually slower. Please do your own measurements instead of
1155+
/// relying solely on the results of this lint.
11531156
///
11541157
/// ### Example
11551158
/// ```rust,ignore

clippy_lints/src/methods/single_char_insert_string.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use super::SINGLE_CHAR_ADD_STR;
1010
/// lint for length-1 `str`s as argument for `insert_str`
1111
pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
1212
let mut applicability = Applicability::MachineApplicable;
13-
if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[1], &mut applicability) {
13+
if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[1], &mut applicability, false) {
1414
let base_string_snippet =
1515
snippet_with_applicability(cx, receiver.span.source_callsite(), "_", &mut applicability);
1616
let pos_arg = snippet_with_applicability(cx, args[0].span, "..", &mut applicability);

clippy_lints/src/methods/single_char_pattern.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_span::symbol::Symbol;
88

99
use super::SINGLE_CHAR_PATTERN;
1010

11-
const PATTERN_METHODS: [(&str, usize); 24] = [
11+
const PATTERN_METHODS: [(&str, usize); 22] = [
1212
("contains", 0),
1313
("starts_with", 0),
1414
("ends_with", 0),
@@ -27,8 +27,6 @@ const PATTERN_METHODS: [(&str, usize); 24] = [
2727
("rmatches", 0),
2828
("match_indices", 0),
2929
("rmatch_indices", 0),
30-
("strip_prefix", 0),
31-
("strip_suffix", 0),
3230
("trim_start_matches", 0),
3331
("trim_end_matches", 0),
3432
("replace", 0),
@@ -50,7 +48,7 @@ pub(super) fn check(
5048
&& args.len() > pos
5149
&& let arg = &args[pos]
5250
&& let mut applicability = Applicability::MachineApplicable
53-
&& let Some(hint) = get_hint_if_single_char_arg(cx, arg, &mut applicability)
51+
&& let Some(hint) = get_hint_if_single_char_arg(cx, arg, &mut applicability, true)
5452
{
5553
span_lint_and_sugg(
5654
cx,

clippy_lints/src/methods/single_char_push_string.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use super::SINGLE_CHAR_ADD_STR;
1010
/// lint for length-1 `str`s as argument for `push_str`
1111
pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
1212
let mut applicability = Applicability::MachineApplicable;
13-
if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[0], &mut applicability) {
13+
if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[0], &mut applicability, false) {
1414
let base_string_snippet =
1515
snippet_with_applicability(cx, receiver.span.source_callsite(), "..", &mut applicability);
1616
let sugg = format!("{base_string_snippet}.push({extension_string})");

clippy_lints/src/methods/utils.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,17 @@ pub(super) fn get_hint_if_single_char_arg(
5252
cx: &LateContext<'_>,
5353
arg: &Expr<'_>,
5454
applicability: &mut Applicability,
55+
ascii_only: bool,
5556
) -> Option<String> {
5657
if let ExprKind::Lit(lit) = &arg.kind
5758
&& let ast::LitKind::Str(r, style) = lit.node
5859
&& let string = r.as_str()
59-
&& string.chars().count() == 1
60+
&& let len = if ascii_only {
61+
string.len()
62+
} else {
63+
string.chars().count()
64+
}
65+
&& len == 1
6066
{
6167
let snip = snippet_with_applicability(cx, arg.span, string, applicability);
6268
let ch = if let ast::StrStyle::Raw(nhash) = style {

tests/ui/single_char_pattern.fixed

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ fn main() {
1010

1111
let y = "x";
1212
x.split(y);
13-
x.split('ß');
14-
x.split('ℝ');
15-
x.split('💣');
13+
x.split("ß");
14+
x.split("ℝ");
15+
x.split("💣");
1616
// Can't use this lint for unicode code points which don't fit in a char
1717
x.split("❤️");
1818
x.split_inclusive('x');
@@ -34,8 +34,6 @@ fn main() {
3434
x.rmatch_indices('x');
3535
x.trim_start_matches('x');
3636
x.trim_end_matches('x');
37-
x.strip_prefix('x');
38-
x.strip_suffix('x');
3937
x.replace('x', "y");
4038
x.replacen('x', "y", 3);
4139
// Make sure we escape characters correctly.
@@ -64,4 +62,8 @@ fn main() {
6462
// Must escape backslash in raw strings when converting to char #8060
6563
x.split('\\');
6664
x.split('\\');
65+
66+
// should not warn, the char versions are actually slower in some cases
67+
x.strip_prefix("x");
68+
x.strip_suffix("x");
6769
}

tests/ui/single_char_pattern.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ fn main() {
3434
x.rmatch_indices("x");
3535
x.trim_start_matches("x");
3636
x.trim_end_matches("x");
37-
x.strip_prefix("x");
38-
x.strip_suffix("x");
3937
x.replace("x", "y");
4038
x.replacen("x", "y", 3);
4139
// Make sure we escape characters correctly.
@@ -64,4 +62,8 @@ fn main() {
6462
// Must escape backslash in raw strings when converting to char #8060
6563
x.split(r#"\"#);
6664
x.split(r"\");
65+
66+
// should not warn, the char versions are actually slower in some cases
67+
x.strip_prefix("x");
68+
x.strip_suffix("x");
6769
}

0 commit comments

Comments
 (0)