about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-07-27 00:48:51 +0000
committerMichael Goulet <michael@errs.io>2023-08-03 18:21:11 +0000
commit4cc659eb3fc99cd44457616b17d390488e80fcb0 (patch)
tree4f4d14a054753952c9c65b69718be89dd2e7801d
parent1bb6ae5874730933188fe4be56b3a2f3d5a66962 (diff)
downloadrust-4cc659eb3fc99cd44457616b17d390488e80fcb0.tar.gz
rust-4cc659eb3fc99cd44457616b17d390488e80fcb0.zip
short-circuit when proj def ids differ
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs23
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs11
2 files changed, 20 insertions, 14 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index 41565fe5dd9..6a23895e1be 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -625,15 +625,20 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         // in b_ty's bound. Use this to first determine *which* apply without
         // having any inference side-effects. We process obligations because
         // unification may initially succeed due to deferred projection equality.
-        let projection_may_match = |ecx: &mut Self, source_projection, target_projection| {
-            ecx.probe(|_| CandidateKind::UpcastProbe)
-                .enter(|ecx| -> Result<(), NoSolution> {
-                    ecx.eq(param_env, source_projection, target_projection)?;
-                    let _ = ecx.try_evaluate_added_goals()?;
-                    Ok(())
-                })
-                .is_ok()
-        };
+        let projection_may_match =
+            |ecx: &mut Self,
+             source_projection: ty::PolyExistentialProjection<'tcx>,
+             target_projection: ty::PolyExistentialProjection<'tcx>| {
+                source_projection.item_def_id() == target_projection.item_def_id()
+                    && ecx
+                        .probe(|_| CandidateKind::UpcastProbe)
+                        .enter(|ecx| -> Result<(), NoSolution> {
+                            ecx.eq(param_env, source_projection, target_projection)?;
+                            let _ = ecx.try_evaluate_added_goals()?;
+                            Ok(())
+                        })
+                        .is_ok()
+            };
 
         for bound in b_data {
             match bound.skip_binder() {
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 77304984402..3cf2735b46b 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -920,11 +920,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         a_data.projection_bounds().filter(|source_projection| {
                             // Eager normalization means that we can just use can_eq
                             // here instead of equating and processing obligations.
-                            self.infcx.can_eq(
-                                obligation.param_env,
-                                *source_projection,
-                                target_projection,
-                            )
+                            source_projection.item_def_id() == target_projection.item_def_id()
+                                && self.infcx.can_eq(
+                                    obligation.param_env,
+                                    *source_projection,
+                                    target_projection,
+                                )
                         });
                     let Some(source_projection) = matching_projections.next() else {
                         return Err(SelectionError::Unimplemented);