Skip to content

Commit 355bf65

Browse files
Do not treat vtable supertraits as distinct when bound with different bound vars
1 parent 62bf38f commit 355bf65

File tree

18 files changed

+151
-118
lines changed

18 files changed

+151
-118
lines changed

compiler/rustc_codegen_cranelift/src/constant.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,10 @@ pub(crate) fn data_id_for_vtable<'tcx>(
245245
ty: Ty<'tcx>,
246246
trait_ref: Option<Binder<'tcx, ExistentialTraitRef<'tcx>>>,
247247
) -> DataId {
248-
let alloc_id = tcx.vtable_allocation((ty, trait_ref));
248+
let alloc_id = tcx.vtable_allocation((
249+
ty,
250+
trait_ref.map(|principal| tcx.instantiate_bound_regions_with_erased(principal)),
251+
));
249252
data_id_for_alloc_id(cx, module, alloc_id, Mutability::Not)
250253
}
251254

compiler/rustc_codegen_gcc/src/common.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,12 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
229229
GlobalAlloc::VTable(ty, dyn_ty) => {
230230
let alloc = self
231231
.tcx
232-
.global_alloc(self.tcx.vtable_allocation((ty, dyn_ty.principal())))
232+
.global_alloc(self.tcx.vtable_allocation((
233+
ty,
234+
dyn_ty.principal().map(|principal| {
235+
self.tcx.instantiate_bound_regions_with_erased(principal)
236+
}),
237+
)))
233238
.unwrap_memory();
234239
let init = const_alloc_to_gcc(self, alloc);
235240
self.static_addr_of(init, alloc.inner().align, None)

compiler/rustc_codegen_llvm/src/common.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,12 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
308308
GlobalAlloc::VTable(ty, dyn_ty) => {
309309
let alloc = self
310310
.tcx
311-
.global_alloc(self.tcx.vtable_allocation((ty, dyn_ty.principal())))
311+
.global_alloc(self.tcx.vtable_allocation((
312+
ty,
313+
dyn_ty.principal().map(|principal| {
314+
self.tcx.instantiate_bound_regions_with_erased(principal)
315+
}),
316+
)))
312317
.unwrap_memory();
313318
let init = const_alloc_to_llvm(self, alloc, /*static*/ false);
314319
let value = self.static_addr_of(init, alloc.inner().align, None);

compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1406,7 +1406,7 @@ fn build_vtable_type_di_node<'ll, 'tcx>(
14061406

14071407
let vtable_entries = if let Some(poly_trait_ref) = poly_trait_ref {
14081408
let trait_ref = poly_trait_ref.with_self_ty(tcx, ty);
1409-
let trait_ref = tcx.erase_regions(trait_ref);
1409+
let trait_ref = tcx.erase_regions(tcx.instantiate_bound_regions_with_erased(trait_ref));
14101410

14111411
tcx.vtable_entries(trait_ref)
14121412
} else {

compiler/rustc_codegen_ssa/src/meth.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -96,24 +96,28 @@ fn dyn_trait_in_self(ty: Ty<'_>) -> Option<ty::PolyExistentialTraitRef<'_>> {
9696
pub(crate) fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
9797
cx: &Cx,
9898
ty: Ty<'tcx>,
99-
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
99+
poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
100100
) -> Cx::Value {
101101
let tcx = cx.tcx();
102102

103103
// Check the cache.
104-
if let Some(&val) = cx.vtables().borrow().get(&(ty, trait_ref)) {
104+
if let Some(&val) = cx.vtables().borrow().get(&(ty, poly_trait_ref)) {
105105
return val;
106106
}
107107

108+
// FIXME(trait_upcasting): Take a non-higher-ranked vtable as arg.
109+
let trait_ref =
110+
poly_trait_ref.map(|trait_ref| tcx.instantiate_bound_regions_with_erased(trait_ref));
111+
108112
let vtable_alloc_id = tcx.vtable_allocation((ty, trait_ref));
109113
let vtable_allocation = tcx.global_alloc(vtable_alloc_id).unwrap_memory();
110114
let vtable_const = cx.const_data_from_alloc(vtable_allocation);
111115
let align = cx.data_layout().pointer_align.abi;
112116
let vtable = cx.static_addr_of(vtable_const, align, Some("vtable"));
113117

114-
cx.apply_vcall_visibility_metadata(ty, trait_ref, vtable);
115-
cx.create_vtable_debuginfo(ty, trait_ref, vtable);
116-
cx.vtables().borrow_mut().insert((ty, trait_ref), vtable);
118+
cx.apply_vcall_visibility_metadata(ty, poly_trait_ref, vtable);
119+
cx.create_vtable_debuginfo(ty, poly_trait_ref, vtable);
120+
cx.vtables().borrow_mut().insert((ty, poly_trait_ref), vtable);
117121
vtable
118122
}
119123

compiler/rustc_const_eval/src/interpret/cast.rs

+1-9
Original file line numberDiff line numberDiff line change
@@ -419,8 +419,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
419419
self.tcx.supertrait_vtable_slot((src_pointee_ty, dest_pointee_ty));
420420
let vtable_entries = self.vtable_entries(data_a.principal(), ty);
421421
if let Some(entry_idx) = vptr_entry_idx {
422-
let Some(&ty::VtblEntry::TraitVPtr(upcast_trait_ref)) =
423-
vtable_entries.get(entry_idx)
422+
let Some(&ty::VtblEntry::TraitVPtr(_)) = vtable_entries.get(entry_idx)
424423
else {
425424
span_bug!(
426425
self.cur_span(),
@@ -429,13 +428,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
429428
dest_pointee_ty
430429
);
431430
};
432-
let erased_trait_ref = upcast_trait_ref
433-
.map_bound(|r| ty::ExistentialTraitRef::erase_self_ty(*self.tcx, r));
434-
assert!(
435-
data_b
436-
.principal()
437-
.is_some_and(|b| self.eq_in_param_env(erased_trait_ref, b))
438-
);
439431
} else {
440432
// In this case codegen would keep using the old vtable. We don't want to do
441433
// that as it has the wrong trait. The reason codegen can do this is that

compiler/rustc_const_eval/src/interpret/traits.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
5454
) -> &'tcx [VtblEntry<'tcx>] {
5555
if let Some(trait_) = trait_ {
5656
let trait_ref = trait_.with_self_ty(*self.tcx, dyn_ty);
57-
let trait_ref = self.tcx.erase_regions(trait_ref);
57+
let trait_ref =
58+
self.tcx.erase_regions(self.tcx.instantiate_bound_regions_with_erased(trait_ref));
5859
self.tcx.vtable_entries(trait_ref)
5960
} else {
6061
TyCtxt::COMMON_VTABLE_ENTRIES

compiler/rustc_interface/src/passes.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1003,7 +1003,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) {
10031003
// Number of vtable entries needed solely for upcasting
10041004
let mut entries_for_upcasting = 0;
10051005

1006-
let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, tr));
1006+
let trait_ref = ty::TraitRef::identity(tcx, tr);
10071007

10081008
// A slightly edited version of the code in
10091009
// `rustc_trait_selection::traits::vtable::vtable_entries`, that works without self
@@ -1041,7 +1041,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) {
10411041
traits::vtable::VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
10421042
// Lookup the shape of vtable for the trait.
10431043
let own_existential_entries =
1044-
tcx.own_existential_vtable_entries(trait_ref.def_id());
1044+
tcx.own_existential_vtable_entries(trait_ref.def_id);
10451045

10461046
// The original code here ignores the method if its predicates are
10471047
// impossible. We can't really do that as, for example, all not trivial

compiler/rustc_middle/src/query/keys.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ impl<'tcx> Key for mir::interpret::GlobalId<'tcx> {
9595
}
9696
}
9797

98-
impl<'tcx> Key for (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>) {
98+
impl<'tcx> Key for (Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>) {
9999
type Cache<V> = DefaultCache<Self, V>;
100100

101101
fn default_span(&self, _: TyCtxt<'_>) -> Span {

compiler/rustc_middle/src/query/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1435,9 +1435,9 @@ rustc_queries! {
14351435
desc { |tcx| "finding all existential vtable entries for trait `{}`", tcx.def_path_str(key) }
14361436
}
14371437

1438-
query vtable_entries(key: ty::PolyTraitRef<'tcx>)
1438+
query vtable_entries(key: ty::TraitRef<'tcx>)
14391439
-> &'tcx [ty::VtblEntry<'tcx>] {
1440-
desc { |tcx| "finding all vtable entries for trait `{}`", tcx.def_path_str(key.def_id()) }
1440+
desc { |tcx| "finding all vtable entries for trait `{}`", tcx.def_path_str(key.def_id) }
14411441
}
14421442

14431443
query first_method_vtable_slot(key: ty::TraitRef<'tcx>) -> usize {
@@ -1449,7 +1449,7 @@ rustc_queries! {
14491449
key.1, key.0 }
14501450
}
14511451

1452-
query vtable_allocation(key: (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>)) -> mir::interpret::AllocId {
1452+
query vtable_allocation(key: (Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>)) -> mir::interpret::AllocId {
14531453
desc { |tcx| "vtable const allocation for <{} as {}>",
14541454
key.0,
14551455
key.1.map(|trait_ref| format!("{trait_ref}")).unwrap_or("_".to_owned())

compiler/rustc_middle/src/ty/layout.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,12 @@ where
848848
}
849849

850850
let mk_dyn_vtable = |principal: Option<ty::PolyExistentialTraitRef<'tcx>>| {
851-
let min_count = ty::vtable_min_entries(tcx, principal);
851+
let min_count = ty::vtable_min_entries(
852+
tcx,
853+
principal.map(|principal| {
854+
tcx.instantiate_bound_regions_with_erased(principal)
855+
}),
856+
);
852857
Ty::new_imm_ref(
853858
tcx,
854859
tcx.lifetimes.re_static,

compiler/rustc_middle/src/ty/vtable.rs

+8-9
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_ast::Mutability;
44
use rustc_macros::HashStable;
55

66
use crate::mir::interpret::{AllocId, Allocation, CTFE_ALLOC_SALT, Pointer, Scalar, alloc_range};
7-
use crate::ty::{self, Instance, PolyTraitRef, Ty, TyCtxt};
7+
use crate::ty::{self, Instance, TraitRef, Ty, TyCtxt};
88

99
#[derive(Clone, Copy, PartialEq, HashStable)]
1010
pub enum VtblEntry<'tcx> {
@@ -19,7 +19,7 @@ pub enum VtblEntry<'tcx> {
1919
/// dispatchable associated function
2020
Method(Instance<'tcx>),
2121
/// pointer to a separate supertrait vtable, can be used by trait upcasting coercion
22-
TraitVPtr(PolyTraitRef<'tcx>),
22+
TraitVPtr(TraitRef<'tcx>),
2323
}
2424

2525
impl<'tcx> fmt::Debug for VtblEntry<'tcx> {
@@ -56,15 +56,15 @@ pub const COMMON_VTABLE_ENTRIES_ALIGN: usize = 2;
5656
// function is an accurate approximation. We verify this when actually computing the vtable below.
5757
pub(crate) fn vtable_min_entries<'tcx>(
5858
tcx: TyCtxt<'tcx>,
59-
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
59+
trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
6060
) -> usize {
6161
let mut count = TyCtxt::COMMON_VTABLE_ENTRIES.len();
6262
let Some(trait_ref) = trait_ref else {
6363
return count;
6464
};
6565

6666
// This includes self in supertraits.
67-
for def_id in tcx.supertrait_def_ids(trait_ref.def_id()) {
67+
for def_id in tcx.supertrait_def_ids(trait_ref.def_id) {
6868
count += tcx.own_existential_vtable_entries(def_id).len();
6969
}
7070

@@ -80,7 +80,7 @@ pub(crate) fn vtable_min_entries<'tcx>(
8080
/// initial contents.)
8181
pub(super) fn vtable_allocation_provider<'tcx>(
8282
tcx: TyCtxt<'tcx>,
83-
key: (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>),
83+
key: (Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>),
8484
) -> AllocId {
8585
let (ty, poly_trait_ref) = key;
8686

@@ -115,7 +115,7 @@ pub(super) fn vtable_allocation_provider<'tcx>(
115115

116116
for (idx, entry) in vtable_entries.iter().enumerate() {
117117
let idx: u64 = u64::try_from(idx).unwrap();
118-
let scalar = match entry {
118+
let scalar = match *entry {
119119
VtblEntry::MetadataDropInPlace => {
120120
if ty.needs_drop(tcx, ty::TypingEnv::fully_monomorphized()) {
121121
let instance = ty::Instance::resolve_drop_in_place(tcx, ty);
@@ -131,13 +131,12 @@ pub(super) fn vtable_allocation_provider<'tcx>(
131131
VtblEntry::Vacant => continue,
132132
VtblEntry::Method(instance) => {
133133
// Prepare the fn ptr we write into the vtable.
134-
let fn_alloc_id = tcx.reserve_and_set_fn_alloc(*instance, CTFE_ALLOC_SALT);
134+
let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance, CTFE_ALLOC_SALT);
135135
let fn_ptr = Pointer::from(fn_alloc_id);
136136
Scalar::from_pointer(fn_ptr, &tcx)
137137
}
138138
VtblEntry::TraitVPtr(trait_ref) => {
139-
let super_trait_ref = trait_ref
140-
.map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
139+
let super_trait_ref = ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref);
141140
let supertrait_alloc_id = tcx.vtable_allocation((ty, Some(super_trait_ref)));
142141
let vptr = Pointer::from(supertrait_alloc_id);
143142
Scalar::from_pointer(vptr, &tcx)

compiler/rustc_monomorphize/src/collector.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -1129,11 +1129,12 @@ fn create_mono_items_for_vtable_methods<'tcx>(
11291129
bug!("create_mono_items_for_vtable_methods: {trait_ty:?} not a trait type");
11301130
};
11311131
if let Some(principal) = trait_ty.principal() {
1132-
let poly_trait_ref = principal.with_self_ty(tcx, impl_ty);
1133-
assert!(!poly_trait_ref.has_escaping_bound_vars());
1132+
let trait_ref =
1133+
tcx.instantiate_bound_regions_with_erased(principal.with_self_ty(tcx, impl_ty));
1134+
assert!(!trait_ref.has_escaping_bound_vars());
11341135

11351136
// Walk all methods of the trait, including those of its supertraits
1136-
let entries = tcx.vtable_entries(poly_trait_ref);
1137+
let entries = tcx.vtable_entries(trait_ref);
11371138
debug!(?entries);
11381139
let methods = entries
11391140
.iter()
@@ -1188,7 +1189,12 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
11881189
}
11891190
}
11901191
GlobalAlloc::VTable(ty, dyn_ty) => {
1191-
let alloc_id = tcx.vtable_allocation((ty, dyn_ty.principal()));
1192+
let alloc_id = tcx.vtable_allocation((
1193+
ty,
1194+
dyn_ty
1195+
.principal()
1196+
.map(|principal| tcx.instantiate_bound_regions_with_erased(principal)),
1197+
));
11921198
collect_alloc(tcx, alloc_id, output)
11931199
}
11941200
}

compiler/rustc_smir/src/rustc_smir/context.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,9 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
751751
let tcx = tables.tcx;
752752
let alloc_id = tables.tcx.vtable_allocation((
753753
ty.internal(&mut *tables, tcx),
754-
trait_ref.internal(&mut *tables, tcx),
754+
trait_ref
755+
.internal(&mut *tables, tcx)
756+
.map(|principal| tcx.instantiate_bound_regions_with_erased(principal)),
755757
));
756758
Some(alloc_id.stable(&mut *tables))
757759
}

compiler/rustc_trait_selection/src/errors.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_hir::intravisit::{Visitor, walk_ty};
1313
use rustc_hir::{FnRetTy, GenericParamKind, Node};
1414
use rustc_macros::{Diagnostic, Subdiagnostic};
1515
use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath};
16-
use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, PolyTraitRef, Region, Ty, TyCtxt};
16+
use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, Region, Ty, TyCtxt};
1717
use rustc_span::{BytePos, Ident, Span, Symbol, kw};
1818

1919
use crate::error_reporting::infer::ObligationCauseAsDiagArg;
@@ -28,7 +28,7 @@ pub mod note_and_explain;
2828
pub struct DumpVTableEntries<'a> {
2929
#[primary_span]
3030
pub span: Span,
31-
pub trait_ref: PolyTraitRef<'a>,
31+
pub trait_ref: ty::TraitRef<'a>,
3232
pub entries: String,
3333
}
3434

0 commit comments

Comments
 (0)