Rollup merge of #88503 - m-ou-se:array-into-inter-ambiguous, r=cjgillot
Warn when [T; N].into_iter() is ambiguous in the new edition. Fixes https://github.com/rust-lang/rust/issues/88475 In https://github.com/rust-lang/rust/issues/88475, a situation was found where `[T; N].into_iter()` becomes *ambiguous* in the new edition. This is different than the case where `(&[T; N]).into_iter()` resolves differently, which was the only case handled by the `array_into_iter` lint. This is almost identical to the new-traits-in-the-prelude problem. Effectively, due to the array-into-iter hack disappearing in Rust 2021, we effectively added `IntoIterator` to the 'prelude' in Rust 2021 specifically for arrays. This modifies the prelude collisions lint to detect that case and emit a `array_into_iter` lint in that case.
This commit is contained in:
commit
caca256b52
7 changed files with 91 additions and 7 deletions
|
@ -4405,6 +4405,7 @@ dependencies = [
|
||||||
"rustc_hir_pretty",
|
"rustc_hir_pretty",
|
||||||
"rustc_index",
|
"rustc_index",
|
||||||
"rustc_infer",
|
"rustc_infer",
|
||||||
|
"rustc_lint",
|
||||||
"rustc_macros",
|
"rustc_macros",
|
||||||
"rustc_middle",
|
"rustc_middle",
|
||||||
"rustc_session",
|
"rustc_session",
|
||||||
|
|
|
@ -62,6 +62,8 @@ mod traits;
|
||||||
mod types;
|
mod types;
|
||||||
mod unused;
|
mod unused;
|
||||||
|
|
||||||
|
pub use array_into_iter::ARRAY_INTO_ITER;
|
||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
|
|
|
@ -26,3 +26,4 @@ rustc_index = { path = "../rustc_index" }
|
||||||
rustc_infer = { path = "../rustc_infer" }
|
rustc_infer = { path = "../rustc_infer" }
|
||||||
rustc_trait_selection = { path = "../rustc_trait_selection" }
|
rustc_trait_selection = { path = "../rustc_trait_selection" }
|
||||||
rustc_ty_utils = { path = "../rustc_ty_utils" }
|
rustc_ty_utils = { path = "../rustc_ty_utils" }
|
||||||
|
rustc_lint = { path = "../rustc_lint" }
|
||||||
|
|
|
@ -5,7 +5,7 @@ use rustc_ast::Mutability;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_middle::ty::subst::InternalSubsts;
|
use rustc_middle::ty::subst::InternalSubsts;
|
||||||
use rustc_middle::ty::{Adt, Ref, Ty};
|
use rustc_middle::ty::{Adt, Array, Ref, Ty};
|
||||||
use rustc_session::lint::builtin::RUST_2021_PRELUDE_COLLISIONS;
|
use rustc_session::lint::builtin::RUST_2021_PRELUDE_COLLISIONS;
|
||||||
use rustc_span::symbol::kw::{Empty, Underscore};
|
use rustc_span::symbol::kw::{Empty, Underscore};
|
||||||
use rustc_span::symbol::{sym, Ident};
|
use rustc_span::symbol::{sym, Ident};
|
||||||
|
@ -38,10 +38,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// These are the method names that were added to prelude in Rust 2021
|
let prelude_or_array_lint = match segment.ident.name {
|
||||||
if !matches!(segment.ident.name, sym::try_into) {
|
// `try_into` was added to the prelude in Rust 2021.
|
||||||
return;
|
sym::try_into => RUST_2021_PRELUDE_COLLISIONS,
|
||||||
}
|
// `into_iter` wasn't added to the prelude,
|
||||||
|
// but `[T; N].into_iter()` doesn't resolve to IntoIterator::into_iter
|
||||||
|
// before Rust 2021, which results in the same problem.
|
||||||
|
// It is only a problem for arrays.
|
||||||
|
sym::into_iter if let Array(..) = self_ty.kind() => {
|
||||||
|
// In this case, it wasn't really a prelude addition that was the problem.
|
||||||
|
// Instead, the problem is that the array-into_iter hack will no longer apply in Rust 2021.
|
||||||
|
rustc_lint::ARRAY_INTO_ITER
|
||||||
|
}
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
|
||||||
// No need to lint if method came from std/core, as that will now be in the prelude
|
// No need to lint if method came from std/core, as that will now be in the prelude
|
||||||
if matches!(self.tcx.crate_name(pick.item.def_id.krate), sym::std | sym::core) {
|
if matches!(self.tcx.crate_name(pick.item.def_id.krate), sym::std | sym::core) {
|
||||||
|
@ -69,7 +79,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// Inherent impls only require not relying on autoref and autoderef in order to
|
// Inherent impls only require not relying on autoref and autoderef in order to
|
||||||
// ensure that the trait implementation won't be used
|
// ensure that the trait implementation won't be used
|
||||||
self.tcx.struct_span_lint_hir(
|
self.tcx.struct_span_lint_hir(
|
||||||
RUST_2021_PRELUDE_COLLISIONS,
|
prelude_or_array_lint,
|
||||||
self_expr.hir_id,
|
self_expr.hir_id,
|
||||||
self_expr.span,
|
self_expr.span,
|
||||||
|lint| {
|
|lint| {
|
||||||
|
@ -130,7 +140,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// trait implementations require full disambiguation to not clash with the new prelude
|
// trait implementations require full disambiguation to not clash with the new prelude
|
||||||
// additions (i.e. convert from dot-call to fully-qualified call)
|
// additions (i.e. convert from dot-call to fully-qualified call)
|
||||||
self.tcx.struct_span_lint_hir(
|
self.tcx.struct_span_lint_hir(
|
||||||
RUST_2021_PRELUDE_COLLISIONS,
|
prelude_or_array_lint,
|
||||||
call_expr.hir_id,
|
call_expr.hir_id,
|
||||||
call_expr.span,
|
call_expr.span,
|
||||||
|lint| {
|
|lint| {
|
||||||
|
|
27
src/test/ui/rust-2021/array-into-iter-ambiguous.fixed
Normal file
27
src/test/ui/rust-2021/array-into-iter-ambiguous.fixed
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// See https://github.com/rust-lang/rust/issues/88475
|
||||||
|
// run-rustfix
|
||||||
|
// edition:2018
|
||||||
|
// check-pass
|
||||||
|
#![warn(array_into_iter)]
|
||||||
|
#![allow(unused)]
|
||||||
|
|
||||||
|
struct FooIter;
|
||||||
|
|
||||||
|
trait MyIntoIter {
|
||||||
|
fn into_iter(self) -> FooIter;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, const N: usize> MyIntoIter for [T; N] {
|
||||||
|
fn into_iter(self) -> FooIter {
|
||||||
|
FooIter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Point;
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let points: [Point; 1] = [Point];
|
||||||
|
let y = MyIntoIter::into_iter(points);
|
||||||
|
//~^ WARNING trait method `into_iter` will become ambiguous in Rust 2021
|
||||||
|
//~| WARNING this changes meaning in Rust 2021
|
||||||
|
}
|
27
src/test/ui/rust-2021/array-into-iter-ambiguous.rs
Normal file
27
src/test/ui/rust-2021/array-into-iter-ambiguous.rs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// See https://github.com/rust-lang/rust/issues/88475
|
||||||
|
// run-rustfix
|
||||||
|
// edition:2018
|
||||||
|
// check-pass
|
||||||
|
#![warn(array_into_iter)]
|
||||||
|
#![allow(unused)]
|
||||||
|
|
||||||
|
struct FooIter;
|
||||||
|
|
||||||
|
trait MyIntoIter {
|
||||||
|
fn into_iter(self) -> FooIter;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, const N: usize> MyIntoIter for [T; N] {
|
||||||
|
fn into_iter(self) -> FooIter {
|
||||||
|
FooIter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Point;
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let points: [Point; 1] = [Point];
|
||||||
|
let y = points.into_iter();
|
||||||
|
//~^ WARNING trait method `into_iter` will become ambiguous in Rust 2021
|
||||||
|
//~| WARNING this changes meaning in Rust 2021
|
||||||
|
}
|
16
src/test/ui/rust-2021/array-into-iter-ambiguous.stderr
Normal file
16
src/test/ui/rust-2021/array-into-iter-ambiguous.stderr
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
warning: trait method `into_iter` will become ambiguous in Rust 2021
|
||||||
|
--> $DIR/array-into-iter-ambiguous.rs:24:13
|
||||||
|
|
|
||||||
|
LL | let y = points.into_iter();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `MyIntoIter::into_iter(points)`
|
||||||
|
|
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/array-into-iter-ambiguous.rs:5:9
|
||||||
|
|
|
||||||
|
LL | #![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>
|
||||||
|
|
||||||
|
warning: 1 warning emitted
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue