Skip to content

Commit ea82d06

Browse files
authored
Rollup merge of rust-lang#88512 - m-ou-se:array-into-iter-deref-stuff, r=estebank
Upgrade array_into_iter lint to include Deref-to-array types. Fixes rust-lang#88099 Fixes the issue mentioned here: rust-lang#84147 (comment)
2 parents 8fd1bf3 + 96d4666 commit ea82d06

File tree

4 files changed

+61
-106
lines changed

4 files changed

+61
-106
lines changed

compiler/rustc_lint/src/array_into_iter.rs

+30-24
Original file line numberDiff line numberDiff line change
@@ -74,39 +74,45 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter {
7474
_ => return,
7575
};
7676

77-
// As this is a method call expression, we have at least one
78-
// argument.
77+
// As this is a method call expression, we have at least one argument.
7978
let receiver_arg = &args[0];
79+
let receiver_ty = cx.typeck_results().expr_ty(receiver_arg);
80+
let adjustments = cx.typeck_results().expr_adjustments(receiver_arg);
8081

81-
// Peel all `Box<_>` layers. We have to special case `Box` here as
82-
// `Box` is the only thing that values can be moved out of via
83-
// method call. `Box::new([1]).into_iter()` should trigger this
84-
// lint.
85-
let mut recv_ty = cx.typeck_results().expr_ty(receiver_arg);
86-
let mut num_box_derefs = 0;
87-
while recv_ty.is_box() {
88-
num_box_derefs += 1;
89-
recv_ty = recv_ty.boxed_ty();
90-
}
82+
let target = match adjustments.last() {
83+
Some(Adjustment { kind: Adjust::Borrow(_), target }) => target,
84+
_ => return,
85+
};
9186

92-
// Make sure we found an array after peeling the boxes.
93-
if !matches!(recv_ty.kind(), ty::Array(..)) {
94-
return;
87+
let types =
88+
std::iter::once(receiver_ty).chain(adjustments.iter().map(|adj| adj.target));
89+
90+
let mut found_array = false;
91+
92+
for ty in types {
93+
match ty.kind() {
94+
// If we run into a &[T; N] or &[T] first, there's nothing to warn about.
95+
// It'll resolve to the reference version.
96+
ty::Ref(_, inner_ty, _) if inner_ty.is_array() => return,
97+
ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), ty::Slice(..)) => return,
98+
// Found an actual array type without matching a &[T; N] first.
99+
// This is the problematic case.
100+
ty::Array(..) => {
101+
found_array = true;
102+
break;
103+
}
104+
_ => {}
105+
}
95106
}
96107

97-
// Make sure that there is an autoref coercion at the expected
98-
// position. The first `num_box_derefs` adjustments are the derefs
99-
// of the box.
100-
match cx.typeck_results().expr_adjustments(receiver_arg).get(num_box_derefs) {
101-
Some(Adjustment { kind: Adjust::Borrow(_), .. }) => {}
102-
_ => return,
108+
if !found_array {
109+
return;
103110
}
104111

105112
// Emit lint diagnostic.
106-
let target = match *cx.typeck_results().expr_ty_adjusted(receiver_arg).kind() {
113+
let target = match *target.kind() {
107114
ty::Ref(_, inner_ty, _) if inner_ty.is_array() => "[T; N]",
108115
ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), ty::Slice(..)) => "[T]",
109-
110116
// We know the original first argument type is an array type,
111117
// we know that the first adjustment was an autoref coercion
112118
// and we know that `IntoIterator` is the trait involved. The
@@ -135,7 +141,7 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter {
135141
String::new(),
136142
Applicability::MaybeIncorrect,
137143
);
138-
} else {
144+
} else if receiver_ty.is_array() {
139145
diag.multipart_suggestion(
140146
"or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value",
141147
vec![

src/test/ui/iterators/into-iter-on-arrays-2018.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@ fn main() {
1919
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
2020
//~| WARNING this changes meaning
2121

22-
// The `array_into_iter` lint doesn't cover other wrappers that deref to an array.
2322
let _: Iter<'_, i32> = Rc::new(array).into_iter();
23+
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
24+
//~| WARNING this changes meaning
2425
let _: Iter<'_, i32> = Array(array).into_iter();
26+
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
27+
//~| WARNING this changes meaning
2528

2629
// But you can always use the trait method explicitly as an array.
2730
let _: IntoIter<i32, 10> = IntoIterator::into_iter(array);

src/test/ui/iterators/into-iter-on-arrays-2018.stderr

+19-9
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,31 @@ warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (du
2020
--> $DIR/into-iter-on-arrays-2018.rs:18:44
2121
|
2222
LL | let _: Iter<'_, i32> = Box::new(array).into_iter();
23-
| ^^^^^^^^^
23+
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
2424
|
2525
= warning: this changes meaning in Rust 2021
2626
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
27-
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
27+
28+
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
29+
--> $DIR/into-iter-on-arrays-2018.rs:22:43
2830
|
29-
LL | let _: Iter<'_, i32> = Box::new(array).iter();
30-
| ~~~~
31-
help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
31+
LL | let _: Iter<'_, i32> = Rc::new(array).into_iter();
32+
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
33+
|
34+
= warning: this changes meaning in Rust 2021
35+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
36+
37+
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
38+
--> $DIR/into-iter-on-arrays-2018.rs:25:41
3239
|
33-
LL | let _: Iter<'_, i32> = IntoIterator::into_iter(Box::new(array));
34-
| ++++++++++++++++++++++++ ~
40+
LL | let _: Iter<'_, i32> = Array(array).into_iter();
41+
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
42+
|
43+
= warning: this changes meaning in Rust 2021
44+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
3545

3646
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
37-
--> $DIR/into-iter-on-arrays-2018.rs:29:24
47+
--> $DIR/into-iter-on-arrays-2018.rs:32:24
3848
|
3949
LL | for _ in [1, 2, 3].into_iter() {}
4050
| ^^^^^^^^^
@@ -51,5 +61,5 @@ LL - for _ in [1, 2, 3].into_iter() {}
5161
LL + for _ in [1, 2, 3] {}
5262
|
5363

54-
warning: 3 warnings emitted
64+
warning: 5 warnings emitted
5565

src/test/ui/iterators/into-iter-on-arrays-lint.stderr

+8-72
Original file line numberDiff line numberDiff line change
@@ -71,137 +71,73 @@ warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (du
7171
--> $DIR/into-iter-on-arrays-lint.rs:23:21
7272
|
7373
LL | Box::new(small).into_iter();
74-
| ^^^^^^^^^
74+
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
7575
|
7676
= warning: this changes meaning in Rust 2021
7777
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
78-
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
79-
|
80-
LL | Box::new(small).iter();
81-
| ~~~~
82-
help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
83-
|
84-
LL | IntoIterator::into_iter(Box::new(small));
85-
| ++++++++++++++++++++++++ ~
8678

8779
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
8880
--> $DIR/into-iter-on-arrays-lint.rs:26:22
8981
|
9082
LL | Box::new([1, 2]).into_iter();
91-
| ^^^^^^^^^
83+
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
9284
|
9385
= warning: this changes meaning in Rust 2021
9486
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
95-
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
96-
|
97-
LL | Box::new([1, 2]).iter();
98-
| ~~~~
99-
help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
100-
|
101-
LL | IntoIterator::into_iter(Box::new([1, 2]));
102-
| ++++++++++++++++++++++++ ~
10387

10488
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
10589
--> $DIR/into-iter-on-arrays-lint.rs:29:19
10690
|
10791
LL | Box::new(big).into_iter();
108-
| ^^^^^^^^^
92+
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
10993
|
11094
= warning: this changes meaning in Rust 2021
11195
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
112-
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
113-
|
114-
LL | Box::new(big).iter();
115-
| ~~~~
116-
help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
117-
|
118-
LL | IntoIterator::into_iter(Box::new(big));
119-
| ++++++++++++++++++++++++ ~
12096

12197
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
12298
--> $DIR/into-iter-on-arrays-lint.rs:32:25
12399
|
124100
LL | Box::new([0u8; 33]).into_iter();
125-
| ^^^^^^^^^
101+
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
126102
|
127103
= warning: this changes meaning in Rust 2021
128104
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
129-
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
130-
|
131-
LL | Box::new([0u8; 33]).iter();
132-
| ~~~~
133-
help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
134-
|
135-
LL | IntoIterator::into_iter(Box::new([0u8; 33]));
136-
| ++++++++++++++++++++++++ ~
137105

138106
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
139107
--> $DIR/into-iter-on-arrays-lint.rs:36:31
140108
|
141109
LL | Box::new(Box::new(small)).into_iter();
142-
| ^^^^^^^^^
110+
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
143111
|
144112
= warning: this changes meaning in Rust 2021
145113
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
146-
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
147-
|
148-
LL | Box::new(Box::new(small)).iter();
149-
| ~~~~
150-
help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
151-
|
152-
LL | IntoIterator::into_iter(Box::new(Box::new(small)));
153-
| ++++++++++++++++++++++++ ~
154114

155115
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
156116
--> $DIR/into-iter-on-arrays-lint.rs:39:32
157117
|
158118
LL | Box::new(Box::new([1, 2])).into_iter();
159-
| ^^^^^^^^^
119+
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
160120
|
161121
= warning: this changes meaning in Rust 2021
162122
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
163-
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
164-
|
165-
LL | Box::new(Box::new([1, 2])).iter();
166-
| ~~~~
167-
help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
168-
|
169-
LL | IntoIterator::into_iter(Box::new(Box::new([1, 2])));
170-
| ++++++++++++++++++++++++ ~
171123

172124
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
173125
--> $DIR/into-iter-on-arrays-lint.rs:42:29
174126
|
175127
LL | Box::new(Box::new(big)).into_iter();
176-
| ^^^^^^^^^
128+
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
177129
|
178130
= warning: this changes meaning in Rust 2021
179131
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
180-
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
181-
|
182-
LL | Box::new(Box::new(big)).iter();
183-
| ~~~~
184-
help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
185-
|
186-
LL | IntoIterator::into_iter(Box::new(Box::new(big)));
187-
| ++++++++++++++++++++++++ ~
188132

189133
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
190134
--> $DIR/into-iter-on-arrays-lint.rs:45:35
191135
|
192136
LL | Box::new(Box::new([0u8; 33])).into_iter();
193-
| ^^^^^^^^^
137+
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
194138
|
195139
= warning: this changes meaning in Rust 2021
196140
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
197-
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
198-
|
199-
LL | Box::new(Box::new([0u8; 33])).iter();
200-
| ~~~~
201-
help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
202-
|
203-
LL | IntoIterator::into_iter(Box::new(Box::new([0u8; 33])));
204-
| ++++++++++++++++++++++++ ~
205141

206142
warning: 12 warnings emitted
207143

0 commit comments

Comments
 (0)