about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-09-29 17:51:38 -0400
committerMichael Goulet <michael@errs.io>2024-09-30 13:17:33 -0400
commitaf3f212453f667981bb07c0029f86bc607f3baa9 (patch)
treef0e1715bfc85cb0c2c4e798469000462540d666b /compiler
parentc3ce4e66a5732a5b89c9f495b44357bf6b29d424 (diff)
downloadrust-af3f212453f667981bb07c0029f86bc607f3baa9.tar.gz
rust-af3f212453f667981bb07c0029f86bc607f3baa9.zip
Instantiate binders in supertrait_vtable_slot
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs40
1 files changed, 30 insertions, 10 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index a2760fe6049..5aed55ef2d2 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -2,6 +2,8 @@ use std::fmt::Debug;
 use std::ops::ControlFlow;
 
 use rustc_hir::def_id::DefId;
+use rustc_infer::infer::{BoundRegionConversionTime, TyCtxtInferExt};
+use rustc_infer::traits::ObligationCause;
 use rustc_infer::traits::util::PredicateSet;
 use rustc_middle::bug;
 use rustc_middle::query::Providers;
@@ -13,7 +15,7 @@ use smallvec::{SmallVec, smallvec};
 use tracing::debug;
 
 use crate::errors::DumpVTableEntries;
-use crate::traits::{impossible_predicates, is_vtable_safe_method};
+use crate::traits::{ObligationCtxt, impossible_predicates, is_vtable_safe_method};
 
 #[derive(Clone, Debug)]
 pub enum VtblSegment<'tcx> {
@@ -383,17 +385,37 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
     let ty::Dynamic(target, _, _) = *target.kind() else {
         bug!();
     };
-    let target_principal = tcx
-        .normalize_erasing_regions(ty::ParamEnv::reveal_all(), target.principal()?)
-        .with_self_ty(tcx, tcx.types.trait_object_dummy_self);
+    let target_principal = target.principal()?.with_self_ty(tcx, tcx.types.trait_object_dummy_self);
 
     // Given that we have a target principal, it is a bug for there not to be a source principal.
     let ty::Dynamic(source, _, _) = *source.kind() else {
         bug!();
     };
-    let source_principal = tcx
-        .normalize_erasing_regions(ty::ParamEnv::reveal_all(), source.principal().unwrap())
-        .with_self_ty(tcx, tcx.types.trait_object_dummy_self);
+    let source_principal =
+        source.principal().unwrap().with_self_ty(tcx, tcx.types.trait_object_dummy_self);
+
+    let infcx = tcx.infer_ctxt().build();
+    let param_env = ty::ParamEnv::reveal_all();
+    let trait_refs_are_compatible =
+        |source: ty::PolyTraitRef<'tcx>, target: ty::PolyTraitRef<'tcx>| {
+            infcx.probe(|_| {
+                let ocx = ObligationCtxt::new(&infcx);
+                let source = ocx.normalize(&ObligationCause::dummy(), param_env, source);
+                let target = ocx.normalize(&ObligationCause::dummy(), param_env, target);
+                infcx.enter_forall(target, |target| {
+                    let source = infcx.instantiate_binder_with_fresh_vars(
+                        DUMMY_SP,
+                        BoundRegionConversionTime::HigherRankedType,
+                        source,
+                    );
+                    let Ok(()) = ocx.eq(&ObligationCause::dummy(), param_env, target, source)
+                    else {
+                        return false;
+                    };
+                    ocx.select_all_or_error().is_empty()
+                })
+            })
+        };
 
     let vtable_segment_callback = {
         let mut vptr_offset = 0;
@@ -404,9 +426,7 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
                 }
                 VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
                     vptr_offset += tcx.own_existential_vtable_entries(trait_ref.def_id()).len();
-                    if tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), trait_ref)
-                        == target_principal
-                    {
+                    if trait_refs_are_compatible(trait_ref, target_principal) {
                         if emit_vptr {
                             return ControlFlow::Break(Some(vptr_offset));
                         } else {