diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index be4f12c6d1cb8..085e3811ac1a3 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -155,6 +155,7 @@ symbols! { FormatSpec, Formatter, From, + FromIterator, Future, FxHashMap, FxHashSet, diff --git a/compiler/rustc_typeck/src/check/method/prelude2021.rs b/compiler/rustc_typeck/src/check/method/prelude2021.rs index 6ca0b3ed66b39..f853c0fd9ccdb 100644 --- a/compiler/rustc_typeck/src/check/method/prelude2021.rs +++ b/compiler/rustc_typeck/src/check/method/prelude2021.rs @@ -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}, @@ -206,6 +208,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; } + // For from_iter, check if the type actualy 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) { diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index 348e1f7e3f23d..7f87ead6feed6 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -89,6 +89,7 @@ over elements of type `{A}`", label = "value of type `{Self}` cannot be built from `std::iter::Iterator`" )] +#[rustc_diagnostic_item = "FromIterator"] pub trait FromIterator: Sized { /// Creates a value from an iterator. ///