From 37e17803b57877637d4b6b13c8813589bd140452 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 25 May 2021 17:12:45 +0200 Subject: [PATCH 1/7] Change wording on array_into_iter lint for 1.53 and edition changes. --- compiler/rustc_lint/src/array_into_iter.rs | 28 +++++++++------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs index 14ffbbc35ebf0..92c6ae3529259 100644 --- a/compiler/rustc_lint/src/array_into_iter.rs +++ b/compiler/rustc_lint/src/array_into_iter.rs @@ -21,21 +21,15 @@ declare_lint! { /// /// ### Explanation /// - /// In the future, it is planned to add an `IntoIter` implementation for - /// arrays such that it will iterate over *values* of the array instead of - /// references. Due to how method resolution works, this will change - /// existing code that uses `into_iter` on arrays. The solution to avoid - /// this warning is to use `iter()` instead of `into_iter()`. - /// - /// This is a [future-incompatible] lint to transition this to a hard error - /// in the future. See [issue #66145] for more details and a more thorough - /// description of the lint. - /// - /// [issue #66145]: https://github.com/rust-lang/rust/issues/66145 - /// [future-incompatible]: ../index.md#future-incompatible-lints + /// Since Rust 1.53, arrays implement `IntoIterator`. However, to avoid + /// breakage, `array.into_iter()` in Rust 2015 and 2018 code will still + /// behave as `(&array).into_iter()`, returning an iterator over + /// references, just like in Rust 1.52 and earlier. + /// This only applies to the method call syntax `array.into_iter()`, not to + /// any other syntax such as `for _ in array` or `IntoIterator::into_iter(array)`. pub ARRAY_INTO_ITER, Warn, - "detects calling `into_iter` on arrays", + "detects calling `into_iter` on arrays in Rust 2015 and 2018", @future_incompatible = FutureIncompatibleInfo { reference: "issue #66145 ", reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2021), @@ -105,10 +99,10 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter { }; cx.struct_span_lint(ARRAY_INTO_ITER, *span, |lint| { lint.build(&format!( - "this method call currently resolves to `<&{} as IntoIterator>::into_iter` (due \ - to autoref coercions), but that might change in the future when \ - `IntoIterator` impls for arrays are added.", - target, + "this method call resolves to `<&{} as IntoIterator>::into_iter` \ + (due to backwards compatibility), \ + but will resolve to <{} as IntoIterator>::into_iter in Rust 2021.", + target, target, )) .span_suggestion( call.ident.span, From 5cfe2a5fc621092ef4a14c22e2855fa07b690cac Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 25 May 2021 17:13:15 +0200 Subject: [PATCH 2/7] Add new suggestion to array_into_iter lint. --- compiler/rustc_lint/src/array_into_iter.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs index 92c6ae3529259..738c63c3b8b49 100644 --- a/compiler/rustc_lint/src/array_into_iter.rs +++ b/compiler/rustc_lint/src/array_into_iter.rs @@ -110,6 +110,14 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter { "iter".into(), Applicability::MachineApplicable, ) + .multipart_suggestion( + "or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value", + vec![ + (expr.span.shrink_to_lo(), "IntoIterator::into_iter(".into()), + (receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()), ")".into()), + ], + Applicability::MaybeIncorrect, + ) .emit(); }) } From aec2c5b2b61a5c69742e5e408aa5e64477be6eb3 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 25 May 2021 17:56:19 +0200 Subject: [PATCH 3/7] Update tests for updated array_into_iter lint. --- .../ui/iterators/into-iter-on-arrays-2018.rs | 4 +- .../iterators/into-iter-on-arrays-2018.stderr | 24 ++- .../iterators/into-iter-on-arrays-lint.fixed | 24 +-- .../ui/iterators/into-iter-on-arrays-lint.rs | 24 +-- .../iterators/into-iter-on-arrays-lint.stderr | 144 +++++++++++++++--- 5 files changed, 166 insertions(+), 54 deletions(-) diff --git a/src/test/ui/iterators/into-iter-on-arrays-2018.rs b/src/test/ui/iterators/into-iter-on-arrays-2018.rs index 546052817d242..255ebfbd8f9e2 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-2018.rs +++ b/src/test/ui/iterators/into-iter-on-arrays-2018.rs @@ -12,11 +12,11 @@ fn main() { // Before 2021, the method dispatched to `IntoIterator for &[T; N]`, // which we continue to support for compatibility. let _: Iter<'_, i32> = array.into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning let _: Iter<'_, i32> = Box::new(array).into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning // The `array_into_iter` lint doesn't cover other wrappers that deref to an array. diff --git a/src/test/ui/iterators/into-iter-on-arrays-2018.stderr b/src/test/ui/iterators/into-iter-on-arrays-2018.stderr index 82596c6f022e0..b6ca4ba22836a 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-2018.stderr +++ b/src/test/ui/iterators/into-iter-on-arrays-2018.stderr @@ -1,21 +1,37 @@ -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. +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. --> $DIR/into-iter-on-arrays-2018.rs:14:34 | LL | let _: Iter<'_, i32> = array.into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | ^^^^^^^^^ | = note: `#[warn(array_into_iter)]` on by default = warning: this changes meaning in Rust 2021 = note: for more information, see issue #66145 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | let _: Iter<'_, i32> = array.iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | let _: Iter<'_, i32> = IntoIterator::into_iter(array); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -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. +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. --> $DIR/into-iter-on-arrays-2018.rs:18:44 | LL | let _: Iter<'_, i32> = Box::new(array).into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | ^^^^^^^^^ | = warning: this changes meaning in Rust 2021 = note: for more information, see issue #66145 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | let _: Iter<'_, i32> = Box::new(array).iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | let _: Iter<'_, i32> = IntoIterator::into_iter(Box::new(array)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ warning: 2 warnings emitted 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 ede96d7cea16c..f206134d83fdb 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-lint.fixed +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.fixed @@ -7,42 +7,42 @@ fn main() { // Expressions that should trigger the lint small.iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning [1, 2].iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning big.iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning [0u8; 33].iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning Box::new(small).iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning Box::new([1, 2]).iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning Box::new(big).iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning Box::new([0u8; 33]).iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning Box::new(Box::new(small)).iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning Box::new(Box::new([1, 2])).iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning Box::new(Box::new(big)).iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning Box::new(Box::new([0u8; 33])).iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning // Expressions that should not 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 3a0cb75ed152d..a43a7ea797f42 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-lint.rs +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.rs @@ -7,42 +7,42 @@ fn main() { // Expressions that should trigger the lint small.into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning [1, 2].into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning big.into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning [0u8; 33].into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning Box::new(small).into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning Box::new([1, 2]).into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning Box::new(big).into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning Box::new([0u8; 33]).into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning Box::new(Box::new(small)).into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning Box::new(Box::new([1, 2])).into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning Box::new(Box::new(big)).into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning Box::new(Box::new([0u8; 33])).into_iter(); - //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` //~| WARNING this changes meaning // Expressions that should not 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 1f33a5c659b5d..fb34384b4e53e 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-lint.stderr +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.stderr @@ -1,111 +1,207 @@ -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. +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. --> $DIR/into-iter-on-arrays-lint.rs:9:11 | LL | small.into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | ^^^^^^^^^ | = note: `#[warn(array_into_iter)]` on by default = warning: this changes meaning in Rust 2021 = note: for more information, see issue #66145 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | small.iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | IntoIterator::into_iter(small); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -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. +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. --> $DIR/into-iter-on-arrays-lint.rs:12:12 | LL | [1, 2].into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | ^^^^^^^^^ | = warning: this changes meaning in Rust 2021 = note: for more information, see issue #66145 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | [1, 2].iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | IntoIterator::into_iter([1, 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -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. +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. --> $DIR/into-iter-on-arrays-lint.rs:15:9 | LL | big.into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | ^^^^^^^^^ | = warning: this changes meaning in Rust 2021 = note: for more information, see issue #66145 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | big.iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | IntoIterator::into_iter(big); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -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. +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. --> $DIR/into-iter-on-arrays-lint.rs:18:15 | LL | [0u8; 33].into_iter(); - | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | ^^^^^^^^^ | = warning: this changes meaning in Rust 2021 = note: for more information, see issue #66145 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | [0u8; 33].iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | IntoIterator::into_iter([0u8; 33]); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -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. +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. --> $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 changes meaning in Rust 2021 = note: for more information, see issue #66145 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | Box::new(small).iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | IntoIterator::into_iter(Box::new(small)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -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. +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. --> $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 changes meaning in Rust 2021 = note: for more information, see issue #66145 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | Box::new([1, 2]).iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | IntoIterator::into_iter(Box::new([1, 2])); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -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. +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. --> $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 changes meaning in Rust 2021 = note: for more information, see issue #66145 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | Box::new(big).iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | IntoIterator::into_iter(Box::new(big)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -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. +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. --> $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 changes meaning in Rust 2021 = note: for more information, see issue #66145 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | Box::new([0u8; 33]).iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | IntoIterator::into_iter(Box::new([0u8; 33])); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -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. +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. --> $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 changes meaning in Rust 2021 = note: for more information, see issue #66145 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | Box::new(Box::new(small)).iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | IntoIterator::into_iter(Box::new(Box::new(small))); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -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. +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. --> $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 changes meaning in Rust 2021 = note: for more information, see issue #66145 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | Box::new(Box::new([1, 2])).iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | IntoIterator::into_iter(Box::new(Box::new([1, 2]))); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -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. +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. --> $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 changes meaning in Rust 2021 = note: for more information, see issue #66145 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | Box::new(Box::new(big)).iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | IntoIterator::into_iter(Box::new(Box::new(big))); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -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. +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. --> $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 changes meaning in Rust 2021 = note: for more information, see issue #66145 +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | Box::new(Box::new([0u8; 33])).iter(); + | ^^^^ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | IntoIterator::into_iter(Box::new(Box::new([0u8; 33]))); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ warning: 12 warnings emitted From ef152d9b9fe9899a8e0ba14d11fa1d75ef56b1d6 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 25 May 2021 19:15:27 +0200 Subject: [PATCH 4/7] Better suggestion for array_into_iter in for loop. --- compiler/rustc_lint/src/array_into_iter.rs | 61 ++++++++++++++++------ compiler/rustc_lint/src/lib.rs | 2 +- 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs index 738c63c3b8b49..77741c7240b0d 100644 --- a/compiler/rustc_lint/src/array_into_iter.rs +++ b/compiler/rustc_lint/src/array_into_iter.rs @@ -6,6 +6,7 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment}; use rustc_session::lint::FutureIncompatibilityReason; use rustc_span::edition::Edition; use rustc_span::symbol::sym; +use rustc_span::Span; declare_lint! { /// The `array_into_iter` lint detects calling `into_iter` on arrays. @@ -36,13 +37,29 @@ declare_lint! { }; } -declare_lint_pass!( - /// Checks for instances of calling `into_iter` on arrays. - ArrayIntoIter => [ARRAY_INTO_ITER] -); +#[derive(Copy, Clone, Default)] +pub struct ArrayIntoIter { + for_expr_span: Span, +} + +impl_lint_pass!(ArrayIntoIter => [ARRAY_INTO_ITER]); impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { + // Save the span of expressions in `for _ in expr` syntax, + // so we can give a better suggestion for those later. + if let hir::ExprKind::Match(arg, [_], hir::MatchSource::ForLoopDesugar) = &expr.kind { + if let hir::ExprKind::Call(path, [arg]) = &arg.kind { + if let hir::ExprKind::Path(hir::QPath::LangItem( + hir::LangItem::IntoIterIntoIter, + _, + )) = &path.kind + { + self.for_expr_span = arg.span; + } + } + } + // We only care about method call expressions. if let hir::ExprKind::MethodCall(call, span, args, _) = &expr.kind { if call.ident.name != sym::into_iter { @@ -98,27 +115,37 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter { _ => bug!("array type coerced to something other than array or slice"), }; cx.struct_span_lint(ARRAY_INTO_ITER, *span, |lint| { - lint.build(&format!( + let mut diag = lint.build(&format!( "this method call resolves to `<&{} as IntoIterator>::into_iter` \ (due to backwards compatibility), \ but will resolve to <{} as IntoIterator>::into_iter in Rust 2021.", target, target, - )) - .span_suggestion( + )); + diag.span_suggestion( call.ident.span, "use `.iter()` instead of `.into_iter()` to avoid ambiguity", "iter".into(), Applicability::MachineApplicable, - ) - .multipart_suggestion( - "or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value", - vec![ - (expr.span.shrink_to_lo(), "IntoIterator::into_iter(".into()), - (receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()), ")".into()), - ], - Applicability::MaybeIncorrect, - ) - .emit(); + ); + if self.for_expr_span == expr.span { + let expr_span = expr.span.ctxt().outer_expn_data().call_site; + diag.span_suggestion( + receiver_arg.span.shrink_to_hi().to(expr_span.shrink_to_hi()), + "or remove `.into_iter()` to iterate by value", + String::new(), + Applicability::MaybeIncorrect, + ); + } else { + diag.multipart_suggestion( + "or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value", + vec![ + (expr.span.shrink_to_lo(), "IntoIterator::into_iter(".into()), + (receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()), ")".into()), + ], + Applicability::MaybeIncorrect, + ); + } + diag.emit(); }) } } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 4f59460aa82a4..89f9809d643e0 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -163,7 +163,7 @@ macro_rules! late_lint_passes { // FIXME: Turn the computation of types which implement Debug into a query // and change this to a module lint pass MissingDebugImplementations: MissingDebugImplementations::default(), - ArrayIntoIter: ArrayIntoIter, + ArrayIntoIter: ArrayIntoIter::default(), ClashingExternDeclarations: ClashingExternDeclarations::new(), DropTraitConstraints: DropTraitConstraints, TemporaryCStringAsPtr: TemporaryCStringAsPtr, From bdeb61437fe3cdbf96d84b48116ab113a38c417c Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 25 May 2021 19:15:48 +0200 Subject: [PATCH 5/7] Add test for suggestion of array_into_iter in for loop. --- .../ui/iterators/into-iter-on-arrays-2018.rs | 3 +++ .../iterators/into-iter-on-arrays-2018.stderr | 17 ++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/test/ui/iterators/into-iter-on-arrays-2018.rs b/src/test/ui/iterators/into-iter-on-arrays-2018.rs index 255ebfbd8f9e2..e2b75610fefc4 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-2018.rs +++ b/src/test/ui/iterators/into-iter-on-arrays-2018.rs @@ -25,6 +25,9 @@ fn main() { // But you can always use the trait method explicitly as an array. let _: IntoIter = IntoIterator::into_iter(array); + + for _ in [1, 2, 3].into_iter() {} + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` } /// User type that dereferences to an array. diff --git a/src/test/ui/iterators/into-iter-on-arrays-2018.stderr b/src/test/ui/iterators/into-iter-on-arrays-2018.stderr index b6ca4ba22836a..daa8a388366c3 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-2018.stderr +++ b/src/test/ui/iterators/into-iter-on-arrays-2018.stderr @@ -33,5 +33,20 @@ help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicit LL | let _: Iter<'_, i32> = IntoIterator::into_iter(Box::new(array)); | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ -warning: 2 warnings emitted +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. + --> $DIR/into-iter-on-arrays-2018.rs:27:24 + | +LL | for _ in [1, 2, 3].into_iter() {} + | ^^^^^^^^^ + | +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | for _ in [1, 2, 3].iter() {} + | ^^^^ +help: or remove `.into_iter()` to iterate by value + | +LL | for _ in [1, 2, 3] {} + | -- + +warning: 3 warnings emitted From c685292fbac0203b63cd8d9d9736b7f451937804 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 10 Jun 2021 14:48:26 +0000 Subject: [PATCH 6/7] Remove issue-78660-cap-lints-future-compat test. --- .../ui/lint/issue-78660-cap-lints-future-compat.rs | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 src/test/ui/lint/issue-78660-cap-lints-future-compat.rs diff --git a/src/test/ui/lint/issue-78660-cap-lints-future-compat.rs b/src/test/ui/lint/issue-78660-cap-lints-future-compat.rs deleted file mode 100644 index 4d98f0ad62d4d..0000000000000 --- a/src/test/ui/lint/issue-78660-cap-lints-future-compat.rs +++ /dev/null @@ -1,10 +0,0 @@ -// compile-flags: -D warnings --cap-lints allow -// check-pass - -// Regression test for issue #78660 -// Tests that we don't ICE when a future-incompat-report lint has -// has a command-line source, but is capped to allow - -fn main() { - ["hi"].into_iter(); -} From dbdf7c7963c8d637c11cac2940161813cd61b8c0 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 25 Jun 2021 17:26:31 +0000 Subject: [PATCH 7/7] Fix array-into-iter tests. --- .../ui/iterators/into-iter-on-arrays-2018.rs | 1 + .../iterators/into-iter-on-arrays-2018.stderr | 4 +++- .../iterators/into-iter-on-arrays-lint.fixed | 1 + .../ui/iterators/into-iter-on-arrays-lint.rs | 1 + .../iterators/into-iter-on-arrays-lint.stderr | 24 +++++++++---------- 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/test/ui/iterators/into-iter-on-arrays-2018.rs b/src/test/ui/iterators/into-iter-on-arrays-2018.rs index e2b75610fefc4..e56c2956a697e 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-2018.rs +++ b/src/test/ui/iterators/into-iter-on-arrays-2018.rs @@ -28,6 +28,7 @@ fn main() { for _ in [1, 2, 3].into_iter() {} //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning } /// User type that dereferences to an array. diff --git a/src/test/ui/iterators/into-iter-on-arrays-2018.stderr b/src/test/ui/iterators/into-iter-on-arrays-2018.stderr index daa8a388366c3..3bd3ca6e875a1 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-2018.stderr +++ b/src/test/ui/iterators/into-iter-on-arrays-2018.stderr @@ -34,11 +34,13 @@ LL | let _: Iter<'_, i32> = IntoIterator::into_iter(Box::new(array)); | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ 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. - --> $DIR/into-iter-on-arrays-2018.rs:27:24 + --> $DIR/into-iter-on-arrays-2018.rs:29:24 | LL | for _ in [1, 2, 3].into_iter() {} | ^^^^^^^^^ | + = warning: this changes meaning in Rust 2021 + = note: for more information, see issue #66145 help: use `.iter()` instead of `.into_iter()` to avoid ambiguity | LL | for _ in [1, 2, 3].iter() {} 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 f206134d83fdb..0055758a6a442 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-lint.fixed +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.fixed @@ -1,5 +1,6 @@ // run-pass // run-rustfix +// rustfix-only-machine-applicable fn main() { let small = [1, 2]; 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 a43a7ea797f42..01857c78a730c 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-lint.rs +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.rs @@ -1,5 +1,6 @@ // run-pass // run-rustfix +// rustfix-only-machine-applicable fn main() { let small = [1, 2]; 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 fb34384b4e53e..01789e0e25748 100644 --- a/src/test/ui/iterators/into-iter-on-arrays-lint.stderr +++ b/src/test/ui/iterators/into-iter-on-arrays-lint.stderr @@ -1,5 +1,5 @@ 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. - --> $DIR/into-iter-on-arrays-lint.rs:9:11 + --> $DIR/into-iter-on-arrays-lint.rs:10:11 | LL | small.into_iter(); | ^^^^^^^^^ @@ -17,7 +17,7 @@ LL | IntoIterator::into_iter(small); | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ 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. - --> $DIR/into-iter-on-arrays-lint.rs:12:12 + --> $DIR/into-iter-on-arrays-lint.rs:13:12 | LL | [1, 2].into_iter(); | ^^^^^^^^^ @@ -34,7 +34,7 @@ LL | IntoIterator::into_iter([1, 2]); | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ 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. - --> $DIR/into-iter-on-arrays-lint.rs:15:9 + --> $DIR/into-iter-on-arrays-lint.rs:16:9 | LL | big.into_iter(); | ^^^^^^^^^ @@ -51,7 +51,7 @@ LL | IntoIterator::into_iter(big); | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ 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. - --> $DIR/into-iter-on-arrays-lint.rs:18:15 + --> $DIR/into-iter-on-arrays-lint.rs:19:15 | LL | [0u8; 33].into_iter(); | ^^^^^^^^^ @@ -68,7 +68,7 @@ LL | IntoIterator::into_iter([0u8; 33]); | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ 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. - --> $DIR/into-iter-on-arrays-lint.rs:22:21 + --> $DIR/into-iter-on-arrays-lint.rs:23:21 | LL | Box::new(small).into_iter(); | ^^^^^^^^^ @@ -85,7 +85,7 @@ LL | IntoIterator::into_iter(Box::new(small)); | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ 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. - --> $DIR/into-iter-on-arrays-lint.rs:25:22 + --> $DIR/into-iter-on-arrays-lint.rs:26:22 | LL | Box::new([1, 2]).into_iter(); | ^^^^^^^^^ @@ -102,7 +102,7 @@ LL | IntoIterator::into_iter(Box::new([1, 2])); | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ 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. - --> $DIR/into-iter-on-arrays-lint.rs:28:19 + --> $DIR/into-iter-on-arrays-lint.rs:29:19 | LL | Box::new(big).into_iter(); | ^^^^^^^^^ @@ -119,7 +119,7 @@ LL | IntoIterator::into_iter(Box::new(big)); | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ 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. - --> $DIR/into-iter-on-arrays-lint.rs:31:25 + --> $DIR/into-iter-on-arrays-lint.rs:32:25 | LL | Box::new([0u8; 33]).into_iter(); | ^^^^^^^^^ @@ -136,7 +136,7 @@ LL | IntoIterator::into_iter(Box::new([0u8; 33])); | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ 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. - --> $DIR/into-iter-on-arrays-lint.rs:35:31 + --> $DIR/into-iter-on-arrays-lint.rs:36:31 | LL | Box::new(Box::new(small)).into_iter(); | ^^^^^^^^^ @@ -153,7 +153,7 @@ LL | IntoIterator::into_iter(Box::new(Box::new(small))); | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ 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. - --> $DIR/into-iter-on-arrays-lint.rs:38:32 + --> $DIR/into-iter-on-arrays-lint.rs:39:32 | LL | Box::new(Box::new([1, 2])).into_iter(); | ^^^^^^^^^ @@ -170,7 +170,7 @@ LL | IntoIterator::into_iter(Box::new(Box::new([1, 2]))); | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ 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. - --> $DIR/into-iter-on-arrays-lint.rs:41:29 + --> $DIR/into-iter-on-arrays-lint.rs:42:29 | LL | Box::new(Box::new(big)).into_iter(); | ^^^^^^^^^ @@ -187,7 +187,7 @@ LL | IntoIterator::into_iter(Box::new(Box::new(big))); | ^^^^^^^^^^^^^^^^^^^^^^^^ ^ 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. - --> $DIR/into-iter-on-arrays-lint.rs:44:35 + --> $DIR/into-iter-on-arrays-lint.rs:45:35 | LL | Box::new(Box::new([0u8; 33])).into_iter(); | ^^^^^^^^^