Skip to content

Commit 95fb131

Browse files
committed
Auto merge of #86904 - m-ou-se:prelude-collision-check-trait, r=nikomatsakis
Check FromIterator trait impl in prelude collision check. Fixes #86902.
2 parents b090cd1 + 2083207 commit 95fb131

File tree

4 files changed

+66
-1
lines changed

4 files changed

+66
-1
lines changed

Diff for: compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ symbols! {
155155
FormatSpec,
156156
Formatter,
157157
From,
158+
FromIterator,
158159
Future,
159160
FxHashMap,
160161
FxHashSet,

Diff for: compiler/rustc_typeck/src/check/method/prelude2021.rs

+21
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ use hir::ItemKind;
44
use rustc_ast::Mutability;
55
use rustc_errors::Applicability;
66
use rustc_hir as hir;
7+
use rustc_middle::ty::subst::InternalSubsts;
78
use rustc_middle::ty::{Ref, Ty};
89
use rustc_session::lint::builtin::RUST_2021_PRELUDE_COLLISIONS;
910
use rustc_span::symbol::kw::Underscore;
1011
use rustc_span::symbol::{sym, Ident};
1112
use rustc_span::Span;
13+
use rustc_trait_selection::infer::InferCtxtExt;
1214

1315
use crate::check::{
1416
method::probe::{self, Pick},
@@ -206,6 +208,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
206208
return;
207209
}
208210

211+
// For from_iter, check if the type actually implements FromIterator.
212+
// If we know it does not, we don't need to warn.
213+
if method_name.name == sym::from_iter {
214+
if let Some(trait_def_id) = self.tcx.get_diagnostic_item(sym::FromIterator) {
215+
if !self
216+
.infcx
217+
.type_implements_trait(
218+
trait_def_id,
219+
self_ty,
220+
InternalSubsts::empty(),
221+
self.param_env,
222+
)
223+
.may_apply()
224+
{
225+
return;
226+
}
227+
}
228+
}
229+
209230
// No need to lint if this is an inherent method called on a specific type, like `Vec::foo(...)`,
210231
// since such methods take precedence over trait methods.
211232
if matches!(pick.kind, probe::PickKind::InherentImplPick) {

Diff for: library/core/src/iter/traits/collect.rs

+1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
over elements of type `{A}`",
9090
label = "value of type `{Self}` cannot be built from `std::iter::Iterator<Item={A}>`"
9191
)]
92+
#[rustc_diagnostic_item = "FromIterator"]
9293
pub trait FromIterator<A>: Sized {
9394
/// Creates a value from an iterator.
9495
///

Diff for: src/test/ui/rust-2021/future-prelude-collision-unneeded.rs

+43-1
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,50 @@ impl S {
1111
}
1212
}
1313

14-
// See https://github.com/rust-lang/rust/issues/86633
14+
struct X;
15+
16+
trait Hey {
17+
fn from_iter(_: i32) -> Self;
18+
}
19+
20+
impl Hey for X {
21+
fn from_iter(_: i32) -> Self {
22+
X
23+
}
24+
}
25+
26+
struct Y<T>(T);
27+
28+
impl Hey for Y<i32> {
29+
fn from_iter(_: i32) -> Self {
30+
Y(0)
31+
}
32+
}
33+
34+
struct Z<T>(T);
35+
36+
impl Hey for Z<i32> {
37+
fn from_iter(_: i32) -> Self {
38+
Z(0)
39+
}
40+
}
41+
42+
impl std::iter::FromIterator<u32> for Z<u32> {
43+
fn from_iter<T: IntoIterator<Item = u32>>(_: T) -> Self {
44+
todo!()
45+
}
46+
}
47+
1548
fn main() {
49+
// See https://github.com/rust-lang/rust/issues/86633
1650
let s = S;
1751
let s2 = s.try_into();
52+
53+
// Check that we do not issue suggestions for types that do not implement `FromIter`.
54+
//
55+
// See https://github.com/rust-lang/rust/issues/86902
56+
X::from_iter(1);
57+
Y::from_iter(1);
58+
Y::<i32>::from_iter(1);
59+
Z::<i32>::from_iter(1);
1860
}

0 commit comments

Comments
 (0)