Only consider auto traits empty for the purposes of omitting vptrs from subtrait vtables
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ]
|
||||
50
tests/ui/traits/vtable/multiple-auto.rs
Normal file
50
tests/ui/traits/vtable/multiple-auto.rs
Normal 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() {}
|
||||
46
tests/ui/traits/vtable/multiple-auto.stderr
Normal file
46
tests/ui/traits/vtable/multiple-auto.stderr
Normal 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
|
||||
|
||||
Reference in New Issue
Block a user