Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

array_into_iter does not trigger for existing trait impl #88475

Closed
ehuss opened this issue Aug 30, 2021 · 2 comments · Fixed by #88503
Closed

array_into_iter does not trigger for existing trait impl #88475

ehuss opened this issue Aug 30, 2021 · 2 comments · Fixed by #88503
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-edition-2021 Area: The 2021 edition A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` C-bug Category: This is a bug.

Comments

@ehuss
Copy link
Contributor

ehuss commented Aug 30, 2021

I tried this code:

#![allow(unused)]

struct FooIter;

trait MyIntoIter {
    fn into_iter(self: Self) -> FooIter;
}

impl<T, const N: usize> MyIntoIter for [T; N] {
    fn into_iter(self: Self) -> FooIter {
        FooIter
    }
}

struct Point;

pub fn foo() {
    let points: [Point; 1] = [Point];
    let y = points.into_iter();
}

This code will not emit the array_into_iter lint. When updating to the 2021 edition, the code fails to compile:

error[E0034]: multiple applicable items in scope
  --> src/lib.rs:19:20
   |
19 |     let y = points.into_iter();
   |                    ^^^^^^^^^ multiple `into_iter` found
   |
note: candidate #1 is defined in an impl of the trait `MyIntoIter` for the type `[T; N]`
  --> src/lib.rs:10:5
   |
10 |     fn into_iter(self: Self) -> FooIter {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: candidate #2 is defined in an impl of the trait `IntoIterator` for the type `[T; N]`
help: disambiguate the associated function for candidate #1
   |
19 |     let y = MyIntoIter::into_iter(points);
   |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
help: disambiguate the associated function for candidate #2
   |
19 |     let y = IntoIterator::into_iter(points);
   |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

I would expect the array_into_iter lint to give the appropriate suggestion.

Found in the 2021 crater run for:

Meta

rustc --version --verbose:

rustc 1.56.0-nightly (5eacec9ec 2021-08-28)
binary: rustc
commit-hash: 5eacec9ec7e112a0de1011519a57c45586d58414
commit-date: 2021-08-28
host: x86_64-apple-darwin
release: 1.56.0-nightly
LLVM version: 13.0.0
@ehuss ehuss added A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug. A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` A-edition-2021 Area: The 2021 edition labels Aug 30, 2021
@m-ou-se
Copy link
Member

m-ou-se commented Aug 30, 2021

The lint specifically checks if it is libcore's IntoIterator::into_iter before producing the lint:

// Check if the method call actually calls the libcore
// `IntoIterator::into_iter`.
let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
match cx.tcx.trait_of_item(def_id) {
Some(trait_id) if cx.tcx.is_diagnostic_item(sym::IntoIterator, trait_id) => {}
_ => return,
};

Maybe the check shouldn't be there. Maybe it should only check if the receiver is an array.

@m-ou-se
Copy link
Member

m-ou-se commented Aug 30, 2021

Changing some of the checks to include this situation for that lint would result in a completely wrong diagnostic:

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.
  --> src/main.rs:20:20
   |
20 |     let y = points.into_iter();
   |                    ^^^^^^^^^
   |
note: the lint level is defined here
  --> src/main.rs:1:9
   |
1  | #![warn(array_into_iter)]
   |         ^^^^^^^^^^^^^^^
   = warning: this changes meaning in Rust 2021
   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
   |
20 |     let y = points.iter();
   |                    ~~~~
help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
   |
20 |     let y = IntoIterator::into_iter(points);
   |             ++++++++++++++++++++++++      ~

Instead, it'd have to do something more like the prelude collision lint. It'd have to generate the right fully explicit call syntax and some message about it becoming ambiguous in the new edition.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-edition-2021 Area: The 2021 edition A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` C-bug Category: This is a bug.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants