From f2930001aa6dd5f5056c69c96c1eaf4b31dfedd8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 25 Apr 2025 15:13:51 +0000 Subject: [PATCH] Use select in projection lookup --- .../traits/fulfillment_errors.rs | 42 ++++++++++--------- .../mismatch-two-relevant-impls.rs | 20 +++++++++ .../mismatch-two-relevant-impls.stderr | 20 +++++++++ 3 files changed, 62 insertions(+), 20 deletions(-) create mode 100644 tests/ui/associated-types/mismatch-two-relevant-impls.rs create mode 100644 tests/ui/associated-types/mismatch-two-relevant-impls.stderr diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index ab2aa0ae46976..970160ba212af 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -15,6 +15,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::{self as hir, LangItem, Node}; use rustc_infer::infer::{InferOk, TypeTrace}; +use rustc_infer::traits::ImplSource; use rustc_infer::traits::solve::Goal; use rustc_middle::traits::SignatureMismatchData; use rustc_middle::traits::select::OverflowError; @@ -48,8 +49,8 @@ use crate::infer::{self, InferCtxt, InferCtxtExt as _}; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use crate::traits::{ MismatchedProjectionTypes, NormalizeExt, Obligation, ObligationCause, ObligationCauseCode, - ObligationCtxt, Overflow, PredicateObligation, SelectionError, SignatureMismatch, - TraitDynIncompatible, elaborate, + ObligationCtxt, Overflow, PredicateObligation, SelectionContext, SelectionError, + SignatureMismatch, TraitDynIncompatible, elaborate, specialization_graph, }; impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { @@ -1495,32 +1496,33 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - let secondary_span = (|| { + let secondary_span = self.probe(|_| { let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) = predicate.kind().skip_binder() else { return None; }; - let mut associated_items = vec![]; - self.tcx.for_each_relevant_impl( - self.tcx.trait_of_item(proj.projection_term.def_id)?, - proj.projection_term.self_ty(), - |impl_def_id| { - associated_items.extend( - self.tcx.associated_items(impl_def_id).in_definition_order().find( - |assoc| { - assoc.trait_item_def_id == Some(proj.projection_term.def_id) - }, - ), - ); - }, - ); + let Ok(Some(ImplSource::UserDefined(impl_data))) = SelectionContext::new(self) + .poly_select(&obligation.with( + self.tcx, + predicate.kind().rebind(proj.projection_term.trait_ref(self.tcx)), + )) + else { + return None; + }; - let [associated_item]: &[ty::AssocItem] = &associated_items[..] else { + let Ok(node) = + specialization_graph::assoc_def(self.tcx, impl_data.impl_def_id, proj.def_id()) + else { return None; }; - match self.tcx.hir_get_if_local(associated_item.def_id) { + + if !node.is_final() { + return None; + } + + match self.tcx.hir_get_if_local(node.item.def_id) { Some( hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(_, Some(ty)), @@ -1543,7 +1545,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { )), _ => None, } - })(); + }); self.note_type_err( &mut diag, diff --git a/tests/ui/associated-types/mismatch-two-relevant-impls.rs b/tests/ui/associated-types/mismatch-two-relevant-impls.rs new file mode 100644 index 0000000000000..58fd567c27800 --- /dev/null +++ b/tests/ui/associated-types/mismatch-two-relevant-impls.rs @@ -0,0 +1,20 @@ +trait Tr { + type Assoc; +} + +struct W(T); + +impl Tr for W { + type Assoc = u32; +} + +impl Tr for W { + type Assoc = i32; +} + +fn needs_unit>() {} + +fn main() { + needs_unit::>(); + //~^ ERROR type mismatch resolving ` as Tr>::Assoc == ()` +} diff --git a/tests/ui/associated-types/mismatch-two-relevant-impls.stderr b/tests/ui/associated-types/mismatch-two-relevant-impls.stderr new file mode 100644 index 0000000000000..2a1f3ef23ca7b --- /dev/null +++ b/tests/ui/associated-types/mismatch-two-relevant-impls.stderr @@ -0,0 +1,20 @@ +error[E0271]: type mismatch resolving ` as Tr>::Assoc == ()` + --> $DIR/mismatch-two-relevant-impls.rs:18:18 + | +LL | needs_unit::>(); + | ^^^^^^ type mismatch resolving ` as Tr>::Assoc == ()` + | +note: expected this to be `()` + --> $DIR/mismatch-two-relevant-impls.rs:8:18 + | +LL | type Assoc = u32; + | ^^^ +note: required by a bound in `needs_unit` + --> $DIR/mismatch-two-relevant-impls.rs:15:21 + | +LL | fn needs_unit>() {} + | ^^^^^^^^^^ required by this bound in `needs_unit` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`.