Skip to content

Commit

Permalink
Auto merge of #67524 - LukasKalbertodt:improve-into-iter-lint, r=matt…
Browse files Browse the repository at this point in the history
…hewjasper

Generalize `array_into_iter` lint to also lint for boxed arrays

`Box` is special in that a method call on a box can move the value out
of the box. Thus, the same backwards-compatibility problem can arise
for boxed arrays as for simple arrays.

---

CC #66145
r? @matthewjasper  (as you reviewed the first PR)
  • Loading branch information
bors committed Dec 25, 2019
2 parents 7bc1665 + f934b83 commit ed33453
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 6 deletions.
24 changes: 18 additions & 6 deletions src/librustc_lint/array_into_iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,26 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIntoIter {
// argument.
let receiver_arg = &args[0];

// Test if the original `self` type is an array type.
match cx.tables.expr_ty(receiver_arg).kind {
ty::Array(..) => {}
_ => return,
// Peel all `Box<_>` layers. We have to special case `Box` here as
// `Box` is the only thing that values can be moved out of via
// method call. `Box::new([1]).into_iter()` should trigger this
// lint.
let mut recv_ty = cx.tables.expr_ty(receiver_arg);
let mut num_box_derefs = 0;
while recv_ty.is_box() {
num_box_derefs += 1;
recv_ty = recv_ty.boxed_ty();
}

// Make sure we found an array after peeling the boxes.
if !matches!(recv_ty.kind, ty::Array(..)) {
return;
}

// Make sure that the first adjustment is an autoref coercion.
match cx.tables.expr_adjustments(receiver_arg).get(0) {
// Make sure that there is an autoref coercion at the expected
// position. The first `num_box_derefs` adjustments are the derefs
// of the box.
match cx.tables.expr_adjustments(receiver_arg).get(num_box_derefs) {
Some(Adjustment { kind: Adjust::Borrow(_), .. }) => {}
_ => return,
}
Expand Down
25 changes: 25 additions & 0 deletions src/test/ui/iterators/into-iter-on-arrays-lint.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,31 @@ fn main() {
//~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter`
//~| WARNING this was previously accepted by the compiler but is being phased out

Box::new(small).iter();
//~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
//~| WARNING this was previously accepted by the compiler but is being phased out
Box::new([1, 2]).iter();
//~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
//~| WARNING this was previously accepted by the compiler but is being phased out
Box::new(big).iter();
//~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter`
//~| WARNING this was previously accepted by the compiler but is being phased out
Box::new([0u8; 33]).iter();
//~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter`
//~| WARNING this was previously accepted by the compiler but is being phased out

Box::new(Box::new(small)).iter();
//~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
//~| WARNING this was previously accepted by the compiler but is being phased out
Box::new(Box::new([1, 2])).iter();
//~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
//~| WARNING this was previously accepted by the compiler but is being phased out
Box::new(Box::new(big)).iter();
//~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter`
//~| WARNING this was previously accepted by the compiler but is being phased out
Box::new(Box::new([0u8; 33])).iter();
//~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter`
//~| WARNING this was previously accepted by the compiler but is being phased out

// Expressions that should not
(&[1, 2]).into_iter();
Expand Down
25 changes: 25 additions & 0 deletions src/test/ui/iterators/into-iter-on-arrays-lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,31 @@ fn main() {
//~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter`
//~| WARNING this was previously accepted by the compiler but is being phased out

Box::new(small).into_iter();
//~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
//~| WARNING this was previously accepted by the compiler but is being phased out
Box::new([1, 2]).into_iter();
//~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
//~| WARNING this was previously accepted by the compiler but is being phased out
Box::new(big).into_iter();
//~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter`
//~| WARNING this was previously accepted by the compiler but is being phased out
Box::new([0u8; 33]).into_iter();
//~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter`
//~| WARNING this was previously accepted by the compiler but is being phased out

Box::new(Box::new(small)).into_iter();
//~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
//~| WARNING this was previously accepted by the compiler but is being phased out
Box::new(Box::new([1, 2])).into_iter();
//~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
//~| WARNING this was previously accepted by the compiler but is being phased out
Box::new(Box::new(big)).into_iter();
//~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter`
//~| WARNING this was previously accepted by the compiler but is being phased out
Box::new(Box::new([0u8; 33])).into_iter();
//~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter`
//~| WARNING this was previously accepted by the compiler but is being phased out

// Expressions that should not
(&[1, 2]).into_iter();
Expand Down
72 changes: 72 additions & 0 deletions src/test/ui/iterators/into-iter-on-arrays-lint.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,75 @@ LL | [0u8; 33].into_iter();
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>

warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
--> $DIR/into-iter-on-arrays-lint.rs:22:21
|
LL | Box::new(small).into_iter();
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>

warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
--> $DIR/into-iter-on-arrays-lint.rs:25:22
|
LL | Box::new([1, 2]).into_iter();
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>

warning: this method call currently resolves to `<&[T] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
--> $DIR/into-iter-on-arrays-lint.rs:28:19
|
LL | Box::new(big).into_iter();
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>

warning: this method call currently resolves to `<&[T] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
--> $DIR/into-iter-on-arrays-lint.rs:31:25
|
LL | Box::new([0u8; 33]).into_iter();
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>

warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
--> $DIR/into-iter-on-arrays-lint.rs:35:31
|
LL | Box::new(Box::new(small)).into_iter();
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>

warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
--> $DIR/into-iter-on-arrays-lint.rs:38:32
|
LL | Box::new(Box::new([1, 2])).into_iter();
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>

warning: this method call currently resolves to `<&[T] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
--> $DIR/into-iter-on-arrays-lint.rs:41:29
|
LL | Box::new(Box::new(big)).into_iter();
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>

warning: this method call currently resolves to `<&[T] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
--> $DIR/into-iter-on-arrays-lint.rs:44:35
|
LL | Box::new(Box::new([0u8; 33])).into_iter();
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>

0 comments on commit ed33453

Please sign in to comment.