about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-04-19 01:41:01 +0000
committerMichael Goulet <michael@errs.io>2023-04-19 02:01:55 +0000
commit14678778dc50ce5886856826f8cd35dc080ead7e (patch)
tree638670ab3276d292bcc2089a973574361ffa3dde /compiler/rustc_trait_selection/src
parentde96f3d8735b70d5dc1ca178aaee198b329b8f3d (diff)
downloadrust-14678778dc50ce5886856826f8cd35dc080ead7e.tar.gz
rust-14678778dc50ce5886856826f8cd35dc080ead7e.zip
Remove find_map_relevant_impl
Diffstat (limited to 'compiler/rustc_trait_selection/src')
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs145
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs22
3 files changed, 103 insertions, 74 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index abd11a15ac2..acfc8e98fcb 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -645,12 +645,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             // FIXME: Handling opaques here is kinda sus. Especially because we
             // simplify them to PlaceholderSimplifiedType.
             | ty::Alias(ty::Opaque, _) => {
-                if let Some(def_id) = self.tcx().find_map_relevant_impl(
+                let mut disqualifying_impl = None;
+                self.tcx().for_each_relevant_impl_treating_projections(
                     goal.predicate.def_id(),
                     goal.predicate.self_ty(),
                     TreatProjections::NextSolverLookup,
-                    Some,
-                ) {
+                    |impl_def_id| {
+                        disqualifying_impl = Some(impl_def_id);
+                    },
+                );
+                if let Some(def_id) = disqualifying_impl {
                     debug!(?def_id, ?goal, "disqualified auto-trait implementation");
                     // No need to actually consider the candidate here,
                     // since we do that in `consider_impl_candidate`.
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 0352f0f380d..660f78509d3 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -32,7 +32,6 @@ use rustc_infer::infer::{InferOk, TypeTrace};
 use rustc_middle::traits::select::OverflowError;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::fast_reject::TreatProjections;
 use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print};
 use rustc_middle::ty::{
@@ -1836,57 +1835,61 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 });
             let mut diag = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271, "{msg}");
 
-            let secondary_span = match predicate.kind().skip_binder() {
-                ty::PredicateKind::Clause(ty::Clause::Projection(proj)) => self
-                    .tcx
-                    .opt_associated_item(proj.projection_ty.def_id)
-                    .and_then(|trait_assoc_item| {
-                        self.tcx
-                            .trait_of_item(proj.projection_ty.def_id)
-                            .map(|id| (trait_assoc_item, id))
-                    })
-                    .and_then(|(trait_assoc_item, id)| {
-                        let trait_assoc_ident = trait_assoc_item.ident(self.tcx);
-                        self.tcx.find_map_relevant_impl(
-                            id,
-                            proj.projection_ty.self_ty(),
-                            TreatProjections::ForLookup,
-                            |did| {
-                                self.tcx
-                                    .associated_items(did)
-                                    .in_definition_order()
-                                    .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident)
-                            },
-                        )
-                    })
-                    .and_then(|item| match self.tcx.hir().get_if_local(item.def_id) {
-                        Some(
-                            hir::Node::TraitItem(hir::TraitItem {
-                                kind: hir::TraitItemKind::Type(_, Some(ty)),
-                                ..
-                            })
-                            | hir::Node::ImplItem(hir::ImplItem {
-                                kind: hir::ImplItemKind::Type(ty),
-                                ..
-                            }),
-                        ) => Some((
-                            ty.span,
-                            with_forced_trimmed_paths!(format!(
-                                "type mismatch resolving `{}`",
-                                self.resolve_vars_if_possible(predicate)
-                                    .print(FmtPrinter::new_with_limit(
-                                        self.tcx,
-                                        Namespace::TypeNS,
-                                        rustc_session::Limit(5),
-                                    ))
-                                    .unwrap()
-                                    .into_buffer()
-                            )),
+            let secondary_span = (|| {
+                let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) =
+                    predicate.kind().skip_binder()
+                else {
+                    return None;
+                };
+
+                let trait_assoc_item = self.tcx.opt_associated_item(proj.projection_ty.def_id)?;
+                let trait_assoc_ident = trait_assoc_item.ident(self.tcx);
+
+                let mut associated_items = vec![];
+                self.tcx.for_each_relevant_impl(
+                    self.tcx.trait_of_item(proj.projection_ty.def_id)?,
+                    proj.projection_ty.self_ty(),
+                    |impl_def_id| {
+                        associated_items.extend(
+                            self.tcx
+                                .associated_items(impl_def_id)
+                                .in_definition_order()
+                                .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident),
+                        );
+                    },
+                );
+
+                let [associated_item]: &[ty::AssocItem] = &associated_items[..] else {
+                    return None;
+                };
+                match self.tcx.hir().get_if_local(associated_item.def_id) {
+                    Some(
+                        hir::Node::TraitItem(hir::TraitItem {
+                            kind: hir::TraitItemKind::Type(_, Some(ty)),
+                            ..
+                        })
+                        | hir::Node::ImplItem(hir::ImplItem {
+                            kind: hir::ImplItemKind::Type(ty),
+                            ..
+                        }),
+                    ) => Some((
+                        ty.span,
+                        with_forced_trimmed_paths!(format!(
+                            "type mismatch resolving `{}`",
+                            self.resolve_vars_if_possible(predicate)
+                                .print(FmtPrinter::new_with_limit(
+                                    self.tcx,
+                                    Namespace::TypeNS,
+                                    rustc_session::Limit(5),
+                                ))
+                                .unwrap()
+                                .into_buffer()
                         )),
-                        _ => None,
-                    }),
-                _ => None,
-            };
+                    )),
+                    _ => None,
+                }
+            })();
+
             self.note_type_err(
                 &mut diag,
                 &obligation.cause,
@@ -2228,14 +2231,18 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         err: &mut Diagnostic,
         trait_ref: &ty::PolyTraitRef<'tcx>,
     ) -> bool {
-        let get_trait_impl = |trait_def_id| {
-            self.tcx.find_map_relevant_impl(
+        let get_trait_impls = |trait_def_id| {
+            let mut trait_impls = vec![];
+            self.tcx.for_each_relevant_impl(
                 trait_def_id,
                 trait_ref.skip_binder().self_ty(),
-                TreatProjections::ForLookup,
-                Some,
-            )
+                |impl_def_id| {
+                    trait_impls.push(impl_def_id);
+                },
+            );
+            trait_impls
         };
+
         let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
         let traits_with_same_path: std::collections::BTreeSet<_> = self
             .tcx
@@ -2245,17 +2252,23 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             .collect();
         let mut suggested = false;
         for trait_with_same_path in traits_with_same_path {
-            if let Some(impl_def_id) = get_trait_impl(trait_with_same_path) {
-                let impl_span = self.tcx.def_span(impl_def_id);
-                err.span_help(impl_span, "trait impl with same name found");
-                let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
-                let crate_msg = format!(
-                    "perhaps two different versions of crate `{}` are being used?",
-                    trait_crate
-                );
-                err.note(&crate_msg);
-                suggested = true;
+            let trait_impls = get_trait_impls(trait_with_same_path);
+            if trait_impls.is_empty() {
+                continue;
             }
+            let impl_spans: Vec<_> =
+                trait_impls.iter().map(|impl_def_id| self.tcx.def_span(*impl_def_id)).collect();
+            err.span_help(
+                impl_spans,
+                format!("trait impl{} with same name found", pluralize!(trait_impls.len())),
+            );
+            let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
+            let crate_msg = format!(
+                "perhaps two different versions of crate `{}` are being used?",
+                trait_crate
+            );
+            err.note(&crate_msg);
+            suggested = true;
         }
         suggested
     }
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 1f5bbc178f7..403593a47c1 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -11,7 +11,7 @@ use hir::LangItem;
 use rustc_hir as hir;
 use rustc_infer::traits::ObligationCause;
 use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
-use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, TreatProjections};
+use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
 use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 
 use crate::traits;
@@ -875,12 +875,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
 
             ty::Adt(..) => {
-                // Find a custom `impl Drop` impl, if it exists
-                let relevant_impl = self.tcx().find_map_relevant_impl(
+                let mut relevant_impl = None;
+                self.tcx().for_each_relevant_impl(
                     self.tcx().require_lang_item(LangItem::Drop, None),
                     obligation.predicate.skip_binder().trait_ref.self_ty(),
-                    TreatProjections::ForLookup,
-                    Some,
+                    |impl_def_id| {
+                        if let Some(old_impl_def_id) = relevant_impl {
+                            self.tcx()
+                                .sess
+                                .struct_span_err(
+                                    self.tcx().def_span(impl_def_id),
+                                    "multiple drop impls found",
+                                )
+                                .span_note(self.tcx().def_span(old_impl_def_id), "other impl here")
+                                .delay_as_bug();
+                        }
+
+                        relevant_impl = Some(impl_def_id);
+                    },
                 );
 
                 if let Some(impl_def_id) = relevant_impl {