Skip to content

Commit caca256

Browse files
authored
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 #88475 In #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.
2 parents db44069 + ac93ca3 commit caca256

File tree

7 files changed

+91
-7
lines changed

7 files changed

+91
-7
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -4405,6 +4405,7 @@ dependencies = [
44054405
"rustc_hir_pretty",
44064406
"rustc_index",
44074407
"rustc_infer",
4408+
"rustc_lint",
44084409
"rustc_macros",
44094410
"rustc_middle",
44104411
"rustc_session",

compiler/rustc_lint/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ mod traits;
6262
mod types;
6363
mod unused;
6464

65+
pub use array_into_iter::ARRAY_INTO_ITER;
66+
6567
use rustc_ast as ast;
6668
use rustc_hir as hir;
6769
use rustc_hir::def_id::LocalDefId;

compiler/rustc_typeck/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ rustc_index = { path = "../rustc_index" }
2626
rustc_infer = { path = "../rustc_infer" }
2727
rustc_trait_selection = { path = "../rustc_trait_selection" }
2828
rustc_ty_utils = { path = "../rustc_ty_utils" }
29+
rustc_lint = { path = "../rustc_lint" }

compiler/rustc_typeck/src/check/method/prelude2021.rs

+17-7
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_ast::Mutability;
55
use rustc_errors::Applicability;
66
use rustc_hir as hir;
77
use rustc_middle::ty::subst::InternalSubsts;
8-
use rustc_middle::ty::{Adt, Ref, Ty};
8+
use rustc_middle::ty::{Adt, Array, Ref, Ty};
99
use rustc_session::lint::builtin::RUST_2021_PRELUDE_COLLISIONS;
1010
use rustc_span::symbol::kw::{Empty, Underscore};
1111
use rustc_span::symbol::{sym, Ident};
@@ -38,10 +38,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3838
return;
3939
}
4040

41-
// These are the method names that were added to prelude in Rust 2021
42-
if !matches!(segment.ident.name, sym::try_into) {
43-
return;
44-
}
41+
let prelude_or_array_lint = match segment.ident.name {
42+
// `try_into` was added to the prelude in Rust 2021.
43+
sym::try_into => RUST_2021_PRELUDE_COLLISIONS,
44+
// `into_iter` wasn't added to the prelude,
45+
// but `[T; N].into_iter()` doesn't resolve to IntoIterator::into_iter
46+
// before Rust 2021, which results in the same problem.
47+
// It is only a problem for arrays.
48+
sym::into_iter if let Array(..) = self_ty.kind() => {
49+
// In this case, it wasn't really a prelude addition that was the problem.
50+
// Instead, the problem is that the array-into_iter hack will no longer apply in Rust 2021.
51+
rustc_lint::ARRAY_INTO_ITER
52+
}
53+
_ => return,
54+
};
4555

4656
// No need to lint if method came from std/core, as that will now be in the prelude
4757
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> {
6979
// Inherent impls only require not relying on autoref and autoderef in order to
7080
// ensure that the trait implementation won't be used
7181
self.tcx.struct_span_lint_hir(
72-
RUST_2021_PRELUDE_COLLISIONS,
82+
prelude_or_array_lint,
7383
self_expr.hir_id,
7484
self_expr.span,
7585
|lint| {
@@ -130,7 +140,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
130140
// trait implementations require full disambiguation to not clash with the new prelude
131141
// additions (i.e. convert from dot-call to fully-qualified call)
132142
self.tcx.struct_span_lint_hir(
133-
RUST_2021_PRELUDE_COLLISIONS,
143+
prelude_or_array_lint,
134144
call_expr.hir_id,
135145
call_expr.span,
136146
|lint| {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// See https://github.com/rust-lang/rust/issues/88475
2+
// run-rustfix
3+
// edition:2018
4+
// check-pass
5+
#![warn(array_into_iter)]
6+
#![allow(unused)]
7+
8+
struct FooIter;
9+
10+
trait MyIntoIter {
11+
fn into_iter(self) -> FooIter;
12+
}
13+
14+
impl<T, const N: usize> MyIntoIter for [T; N] {
15+
fn into_iter(self) -> FooIter {
16+
FooIter
17+
}
18+
}
19+
20+
struct Point;
21+
22+
pub fn main() {
23+
let points: [Point; 1] = [Point];
24+
let y = MyIntoIter::into_iter(points);
25+
//~^ WARNING trait method `into_iter` will become ambiguous in Rust 2021
26+
//~| WARNING this changes meaning in Rust 2021
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// See https://github.com/rust-lang/rust/issues/88475
2+
// run-rustfix
3+
// edition:2018
4+
// check-pass
5+
#![warn(array_into_iter)]
6+
#![allow(unused)]
7+
8+
struct FooIter;
9+
10+
trait MyIntoIter {
11+
fn into_iter(self) -> FooIter;
12+
}
13+
14+
impl<T, const N: usize> MyIntoIter for [T; N] {
15+
fn into_iter(self) -> FooIter {
16+
FooIter
17+
}
18+
}
19+
20+
struct Point;
21+
22+
pub fn main() {
23+
let points: [Point; 1] = [Point];
24+
let y = points.into_iter();
25+
//~^ WARNING trait method `into_iter` will become ambiguous in Rust 2021
26+
//~| WARNING this changes meaning in Rust 2021
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
warning: trait method `into_iter` will become ambiguous in Rust 2021
2+
--> $DIR/array-into-iter-ambiguous.rs:24:13
3+
|
4+
LL | let y = points.into_iter();
5+
| ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `MyIntoIter::into_iter(points)`
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/array-into-iter-ambiguous.rs:5:9
9+
|
10+
LL | #![warn(array_into_iter)]
11+
| ^^^^^^^^^^^^^^^
12+
= warning: this changes meaning in Rust 2021
13+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
14+
15+
warning: 1 warning emitted
16+

0 commit comments

Comments
 (0)