about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/loops/char_indices_as_byte_indices.rs5
-rw-r--r--tests/ui/char_indices_as_byte_indices.fixed6
-rw-r--r--tests/ui/char_indices_as_byte_indices.rs6
-rw-r--r--tests/ui/char_indices_as_byte_indices.stderr35
4 files changed, 37 insertions, 15 deletions
diff --git a/clippy_lints/src/loops/char_indices_as_byte_indices.rs b/clippy_lints/src/loops/char_indices_as_byte_indices.rs
index 90e6f71e41a..8916454ada1 100644
--- a/clippy_lints/src/loops/char_indices_as_byte_indices.rs
+++ b/clippy_lints/src/loops/char_indices_as_byte_indices.rs
@@ -84,6 +84,9 @@ fn check_index_usage<'tcx>(
     let is_string_like = |ty: Ty<'_>| ty.is_str() || is_type_lang_item(cx, ty, LangItem::String);
     let message = match parent_expr.kind {
         ExprKind::MethodCall(segment, recv, ..)
+            // We currently only lint `str` methods (which `String` can deref to), so a `.is_str()` check is sufficient here
+            // (contrary to the `ExprKind::Index` case which needs to handle both with `is_string_like` because `String` implements
+            // `Index` directly and no deref to `str` would happen in that case).
             if cx.typeck_results().expr_ty_adjusted(recv).peel_refs().is_str()
                 && BYTE_INDEX_METHODS.contains(&segment.ident.name.as_str())
                 && eq_expr_value(cx, chars_recv, recv) =>
@@ -126,7 +129,7 @@ fn check_index_usage<'tcx>(
 /// but for `.get(..idx)` we want to consider the method call the consuming expression,
 /// which requires skipping past the range expression.
 fn index_consumed_at<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
-    for (_, node) in cx.tcx.hir().parent_iter(expr.hir_id) {
+    for (_, node) in cx.tcx.hir_parent_iter(expr.hir_id) {
         match node {
             Node::Expr(expr) if higher::Range::hir(expr).is_some() => {},
             Node::ExprField(_) => {},
diff --git a/tests/ui/char_indices_as_byte_indices.fixed b/tests/ui/char_indices_as_byte_indices.fixed
index a7c6bcd2681..04c8f6782c5 100644
--- a/tests/ui/char_indices_as_byte_indices.fixed
+++ b/tests/ui/char_indices_as_byte_indices.fixed
@@ -54,6 +54,12 @@ fn good(prim: &str, prim2: &str) {
         // str method taking a usize that doesn't represent a byte index
         prim.splitn(idx, prim2);
     }
+
+    let mut string = "äa".to_owned();
+    for (idx, _) in string.clone().chars().enumerate() {
+        // Even though the receiver is the same expression, it should not be treated as the same value.
+        string.clone().remove(idx);
+    }
 }
 
 fn main() {}
diff --git a/tests/ui/char_indices_as_byte_indices.rs b/tests/ui/char_indices_as_byte_indices.rs
index bb0f5df19bc..773a4fc65f1 100644
--- a/tests/ui/char_indices_as_byte_indices.rs
+++ b/tests/ui/char_indices_as_byte_indices.rs
@@ -54,6 +54,12 @@ fn good(prim: &str, prim2: &str) {
         // str method taking a usize that doesn't represent a byte index
         prim.splitn(idx, prim2);
     }
+
+    let mut string = "äa".to_owned();
+    for (idx, _) in string.clone().chars().enumerate() {
+        // Even though the receiver is the same expression, it should not be treated as the same value.
+        string.clone().remove(idx);
+    }
 }
 
 fn main() {}
diff --git a/tests/ui/char_indices_as_byte_indices.stderr b/tests/ui/char_indices_as_byte_indices.stderr
index a3c84578392..e2b4c1db78c 100644
--- a/tests/ui/char_indices_as_byte_indices.stderr
+++ b/tests/ui/char_indices_as_byte_indices.stderr
@@ -14,8 +14,9 @@ LL |     for (idx, _) in prim.chars().enumerate() {
    = help: to override `-D warnings` add `#[allow(clippy::char_indices_as_byte_indices)]`
 help: consider using `.char_indices()` instead
    |
-LL |     for (idx, _) in prim.char_indices() {
-   |                          ~~~~~~~~~~~~~~
+LL -     for (idx, _) in prim.chars().enumerate() {
+LL +     for (idx, _) in prim.char_indices() {
+   |
 
 error: passing a character position to a method that expects a byte index
   --> tests/ui/char_indices_as_byte_indices.rs:15:23
@@ -31,8 +32,9 @@ LL |     for (idx, _) in prim.chars().enumerate() {
    |          ^^^                     ^^^^^^^^^^^
 help: consider using `.char_indices()` instead
    |
-LL |     for (idx, _) in prim.char_indices() {
-   |                          ~~~~~~~~~~~~~~
+LL -     for (idx, _) in prim.chars().enumerate() {
+LL +     for (idx, _) in prim.char_indices() {
+   |
 
 error: passing a character position to a method that expects a byte index
   --> tests/ui/char_indices_as_byte_indices.rs:19:49
@@ -48,8 +50,9 @@ LL |     for (idx, _) in prim.chars().enumerate() {
    |          ^^^                     ^^^^^^^^^^^
 help: consider using `.char_indices()` instead
    |
-LL |     for (idx, _) in prim.char_indices() {
-   |                          ~~~~~~~~~~~~~~
+LL -     for (idx, _) in prim.chars().enumerate() {
+LL +     for (idx, _) in prim.char_indices() {
+   |
 
 error: indexing into a string with a character position where a byte index is expected
   --> tests/ui/char_indices_as_byte_indices.rs:29:24
@@ -65,8 +68,9 @@ LL |     for c in prim.chars().enumerate() {
    |         ^                 ^^^^^^^^^^^
 help: consider using `.char_indices()` instead
    |
-LL |     for c in prim.char_indices() {
-   |                   ~~~~~~~~~~~~~~
+LL -     for c in prim.chars().enumerate() {
+LL +     for c in prim.char_indices() {
+   |
 
 error: passing a character position to a method that expects a byte index
   --> tests/ui/char_indices_as_byte_indices.rs:31:23
@@ -82,8 +86,9 @@ LL |     for c in prim.chars().enumerate() {
    |         ^                 ^^^^^^^^^^^
 help: consider using `.char_indices()` instead
    |
-LL |     for c in prim.char_indices() {
-   |                   ~~~~~~~~~~~~~~
+LL -     for c in prim.chars().enumerate() {
+LL +     for c in prim.char_indices() {
+   |
 
 error: indexing into a string with a character position where a byte index is expected
   --> tests/ui/char_indices_as_byte_indices.rs:36:26
@@ -99,8 +104,9 @@ LL |     for (idx, _) in string.chars().enumerate() {
    |          ^^^                       ^^^^^^^^^^^
 help: consider using `.char_indices()` instead
    |
-LL |     for (idx, _) in string.char_indices() {
-   |                            ~~~~~~~~~~~~~~
+LL -     for (idx, _) in string.chars().enumerate() {
+LL +     for (idx, _) in string.char_indices() {
+   |
 
 error: passing a character position to a method that expects a byte index
   --> tests/ui/char_indices_as_byte_indices.rs:38:25
@@ -116,8 +122,9 @@ LL |     for (idx, _) in string.chars().enumerate() {
    |          ^^^                       ^^^^^^^^^^^
 help: consider using `.char_indices()` instead
    |
-LL |     for (idx, _) in string.char_indices() {
-   |                            ~~~~~~~~~~~~~~
+LL -     for (idx, _) in string.chars().enumerate() {
+LL +     for (idx, _) in string.char_indices() {
+   |
 
 error: aborting due to 7 previous errors