Skip to content

Commit

Permalink
Auto merge of #86904 - m-ou-se:prelude-collision-check-trait, r=nikom…
Browse files Browse the repository at this point in the history
…atsakis

Check FromIterator trait impl in prelude collision check.

Fixes #86902.
  • Loading branch information
bors committed Jul 9, 2021
2 parents b090cd1 + 2083207 commit 95fb131
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 1 deletion.
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ symbols! {
FormatSpec,
Formatter,
From,
FromIterator,
Future,
FxHashMap,
FxHashSet,
Expand Down
21 changes: 21 additions & 0 deletions compiler/rustc_typeck/src/check/method/prelude2021.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ use hir::ItemKind;
use rustc_ast::Mutability;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::{Ref, Ty};
use rustc_session::lint::builtin::RUST_2021_PRELUDE_COLLISIONS;
use rustc_span::symbol::kw::Underscore;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
use rustc_trait_selection::infer::InferCtxtExt;

use crate::check::{
method::probe::{self, Pick},
Expand Down Expand Up @@ -206,6 +208,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return;
}

// For from_iter, check if the type actually implements FromIterator.
// If we know it does not, we don't need to warn.
if method_name.name == sym::from_iter {
if let Some(trait_def_id) = self.tcx.get_diagnostic_item(sym::FromIterator) {
if !self
.infcx
.type_implements_trait(
trait_def_id,
self_ty,
InternalSubsts::empty(),
self.param_env,
)
.may_apply()
{
return;
}
}
}

// No need to lint if this is an inherent method called on a specific type, like `Vec::foo(...)`,
// since such methods take precedence over trait methods.
if matches!(pick.kind, probe::PickKind::InherentImplPick) {
Expand Down
1 change: 1 addition & 0 deletions library/core/src/iter/traits/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
over elements of type `{A}`",
label = "value of type `{Self}` cannot be built from `std::iter::Iterator<Item={A}>`"
)]
#[rustc_diagnostic_item = "FromIterator"]
pub trait FromIterator<A>: Sized {
/// Creates a value from an iterator.
///
Expand Down
44 changes: 43 additions & 1 deletion src/test/ui/rust-2021/future-prelude-collision-unneeded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,50 @@ impl S {
}
}

// See https://github.com/rust-lang/rust/issues/86633
struct X;

trait Hey {
fn from_iter(_: i32) -> Self;
}

impl Hey for X {
fn from_iter(_: i32) -> Self {
X
}
}

struct Y<T>(T);

impl Hey for Y<i32> {
fn from_iter(_: i32) -> Self {
Y(0)
}
}

struct Z<T>(T);

impl Hey for Z<i32> {
fn from_iter(_: i32) -> Self {
Z(0)
}
}

impl std::iter::FromIterator<u32> for Z<u32> {
fn from_iter<T: IntoIterator<Item = u32>>(_: T) -> Self {
todo!()
}
}

fn main() {
// See https://github.com/rust-lang/rust/issues/86633
let s = S;
let s2 = s.try_into();

// Check that we do not issue suggestions for types that do not implement `FromIter`.
//
// See https://github.com/rust-lang/rust/issues/86902
X::from_iter(1);
Y::from_iter(1);
Y::<i32>::from_iter(1);
Z::<i32>::from_iter(1);
}

0 comments on commit 95fb131

Please sign in to comment.