Skip to content

Commit 904e83c

Browse files
committed
Only consider auto traits empty for the purposes of omitting vptrs from subtrait vtables
1 parent c5a6a7b commit 904e83c

File tree

5 files changed

+167
-1
lines changed

5 files changed

+167
-1
lines changed

compiler/rustc_trait_selection/src/traits/vtable.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,12 @@ fn prepare_vtable_segments_inner<'tcx, T>(
153153

154154
// emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level.
155155
while let Some((inner_most_trait_ref, emit_vptr, mut siblings)) = stack.pop() {
156-
let has_entries = has_own_existential_vtable_entries(tcx, inner_most_trait_ref.def_id);
156+
// We don't need to emit a vptr for "truly-empty" supertraits, but we *do* need to emit a
157+
// vptr for supertraits that have no methods, but that themselves have supertraits
158+
// with methods, so we check if any transitive supertrait has entries here (this includes
159+
// the trait itself).
160+
let has_entries = ty::elaborate::supertrait_def_ids(tcx, inner_most_trait_ref.def_id)
161+
.any(|def_id| has_own_existential_vtable_entries(tcx, def_id));
157162

158163
segment_visitor(VtblSegment::TraitOwnEntries {
159164
trait_ref: inner_most_trait_ref,
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error: vtable entries: [
2+
MetadataDropInPlace,
3+
MetadataSize,
4+
MetadataAlign,
5+
Method(<dyn OneTwo as One>::one - shim(reify)),
6+
Method(<dyn OneTwo as Two>::two - shim(reify)),
7+
TraitVPtr(<dyn OneTwo as Two>),
8+
TraitVPtr(<dyn OneTwo as TwoAgain>),
9+
]
10+
--> $DIR/empty-supertrait-with-nonempty-supersupertrait.rs:40:1
11+
|
12+
LL | type T = dyn OneTwo;
13+
| ^^^^^^
14+
15+
error: aborting due to 1 previous error
16+
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//@ revisions: run dump
2+
//@[run] run-pass
3+
//@[dump] check-fail
4+
//! Regression test for #145752
5+
//! Ensure that `OneTwo` contains a vptr for `TwoAgain`
6+
#![allow(unused)]
7+
#![cfg_attr(dump, feature(rustc_attrs))]
8+
9+
trait One {
10+
fn one(&self) {
11+
panic!("don't call this");
12+
}
13+
}
14+
impl One for () {}
15+
16+
trait Two {
17+
fn two(&self) {
18+
println!("good");
19+
}
20+
}
21+
impl Two for () {}
22+
23+
trait TwoAgain: Two {}
24+
impl<T: Two> TwoAgain for T {}
25+
26+
trait OneTwo: One + TwoAgain {}
27+
impl<T: One + Two> OneTwo for T {}
28+
29+
fn main() {
30+
(&()).two();
31+
(&() as &dyn OneTwo).two();
32+
(&() as &dyn OneTwo as &dyn Two).two();
33+
34+
// these two used to panic because they called `one` due to #145752
35+
(&() as &dyn OneTwo as &dyn TwoAgain).two();
36+
(&() as &dyn OneTwo as &dyn TwoAgain as &dyn Two).two();
37+
}
38+
39+
#[cfg_attr(dump, rustc_dump_vtable)]
40+
type T = dyn OneTwo;
41+
//[dump]~^ ERROR vtable entries: [
42+
//[dump]~| ERROR MetadataDropInPlace,
43+
//[dump]~| ERROR MetadataSize,
44+
//[dump]~| ERROR MetadataAlign,
45+
//[dump]~| ERROR Method(<dyn OneTwo as One>::one - shim(reify)),
46+
//[dump]~| ERROR Method(<dyn OneTwo as Two>::two - shim(reify)),
47+
//[dump]~| ERROR TraitVPtr(<dyn OneTwo as Two>),
48+
//[dump]~| ERROR TraitVPtr(<dyn OneTwo as TwoAgain>),
49+
//[dump]~| ERROR ]
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Related to <https://github.com/rust-lang/rust/issues/113840>
2+
//
3+
// This test makes sure that multiple auto traits can reuse the
4+
// same pointer for upcasting (e.g. `Send`/`Sync`)
5+
6+
#![crate_type = "lib"]
7+
#![feature(rustc_attrs, auto_traits)]
8+
9+
// Markers
10+
auto trait M0 {}
11+
auto trait M1 {}
12+
auto trait M2 {}
13+
14+
// Just a trait with a method
15+
trait T {
16+
fn method(&self) {}
17+
}
18+
19+
trait A: M0 + M1 + M2 + T {}
20+
21+
trait B: M0 + M1 + T + M2 {}
22+
23+
trait C: M0 + T + M1 + M2 {}
24+
25+
trait D: T + M0 + M1 + M2 {}
26+
27+
struct S;
28+
29+
impl M0 for S {}
30+
impl M1 for S {}
31+
impl M2 for S {}
32+
impl T for S {}
33+
34+
#[rustc_dump_vtable]
35+
impl A for S {}
36+
//~^ ERROR vtable entries
37+
38+
#[rustc_dump_vtable]
39+
impl B for S {}
40+
//~^ ERROR vtable entries
41+
42+
#[rustc_dump_vtable]
43+
impl C for S {}
44+
//~^ ERROR vtable entries
45+
46+
#[rustc_dump_vtable]
47+
impl D for S {}
48+
//~^ ERROR vtable entries
49+
50+
fn main() {}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
error: vtable entries: [
2+
MetadataDropInPlace,
3+
MetadataSize,
4+
MetadataAlign,
5+
Method(<S as T>::method),
6+
]
7+
--> $DIR/multiple-auto.rs:35:1
8+
|
9+
LL | impl A for S {}
10+
| ^^^^^^^^^^^^
11+
12+
error: vtable entries: [
13+
MetadataDropInPlace,
14+
MetadataSize,
15+
MetadataAlign,
16+
Method(<S as T>::method),
17+
]
18+
--> $DIR/multiple-auto.rs:39:1
19+
|
20+
LL | impl B for S {}
21+
| ^^^^^^^^^^^^
22+
23+
error: vtable entries: [
24+
MetadataDropInPlace,
25+
MetadataSize,
26+
MetadataAlign,
27+
Method(<S as T>::method),
28+
]
29+
--> $DIR/multiple-auto.rs:43:1
30+
|
31+
LL | impl C for S {}
32+
| ^^^^^^^^^^^^
33+
34+
error: vtable entries: [
35+
MetadataDropInPlace,
36+
MetadataSize,
37+
MetadataAlign,
38+
Method(<S as T>::method),
39+
]
40+
--> $DIR/multiple-auto.rs:47:1
41+
|
42+
LL | impl D for S {}
43+
| ^^^^^^^^^^^^
44+
45+
error: aborting due to 4 previous errors
46+

0 commit comments

Comments
 (0)