Skip to content

Commit c50d86f

Browse files
committed
Auto merge of #11418 - Benjscho:explicit_iter_loop_config, r=llogiq
Add config flag for reborrows in explicit_iter_loop This PR adds a config flag for enforcing explicit into iter lint for reborrowed values. The config flag, `enforce_iter_loop_reborrow`, can be added to clippy.toml files to enable the linting behaviour. By default the reborrow lint is disabled. fixes: #11074 changelog: [`explicit_iter_loop`]: add config flag `enforce_iter_loop_reborrow` to disable reborrow linting by default
2 parents 3da21b0 + 55bd0fe commit c50d86f

File tree

10 files changed

+93
-56
lines changed

10 files changed

+93
-56
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -5571,4 +5571,5 @@ Released 2018-09-13
55715571
[`allow-one-hash-in-raw-strings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-one-hash-in-raw-strings
55725572
[`absolute-paths-max-segments`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-max-segments
55735573
[`absolute-paths-allowed-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-allowed-crates
5574+
[`enforce-iter-loop-reborrow`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforce-iter-loop-reborrow
55745575
<!-- end autogenerated links to configuration documentation -->

book/src/lint_configuration.md

+24
Original file line numberDiff line numberDiff line change
@@ -751,3 +751,27 @@ Which crates to allow absolute paths from
751751
* [`absolute_paths`](https://rust-lang.github.io/rust-clippy/master/index.html#absolute_paths)
752752

753753

754+
## `enforce-iter-loop-reborrow`
755+
#### Example
756+
```
757+
let mut vec = vec![1, 2, 3];
758+
let rmvec = &mut vec;
759+
for _ in rmvec.iter() {}
760+
for _ in rmvec.iter_mut() {}
761+
```
762+
763+
Use instead:
764+
```
765+
let mut vec = vec![1, 2, 3];
766+
let rmvec = &mut vec;
767+
for _ in &*rmvec {}
768+
for _ in &mut *rmvec {}
769+
```
770+
771+
**Default Value:** `false` (`bool`)
772+
773+
---
774+
**Affected lints:**
775+
* [`explicit_iter_loop`](https://rust-lang.github.io/rust-clippy/master/index.html#explicit_iter_loop)
776+
777+

clippy_lints/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -695,7 +695,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
695695
});
696696
store.register_late_pass(|_| Box::<shadow::Shadow>::default());
697697
store.register_late_pass(|_| Box::new(unit_types::UnitTypes));
698-
store.register_late_pass(move |_| Box::new(loops::Loops::new(msrv())));
698+
let enforce_iter_loop_reborrow = conf.enforce_iter_loop_reborrow;
699+
store.register_late_pass(move |_| Box::new(loops::Loops::new(msrv(), enforce_iter_loop_reborrow)));
699700
store.register_late_pass(|_| Box::<main_recursion::MainRecursion>::default());
700701
store.register_late_pass(|_| Box::new(lifetimes::Lifetimes));
701702
store.register_late_pass(|_| Box::new(entry::HashMapPass));

clippy_lints/src/loops/explicit_iter_loop.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,14 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMut
1313
use rustc_middle::ty::{self, EarlyBinder, Ty, TypeAndMut};
1414
use rustc_span::sym;
1515

16-
pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr<'_>, msrv: &Msrv) {
17-
let Some((adjust, ty)) = is_ref_iterable(cx, self_arg, call_expr) else {
16+
pub(super) fn check(
17+
cx: &LateContext<'_>,
18+
self_arg: &Expr<'_>,
19+
call_expr: &Expr<'_>,
20+
msrv: &Msrv,
21+
enforce_iter_loop_reborrow: bool,
22+
) {
23+
let Some((adjust, ty)) = is_ref_iterable(cx, self_arg, call_expr, enforce_iter_loop_reborrow) else {
1824
return;
1925
};
2026
if let ty::Array(_, count) = *ty.peel_refs().kind() {
@@ -102,6 +108,7 @@ fn is_ref_iterable<'tcx>(
102108
cx: &LateContext<'tcx>,
103109
self_arg: &Expr<'_>,
104110
call_expr: &Expr<'_>,
111+
enforce_iter_loop_reborrow: bool,
105112
) -> Option<(AdjustKind, Ty<'tcx>)> {
106113
let typeck = cx.typeck_results();
107114
if let Some(trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator)
@@ -142,7 +149,8 @@ fn is_ref_iterable<'tcx>(
142149
{
143150
return Some((AdjustKind::None, self_ty));
144151
}
145-
} else if let ty::Ref(region, ty, Mutability::Mut) = *self_ty.kind()
152+
} else if enforce_iter_loop_reborrow
153+
&& let ty::Ref(region, ty, Mutability::Mut) = *self_ty.kind()
146154
&& let Some(mutbl) = mutbl
147155
{
148156
// Attempt to reborrow the mutable reference
@@ -186,7 +194,8 @@ fn is_ref_iterable<'tcx>(
186194
},
187195
..
188196
] => {
189-
if target != self_ty
197+
if enforce_iter_loop_reborrow
198+
&& target != self_ty
190199
&& implements_trait(cx, target, trait_id, &[])
191200
&& let Some(ty) =
192201
make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target])

clippy_lints/src/loops/mod.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -609,10 +609,14 @@ declare_clippy_lint! {
609609

610610
pub struct Loops {
611611
msrv: Msrv,
612+
enforce_iter_loop_reborrow: bool,
612613
}
613614
impl Loops {
614-
pub fn new(msrv: Msrv) -> Self {
615-
Self { msrv }
615+
pub fn new(msrv: Msrv, enforce_iter_loop_reborrow: bool) -> Self {
616+
Self {
617+
msrv,
618+
enforce_iter_loop_reborrow,
619+
}
616620
}
617621
}
618622
impl_lint_pass!(Loops => [
@@ -719,7 +723,7 @@ impl Loops {
719723
if let ExprKind::MethodCall(method, self_arg, [], _) = arg.kind {
720724
match method.ident.as_str() {
721725
"iter" | "iter_mut" => {
722-
explicit_iter_loop::check(cx, self_arg, arg, &self.msrv);
726+
explicit_iter_loop::check(cx, self_arg, arg, &self.msrv, self.enforce_iter_loop_reborrow);
723727
},
724728
"into_iter" => {
725729
explicit_into_iter_loop::check(cx, self_arg, arg);

clippy_lints/src/utils/conf.rs

+20
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,26 @@ define_Conf! {
561561
/// Which crates to allow absolute paths from
562562
(absolute_paths_allowed_crates: rustc_data_structures::fx::FxHashSet<String> =
563563
rustc_data_structures::fx::FxHashSet::default()),
564+
/// Lint: EXPLICIT_ITER_LOOP
565+
///
566+
/// Whether to recommend using implicit into iter for reborrowed values.
567+
///
568+
/// #### Example
569+
/// ```
570+
/// let mut vec = vec![1, 2, 3];
571+
/// let rmvec = &mut vec;
572+
/// for _ in rmvec.iter() {}
573+
/// for _ in rmvec.iter_mut() {}
574+
/// ```
575+
///
576+
/// Use instead:
577+
/// ```
578+
/// let mut vec = vec![1, 2, 3];
579+
/// let rmvec = &mut vec;
580+
/// for _ in &*rmvec {}
581+
/// for _ in &mut *rmvec {}
582+
/// ```
583+
(enforce_iter_loop_reborrow: bool = false),
564584
}
565585

566586
/// Search for the configuration file.

tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
2828
disallowed-types
2929
doc-valid-idents
3030
enable-raw-pointer-heuristic-for-send
31+
enforce-iter-loop-reborrow
3132
enforced-import-renames
3233
enum-variant-name-threshold
3334
enum-variant-size-threshold
@@ -99,6 +100,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
99100
disallowed-types
100101
doc-valid-idents
101102
enable-raw-pointer-heuristic-for-send
103+
enforce-iter-loop-reborrow
102104
enforced-import-renames
103105
enum-variant-name-threshold
104106
enum-variant-size-threshold

tests/ui/explicit_iter_loop.fixed

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
clippy::similar_names,
55
clippy::needless_borrow,
66
clippy::deref_addrof,
7+
clippy::unnecessary_mut_passed,
78
dead_code
89
)]
910

@@ -20,15 +21,15 @@ fn main() {
2021
for _ in rvec {}
2122

2223
let rmvec = &mut vec;
23-
for _ in &*rmvec {}
24-
for _ in &mut *rmvec {}
24+
for _ in rmvec.iter() {}
25+
for _ in rmvec.iter_mut() {}
2526

2627
for _ in &vec {} // these are fine
2728
for _ in &mut vec {} // these are fine
2829

2930
for _ in &[1, 2, 3] {}
3031

31-
for _ in &*(&mut [1, 2, 3]) {}
32+
for _ in (&mut [1, 2, 3]).iter() {}
3233

3334
for _ in &[0; 32] {}
3435
for _ in &[0; 33] {}

tests/ui/explicit_iter_loop.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
clippy::similar_names,
55
clippy::needless_borrow,
66
clippy::deref_addrof,
7+
clippy::unnecessary_mut_passed,
78
dead_code
89
)]
910

tests/ui/explicit_iter_loop.stderr

+19-45
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: it is more concise to loop over references to containers instead of using explicit iteration methods
2-
--> $DIR/explicit_iter_loop.rs:16:14
2+
--> $DIR/explicit_iter_loop.rs:17:14
33
|
44
LL | for _ in vec.iter() {}
55
| ^^^^^^^^^^ help: to write this more concisely, try: `&vec`
@@ -11,132 +11,106 @@ LL | #![deny(clippy::explicit_iter_loop)]
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
1212

1313
error: it is more concise to loop over references to containers instead of using explicit iteration methods
14-
--> $DIR/explicit_iter_loop.rs:17:14
14+
--> $DIR/explicit_iter_loop.rs:18:14
1515
|
1616
LL | for _ in vec.iter_mut() {}
1717
| ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec`
1818

1919
error: it is more concise to loop over references to containers instead of using explicit iteration methods
20-
--> $DIR/explicit_iter_loop.rs:20:14
20+
--> $DIR/explicit_iter_loop.rs:21:14
2121
|
2222
LL | for _ in rvec.iter() {}
2323
| ^^^^^^^^^^^ help: to write this more concisely, try: `rvec`
2424

2525
error: it is more concise to loop over references to containers instead of using explicit iteration methods
26-
--> $DIR/explicit_iter_loop.rs:23:14
27-
|
28-
LL | for _ in rmvec.iter() {}
29-
| ^^^^^^^^^^^^ help: to write this more concisely, try: `&*rmvec`
30-
31-
error: it is more concise to loop over references to containers instead of using explicit iteration methods
32-
--> $DIR/explicit_iter_loop.rs:24:14
33-
|
34-
LL | for _ in rmvec.iter_mut() {}
35-
| ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut *rmvec`
36-
37-
error: it is more concise to loop over references to containers instead of using explicit iteration methods
38-
--> $DIR/explicit_iter_loop.rs:29:14
26+
--> $DIR/explicit_iter_loop.rs:30:14
3927
|
4028
LL | for _ in [1, 2, 3].iter() {}
4129
| ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]`
4230

4331
error: it is more concise to loop over references to containers instead of using explicit iteration methods
44-
--> $DIR/explicit_iter_loop.rs:31:14
45-
|
46-
LL | for _ in (&mut [1, 2, 3]).iter() {}
47-
| ^^^^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&*(&mut [1, 2, 3])`
48-
49-
error: the method `iter` doesn't need a mutable reference
50-
--> $DIR/explicit_iter_loop.rs:31:14
51-
|
52-
LL | for _ in (&mut [1, 2, 3]).iter() {}
53-
| ^^^^^^^^^^^^^^^^
54-
|
55-
= note: `-D clippy::unnecessary-mut-passed` implied by `-D warnings`
56-
57-
error: it is more concise to loop over references to containers instead of using explicit iteration methods
58-
--> $DIR/explicit_iter_loop.rs:33:14
32+
--> $DIR/explicit_iter_loop.rs:34:14
5933
|
6034
LL | for _ in [0; 32].iter() {}
6135
| ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]`
6236

6337
error: it is more concise to loop over references to containers instead of using explicit iteration methods
64-
--> $DIR/explicit_iter_loop.rs:34:14
38+
--> $DIR/explicit_iter_loop.rs:35:14
6539
|
6640
LL | for _ in [0; 33].iter() {}
6741
| ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 33]`
6842

6943
error: it is more concise to loop over references to containers instead of using explicit iteration methods
70-
--> $DIR/explicit_iter_loop.rs:37:14
44+
--> $DIR/explicit_iter_loop.rs:38:14
7145
|
7246
LL | for _ in ll.iter() {}
7347
| ^^^^^^^^^ help: to write this more concisely, try: `&ll`
7448

7549
error: it is more concise to loop over references to containers instead of using explicit iteration methods
76-
--> $DIR/explicit_iter_loop.rs:39:14
50+
--> $DIR/explicit_iter_loop.rs:40:14
7751
|
7852
LL | for _ in rll.iter() {}
7953
| ^^^^^^^^^^ help: to write this more concisely, try: `rll`
8054

8155
error: it is more concise to loop over references to containers instead of using explicit iteration methods
82-
--> $DIR/explicit_iter_loop.rs:42:14
56+
--> $DIR/explicit_iter_loop.rs:43:14
8357
|
8458
LL | for _ in vd.iter() {}
8559
| ^^^^^^^^^ help: to write this more concisely, try: `&vd`
8660

8761
error: it is more concise to loop over references to containers instead of using explicit iteration methods
88-
--> $DIR/explicit_iter_loop.rs:44:14
62+
--> $DIR/explicit_iter_loop.rs:45:14
8963
|
9064
LL | for _ in rvd.iter() {}
9165
| ^^^^^^^^^^ help: to write this more concisely, try: `rvd`
9266

9367
error: it is more concise to loop over references to containers instead of using explicit iteration methods
94-
--> $DIR/explicit_iter_loop.rs:47:14
68+
--> $DIR/explicit_iter_loop.rs:48:14
9569
|
9670
LL | for _ in bh.iter() {}
9771
| ^^^^^^^^^ help: to write this more concisely, try: `&bh`
9872

9973
error: it is more concise to loop over references to containers instead of using explicit iteration methods
100-
--> $DIR/explicit_iter_loop.rs:50:14
74+
--> $DIR/explicit_iter_loop.rs:51:14
10175
|
10276
LL | for _ in hm.iter() {}
10377
| ^^^^^^^^^ help: to write this more concisely, try: `&hm`
10478

10579
error: it is more concise to loop over references to containers instead of using explicit iteration methods
106-
--> $DIR/explicit_iter_loop.rs:53:14
80+
--> $DIR/explicit_iter_loop.rs:54:14
10781
|
10882
LL | for _ in bt.iter() {}
10983
| ^^^^^^^^^ help: to write this more concisely, try: `&bt`
11084

11185
error: it is more concise to loop over references to containers instead of using explicit iteration methods
112-
--> $DIR/explicit_iter_loop.rs:56:14
86+
--> $DIR/explicit_iter_loop.rs:57:14
11387
|
11488
LL | for _ in hs.iter() {}
11589
| ^^^^^^^^^ help: to write this more concisely, try: `&hs`
11690

11791
error: it is more concise to loop over references to containers instead of using explicit iteration methods
118-
--> $DIR/explicit_iter_loop.rs:59:14
92+
--> $DIR/explicit_iter_loop.rs:60:14
11993
|
12094
LL | for _ in bs.iter() {}
12195
| ^^^^^^^^^ help: to write this more concisely, try: `&bs`
12296

12397
error: it is more concise to loop over references to containers instead of using explicit iteration methods
124-
--> $DIR/explicit_iter_loop.rs:148:14
98+
--> $DIR/explicit_iter_loop.rs:149:14
12599
|
126100
LL | for _ in x.iter() {}
127101
| ^^^^^^^^ help: to write this more concisely, try: `&x`
128102

129103
error: it is more concise to loop over references to containers instead of using explicit iteration methods
130-
--> $DIR/explicit_iter_loop.rs:149:14
104+
--> $DIR/explicit_iter_loop.rs:150:14
131105
|
132106
LL | for _ in x.iter_mut() {}
133107
| ^^^^^^^^^^^^ help: to write this more concisely, try: `&mut x`
134108

135109
error: it is more concise to loop over references to containers instead of using explicit iteration methods
136-
--> $DIR/explicit_iter_loop.rs:152:14
110+
--> $DIR/explicit_iter_loop.rs:153:14
137111
|
138112
LL | for _ in r.iter() {}
139113
| ^^^^^^^^ help: to write this more concisely, try: `r`
140114

141-
error: aborting due to 22 previous errors
115+
error: aborting due to 18 previous errors
142116

0 commit comments

Comments
 (0)