Skip to content

Commit 871ad80

Browse files
committed
Auto merge of #7690 - Jarcho:while_loop_by_ref, r=xFrednet
Change `while_let_on_iterator` suggestion to use `by_ref()` It came up in the discussion #7659 that suggesting `iter.by_ref()` is a clearer suggestion than `&mut iter`. I personally think they're equivalent, but if `by_ref()` is clearer to people then that should be the suggestion. changelog: Change `while_let_on_iterator` suggestion when using `&mut` to use `by_ref()`
2 parents 59cd777 + ee6a6b5 commit 871ad80

File tree

3 files changed

+22
-27
lines changed

3 files changed

+22
-27
lines changed

clippy_lints/src/loops/while_let_on_iterator.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use clippy_utils::{
88
use if_chain::if_chain;
99
use rustc_errors::Applicability;
1010
use rustc_hir::intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor};
11-
use rustc_hir::{def::Res, Expr, ExprKind, HirId, Local, Mutability, PatKind, QPath, UnOp};
11+
use rustc_hir::{def::Res, Expr, ExprKind, HirId, Local, PatKind, QPath, UnOp};
1212
use rustc_lint::LateContext;
1313
use rustc_span::{symbol::sym, Span, Symbol};
1414

@@ -47,13 +47,8 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
4747
// If the iterator is a field or the iterator is accessed after the loop is complete it needs to be
4848
// borrowed mutably. TODO: If the struct can be partially moved from and the struct isn't used
4949
// afterwards a mutable borrow of a field isn't necessary.
50-
let ref_mut = if !iter_expr.fields.is_empty() || needs_mutable_borrow(cx, &iter_expr, loop_expr) {
51-
if cx.typeck_results().node_type(iter_expr.hir_id).ref_mutability() == Some(Mutability::Mut) {
52-
// Reborrow for mutable references. It may not be possible to get a mutable reference here.
53-
"&mut *"
54-
} else {
55-
"&mut "
56-
}
50+
let by_ref = if !iter_expr.fields.is_empty() || needs_mutable_borrow(cx, &iter_expr, loop_expr) {
51+
".by_ref()"
5752
} else {
5853
""
5954
};
@@ -65,7 +60,7 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
6560
expr.span.with_hi(scrutinee_expr.span.hi()),
6661
"this loop could be written as a `for` loop",
6762
"try",
68-
format!("for {} in {}{}", loop_var, ref_mut, iterator),
63+
format!("for {} in {}{}", loop_var, iterator, by_ref),
6964
applicability,
7065
);
7166
}

tests/ui/while_let_on_iterator.fixed

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ fn issue6491() {
188188
// Used in outer loop, needs &mut
189189
let mut it = 1..40;
190190
while let Some(n) = it.next() {
191-
for m in &mut it {
191+
for m in it.by_ref() {
192192
if m % 10 == 0 {
193193
break;
194194
}
@@ -219,7 +219,7 @@ fn issue6491() {
219219

220220
// Used after the loop, needs &mut.
221221
let mut it = 1..40;
222-
for m in &mut it {
222+
for m in it.by_ref() {
223223
if m % 10 == 0 {
224224
break;
225225
}
@@ -236,7 +236,7 @@ fn issue6231() {
236236
let mut it = 1..40;
237237
let mut opt = Some(0);
238238
while let Some(n) = opt.take().or_else(|| it.next()) {
239-
for m in &mut it {
239+
for m in it.by_ref() {
240240
if n % 10 == 0 {
241241
break;
242242
}
@@ -251,7 +251,7 @@ fn issue1924() {
251251
impl<T: Iterator<Item = u32>> S<T> {
252252
fn f(&mut self) -> Option<u32> {
253253
// Used as a field.
254-
for i in &mut self.0 {
254+
for i in self.0.by_ref() {
255255
if !(3..=7).contains(&i) {
256256
return Some(i);
257257
}
@@ -283,7 +283,7 @@ fn issue1924() {
283283
}
284284
}
285285
// This one is fine, a different field is borrowed
286-
for i in &mut self.0.0.0 {
286+
for i in self.0.0.0.by_ref() {
287287
if i == 1 {
288288
return self.0.1.take();
289289
} else {
@@ -312,7 +312,7 @@ fn issue1924() {
312312

313313
// Needs &mut, field of the iterator is accessed after the loop
314314
let mut it = S2(1..40, 0);
315-
for n in &mut it {
315+
for n in it.by_ref() {
316316
if n == 0 {
317317
break;
318318
}
@@ -324,7 +324,7 @@ fn issue7249() {
324324
let mut it = 0..10;
325325
let mut x = || {
326326
// Needs &mut, the closure can be called multiple times
327-
for x in &mut it {
327+
for x in it.by_ref() {
328328
if x % 2 == 0 {
329329
break;
330330
}
@@ -338,7 +338,7 @@ fn issue7510() {
338338
let mut it = 0..10;
339339
let it = &mut it;
340340
// Needs to reborrow `it` as the binding isn't mutable
341-
for x in &mut *it {
341+
for x in it.by_ref() {
342342
if x % 2 == 0 {
343343
break;
344344
}
@@ -349,7 +349,7 @@ fn issue7510() {
349349
let mut it = 0..10;
350350
let it = S(&mut it);
351351
// Needs to reborrow `it.0` as the binding isn't mutable
352-
for x in &mut *it.0 {
352+
for x in it.0.by_ref() {
353353
if x % 2 == 0 {
354354
break;
355355
}

tests/ui/while_let_on_iterator.stderr

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ error: this loop could be written as a `for` loop
4646
--> $DIR/while_let_on_iterator.rs:191:9
4747
|
4848
LL | while let Some(m) = it.next() {
49-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in &mut it`
49+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()`
5050

5151
error: this loop could be written as a `for` loop
5252
--> $DIR/while_let_on_iterator.rs:202:5
@@ -70,19 +70,19 @@ error: this loop could be written as a `for` loop
7070
--> $DIR/while_let_on_iterator.rs:222:9
7171
|
7272
LL | while let Some(m) = it.next() {
73-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in &mut it`
73+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()`
7474

7575
error: this loop could be written as a `for` loop
7676
--> $DIR/while_let_on_iterator.rs:239:9
7777
|
7878
LL | while let Some(m) = it.next() {
79-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in &mut it`
79+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()`
8080

8181
error: this loop could be written as a `for` loop
8282
--> $DIR/while_let_on_iterator.rs:254:13
8383
|
8484
LL | while let Some(i) = self.0.next() {
85-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in &mut self.0`
85+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.by_ref()`
8686

8787
error: manual `!RangeInclusive::contains` implementation
8888
--> $DIR/while_let_on_iterator.rs:255:20
@@ -96,31 +96,31 @@ error: this loop could be written as a `for` loop
9696
--> $DIR/while_let_on_iterator.rs:286:13
9797
|
9898
LL | while let Some(i) = self.0.0.0.next() {
99-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in &mut self.0.0.0`
99+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.0.0.by_ref()`
100100

101101
error: this loop could be written as a `for` loop
102102
--> $DIR/while_let_on_iterator.rs:315:5
103103
|
104104
LL | while let Some(n) = it.next() {
105-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in &mut it`
105+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it.by_ref()`
106106

107107
error: this loop could be written as a `for` loop
108108
--> $DIR/while_let_on_iterator.rs:327:9
109109
|
110110
LL | while let Some(x) = it.next() {
111-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in &mut it`
111+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()`
112112

113113
error: this loop could be written as a `for` loop
114114
--> $DIR/while_let_on_iterator.rs:341:5
115115
|
116116
LL | while let Some(x) = it.next() {
117-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in &mut *it`
117+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()`
118118

119119
error: this loop could be written as a `for` loop
120120
--> $DIR/while_let_on_iterator.rs:352:5
121121
|
122122
LL | while let Some(x) = it.0.next() {
123-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in &mut *it.0`
123+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.0.by_ref()`
124124

125125
error: this loop could be written as a `for` loop
126126
--> $DIR/while_let_on_iterator.rs:371:5

0 commit comments

Comments
 (0)