From f934b836ce3768915388880696256dffad2f00ca Mon Sep 17 00:00:00 2001 From: Lukas Kalbertodt Date: Sun, 22 Dec 2019 14:26:28 +0100 Subject: [PATCH] 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. --- src/librustc_lint/array_into_iter.rs | 24 +++++-- .../iterators/into-iter-on-arrays-lint.fixed | 25 +++++++ .../ui/iterators/into-iter-on-arrays-lint.rs | 25 +++++++ .../iterators/into-iter-on-arrays-lint.stderr | 72 +++++++++++++++++++ 4 files changed, 140 insertions(+), 6 deletions(-) diff --git a/src/librustc_lint/array_into_iter.rs b/src/librustc_lint/array_into_iter.rs index e73414174fb35..2d716665fe9b5 100644 --- a/src/librustc_lint/array_into_iter.rs +++ b/src/librustc_lint/array_into_iter.rs @@ -48,14 +48,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, } diff --git a/src/test/ui/iterators/into-iter-on-arrays-lint.fixed b/src/test/ui/iterators/into-iter-on-arrays-lint.fixed index f88a52d315918..c1aa3d70f77cc 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-lint.fixed +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.fixed @@ -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(); diff --git a/src/test/ui/iterators/into-iter-on-arrays-lint.rs b/src/test/ui/iterators/into-iter-on-arrays-lint.rs index e1a4b535f3832..afdf6cb7f4420 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-lint.rs +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.rs @@ -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(); diff --git a/src/test/ui/iterators/into-iter-on-arrays-lint.stderr b/src/test/ui/iterators/into-iter-on-arrays-lint.stderr index b5964bd44bff7..e9cc427f6d8b7 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-lint.stderr +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.stderr @@ -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 +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 +