diff options
Diffstat (limited to 'compiler')
37 files changed, 342 insertions, 402 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 3e7b81a96b6..425b2adf32a 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -6,7 +6,7 @@ use cranelift_module::*; use rustc_data_structures::fx::FxHashSet; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::interpret::{AllocId, GlobalAlloc, Scalar, read_target_uint}; -use rustc_middle::ty::{Binder, ExistentialTraitRef, ScalarInt}; +use rustc_middle::ty::{ExistentialTraitRef, ScalarInt}; use crate::prelude::*; @@ -167,7 +167,9 @@ pub(crate) fn codegen_const_value<'tcx>( &mut fx.constants_cx, fx.module, ty, - dyn_ty.principal(), + dyn_ty.principal().map(|principal| { + fx.tcx.instantiate_bound_regions_with_erased(principal) + }), ); let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func); @@ -243,7 +245,7 @@ pub(crate) fn data_id_for_vtable<'tcx>( cx: &mut ConstantCx, module: &mut dyn Module, ty: Ty<'tcx>, - trait_ref: Option<Binder<'tcx, ExistentialTraitRef<'tcx>>>, + trait_ref: Option<ExistentialTraitRef<'tcx>>, ) -> DataId { let alloc_id = tcx.vtable_allocation((ty, trait_ref)); data_id_for_alloc_id(cx, module, alloc_id, Mutability::Not) @@ -460,9 +462,15 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant GlobalAlloc::Memory(target_alloc) => { data_id_for_alloc_id(cx, module, alloc_id, target_alloc.inner().mutability) } - GlobalAlloc::VTable(ty, dyn_ty) => { - data_id_for_vtable(tcx, cx, module, ty, dyn_ty.principal()) - } + GlobalAlloc::VTable(ty, dyn_ty) => data_id_for_vtable( + tcx, + cx, + module, + ty, + dyn_ty + .principal() + .map(|principal| tcx.instantiate_bound_regions_with_erased(principal)), + ), GlobalAlloc::Static(def_id) => { if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) { diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs index 2843e5bbdfb..f8bbb214920 100644 --- a/compiler/rustc_codegen_cranelift/src/unsize.rs +++ b/compiler/rustc_codegen_cranelift/src/unsize.rs @@ -61,7 +61,12 @@ pub(crate) fn unsized_info<'tcx>( old_info } } - (_, ty::Dynamic(data, ..)) => crate::vtable::get_vtable(fx, source, data.principal()), + (_, ty::Dynamic(data, ..)) => crate::vtable::get_vtable( + fx, + source, + data.principal() + .map(|principal| fx.tcx.instantiate_bound_regions_with_erased(principal)), + ), _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", source, target), } } diff --git a/compiler/rustc_codegen_cranelift/src/vtable.rs b/compiler/rustc_codegen_cranelift/src/vtable.rs index 82b6178be9d..a460023b59c 100644 --- a/compiler/rustc_codegen_cranelift/src/vtable.rs +++ b/compiler/rustc_codegen_cranelift/src/vtable.rs @@ -90,7 +90,7 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>( pub(crate) fn get_vtable<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>, - trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>, + trait_ref: Option<ty::ExistentialTraitRef<'tcx>>, ) -> Value { let data_id = data_id_for_vtable(fx.tcx, &mut fx.constants_cx, fx.module, ty, trait_ref); let local_data_id = fx.module.declare_data_in_func(data_id, fx.bcx.func); diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index bd5d6ba387c..20a3482aaa2 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -234,7 +234,12 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { GlobalAlloc::VTable(ty, dyn_ty) => { let alloc = self .tcx - .global_alloc(self.tcx.vtable_allocation((ty, dyn_ty.principal()))) + .global_alloc(self.tcx.vtable_allocation(( + ty, + dyn_ty.principal().map(|principal| { + self.tcx.instantiate_bound_regions_with_erased(principal) + }), + ))) .unwrap_memory(); let init = const_alloc_to_gcc(self, alloc); self.static_addr_of(init, alloc.inner().align, None) diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 30732c74eb3..570ef938dc4 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -14,7 +14,7 @@ use rustc_middle::ty::layout::{ FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers, }; -use rustc_middle::ty::{self, Instance, PolyExistentialTraitRef, Ty, TyCtxt}; +use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt}; use rustc_session::Session; use rustc_span::source_map::respan; use rustc_span::{DUMMY_SP, Span}; @@ -90,7 +90,7 @@ pub struct CodegenCx<'gcc, 'tcx> { pub function_instances: RefCell<FxHashMap<Instance<'tcx>, Function<'gcc>>>, /// Cache generated vtables pub vtables: - RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>>, + RefCell<FxHashMap<(Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), RValue<'gcc>>>, // TODO(antoyo): improve the SSA API to not require those. /// Mapping from function pointer type to indexes of on stack parameters. @@ -401,7 +401,7 @@ impl<'gcc, 'tcx> BackendTypes for CodegenCx<'gcc, 'tcx> { impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn vtables( &self, - ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>> { + ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ExistentialTraitRef<'tcx>>), RValue<'gcc>>> { &self.vtables } diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs index 4b84b1dbfd3..86d3de225f7 100644 --- a/compiler/rustc_codegen_gcc/src/debuginfo.rs +++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs @@ -7,7 +7,7 @@ use rustc_data_structures::sync::Lrc; use rustc_index::bit_set::DenseBitSet; use rustc_index::{Idx, IndexVec}; use rustc_middle::mir::{self, Body, SourceScope}; -use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty}; +use rustc_middle::ty::{ExistentialTraitRef, Instance, Ty}; use rustc_session::config::DebugInfo; use rustc_span::{BytePos, Pos, SourceFile, SourceFileAndLine, Span, Symbol}; use rustc_target::abi::Size; @@ -214,7 +214,7 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn create_vtable_debuginfo( &self, _ty: Ty<'tcx>, - _trait_ref: Option<PolyExistentialTraitRef<'tcx>>, + _trait_ref: Option<ExistentialTraitRef<'tcx>>, _vtable: Self::Value, ) { // TODO(antoyo) diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index f8b30cb507a..8c94a46ebf3 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -314,7 +314,12 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { GlobalAlloc::VTable(ty, dyn_ty) => { let alloc = self .tcx - .global_alloc(self.tcx.vtable_allocation((ty, dyn_ty.principal()))) + .global_alloc(self.tcx.vtable_allocation(( + ty, + dyn_ty.principal().map(|principal| { + self.tcx.instantiate_bound_regions_with_erased(principal) + }), + ))) .unwrap_memory(); let init = const_alloc_to_llvm(self, alloc, /*static*/ false); let value = self.static_addr_of_impl(init, alloc.inner().align, None); diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 79381f35a3c..ba4fd75fb94 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -77,8 +77,7 @@ pub(crate) struct CodegenCx<'ll, 'tcx> { /// Cache instances of monomorphic and polymorphic items pub instances: RefCell<FxHashMap<Instance<'tcx>, &'ll Value>>, /// Cache generated vtables - pub vtables: - RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), &'ll Value>>, + pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), &'ll Value>>, /// Cache of constant strings, pub const_str_cache: RefCell<FxHashMap<String, &'ll Value>>, @@ -663,15 +662,14 @@ impl<'ll> SimpleCx<'ll> { impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn vtables( &self, - ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), &'ll Value>> - { + ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), &'ll Value>> { &self.vtables } fn apply_vcall_visibility_metadata( &self, ty: Ty<'tcx>, - poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>, + poly_trait_ref: Option<ty::ExistentialTraitRef<'tcx>>, vtable: &'ll Value, ) { apply_vcall_visibility_metadata(self, ty, poly_trait_ref, vtable); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 6eae16d8be6..3a0c7f007bd 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -13,7 +13,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::bug; use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf, TyAndLayout}; use rustc_middle::ty::{ - self, AdtKind, CoroutineArgsExt, Instance, PolyExistentialTraitRef, Ty, TyCtxt, Visibility, + self, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility, }; use rustc_session::config::{self, DebugInfo, Lto}; use rustc_span::{DUMMY_SP, FileName, FileNameDisplayPreference, SourceFile, Symbol, hygiene}; @@ -1399,7 +1399,7 @@ pub(crate) fn build_global_var_di_node<'ll>( fn build_vtable_type_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, - poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>, + poly_trait_ref: Option<ty::ExistentialTraitRef<'tcx>>, ) -> &'ll DIType { let tcx = cx.tcx; @@ -1510,7 +1510,7 @@ fn find_vtable_behind_cast<'ll>(vtable: &'ll Value) -> &'ll Value { pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, - trait_ref: Option<PolyExistentialTraitRef<'tcx>>, + trait_ref: Option<ExistentialTraitRef<'tcx>>, vtable: &'ll Value, ) { // FIXME(flip1995): The virtual function elimination optimization only works with full LTO in @@ -1531,7 +1531,7 @@ pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>( let vtable = find_vtable_behind_cast(vtable); let trait_ref_self = trait_ref.with_self_ty(cx.tcx, ty); let trait_ref_self = cx.tcx.erase_regions(trait_ref_self); - let trait_def_id = trait_ref_self.def_id(); + let trait_def_id = trait_ref_self.def_id; let trait_vis = cx.tcx.visibility(trait_def_id); let cgus = cx.sess().codegen_units().as_usize(); @@ -1590,7 +1590,7 @@ pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>( pub(crate) fn create_vtable_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, - poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>, + poly_trait_ref: Option<ty::ExistentialTraitRef<'tcx>>, vtable: &'ll Value, ) { if cx.dbg_cx.is_none() { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs index a37e719d43f..af1d503ad6a 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_macros::HashStable; use rustc_middle::bug; -use rustc_middle::ty::{self, PolyExistentialTraitRef, Ty, TyCtxt}; +use rustc_middle::ty::{self, ExistentialTraitRef, Ty, TyCtxt}; use super::{DefinitionLocation, SmallVec, UNKNOWN_LINE_NUMBER, unknown_file_metadata}; use crate::common::{AsCCharPtr, CodegenCx}; @@ -44,7 +44,7 @@ pub(super) enum UniqueTypeId<'tcx> { /// The ID for the additional wrapper struct type describing an enum variant in CPP-like mode. VariantStructTypeCppLikeWrapper(Ty<'tcx>, VariantIdx, private::HiddenZst), /// The ID of the artificial type we create for VTables. - VTableTy(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>, private::HiddenZst), + VTableTy(Ty<'tcx>, Option<ExistentialTraitRef<'tcx>>, private::HiddenZst), } impl<'tcx> UniqueTypeId<'tcx> { @@ -88,7 +88,7 @@ impl<'tcx> UniqueTypeId<'tcx> { pub(crate) fn for_vtable_ty( tcx: TyCtxt<'tcx>, self_type: Ty<'tcx>, - implemented_trait: Option<PolyExistentialTraitRef<'tcx>>, + implemented_trait: Option<ExistentialTraitRef<'tcx>>, ) -> Self { assert_eq!( self_type, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 5089560784a..b1ce52667bd 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -588,7 +588,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn create_vtable_debuginfo( &self, ty: Ty<'tcx>, - trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>, + trait_ref: Option<ty::ExistentialTraitRef<'tcx>>, vtable: Self::Value, ) { metadata::create_vtable_di_node(self, ty, trait_ref, vtable) diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 83a9e6e2309..ee98c8c4861 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -25,7 +25,6 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_session::Session; use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType}; use rustc_span::{DUMMY_SP, Symbol, sym}; -use rustc_trait_selection::infer::at::ToTrace; use rustc_trait_selection::infer::{BoundRegionConversionTime, TyCtxtInferExt}; use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt}; use tracing::{debug, info}; @@ -129,14 +128,9 @@ pub fn validate_trivial_unsize<'tcx>( BoundRegionConversionTime::HigherRankedType, hr_source_principal, ); - let Ok(()) = ocx.eq_trace( + let Ok(()) = ocx.eq( &ObligationCause::dummy(), param_env, - ToTrace::to_trace( - &ObligationCause::dummy(), - hr_target_principal, - hr_source_principal, - ), target_principal, source_principal, ) else { @@ -211,7 +205,12 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( old_info } } - (_, ty::Dynamic(data, _, _)) => meth::get_vtable(cx, source, data.principal()), + (_, ty::Dynamic(data, _, _)) => meth::get_vtable( + cx, + source, + data.principal() + .map(|principal| bx.tcx().instantiate_bound_regions_with_erased(principal)), + ), _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", source, target), } } diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index d766ae37e5b..05175371591 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -507,7 +507,7 @@ pub enum VTableNameKind { pub fn compute_debuginfo_vtable_name<'tcx>( tcx: TyCtxt<'tcx>, t: Ty<'tcx>, - trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>, + trait_ref: Option<ty::ExistentialTraitRef<'tcx>>, kind: VTableNameKind, ) -> String { let cpp_like_debuginfo = cpp_like_debuginfo(tcx); @@ -530,8 +530,8 @@ pub fn compute_debuginfo_vtable_name<'tcx>( } if let Some(trait_ref) = trait_ref { - let trait_ref = tcx - .normalize_erasing_late_bound_regions(ty::TypingEnv::fully_monomorphized(), trait_ref); + let trait_ref = + tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), trait_ref); push_item_name(tcx, trait_ref.def_id, true, &mut vtable_name); visited.clear(); push_generic_params_internal(tcx, trait_ref.args, &mut vtable_name, &mut visited); diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs index 64cd4c38937..399c592432a 100644 --- a/compiler/rustc_codegen_ssa/src/meth.rs +++ b/compiler/rustc_codegen_ssa/src/meth.rs @@ -1,5 +1,5 @@ use rustc_middle::bug; -use rustc_middle::ty::{self, GenericArgKind, Ty}; +use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt}; use rustc_session::config::Lto; use rustc_symbol_mangling::typeid_for_trait_ref; use rustc_target::callconv::FnAbi; @@ -72,12 +72,19 @@ impl<'a, 'tcx> VirtualIndex { /// This takes a valid `self` receiver type and extracts the principal trait /// ref of the type. Return `None` if there is no principal trait. -fn dyn_trait_in_self(ty: Ty<'_>) -> Option<ty::PolyExistentialTraitRef<'_>> { +fn dyn_trait_in_self<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, +) -> Option<ty::ExistentialTraitRef<'tcx>> { for arg in ty.peel_refs().walk() { if let GenericArgKind::Type(ty) = arg.unpack() && let ty::Dynamic(data, _, _) = ty.kind() { - return data.principal(); + // FIXME(arbitrary_self_types): This is likely broken for receivers which + // have a "non-self" trait objects as a generic argument. + return data + .principal() + .map(|principal| tcx.instantiate_bound_regions_with_erased(principal)); } } @@ -96,7 +103,7 @@ fn dyn_trait_in_self(ty: Ty<'_>) -> Option<ty::PolyExistentialTraitRef<'_>> { pub(crate) fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( cx: &Cx, ty: Ty<'tcx>, - trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>, + trait_ref: Option<ty::ExistentialTraitRef<'tcx>>, ) -> Cx::Value { let tcx = cx.tcx(); @@ -131,7 +138,7 @@ pub(crate) fn load_vtable<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( if bx.cx().sess().opts.unstable_opts.virtual_function_elimination && bx.cx().sess().lto() == Lto::Fat { - if let Some(trait_ref) = dyn_trait_in_self(ty) { + if let Some(trait_ref) = dyn_trait_in_self(bx.tcx(), ty) { let typeid = bx.typeid_metadata(typeid_for_trait_ref(bx.tcx(), trait_ref)).unwrap(); let func = bx.type_checked_load(llvtable, vtable_byte_offset, typeid); return func; diff --git a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs index fe135e911fb..30d77c206a5 100644 --- a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs @@ -2,7 +2,7 @@ use std::ops::Range; use rustc_abi::Size; use rustc_middle::mir; -use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty}; +use rustc_middle::ty::{ExistentialTraitRef, Instance, Ty}; use rustc_span::{SourceFile, Span, Symbol}; use rustc_target::callconv::FnAbi; @@ -13,7 +13,7 @@ pub trait DebugInfoCodegenMethods<'tcx>: BackendTypes { fn create_vtable_debuginfo( &self, ty: Ty<'tcx>, - trait_ref: Option<PolyExistentialTraitRef<'tcx>>, + trait_ref: Option<ExistentialTraitRef<'tcx>>, vtable: Self::Value, ); diff --git a/compiler/rustc_codegen_ssa/src/traits/misc.rs b/compiler/rustc_codegen_ssa/src/traits/misc.rs index 5b33fd7ab10..4004947b464 100644 --- a/compiler/rustc_codegen_ssa/src/traits/misc.rs +++ b/compiler/rustc_codegen_ssa/src/traits/misc.rs @@ -10,11 +10,11 @@ use super::BackendTypes; pub trait MiscCodegenMethods<'tcx>: BackendTypes { fn vtables( &self, - ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), Self::Value>>; + ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), Self::Value>>; fn apply_vcall_visibility_metadata( &self, _ty: Ty<'tcx>, - _poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>, + _poly_trait_ref: Option<ty::ExistentialTraitRef<'tcx>>, _vtable: Self::Value, ) { } diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index e6a34193c9d..e2e6e16d8a7 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -5,6 +5,7 @@ use std::borrow::Cow; use either::{Left, Right}; use rustc_abi::{self as abi, ExternAbi, FieldIdx, Integer, VariantIdx}; +use rustc_hir::def_id::DefId; use rustc_middle::ty::layout::{FnAbiOf, IntegerExt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, AdtDef, Instance, Ty, VariantDef}; use rustc_middle::{bug, mir, span_bug}; @@ -693,25 +694,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { trace!("Virtual call dispatches to {fn_inst:#?}"); // We can also do the lookup based on `def_id` and `dyn_ty`, and check that that // produces the same result. - if cfg!(debug_assertions) { - let tcx = *self.tcx; - - let trait_def_id = tcx.trait_of_item(def_id).unwrap(); - let virtual_trait_ref = - ty::TraitRef::from_method(tcx, trait_def_id, instance.args); - let existential_trait_ref = - ty::ExistentialTraitRef::erase_self_ty(tcx, virtual_trait_ref); - let concrete_trait_ref = existential_trait_ref.with_self_ty(tcx, dyn_ty); - - let concrete_method = Instance::expect_resolve_for_vtable( - tcx, - self.typing_env, - def_id, - instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args), - self.cur_span(), - ); - assert_eq!(fn_inst, concrete_method); - } + self.assert_virtual_instance_matches_concrete(dyn_ty, def_id, instance, fn_inst); // Adjust receiver argument. Layout can be any (thin) ptr. let receiver_ty = Ty::new_mut_ptr(self.tcx.tcx, dyn_ty); @@ -744,6 +727,30 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } } + fn assert_virtual_instance_matches_concrete( + &self, + dyn_ty: Ty<'tcx>, + def_id: DefId, + virtual_instance: ty::Instance<'tcx>, + concrete_instance: ty::Instance<'tcx>, + ) { + let tcx = *self.tcx; + + let trait_def_id = tcx.trait_of_item(def_id).unwrap(); + let virtual_trait_ref = ty::TraitRef::from_method(tcx, trait_def_id, virtual_instance.args); + let existential_trait_ref = ty::ExistentialTraitRef::erase_self_ty(tcx, virtual_trait_ref); + let concrete_trait_ref = existential_trait_ref.with_self_ty(tcx, dyn_ty); + + let concrete_method = Instance::expect_resolve_for_vtable( + tcx, + self.typing_env, + def_id, + virtual_instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args), + self.cur_span(), + ); + assert_eq!(concrete_instance, concrete_method); + } + /// Initiate a tail call to this function -- popping the current stack frame, pushing the new /// stack frame and initializing the arguments. pub(super) fn init_fn_tail_call( diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index ef3e96784ce..e110c155da0 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -414,36 +414,33 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // Sanity-check that `supertrait_vtable_slot` in this type's vtable indeed produces // our destination trait. - if cfg!(debug_assertions) { - let vptr_entry_idx = - self.tcx.supertrait_vtable_slot((src_pointee_ty, dest_pointee_ty)); - let vtable_entries = self.vtable_entries(data_a.principal(), ty); - if let Some(entry_idx) = vptr_entry_idx { - let Some(&ty::VtblEntry::TraitVPtr(upcast_trait_ref)) = - vtable_entries.get(entry_idx) - else { - span_bug!( - self.cur_span(), - "invalid vtable entry index in {} -> {} upcast", - src_pointee_ty, - dest_pointee_ty - ); - }; - let erased_trait_ref = upcast_trait_ref - .map_bound(|r| ty::ExistentialTraitRef::erase_self_ty(*self.tcx, r)); - assert!( - data_b - .principal() - .is_some_and(|b| self.eq_in_param_env(erased_trait_ref, b)) + let vptr_entry_idx = + self.tcx.supertrait_vtable_slot((src_pointee_ty, dest_pointee_ty)); + let vtable_entries = self.vtable_entries(data_a.principal(), ty); + if let Some(entry_idx) = vptr_entry_idx { + let Some(&ty::VtblEntry::TraitVPtr(upcast_trait_ref)) = + vtable_entries.get(entry_idx) + else { + span_bug!( + self.cur_span(), + "invalid vtable entry index in {} -> {} upcast", + src_pointee_ty, + dest_pointee_ty ); - } else { - // In this case codegen would keep using the old vtable. We don't want to do - // that as it has the wrong trait. The reason codegen can do this is that - // one vtable is a prefix of the other, so we double-check that. - let vtable_entries_b = self.vtable_entries(data_b.principal(), ty); - assert!(&vtable_entries[..vtable_entries_b.len()] == vtable_entries_b); }; - } + let erased_trait_ref = + ty::ExistentialTraitRef::erase_self_ty(*self.tcx, upcast_trait_ref); + assert!(data_b.principal().is_some_and(|b| self.eq_in_param_env( + erased_trait_ref, + self.tcx.instantiate_bound_regions_with_erased(b) + ))); + } else { + // In this case codegen would keep using the old vtable. We don't want to do + // that as it has the wrong trait. The reason codegen can do this is that + // one vtable is a prefix of the other, so we double-check that. + let vtable_entries_b = self.vtable_entries(data_b.principal(), ty); + assert!(&vtable_entries[..vtable_entries_b.len()] == vtable_entries_b); + }; // Get the destination trait vtable and return that. let new_vptr = self.get_vtable_ptr(ty, data_b)?; diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs index af8d618b6b5..4cfaacebfcd 100644 --- a/compiler/rustc_const_eval/src/interpret/traits.rs +++ b/compiler/rustc_const_eval/src/interpret/traits.rs @@ -54,7 +54,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ) -> &'tcx [VtblEntry<'tcx>] { if let Some(trait_) = trait_ { let trait_ref = trait_.with_self_ty(*self.tcx, dyn_ty); - let trait_ref = self.tcx.erase_regions(trait_ref); + let trait_ref = + self.tcx.erase_regions(self.tcx.instantiate_bound_regions_with_erased(trait_ref)); self.tcx.vtable_entries(trait_ref) } else { TyCtxt::COMMON_VTABLE_ENTRIES diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 17433eed9e7..684fc5e37e0 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -1136,7 +1136,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), rustc_attr!( TEST, rustc_dump_vtable, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::Yes + WarnFollowing, EncodeCrossCrate::No ), rustc_attr!( TEST, rustc_dummy, Normal, template!(Word /* doesn't matter*/), diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs index f1022d95753..4a508fc0cf6 100644 --- a/compiler/rustc_hir_analysis/src/collect/dump.rs +++ b/compiler/rustc_hir_analysis/src/collect/dump.rs @@ -1,7 +1,8 @@ +use rustc_hir as hir; use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; use rustc_hir::intravisit; use rustc_middle::hir::nested_filter; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_span::sym; pub(crate) fn opaque_hidden_types(tcx: TyCtxt<'_>) { @@ -87,3 +88,82 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) { } } } + +pub(crate) fn vtables<'tcx>(tcx: TyCtxt<'tcx>) { + for id in tcx.hir().items() { + let def_id = id.owner_id.def_id; + + let Some(attr) = tcx.get_attr(def_id, sym::rustc_dump_vtable) else { + continue; + }; + + let vtable_entries = match tcx.hir().item(id).kind { + hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) => { + let trait_ref = tcx.impl_trait_ref(def_id).unwrap().instantiate_identity(); + if trait_ref.has_non_region_param() { + tcx.dcx().span_err( + attr.span, + "`rustc_dump_vtable` must be applied to non-generic impl", + ); + continue; + } + if !tcx.is_dyn_compatible(trait_ref.def_id) { + tcx.dcx().span_err( + attr.span, + "`rustc_dump_vtable` must be applied to dyn-compatible trait", + ); + continue; + } + let Ok(trait_ref) = tcx + .try_normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), trait_ref) + else { + tcx.dcx().span_err( + attr.span, + "`rustc_dump_vtable` applied to impl header that cannot be normalized", + ); + continue; + }; + tcx.vtable_entries(trait_ref) + } + hir::ItemKind::TyAlias(_, _) => { + let ty = tcx.type_of(def_id).instantiate_identity(); + if ty.has_non_region_param() { + tcx.dcx().span_err( + attr.span, + "`rustc_dump_vtable` must be applied to non-generic type", + ); + continue; + } + let Ok(ty) = + tcx.try_normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty) + else { + tcx.dcx().span_err( + attr.span, + "`rustc_dump_vtable` applied to type alias that cannot be normalized", + ); + continue; + }; + let ty::Dynamic(data, _, _) = *ty.kind() else { + tcx.dcx().span_err(attr.span, "`rustc_dump_vtable` to type alias of dyn type"); + continue; + }; + if let Some(principal) = data.principal() { + tcx.vtable_entries( + tcx.instantiate_bound_regions_with_erased(principal).with_self_ty(tcx, ty), + ) + } else { + TyCtxt::COMMON_VTABLE_ENTRIES + } + } + _ => { + tcx.dcx().span_err( + attr.span, + "`rustc_dump_vtable` only applies to impl, or type alias of dyn type", + ); + continue; + } + }; + + tcx.dcx().span_err(tcx.def_span(def_id), format!("vtable entries: {vtable_entries:#?}")); + } +} diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index bc7d4365eee..03dd0cccf75 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -152,11 +152,14 @@ pub fn check_crate(tcx: TyCtxt<'_>) { }); if tcx.features().rustc_attrs() { - tcx.sess.time("outlives_dumping", || outlives::dump::inferred_outlives(tcx)); - tcx.sess.time("variance_dumping", || variance::dump::variances(tcx)); - collect::dump::opaque_hidden_types(tcx); - collect::dump::predicates_and_item_bounds(tcx); - collect::dump::def_parents(tcx); + tcx.sess.time("dumping_rustc_attr_data", || { + outlives::dump::inferred_outlives(tcx); + variance::dump::variances(tcx); + collect::dump::opaque_hidden_types(tcx); + collect::dump::predicates_and_item_bounds(tcx); + collect::dump::def_parents(tcx); + collect::dump::vtables(tcx); + }); } // Make sure we evaluate all static and (non-associated) const items, even if unused. diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 12e2bbc968f..ad15b764bcc 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -402,6 +402,18 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialTraitRef<'tcx> { } } +impl<'tcx> ToTrace<'tcx> for ty::ExistentialTraitRef<'tcx> { + fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { + TypeTrace { + cause: cause.clone(), + values: ValuePairs::ExistentialTraitRef(ExpectedFound::new( + ty::Binder::dummy(a), + ty::Binder::dummy(b), + )), + } + } +} + impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialProjection<'tcx> { fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { TypeTrace { @@ -410,3 +422,15 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialProjection<'tcx> { } } } + +impl<'tcx> ToTrace<'tcx> for ty::ExistentialProjection<'tcx> { + fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { + TypeTrace { + cause: cause.clone(), + values: ValuePairs::ExistentialProjection(ExpectedFound::new( + ty::Binder::dummy(a), + ty::Binder::dummy(b), + )), + } + } +} diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 241bc35857a..0b91c023cfc 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -26,7 +26,6 @@ use rustc_parse::{ }; use rustc_passes::{abi_test, input_stats, layout_test}; use rustc_resolve::Resolver; -use rustc_session::code_stats::VTableSizeInfo; use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType}; use rustc_session::cstore::Untracked; use rustc_session::output::{collect_crate_types, filename_for_input, find_crate_name}; @@ -989,90 +988,6 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) { // we will fail to emit overlap diagnostics. Thus we invoke it here unconditionally. let _ = tcx.all_diagnostic_items(()); }); - - if sess.opts.unstable_opts.print_vtable_sizes { - let traits = tcx.traits(LOCAL_CRATE); - - for &tr in traits { - if !tcx.is_dyn_compatible(tr) { - continue; - } - - let name = ty::print::with_no_trimmed_paths!(tcx.def_path_str(tr)); - - let mut first_dsa = true; - - // Number of vtable entries, if we didn't have upcasting - let mut entries_ignoring_upcasting = 0; - // Number of vtable entries needed solely for upcasting - let mut entries_for_upcasting = 0; - - let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, tr)); - - // A slightly edited version of the code in - // `rustc_trait_selection::traits::vtable::vtable_entries`, that works without self - // type and just counts number of entries. - // - // Note that this is technically wrong, for traits which have associated types in - // supertraits: - // - // trait A: AsRef<Self::T> + AsRef<()> { type T; } - // - // Without self type we can't normalize `Self::T`, so we can't know if `AsRef<Self::T>` - // and `AsRef<()>` are the same trait, thus we assume that those are different, and - // potentially over-estimate how many vtable entries there are. - // - // Similarly this is wrong for traits that have methods with possibly-impossible bounds. - // For example: - // - // trait B<T> { fn f(&self) where T: Copy; } - // - // Here `dyn B<u8>` will have 4 entries, while `dyn B<String>` will only have 3. - // However, since we don't know `T`, we can't know if `T: Copy` holds or not, - // thus we lean on the bigger side and say it has 4 entries. - traits::vtable::prepare_vtable_segments(tcx, trait_ref, |segment| { - match segment { - traits::vtable::VtblSegment::MetadataDSA => { - // If this is the first dsa, it would be included either way, - // otherwise it's needed for upcasting - if std::mem::take(&mut first_dsa) { - entries_ignoring_upcasting += 3; - } else { - entries_for_upcasting += 3; - } - } - - traits::vtable::VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => { - // Lookup the shape of vtable for the trait. - let own_existential_entries = - tcx.own_existential_vtable_entries(trait_ref.def_id()); - - // The original code here ignores the method if its predicates are - // impossible. We can't really do that as, for example, all not trivial - // bounds on generic parameters are impossible (since we don't know the - // parameters...), see the comment above. - entries_ignoring_upcasting += own_existential_entries.len(); - - if emit_vptr { - entries_for_upcasting += 1; - } - } - } - - std::ops::ControlFlow::Continue::<std::convert::Infallible>(()) - }); - - sess.code_stats.record_vtable_size(tr, &name, VTableSizeInfo { - trait_name: name.clone(), - entries: entries_ignoring_upcasting + entries_for_upcasting, - entries_ignoring_upcasting, - entries_for_upcasting, - upcasting_cost_percent: entries_for_upcasting as f64 - / entries_ignoring_upcasting as f64 - * 100., - }) - } - } } /// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used @@ -1153,12 +1068,6 @@ pub(crate) fn start_codegen<'tcx>( tcx.sess.code_stats.print_type_sizes(); } - if tcx.sess.opts.unstable_opts.print_vtable_sizes { - let crate_name = tcx.crate_name(LOCAL_CRATE); - - tcx.sess.code_stats.print_vtable_sizes(crate_name); - } - codegen } diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index f7090fa69e2..949d8303385 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -95,7 +95,7 @@ impl<'tcx> Key for mir::interpret::GlobalId<'tcx> { } } -impl<'tcx> Key for (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>) { +impl<'tcx> Key for (Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>) { type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _: TyCtxt<'_>) -> Span { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 560e3bf3ade..41e9858030c 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1437,9 +1437,9 @@ rustc_queries! { desc { |tcx| "finding all existential vtable entries for trait `{}`", tcx.def_path_str(key) } } - query vtable_entries(key: ty::PolyTraitRef<'tcx>) + query vtable_entries(key: ty::TraitRef<'tcx>) -> &'tcx [ty::VtblEntry<'tcx>] { - desc { |tcx| "finding all vtable entries for trait `{}`", tcx.def_path_str(key.def_id()) } + desc { |tcx| "finding all vtable entries for trait `{}`", tcx.def_path_str(key.def_id) } } query first_method_vtable_slot(key: ty::TraitRef<'tcx>) -> usize { @@ -1451,7 +1451,7 @@ rustc_queries! { key.1, key.0 } } - query vtable_allocation(key: (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>)) -> mir::interpret::AllocId { + query vtable_allocation(key: (Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>)) -> mir::interpret::AllocId { desc { |tcx| "vtable const allocation for <{} as {}>", key.0, key.1.map(|trait_ref| format!("{trait_ref}")).unwrap_or("_".to_owned()) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index b212992bd2d..3ced64b5b80 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -858,7 +858,12 @@ where } let mk_dyn_vtable = |principal: Option<ty::PolyExistentialTraitRef<'tcx>>| { - let min_count = ty::vtable_min_entries(tcx, principal); + let min_count = ty::vtable_min_entries( + tcx, + principal.map(|principal| { + tcx.instantiate_bound_regions_with_erased(principal) + }), + ); Ty::new_imm_ref( tcx, tcx.lifetimes.re_static, diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index 455bd16ff8c..6c9e0e7c0eb 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -7,7 +7,7 @@ use rustc_type_ir::elaborate; use crate::mir::interpret::{ AllocId, AllocInit, Allocation, CTFE_ALLOC_SALT, Pointer, Scalar, alloc_range, }; -use crate::ty::{self, Instance, PolyTraitRef, Ty, TyCtxt}; +use crate::ty::{self, Instance, TraitRef, Ty, TyCtxt}; #[derive(Clone, Copy, PartialEq, HashStable)] pub enum VtblEntry<'tcx> { @@ -22,7 +22,7 @@ pub enum VtblEntry<'tcx> { /// dispatchable associated function Method(Instance<'tcx>), /// pointer to a separate supertrait vtable, can be used by trait upcasting coercion - TraitVPtr(PolyTraitRef<'tcx>), + TraitVPtr(TraitRef<'tcx>), } impl<'tcx> fmt::Debug for VtblEntry<'tcx> { @@ -59,7 +59,7 @@ pub const COMMON_VTABLE_ENTRIES_ALIGN: usize = 2; // function is an accurate approximation. We verify this when actually computing the vtable below. pub(crate) fn vtable_min_entries<'tcx>( tcx: TyCtxt<'tcx>, - trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>, + trait_ref: Option<ty::ExistentialTraitRef<'tcx>>, ) -> usize { let mut count = TyCtxt::COMMON_VTABLE_ENTRIES.len(); let Some(trait_ref) = trait_ref else { @@ -67,7 +67,7 @@ pub(crate) fn vtable_min_entries<'tcx>( }; // This includes self in supertraits. - for def_id in elaborate::supertrait_def_ids(tcx, trait_ref.def_id()) { + for def_id in elaborate::supertrait_def_ids(tcx, trait_ref.def_id) { count += tcx.own_existential_vtable_entries(def_id).len(); } @@ -83,7 +83,7 @@ pub(crate) fn vtable_min_entries<'tcx>( /// initial contents.) pub(super) fn vtable_allocation_provider<'tcx>( tcx: TyCtxt<'tcx>, - key: (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), + key: (Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), ) -> AllocId { let (ty, poly_trait_ref) = key; @@ -118,7 +118,7 @@ pub(super) fn vtable_allocation_provider<'tcx>( for (idx, entry) in vtable_entries.iter().enumerate() { let idx: u64 = u64::try_from(idx).unwrap(); - let scalar = match entry { + let scalar = match *entry { VtblEntry::MetadataDropInPlace => { if ty.needs_drop(tcx, ty::TypingEnv::fully_monomorphized()) { let instance = ty::Instance::resolve_drop_in_place(tcx, ty); @@ -134,13 +134,12 @@ pub(super) fn vtable_allocation_provider<'tcx>( VtblEntry::Vacant => continue, VtblEntry::Method(instance) => { // Prepare the fn ptr we write into the vtable. - let fn_alloc_id = tcx.reserve_and_set_fn_alloc(*instance, CTFE_ALLOC_SALT); + let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance, CTFE_ALLOC_SALT); let fn_ptr = Pointer::from(fn_alloc_id); Scalar::from_pointer(fn_ptr, &tcx) } VtblEntry::TraitVPtr(trait_ref) => { - let super_trait_ref = trait_ref - .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)); + let super_trait_ref = ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref); let supertrait_alloc_id = tcx.vtable_allocation((ty, Some(super_trait_ref))); let vptr = Pointer::from(supertrait_alloc_id); Scalar::from_pointer(vptr, &tcx) diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index d53848f7461..150594ab94d 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1138,11 +1138,12 @@ fn create_mono_items_for_vtable_methods<'tcx>( bug!("create_mono_items_for_vtable_methods: {trait_ty:?} not a trait type"); }; if let Some(principal) = trait_ty.principal() { - let poly_trait_ref = principal.with_self_ty(tcx, impl_ty); - assert!(!poly_trait_ref.has_escaping_bound_vars()); + let trait_ref = + tcx.instantiate_bound_regions_with_erased(principal.with_self_ty(tcx, impl_ty)); + assert!(!trait_ref.has_escaping_bound_vars()); // Walk all methods of the trait, including those of its supertraits - let entries = tcx.vtable_entries(poly_trait_ref); + let entries = tcx.vtable_entries(trait_ref); debug!(?entries); let methods = entries .iter() @@ -1197,7 +1198,12 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt } } GlobalAlloc::VTable(ty, dyn_ty) => { - let alloc_id = tcx.vtable_allocation((ty, dyn_ty.principal())); + let alloc_id = tcx.vtable_allocation(( + ty, + dyn_ty + .principal() + .map(|principal| tcx.instantiate_bound_regions_with_erased(principal)), + )); collect_alloc(tcx, alloc_id, output) } } diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs index f3c21992784..b4597ae2515 100644 --- a/compiler/rustc_session/src/code_stats.rs +++ b/compiler/rustc_session/src/code_stats.rs @@ -1,10 +1,9 @@ use std::cmp; use rustc_abi::{Align, Size}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lock; use rustc_span::Symbol; -use rustc_span::def_id::DefId; #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub struct VariantInfo { @@ -71,29 +70,9 @@ pub struct TypeSizeInfo { pub variants: Vec<VariantInfo>, } -pub struct VTableSizeInfo { - pub trait_name: String, - - /// Number of entries in a vtable with the current algorithm - /// (i.e. with upcasting). - pub entries: usize, - - /// Number of entries in a vtable, as-if we did not have trait upcasting. - pub entries_ignoring_upcasting: usize, - - /// Number of entries in a vtable needed solely for upcasting - /// (i.e. `entries - entries_ignoring_upcasting`). - pub entries_for_upcasting: usize, - - /// Cost of having upcasting in % relative to the number of entries without - /// upcasting (i.e. `entries_for_upcasting / entries_ignoring_upcasting * 100%`). - pub upcasting_cost_percent: f64, -} - #[derive(Default)] pub struct CodeStats { type_sizes: Lock<FxHashSet<TypeSizeInfo>>, - vtable_sizes: Lock<FxHashMap<DefId, VTableSizeInfo>>, } impl CodeStats { @@ -127,14 +106,6 @@ impl CodeStats { self.type_sizes.borrow_mut().insert(info); } - pub fn record_vtable_size(&self, trait_did: DefId, trait_name: &str, info: VTableSizeInfo) { - let prev = self.vtable_sizes.lock().insert(trait_did, info); - assert!( - prev.is_none(), - "size of vtable for `{trait_name}` ({trait_did:?}) is already recorded" - ); - } - pub fn print_type_sizes(&self) { let type_sizes = self.type_sizes.borrow(); // We will soon sort, so the initial order does not matter. @@ -238,33 +209,4 @@ impl CodeStats { } } } - - pub fn print_vtable_sizes(&self, crate_name: Symbol) { - // We will soon sort, so the initial order does not matter. - #[allow(rustc::potential_query_instability)] - let mut infos = - std::mem::take(&mut *self.vtable_sizes.lock()).into_values().collect::<Vec<_>>(); - - // Primary sort: cost % in reverse order (from largest to smallest) - // Secondary sort: trait_name - infos.sort_by(|a, b| { - a.upcasting_cost_percent - .total_cmp(&b.upcasting_cost_percent) - .reverse() - .then_with(|| a.trait_name.cmp(&b.trait_name)) - }); - - for VTableSizeInfo { - trait_name, - entries, - entries_ignoring_upcasting, - entries_for_upcasting, - upcasting_cost_percent, - } in infos - { - println!( - r#"print-vtable-sizes {{ "crate_name": "{crate_name}", "trait_name": "{trait_name}", "entries": "{entries}", "entries_ignoring_upcasting": "{entries_ignoring_upcasting}", "entries_for_upcasting": "{entries_for_upcasting}", "upcasting_cost_percent": "{upcasting_cost_percent}" }}"# - ); - } - } } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index c7af40a8ad4..e3236350cad 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2034,8 +2034,6 @@ options! { Note that this overwrites the effect `-Clink-dead-code` has on collection!"), print_type_sizes: bool = (false, parse_bool, [UNTRACKED], "print layout information for each type encountered (default: no)"), - print_vtable_sizes: bool = (false, parse_bool, [UNTRACKED], - "print size comparison between old and new vtable layouts (default: no)"), proc_macro_backtrace: bool = (false, parse_bool, [UNTRACKED], "show backtraces for panics during proc-macro execution (default: no)"), proc_macro_execution_strategy: ProcMacroExecutionStrategy = (ProcMacroExecutionStrategy::SameThread, diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index 8d4e55dc036..cdc56782a26 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -747,7 +747,9 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let tcx = tables.tcx; let alloc_id = tables.tcx.vtable_allocation(( ty.internal(&mut *tables, tcx), - trait_ref.internal(&mut *tables, tcx), + trait_ref + .internal(&mut *tables, tcx) + .map(|principal| tcx.instantiate_bound_regions_with_erased(principal)), )); Some(alloc_id.stable(&mut *tables)) } diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 5c5ab435dbd..4312c82815c 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -151,7 +151,7 @@ fn symbol_name_provider<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> ty pub fn typeid_for_trait_ref<'tcx>( tcx: TyCtxt<'tcx>, - trait_ref: ty::PolyExistentialTraitRef<'tcx>, + trait_ref: ty::ExistentialTraitRef<'tcx>, ) -> String { v0::mangle_typeid_for_trait_ref(tcx, trait_ref) } diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 5b3272feecd..7b040a8b2c4 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -72,7 +72,7 @@ pub(super) fn mangle<'tcx>( pub(super) fn mangle_typeid_for_trait_ref<'tcx>( tcx: TyCtxt<'tcx>, - trait_ref: ty::PolyExistentialTraitRef<'tcx>, + trait_ref: ty::ExistentialTraitRef<'tcx>, ) -> String { // FIXME(flip1995): See comment in `mangle_typeid_for_fnabi`. let mut cx = SymbolMangler { @@ -84,7 +84,7 @@ pub(super) fn mangle_typeid_for_trait_ref<'tcx>( binders: vec![], out: String::new(), }; - cx.print_def_path(trait_ref.def_id(), &[]).unwrap(); + cx.print_def_path(trait_ref.def_id, &[]).unwrap(); std::mem::take(&mut cx.out) } diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl index 7c72318b4d7..055a3edcc32 100644 --- a/compiler/rustc_trait_selection/messages.ftl +++ b/compiler/rustc_trait_selection/messages.ftl @@ -148,8 +148,6 @@ trait_selection_dtcs_has_req_note = the used `impl` has a `'static` requirement trait_selection_dtcs_introduces_requirement = calling this method introduces the `impl`'s `'static` requirement trait_selection_dtcs_suggestion = consider relaxing the implicit `'static` requirement -trait_selection_dump_vtable_entries = vtable entries for `{$trait_ref}`: {$entries} - trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]` .label = empty on-clause here diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index c8672b9dbd2..c5ab8a71c78 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -12,7 +12,7 @@ use rustc_hir::intravisit::{Visitor, VisitorExt, walk_ty}; use rustc_hir::{self as hir, AmbigArg, FnRetTy, GenericParamKind, Node}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath}; -use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, PolyTraitRef, Region, Ty, TyCtxt}; +use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, Region, Ty, TyCtxt}; use rustc_span::{BytePos, Ident, Span, Symbol, kw}; use crate::error_reporting::infer::ObligationCauseAsDiagArg; @@ -23,15 +23,6 @@ use crate::fluent_generated as fluent; pub mod note_and_explain; #[derive(Diagnostic)] -#[diag(trait_selection_dump_vtable_entries)] -pub struct DumpVTableEntries<'a> { - #[primary_span] - pub span: Span, - pub trait_ref: PolyTraitRef<'a>, - pub entries: String, -} - -#[derive(Diagnostic)] #[diag(trait_selection_unable_to_construct_constant_value)] pub struct UnableToConstructConstantValue<'a> { #[primary_span] diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index b5bc8364c7b..000e6a765d3 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -2,26 +2,22 @@ use std::fmt::Debug; use std::ops::ControlFlow; use rustc_hir::def_id::DefId; -use rustc_infer::infer::at::ToTrace; -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; use rustc_middle::ty::{ self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, Upcast, VtblEntry, }; -use rustc_span::{DUMMY_SP, Span, sym}; +use rustc_span::DUMMY_SP; use smallvec::{SmallVec, smallvec}; use tracing::debug; -use crate::errors::DumpVTableEntries; -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> { MetadataDSA, - TraitOwnEntries { trait_ref: ty::PolyTraitRef<'tcx>, emit_vptr: bool }, + TraitOwnEntries { trait_ref: ty::TraitRef<'tcx>, emit_vptr: bool }, } /// Prepare the segments for a vtable @@ -29,7 +25,7 @@ pub enum VtblSegment<'tcx> { // about our `Self` type here. pub fn prepare_vtable_segments<'tcx, T>( tcx: TyCtxt<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, + trait_ref: ty::TraitRef<'tcx>, segment_visitor: impl FnMut(VtblSegment<'tcx>) -> ControlFlow<T>, ) -> Option<T> { prepare_vtable_segments_inner(tcx, trait_ref, segment_visitor).break_value() @@ -39,7 +35,7 @@ pub fn prepare_vtable_segments<'tcx, T>( /// such that we can use `?` in the body. fn prepare_vtable_segments_inner<'tcx, T>( tcx: TyCtxt<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, + trait_ref: ty::TraitRef<'tcx>, mut segment_visitor: impl FnMut(VtblSegment<'tcx>) -> ControlFlow<T>, ) -> ControlFlow<T> { // The following constraints holds for the final arrangement. @@ -92,7 +88,7 @@ fn prepare_vtable_segments_inner<'tcx, T>( let mut emit_vptr_on_new_entry = false; let mut visited = PredicateSet::new(tcx); let predicate = trait_ref.upcast(tcx); - let mut stack: SmallVec<[(ty::PolyTraitRef<'tcx>, _, _); 5]> = + let mut stack: SmallVec<[(ty::TraitRef<'tcx>, _, _); 5]> = smallvec![(trait_ref, emit_vptr_on_new_entry, maybe_iter(None))]; visited.insert(predicate); @@ -125,10 +121,18 @@ fn prepare_vtable_segments_inner<'tcx, T>( let &(inner_most_trait_ref, _, _) = stack.last().unwrap(); let mut direct_super_traits_iter = tcx - .explicit_super_predicates_of(inner_most_trait_ref.def_id()) + .explicit_super_predicates_of(inner_most_trait_ref.def_id) .iter_identity_copied() .filter_map(move |(pred, _)| { - pred.instantiate_supertrait(tcx, inner_most_trait_ref).as_trait_clause() + pred.instantiate_supertrait(tcx, ty::Binder::dummy(inner_most_trait_ref)) + .as_trait_clause() + }) + .map(move |pred| { + tcx.normalize_erasing_late_bound_regions( + ty::TypingEnv::fully_monomorphized(), + pred, + ) + .trait_ref }); // Find an unvisited supertrait @@ -136,16 +140,11 @@ fn prepare_vtable_segments_inner<'tcx, T>( .find(|&super_trait| visited.insert(super_trait.upcast(tcx))) { // Push it to the stack for the next iteration of 'diving_in to pick up - Some(unvisited_super_trait) => { - // We're throwing away potential constness of super traits here. - // FIXME: handle ~const super traits - let next_super_trait = unvisited_super_trait.map_bound(|t| t.trait_ref); - stack.push(( - next_super_trait, - emit_vptr_on_new_entry, - maybe_iter(Some(direct_super_traits_iter)), - )) - } + Some(next_super_trait) => stack.push(( + next_super_trait, + emit_vptr_on_new_entry, + maybe_iter(Some(direct_super_traits_iter)), + )), // There are no more unvisited direct super traits, dive-in finished None => break 'diving_in, @@ -154,8 +153,7 @@ fn prepare_vtable_segments_inner<'tcx, T>( // emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level. while let Some((inner_most_trait_ref, emit_vptr, mut siblings)) = stack.pop() { - let has_entries = - has_own_existential_vtable_entries(tcx, inner_most_trait_ref.def_id()); + let has_entries = has_own_existential_vtable_entries(tcx, inner_most_trait_ref.def_id); segment_visitor(VtblSegment::TraitOwnEntries { trait_ref: inner_most_trait_ref, @@ -169,11 +167,6 @@ fn prepare_vtable_segments_inner<'tcx, T>( if let Some(next_inner_most_trait_ref) = siblings.find(|&sibling| visited.insert(sibling.upcast(tcx))) { - // We're throwing away potential constness of super traits here. - // FIXME: handle ~const super traits - let next_inner_most_trait_ref = - next_inner_most_trait_ref.map_bound(|t| t.trait_ref); - stack.push((next_inner_most_trait_ref, emit_vptr_on_new_entry, siblings)); // just pushed a new trait onto the stack, so we need to go through its super traits @@ -192,15 +185,6 @@ fn maybe_iter<I: Iterator>(i: Option<I>) -> impl Iterator<Item = I::Item> { i.into_iter().flatten() } -fn dump_vtable_entries<'tcx>( - tcx: TyCtxt<'tcx>, - sp: Span, - trait_ref: ty::PolyTraitRef<'tcx>, - entries: &[VtblEntry<'tcx>], -) { - tcx.dcx().emit_err(DumpVTableEntries { span: sp, trait_ref, entries: format!("{entries:#?}") }); -} - fn has_own_existential_vtable_entries(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool { own_existential_vtable_entries_iter(tcx, trait_def_id).next().is_some() } @@ -239,8 +223,15 @@ fn own_existential_vtable_entries_iter( /// that come from `trait_ref`, including its supertraits. fn vtable_entries<'tcx>( tcx: TyCtxt<'tcx>, - trait_ref: ty::PolyTraitRef<'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); let mut entries = vec![]; @@ -251,33 +242,26 @@ fn vtable_entries<'tcx>( entries.extend(TyCtxt::COMMON_VTABLE_ENTRIES); } VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => { - let existential_trait_ref = trait_ref - .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)); + let existential_trait_ref = ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref); // Lookup the shape of vtable for the trait. let own_existential_entries = - tcx.own_existential_vtable_entries(existential_trait_ref.def_id()); + tcx.own_existential_vtable_entries(existential_trait_ref.def_id); let own_entries = own_existential_entries.iter().copied().map(|def_id| { debug!("vtable_entries: trait_method={:?}", def_id); // The method may have some early-bound lifetimes; add regions for those. - let args = trait_ref.map_bound(|trait_ref| { + // FIXME: Is this normalize needed? + let args = tcx.normalize_erasing_regions( + ty::TypingEnv::fully_monomorphized(), GenericArgs::for_item(tcx, def_id, |param, _| match param.kind { GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(), GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { trait_ref.args[param.index as usize] } - }) - }); - - // The trait type may have higher-ranked lifetimes in it; - // erase them if they appear, so that we get the type - // at some particular call site. - let args = tcx.normalize_erasing_late_bound_regions( - ty::TypingEnv::fully_monomorphized(), - args, + }), ); // It's possible that the method relies on where-clauses that @@ -317,11 +301,6 @@ fn vtable_entries<'tcx>( let _ = prepare_vtable_segments(tcx, trait_ref, vtable_segment_callback); - if tcx.has_attr(trait_ref.def_id(), sym::rustc_dump_vtable) { - let sp = tcx.def_span(trait_ref.def_id()); - dump_vtable_entries(tcx, sp, trait_ref, &entries); - } - tcx.arena.alloc_from_iter(entries) } @@ -329,14 +308,20 @@ 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!(); }; - let source_principal = - source.principal().unwrap().with_self_ty(tcx, tcx.types.trait_object_dummy_self); + let source_principal = tcx.instantiate_bound_regions_with_erased( + source.principal().unwrap().with_self_ty(tcx, tcx.types.trait_object_dummy_self), + ); - let target_principal = ty::Binder::dummy(ty::ExistentialTraitRef::erase_self_ty(tcx, key)); + let target_principal = ty::ExistentialTraitRef::erase_self_ty(tcx, key); let vtable_segment_callback = { let mut vptr_offset = 0; @@ -346,17 +331,14 @@ 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, - vtable_principal - .map_bound(|t| ty::ExistentialTraitRef::erase_self_ty(tcx, t)), - target_principal, - ) { + if ty::ExistentialTraitRef::erase_self_ty(tcx, vtable_principal) + == target_principal + { return ControlFlow::Break(vptr_offset); } vptr_offset += - tcx.own_existential_vtable_entries(vtable_principal.def_id()).len(); + tcx.own_existential_vtable_entries(vtable_principal.def_id).len(); if emit_vptr { vptr_offset += 1; @@ -382,20 +364,27 @@ 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`. let ty::Dynamic(target, _, _) = *target.kind() else { bug!(); }; - let target_principal = target.principal()?; + let target_principal = tcx.instantiate_bound_regions_with_erased(target.principal()?); // 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 = - source.principal().unwrap().with_self_ty(tcx, tcx.types.trait_object_dummy_self); + let source_principal = tcx.instantiate_bound_regions_with_erased( + source.principal().unwrap().with_self_ty(tcx, tcx.types.trait_object_dummy_self), + ); let vtable_segment_callback = { let mut vptr_offset = 0; @@ -406,13 +395,10 @@ 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, - vtable_principal - .map_bound(|t| ty::ExistentialTraitRef::erase_self_ty(tcx, t)), - target_principal, - ) { + tcx.own_existential_vtable_entries(vtable_principal.def_id).len(); + if ty::ExistentialTraitRef::erase_self_ty(tcx, vtable_principal) + == target_principal + { if emit_vptr { return ControlFlow::Break(Some(vptr_offset)); } else { @@ -432,41 +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>, - hr_vtable_principal: ty::PolyExistentialTraitRef<'tcx>, - hr_target_principal: ty::PolyExistentialTraitRef<'tcx>, -) -> bool { - if hr_vtable_principal.def_id() != hr_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 hr_source_principal = - ocx.normalize(&ObligationCause::dummy(), param_env, hr_vtable_principal); - let hr_target_principal = - ocx.normalize(&ObligationCause::dummy(), param_env, hr_target_principal); - infcx.enter_forall(hr_target_principal, |target_principal| { - let source_principal = infcx.instantiate_binder_with_fresh_vars( - DUMMY_SP, - BoundRegionConversionTime::HigherRankedType, - hr_source_principal, - ); - let Ok(()) = ocx.eq_trace( - &ObligationCause::dummy(), - param_env, - ToTrace::to_trace(&ObligationCause::dummy(), hr_target_principal, hr_source_principal), - 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, |
