]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_typeck/src/check/method/prelude2021.rs
Check FromIterator trait impl in prelude collision check.
[rust.git] / compiler / rustc_typeck / src / check / method / prelude2021.rs
index e8748dd062f5334beda61776ecccc603e3e628cb..f853c0fd9ccdb481a2865964870ad8964a521fb8 100644 (file)
@@ -4,11 +4,13 @@
 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::FUTURE_PRELUDE_COLLISION;
+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},
@@ -67,7 +69,7 @@ pub(super) fn lint_dot_call_from_2018(
             // Inherent impls only require not relying on autoref and autoderef in order to
             // ensure that the trait implementation won't be used
             self.tcx.struct_span_lint_hir(
-                FUTURE_PRELUDE_COLLISION,
+                RUST_2021_PRELUDE_COLLISIONS,
                 self_expr.hir_id,
                 self_expr.span,
                 |lint| {
@@ -128,7 +130,7 @@ pub(super) fn lint_dot_call_from_2018(
             // trait implementations require full disambiguation to not clash with the new prelude
             // additions (i.e. convert from dot-call to fully-qualified call)
             self.tcx.struct_span_lint_hir(
-                FUTURE_PRELUDE_COLLISION,
+                RUST_2021_PRELUDE_COLLISIONS,
                 call_expr.hir_id,
                 call_expr.span,
                 |lint| {
@@ -206,13 +208,32 @@ pub(super) fn lint_fully_qualified_call_from_2018(
             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) {
             return;
         }
 
-        self.tcx.struct_span_lint_hir(FUTURE_PRELUDE_COLLISION, expr_id, span, |lint| {
+        self.tcx.struct_span_lint_hir(RUST_2021_PRELUDE_COLLISIONS, expr_id, span, |lint| {
             // "type" refers to either a type or, more likely, a trait from which
             // the associated function or method is from.
             let trait_path = self.trait_path_or_bare_name(span, expr_id, pick.item.container.id());