Only consider auto traits empty for the purposes of omitting vptrs from subtrait vtables

This commit is contained in:
Zachary S
2025-08-23 20:48:44 -05:00
parent c5a6a7bdd8
commit 904e83c53f
5 changed files with 167 additions and 1 deletions

View File

@@ -153,7 +153,12 @@ 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);
// We don't need to emit a vptr for "truly-empty" supertraits, but we *do* need to emit a
// vptr for supertraits that have no methods, but that themselves have supertraits
// with methods, so we check if any transitive supertrait has entries here (this includes
// the trait itself).
let has_entries = ty::elaborate::supertrait_def_ids(tcx, inner_most_trait_ref.def_id)
.any(|def_id| has_own_existential_vtable_entries(tcx, def_id));
segment_visitor(VtblSegment::TraitOwnEntries {
trait_ref: inner_most_trait_ref,

View File

@@ -0,0 +1,16 @@
error: vtable entries: [
MetadataDropInPlace,
MetadataSize,
MetadataAlign,
Method(<dyn OneTwo as One>::one - shim(reify)),
Method(<dyn OneTwo as Two>::two - shim(reify)),
TraitVPtr(<dyn OneTwo as Two>),
TraitVPtr(<dyn OneTwo as TwoAgain>),
]
--> $DIR/empty-supertrait-with-nonempty-supersupertrait.rs:40:1
|
LL | type T = dyn OneTwo;
| ^^^^^^
error: aborting due to 1 previous error

View File

@@ -0,0 +1,49 @@
//@ revisions: run dump
//@[run] run-pass
//@[dump] check-fail
//! Regression test for #145752
//! Ensure that `OneTwo` contains a vptr for `TwoAgain`
#![allow(unused)]
#![cfg_attr(dump, feature(rustc_attrs))]
trait One {
fn one(&self) {
panic!("don't call this");
}
}
impl One for () {}
trait Two {
fn two(&self) {
println!("good");
}
}
impl Two for () {}
trait TwoAgain: Two {}
impl<T: Two> TwoAgain for T {}
trait OneTwo: One + TwoAgain {}
impl<T: One + Two> OneTwo for T {}
fn main() {
(&()).two();
(&() as &dyn OneTwo).two();
(&() as &dyn OneTwo as &dyn Two).two();
// these two used to panic because they called `one` due to #145752
(&() as &dyn OneTwo as &dyn TwoAgain).two();
(&() as &dyn OneTwo as &dyn TwoAgain as &dyn Two).two();
}
#[cfg_attr(dump, rustc_dump_vtable)]
type T = dyn OneTwo;
//[dump]~^ ERROR vtable entries: [
//[dump]~| ERROR MetadataDropInPlace,
//[dump]~| ERROR MetadataSize,
//[dump]~| ERROR MetadataAlign,
//[dump]~| ERROR Method(<dyn OneTwo as One>::one - shim(reify)),
//[dump]~| ERROR Method(<dyn OneTwo as Two>::two - shim(reify)),
//[dump]~| ERROR TraitVPtr(<dyn OneTwo as Two>),
//[dump]~| ERROR TraitVPtr(<dyn OneTwo as TwoAgain>),
//[dump]~| ERROR ]

View File

@@ -0,0 +1,50 @@
// Related to <https://github.com/rust-lang/rust/issues/113840>
//
// This test makes sure that multiple auto traits can reuse the
// same pointer for upcasting (e.g. `Send`/`Sync`)
#![crate_type = "lib"]
#![feature(rustc_attrs, auto_traits)]
// Markers
auto trait M0 {}
auto trait M1 {}
auto trait M2 {}
// Just a trait with a method
trait T {
fn method(&self) {}
}
trait A: M0 + M1 + M2 + T {}
trait B: M0 + M1 + T + M2 {}
trait C: M0 + T + M1 + M2 {}
trait D: T + M0 + M1 + M2 {}
struct S;
impl M0 for S {}
impl M1 for S {}
impl M2 for S {}
impl T for S {}
#[rustc_dump_vtable]
impl A for S {}
//~^ ERROR vtable entries
#[rustc_dump_vtable]
impl B for S {}
//~^ ERROR vtable entries
#[rustc_dump_vtable]
impl C for S {}
//~^ ERROR vtable entries
#[rustc_dump_vtable]
impl D for S {}
//~^ ERROR vtable entries
fn main() {}

View File

@@ -0,0 +1,46 @@
error: vtable entries: [
MetadataDropInPlace,
MetadataSize,
MetadataAlign,
Method(<S as T>::method),
]
--> $DIR/multiple-auto.rs:35:1
|
LL | impl A for S {}
| ^^^^^^^^^^^^
error: vtable entries: [
MetadataDropInPlace,
MetadataSize,
MetadataAlign,
Method(<S as T>::method),
]
--> $DIR/multiple-auto.rs:39:1
|
LL | impl B for S {}
| ^^^^^^^^^^^^
error: vtable entries: [
MetadataDropInPlace,
MetadataSize,
MetadataAlign,
Method(<S as T>::method),
]
--> $DIR/multiple-auto.rs:43:1
|
LL | impl C for S {}
| ^^^^^^^^^^^^
error: vtable entries: [
MetadataDropInPlace,
MetadataSize,
MetadataAlign,
Method(<S as T>::method),
]
--> $DIR/multiple-auto.rs:47:1
|
LL | impl D for S {}
| ^^^^^^^^^^^^
error: aborting due to 4 previous errors