Skip to content

Commit 739ef83

Browse files
Normalize vtable entries before walking and deduplicating them
1 parent fdc4bd2 commit 739ef83

File tree

6 files changed

+77
-24
lines changed

6 files changed

+77
-24
lines changed

Diff for: compiler/rustc_const_eval/src/interpret/cast.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,8 @@ 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(_)) = vtable_entries.get(entry_idx)
422+
let Some(&ty::VtblEntry::TraitVPtr(upcast_trait_ref)) =
423+
vtable_entries.get(entry_idx)
423424
else {
424425
span_bug!(
425426
self.cur_span(),
@@ -428,6 +429,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
428429
dest_pointee_ty
429430
);
430431
};
432+
let erased_trait_ref =
433+
ty::ExistentialTraitRef::erase_self_ty(*self.tcx, upcast_trait_ref);
434+
assert!(data_b.principal().is_some_and(|b| self.eq_in_param_env(
435+
erased_trait_ref,
436+
self.tcx.instantiate_bound_regions_with_erased(b)
437+
)));
431438
} else {
432439
// In this case codegen would keep using the old vtable. We don't want to do
433440
// that as it has the wrong trait. The reason codegen can do this is that

Diff for: compiler/rustc_infer/src/infer/at.rs

+24
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,18 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialTraitRef<'tcx> {
402402
}
403403
}
404404

405+
impl<'tcx> ToTrace<'tcx> for ty::ExistentialTraitRef<'tcx> {
406+
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
407+
TypeTrace {
408+
cause: cause.clone(),
409+
values: ValuePairs::ExistentialTraitRef(ExpectedFound::new(
410+
ty::Binder::dummy(a),
411+
ty::Binder::dummy(b),
412+
)),
413+
}
414+
}
415+
}
416+
405417
impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialProjection<'tcx> {
406418
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
407419
TypeTrace {
@@ -410,3 +422,15 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialProjection<'tcx> {
410422
}
411423
}
412424
}
425+
426+
impl<'tcx> ToTrace<'tcx> for ty::ExistentialProjection<'tcx> {
427+
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
428+
TypeTrace {
429+
cause: cause.clone(),
430+
values: ValuePairs::ExistentialProjection(ExpectedFound::new(
431+
ty::Binder::dummy(a),
432+
ty::Binder::dummy(b),
433+
)),
434+
}
435+
}
436+
}

Diff for: compiler/rustc_trait_selection/src/traits/vtable.rs

+12-21
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use std::ops::ControlFlow;
33

44
use rustc_hir::def_id::DefId;
55
use rustc_infer::infer::TyCtxtInferExt;
6-
use rustc_infer::infer::at::ToTrace;
76
use rustc_infer::traits::ObligationCause;
87
use rustc_infer::traits::util::PredicateSet;
98
use rustc_middle::bug;
@@ -127,16 +126,15 @@ fn prepare_vtable_segments_inner<'tcx, T>(
127126
.explicit_super_predicates_of(inner_most_trait_ref.def_id)
128127
.iter_identity_copied()
129128
.filter_map(move |(pred, _)| {
130-
Some(
131-
tcx.instantiate_bound_regions_with_erased(
132-
pred.instantiate_supertrait(
133-
tcx,
134-
ty::Binder::dummy(inner_most_trait_ref),
135-
)
136-
.as_trait_clause()?,
137-
)
138-
.trait_ref,
129+
pred.instantiate_supertrait(tcx, ty::Binder::dummy(inner_most_trait_ref))
130+
.as_trait_clause()
131+
})
132+
.map(move |pred| {
133+
tcx.normalize_erasing_late_bound_regions(
134+
ty::TypingEnv::fully_monomorphized(),
135+
pred,
139136
)
137+
.trait_ref
140138
});
141139

142140
// Find an unvisited supertrait
@@ -229,6 +227,8 @@ fn vtable_entries<'tcx>(
229227
tcx: TyCtxt<'tcx>,
230228
trait_ref: ty::TraitRef<'tcx>,
231229
) -> &'tcx [VtblEntry<'tcx>] {
230+
debug_assert!(!trait_ref.has_non_region_infer() && !trait_ref.has_non_region_param());
231+
232232
debug!("vtable_entries({:?})", trait_ref);
233233

234234
let mut entries = vec![];
@@ -422,17 +422,8 @@ fn trait_refs_are_compatible<'tcx>(
422422
let ocx = ObligationCtxt::new(&infcx);
423423
let source_principal = ocx.normalize(&ObligationCause::dummy(), param_env, vtable_principal);
424424
let target_principal = ocx.normalize(&ObligationCause::dummy(), param_env, target_principal);
425-
let Ok(()) = ocx.eq_trace(
426-
&ObligationCause::dummy(),
427-
param_env,
428-
ToTrace::to_trace(
429-
&ObligationCause::dummy(),
430-
ty::Binder::dummy(target_principal),
431-
ty::Binder::dummy(source_principal),
432-
),
433-
target_principal,
434-
source_principal,
435-
) else {
425+
let Ok(()) = ocx.eq(&ObligationCause::dummy(), param_env, target_principal, source_principal)
426+
else {
436427
return false;
437428
};
438429
ocx.select_all_or_error().is_empty()

Diff for: tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization-vtable.stderr

-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ error: vtable entries: [
33
MetadataSize,
44
MetadataAlign,
55
Method(<() as Supertrait<()>>::_print_numbers),
6-
Method(<() as Supertrait<()>>::_print_numbers),
7-
TraitVPtr(<() as Supertrait<<() as Identity>::Selff>>),
86
Method(<() as Middle<()>>::say_hello),
97
]
108
--> $DIR/multiple-supertraits-modulo-normalization-vtable.rs:29:1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//@ run-pass
2+
//@ check-run-results
3+
4+
#![feature(trait_upcasting)]
5+
6+
trait Supertrait<T> {
7+
fn _print_numbers(&self, mem: &[usize; 100]) {
8+
println!("{mem:?}");
9+
}
10+
}
11+
impl<T> Supertrait<T> for () {}
12+
13+
trait Identity {
14+
type Selff;
15+
}
16+
impl<Selff> Identity for Selff {
17+
type Selff = Selff;
18+
}
19+
20+
trait Middle<T>: Supertrait<()> + Supertrait<T> {
21+
fn say_hello(&self, _: &usize) {
22+
println!("Hello!");
23+
}
24+
}
25+
impl<T> Middle<T> for () {}
26+
27+
trait Trait: Middle<<() as Identity>::Selff> {}
28+
impl Trait for () {}
29+
30+
fn main() {
31+
(&() as &dyn Trait as &dyn Middle<()>).say_hello(&0);
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello!

0 commit comments

Comments
 (0)