Skip to content

Commit c9ae1a0

Browse files
Normalize vtable entries before walking and deduplicating them
1 parent 355bf65 commit c9ae1a0

File tree

4 files changed

+87
-29
lines changed

4 files changed

+87
-29
lines changed

compiler/rustc_interface/src/passes.rs

+29-24
Original file line numberDiff line numberDiff line change
@@ -1026,37 +1026,42 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) {
10261026
// Here `dyn B<u8>` will have 4 entries, while `dyn B<String>` will only have 3.
10271027
// However, since we don't know `T`, we can't know if `T: Copy` holds or not,
10281028
// thus we lean on the bigger side and say it has 4 entries.
1029-
traits::vtable::prepare_vtable_segments(tcx, trait_ref, |segment| {
1030-
match segment {
1031-
traits::vtable::VtblSegment::MetadataDSA => {
1032-
// If this is the first dsa, it would be included either way,
1033-
// otherwise it's needed for upcasting
1034-
if std::mem::take(&mut first_dsa) {
1035-
entries_ignoring_upcasting += 3;
1036-
} else {
1037-
entries_for_upcasting += 3;
1029+
traits::vtable::prepare_vtable_segments(
1030+
tcx,
1031+
trait_ref,
1032+
ty::TypingEnv::post_analysis(tcx, tr),
1033+
|segment| {
1034+
match segment {
1035+
traits::vtable::VtblSegment::MetadataDSA => {
1036+
// If this is the first dsa, it would be included either way,
1037+
// otherwise it's needed for upcasting
1038+
if std::mem::take(&mut first_dsa) {
1039+
entries_ignoring_upcasting += 3;
1040+
} else {
1041+
entries_for_upcasting += 3;
1042+
}
10381043
}
1039-
}
10401044

1041-
traits::vtable::VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
1042-
// Lookup the shape of vtable for the trait.
1043-
let own_existential_entries =
1044-
tcx.own_existential_vtable_entries(trait_ref.def_id);
1045+
traits::vtable::VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
1046+
// Lookup the shape of vtable for the trait.
1047+
let own_existential_entries =
1048+
tcx.own_existential_vtable_entries(trait_ref.def_id);
10451049

1046-
// The original code here ignores the method if its predicates are
1047-
// impossible. We can't really do that as, for example, all not trivial
1048-
// bounds on generic parameters are impossible (since we don't know the
1049-
// parameters...), see the comment above.
1050-
entries_ignoring_upcasting += own_existential_entries.len();
1050+
// The original code here ignores the method if its predicates are
1051+
// impossible. We can't really do that as, for example, all not trivial
1052+
// bounds on generic parameters are impossible (since we don't know the
1053+
// parameters...), see the comment above.
1054+
entries_ignoring_upcasting += own_existential_entries.len();
10511055

1052-
if emit_vptr {
1053-
entries_for_upcasting += 1;
1056+
if emit_vptr {
1057+
entries_for_upcasting += 1;
1058+
}
10541059
}
10551060
}
1056-
}
10571061

1058-
std::ops::ControlFlow::Continue::<std::convert::Infallible>(())
1059-
});
1062+
std::ops::ControlFlow::Continue::<std::convert::Infallible>(())
1063+
},
1064+
);
10601065

10611066
sess.code_stats.record_vtable_size(tr, &name, VTableSizeInfo {
10621067
trait_name: name.clone(),

compiler/rustc_trait_selection/src/traits/vtable.rs

+25-5
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,18 @@ pub enum VtblSegment<'tcx> {
3030
pub fn prepare_vtable_segments<'tcx, T>(
3131
tcx: TyCtxt<'tcx>,
3232
trait_ref: ty::TraitRef<'tcx>,
33+
typing_env: ty::TypingEnv<'tcx>,
3334
segment_visitor: impl FnMut(VtblSegment<'tcx>) -> ControlFlow<T>,
3435
) -> Option<T> {
35-
prepare_vtable_segments_inner(tcx, trait_ref, segment_visitor).break_value()
36+
prepare_vtable_segments_inner(tcx, trait_ref, typing_env, segment_visitor).break_value()
3637
}
3738

3839
/// Helper for [`prepare_vtable_segments`] that returns `ControlFlow`,
3940
/// such that we can use `?` in the body.
4041
fn prepare_vtable_segments_inner<'tcx, T>(
4142
tcx: TyCtxt<'tcx>,
4243
trait_ref: ty::TraitRef<'tcx>,
44+
typing_env: ty::TypingEnv<'tcx>,
4345
mut segment_visitor: impl FnMut(VtblSegment<'tcx>) -> ControlFlow<T>,
4446
) -> ControlFlow<T> {
4547
// The following constraints holds for the final arrangement.
@@ -129,7 +131,8 @@ fn prepare_vtable_segments_inner<'tcx, T>(
129131
.iter_identity_copied()
130132
.filter_map(move |(pred, _)| {
131133
Some(
132-
tcx.instantiate_bound_regions_with_erased(
134+
tcx.normalize_erasing_late_bound_regions(
135+
typing_env,
133136
pred.instantiate_supertrait(
134137
tcx,
135138
ty::Binder::dummy(inner_most_trait_ref),
@@ -306,7 +309,12 @@ fn vtable_entries<'tcx>(
306309
ControlFlow::Continue(())
307310
};
308311

309-
let _ = prepare_vtable_segments(tcx, trait_ref, vtable_segment_callback);
312+
let _ = prepare_vtable_segments(
313+
tcx,
314+
trait_ref,
315+
ty::TypingEnv::fully_monomorphized(),
316+
vtable_segment_callback,
317+
);
310318

311319
if tcx.has_attr(trait_ref.def_id, sym::rustc_dump_vtable) {
312320
let sp = tcx.def_span(trait_ref.def_id);
@@ -358,7 +366,13 @@ pub(crate) fn first_method_vtable_slot<'tcx>(tcx: TyCtxt<'tcx>, key: ty::TraitRe
358366
}
359367
};
360368

361-
prepare_vtable_segments(tcx, source_principal, vtable_segment_callback).unwrap()
369+
prepare_vtable_segments(
370+
tcx,
371+
source_principal,
372+
ty::TypingEnv::fully_monomorphized(),
373+
vtable_segment_callback,
374+
)
375+
.unwrap()
362376
}
363377

364378
/// Given a `dyn Subtrait` and `dyn Supertrait` trait object, find the slot of
@@ -420,7 +434,13 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
420434
}
421435
};
422436

423-
prepare_vtable_segments(tcx, source_principal, vtable_segment_callback).unwrap()
437+
prepare_vtable_segments(
438+
tcx,
439+
source_principal,
440+
ty::TypingEnv::fully_monomorphized(),
441+
vtable_segment_callback,
442+
)
443+
.unwrap()
424444
}
425445

426446
fn trait_refs_are_compatible<'tcx>(
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)