about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAndre Bogus <bogusandre@gmail.com>2023-11-21 14:35:02 +0100
committerAndre Bogus <bogusandre@gmail.com>2024-04-11 18:09:55 +0200
commit58c53e8ea9fd56e1caea002f2a43b7a631508ba7 (patch)
treee04aef631a1fb6b87bee1e1e1fa4308bdebb222d
parent6b1c828d91f72269156cb70561148e511dd4ef15 (diff)
downloadrust-58c53e8ea9fd56e1caea002f2a43b7a631508ba7.tar.gz
rust-58c53e8ea9fd56e1caea002f2a43b7a631508ba7.zip
reduce `single_char_pattern` to only lint on ascii chars
-rw-r--r--clippy_lints/src/methods/mod.rs9
-rw-r--r--clippy_lints/src/methods/single_char_insert_string.rs2
-rw-r--r--clippy_lints/src/methods/single_char_pattern.rs6
-rw-r--r--clippy_lints/src/methods/single_char_push_string.rs2
-rw-r--r--clippy_lints/src/methods/utils.rs8
-rw-r--r--tests/ui/single_char_pattern.fixed12
-rw-r--r--tests/ui/single_char_pattern.rs6
7 files changed, 28 insertions, 17 deletions
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index 0939c028564..609deba7352 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -1145,11 +1145,14 @@ declare_clippy_lint! {
     /// `str` as an argument, e.g., `_.split("x")`.
     ///
     /// ### Why is this bad?
-    /// Performing these methods using a `char` is faster than
-    /// using a `str`.
+    /// Performing these methods using a `char` can be faster than
+    /// using a `str` because it needs one less indirection.
     ///
     /// ### Known problems
-    /// Does not catch multi-byte unicode characters.
+    /// Does not catch multi-byte unicode characters. This is by
+    /// design, on many machines, splitting by a non-ascii char is
+    /// actually slower. Please do your own measurements instead of
+    /// relying solely on the results of this lint.
     ///
     /// ### Example
     /// ```rust,ignore
diff --git a/clippy_lints/src/methods/single_char_insert_string.rs b/clippy_lints/src/methods/single_char_insert_string.rs
index 44a7ad394fa..20ec2b74d81 100644
--- a/clippy_lints/src/methods/single_char_insert_string.rs
+++ b/clippy_lints/src/methods/single_char_insert_string.rs
@@ -10,7 +10,7 @@ use super::SINGLE_CHAR_ADD_STR;
 /// lint for length-1 `str`s as argument for `insert_str`
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
     let mut applicability = Applicability::MachineApplicable;
-    if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[1], &mut applicability) {
+    if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[1], &mut applicability, false) {
         let base_string_snippet =
             snippet_with_applicability(cx, receiver.span.source_callsite(), "_", &mut applicability);
         let pos_arg = snippet_with_applicability(cx, args[0].span, "..", &mut applicability);
diff --git a/clippy_lints/src/methods/single_char_pattern.rs b/clippy_lints/src/methods/single_char_pattern.rs
index 363b1f2b812..982a7901c45 100644
--- a/clippy_lints/src/methods/single_char_pattern.rs
+++ b/clippy_lints/src/methods/single_char_pattern.rs
@@ -8,7 +8,7 @@ use rustc_span::symbol::Symbol;
 
 use super::SINGLE_CHAR_PATTERN;
 
-const PATTERN_METHODS: [(&str, usize); 24] = [
+const PATTERN_METHODS: [(&str, usize); 22] = [
     ("contains", 0),
     ("starts_with", 0),
     ("ends_with", 0),
@@ -27,8 +27,6 @@ const PATTERN_METHODS: [(&str, usize); 24] = [
     ("rmatches", 0),
     ("match_indices", 0),
     ("rmatch_indices", 0),
-    ("strip_prefix", 0),
-    ("strip_suffix", 0),
     ("trim_start_matches", 0),
     ("trim_end_matches", 0),
     ("replace", 0),
@@ -50,7 +48,7 @@ pub(super) fn check(
             && args.len() > pos
             && let arg = &args[pos]
             && let mut applicability = Applicability::MachineApplicable
-            && let Some(hint) = get_hint_if_single_char_arg(cx, arg, &mut applicability)
+            && let Some(hint) = get_hint_if_single_char_arg(cx, arg, &mut applicability, true)
         {
             span_lint_and_sugg(
                 cx,
diff --git a/clippy_lints/src/methods/single_char_push_string.rs b/clippy_lints/src/methods/single_char_push_string.rs
index 0698bd6a0c5..97c13825bc1 100644
--- a/clippy_lints/src/methods/single_char_push_string.rs
+++ b/clippy_lints/src/methods/single_char_push_string.rs
@@ -10,7 +10,7 @@ use super::SINGLE_CHAR_ADD_STR;
 /// lint for length-1 `str`s as argument for `push_str`
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
     let mut applicability = Applicability::MachineApplicable;
-    if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[0], &mut applicability) {
+    if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[0], &mut applicability, false) {
         let base_string_snippet =
             snippet_with_applicability(cx, receiver.span.source_callsite(), "..", &mut applicability);
         let sugg = format!("{base_string_snippet}.push({extension_string})");
diff --git a/clippy_lints/src/methods/utils.rs b/clippy_lints/src/methods/utils.rs
index ef00c812d51..c50f24f824a 100644
--- a/clippy_lints/src/methods/utils.rs
+++ b/clippy_lints/src/methods/utils.rs
@@ -52,11 +52,17 @@ pub(super) fn get_hint_if_single_char_arg(
     cx: &LateContext<'_>,
     arg: &Expr<'_>,
     applicability: &mut Applicability,
+    ascii_only: bool,
 ) -> Option<String> {
     if let ExprKind::Lit(lit) = &arg.kind
         && let ast::LitKind::Str(r, style) = lit.node
         && let string = r.as_str()
-        && string.chars().count() == 1
+        && let len = if ascii_only {
+            string.len()
+        } else {
+            string.chars().count()
+        }
+        && len == 1
     {
         let snip = snippet_with_applicability(cx, arg.span, string, applicability);
         let ch = if let ast::StrStyle::Raw(nhash) = style {
diff --git a/tests/ui/single_char_pattern.fixed b/tests/ui/single_char_pattern.fixed
index 9573fdbcfde..3ffdf474196 100644
--- a/tests/ui/single_char_pattern.fixed
+++ b/tests/ui/single_char_pattern.fixed
@@ -10,9 +10,9 @@ fn main() {
 
     let y = "x";
     x.split(y);
-    x.split('ß');
-    x.split('ℝ');
-    x.split('💣');
+    x.split("ß");
+    x.split("ℝ");
+    x.split("💣");
     // Can't use this lint for unicode code points which don't fit in a char
     x.split("❤️");
     x.split_inclusive('x');
@@ -34,8 +34,6 @@ fn main() {
     x.rmatch_indices('x');
     x.trim_start_matches('x');
     x.trim_end_matches('x');
-    x.strip_prefix('x');
-    x.strip_suffix('x');
     x.replace('x', "y");
     x.replacen('x', "y", 3);
     // Make sure we escape characters correctly.
@@ -64,4 +62,8 @@ fn main() {
     // Must escape backslash in raw strings when converting to char #8060
     x.split('\\');
     x.split('\\');
+
+    // should not warn, the char versions are actually slower in some cases
+    x.strip_prefix("x");
+    x.strip_suffix("x");
 }
diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs
index 8a04480dbc6..74ab3aa5fb0 100644
--- a/tests/ui/single_char_pattern.rs
+++ b/tests/ui/single_char_pattern.rs
@@ -34,8 +34,6 @@ fn main() {
     x.rmatch_indices("x");
     x.trim_start_matches("x");
     x.trim_end_matches("x");
-    x.strip_prefix("x");
-    x.strip_suffix("x");
     x.replace("x", "y");
     x.replacen("x", "y", 3);
     // Make sure we escape characters correctly.
@@ -64,4 +62,8 @@ fn main() {
     // Must escape backslash in raw strings when converting to char #8060
     x.split(r#"\"#);
     x.split(r"\");
+
+    // should not warn, the char versions are actually slower in some cases
+    x.strip_prefix("x");
+    x.strip_suffix("x");
 }