Skip to content

Commit c739027

Browse files
committed
add comment and .clone() test case
1 parent d5d2189 commit c739027

4 files changed

+37
-15
lines changed

clippy_lints/src/loops/char_indices_as_byte_indices.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ fn check_index_usage<'tcx>(
8484
let is_string_like = |ty: Ty<'_>| ty.is_str() || is_type_lang_item(cx, ty, LangItem::String);
8585
let message = match parent_expr.kind {
8686
ExprKind::MethodCall(segment, recv, ..)
87+
// We currently only lint `str` methods (which `String` can deref to), so a `.is_str()` check is sufficient here
88+
// (contrary to the `ExprKind::Index` case which needs to handle both with `is_string_like` because `String` implements
89+
// `Index` directly and no deref to `str` would happen in that case).
8790
if cx.typeck_results().expr_ty_adjusted(recv).peel_refs().is_str()
8891
&& BYTE_INDEX_METHODS.contains(&segment.ident.name.as_str())
8992
&& eq_expr_value(cx, chars_recv, recv) =>
@@ -126,7 +129,7 @@ fn check_index_usage<'tcx>(
126129
/// but for `.get(..idx)` we want to consider the method call the consuming expression,
127130
/// which requires skipping past the range expression.
128131
fn index_consumed_at<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
129-
for (_, node) in cx.tcx.hir().parent_iter(expr.hir_id) {
132+
for (_, node) in cx.tcx.hir_parent_iter(expr.hir_id) {
130133
match node {
131134
Node::Expr(expr) if higher::Range::hir(expr).is_some() => {},
132135
Node::ExprField(_) => {},

tests/ui/char_indices_as_byte_indices.fixed

+6
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ fn good(prim: &str, prim2: &str) {
5454
// str method taking a usize that doesn't represent a byte index
5555
prim.splitn(idx, prim2);
5656
}
57+
58+
let mut string = "äa".to_owned();
59+
for (idx, _) in string.clone().chars().enumerate() {
60+
// Even though the receiver is the same expression, it should not be treated as the same value.
61+
string.clone().remove(idx);
62+
}
5763
}
5864

5965
fn main() {}

tests/ui/char_indices_as_byte_indices.rs

+6
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ fn good(prim: &str, prim2: &str) {
5454
// str method taking a usize that doesn't represent a byte index
5555
prim.splitn(idx, prim2);
5656
}
57+
58+
let mut string = "äa".to_owned();
59+
for (idx, _) in string.clone().chars().enumerate() {
60+
// Even though the receiver is the same expression, it should not be treated as the same value.
61+
string.clone().remove(idx);
62+
}
5763
}
5864

5965
fn main() {}

tests/ui/char_indices_as_byte_indices.stderr

+21-14
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ LL | for (idx, _) in prim.chars().enumerate() {
1414
= help: to override `-D warnings` add `#[allow(clippy::char_indices_as_byte_indices)]`
1515
help: consider using `.char_indices()` instead
1616
|
17-
LL | for (idx, _) in prim.char_indices() {
18-
| ~~~~~~~~~~~~~~
17+
LL - for (idx, _) in prim.chars().enumerate() {
18+
LL + for (idx, _) in prim.char_indices() {
19+
|
1920

2021
error: passing a character position to a method that expects a byte index
2122
--> tests/ui/char_indices_as_byte_indices.rs:15:23
@@ -31,8 +32,9 @@ LL | for (idx, _) in prim.chars().enumerate() {
3132
| ^^^ ^^^^^^^^^^^
3233
help: consider using `.char_indices()` instead
3334
|
34-
LL | for (idx, _) in prim.char_indices() {
35-
| ~~~~~~~~~~~~~~
35+
LL - for (idx, _) in prim.chars().enumerate() {
36+
LL + for (idx, _) in prim.char_indices() {
37+
|
3638

3739
error: passing a character position to a method that expects a byte index
3840
--> tests/ui/char_indices_as_byte_indices.rs:19:49
@@ -48,8 +50,9 @@ LL | for (idx, _) in prim.chars().enumerate() {
4850
| ^^^ ^^^^^^^^^^^
4951
help: consider using `.char_indices()` instead
5052
|
51-
LL | for (idx, _) in prim.char_indices() {
52-
| ~~~~~~~~~~~~~~
53+
LL - for (idx, _) in prim.chars().enumerate() {
54+
LL + for (idx, _) in prim.char_indices() {
55+
|
5356

5457
error: indexing into a string with a character position where a byte index is expected
5558
--> tests/ui/char_indices_as_byte_indices.rs:29:24
@@ -65,8 +68,9 @@ LL | for c in prim.chars().enumerate() {
6568
| ^ ^^^^^^^^^^^
6669
help: consider using `.char_indices()` instead
6770
|
68-
LL | for c in prim.char_indices() {
69-
| ~~~~~~~~~~~~~~
71+
LL - for c in prim.chars().enumerate() {
72+
LL + for c in prim.char_indices() {
73+
|
7074

7175
error: passing a character position to a method that expects a byte index
7276
--> tests/ui/char_indices_as_byte_indices.rs:31:23
@@ -82,8 +86,9 @@ LL | for c in prim.chars().enumerate() {
8286
| ^ ^^^^^^^^^^^
8387
help: consider using `.char_indices()` instead
8488
|
85-
LL | for c in prim.char_indices() {
86-
| ~~~~~~~~~~~~~~
89+
LL - for c in prim.chars().enumerate() {
90+
LL + for c in prim.char_indices() {
91+
|
8792

8893
error: indexing into a string with a character position where a byte index is expected
8994
--> tests/ui/char_indices_as_byte_indices.rs:36:26
@@ -99,8 +104,9 @@ LL | for (idx, _) in string.chars().enumerate() {
99104
| ^^^ ^^^^^^^^^^^
100105
help: consider using `.char_indices()` instead
101106
|
102-
LL | for (idx, _) in string.char_indices() {
103-
| ~~~~~~~~~~~~~~
107+
LL - for (idx, _) in string.chars().enumerate() {
108+
LL + for (idx, _) in string.char_indices() {
109+
|
104110

105111
error: passing a character position to a method that expects a byte index
106112
--> tests/ui/char_indices_as_byte_indices.rs:38:25
@@ -116,8 +122,9 @@ LL | for (idx, _) in string.chars().enumerate() {
116122
| ^^^ ^^^^^^^^^^^
117123
help: consider using `.char_indices()` instead
118124
|
119-
LL | for (idx, _) in string.char_indices() {
120-
| ~~~~~~~~~~~~~~
125+
LL - for (idx, _) in string.chars().enumerate() {
126+
LL + for (idx, _) in string.char_indices() {
127+
|
121128

122129
error: aborting due to 7 previous errors
123130

0 commit comments

Comments
 (0)