about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src/traits/vtable.rs
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2025-01-11 19:31:28 +0000
committerMichael Goulet <michael@errs.io>2025-01-30 17:44:28 +0000
commitd98b99af56e1260f520102a93f198ffe47793722 (patch)
treea979e01fa24aa7e24982892e0ad70394b1c483a3 /compiler/rustc_trait_selection/src/traits/vtable.rs
parent9dc41a048d7dc765b28102d557eec40ff050e6ab (diff)
downloadrust-d98b99af56e1260f520102a93f198ffe47793722.tar.gz
rust-d98b99af56e1260f520102a93f198ffe47793722.zip
More assertions, tests, and miri coverage
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits/vtable.rs')
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs57
1 files changed, 23 insertions, 34 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index abdf5df6f72..000e6a765d3 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -2,8 +2,6 @@ use std::fmt::Debug;
 use std::ops::ControlFlow;
 
 use rustc_hir::def_id::DefId;
-use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits::ObligationCause;
 use rustc_infer::traits::util::PredicateSet;
 use rustc_middle::bug;
 use rustc_middle::query::Providers;
@@ -14,7 +12,7 @@ use rustc_span::DUMMY_SP;
 use smallvec::{SmallVec, smallvec};
 use tracing::debug;
 
-use crate::traits::{ObligationCtxt, impossible_predicates, is_vtable_safe_method};
+use crate::traits::{impossible_predicates, is_vtable_safe_method};
 
 #[derive(Clone, Debug)]
 pub enum VtblSegment<'tcx> {
@@ -228,6 +226,11 @@ fn vtable_entries<'tcx>(
     trait_ref: ty::TraitRef<'tcx>,
 ) -> &'tcx [VtblEntry<'tcx>] {
     debug_assert!(!trait_ref.has_non_region_infer() && !trait_ref.has_non_region_param());
+    debug_assert_eq!(
+        tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), trait_ref),
+        trait_ref,
+        "vtable trait ref should be normalized"
+    );
 
     debug!("vtable_entries({:?})", trait_ref);
 
@@ -305,6 +308,11 @@ fn vtable_entries<'tcx>(
 // for `Supertrait`'s methods in the vtable of `Subtrait`.
 pub(crate) fn first_method_vtable_slot<'tcx>(tcx: TyCtxt<'tcx>, key: ty::TraitRef<'tcx>) -> usize {
     debug_assert!(!key.has_non_region_infer() && !key.has_non_region_param());
+    debug_assert_eq!(
+        tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), key),
+        key,
+        "vtable trait ref should be normalized"
+    );
 
     let ty::Dynamic(source, _, _) = *key.self_ty().kind() else {
         bug!();
@@ -323,11 +331,9 @@ pub(crate) fn first_method_vtable_slot<'tcx>(tcx: TyCtxt<'tcx>, key: ty::TraitRe
                     vptr_offset += TyCtxt::COMMON_VTABLE_ENTRIES.len();
                 }
                 VtblSegment::TraitOwnEntries { trait_ref: vtable_principal, emit_vptr } => {
-                    if trait_refs_are_compatible(
-                        tcx,
-                        ty::ExistentialTraitRef::erase_self_ty(tcx, vtable_principal),
-                        target_principal,
-                    ) {
+                    if ty::ExistentialTraitRef::erase_self_ty(tcx, vtable_principal)
+                        == target_principal
+                    {
                         return ControlFlow::Break(vptr_offset);
                     }
 
@@ -358,6 +364,12 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
     ),
 ) -> Option<usize> {
     debug_assert!(!key.has_non_region_infer() && !key.has_non_region_param());
+    debug_assert_eq!(
+        tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), key),
+        key,
+        "upcasting trait refs should be normalized"
+    );
+
     let (source, target) = key;
 
     // If the target principal is `None`, we can just return `None`.
@@ -384,11 +396,9 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
                 VtblSegment::TraitOwnEntries { trait_ref: vtable_principal, emit_vptr } => {
                     vptr_offset +=
                         tcx.own_existential_vtable_entries(vtable_principal.def_id).len();
-                    if trait_refs_are_compatible(
-                        tcx,
-                        ty::ExistentialTraitRef::erase_self_ty(tcx, vtable_principal),
-                        target_principal,
-                    ) {
+                    if ty::ExistentialTraitRef::erase_self_ty(tcx, vtable_principal)
+                        == target_principal
+                    {
                         if emit_vptr {
                             return ControlFlow::Break(Some(vptr_offset));
                         } else {
@@ -408,27 +418,6 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
     prepare_vtable_segments(tcx, source_principal, vtable_segment_callback).unwrap()
 }
 
-fn trait_refs_are_compatible<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    vtable_principal: ty::ExistentialTraitRef<'tcx>,
-    target_principal: ty::ExistentialTraitRef<'tcx>,
-) -> bool {
-    if vtable_principal.def_id != target_principal.def_id {
-        return false;
-    }
-
-    let (infcx, param_env) =
-        tcx.infer_ctxt().build_with_typing_env(ty::TypingEnv::fully_monomorphized());
-    let ocx = ObligationCtxt::new(&infcx);
-    let source_principal = ocx.normalize(&ObligationCause::dummy(), param_env, vtable_principal);
-    let target_principal = ocx.normalize(&ObligationCause::dummy(), param_env, target_principal);
-    let Ok(()) = ocx.eq(&ObligationCause::dummy(), param_env, target_principal, source_principal)
-    else {
-        return false;
-    };
-    ocx.select_all_or_error().is_empty()
-}
-
 pub(super) fn provide(providers: &mut Providers) {
     *providers = Providers {
         own_existential_vtable_entries,