diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 6e6f948a2cdc4..ed221e2a1835f 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -154,18 +154,17 @@ 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()); + segment_visitor(VtblSegment::TraitOwnEntries { trait_ref: inner_most_trait_ref, - emit_vptr: emit_vptr && !tcx.sess.opts.unstable_opts.no_trait_vptr, + emit_vptr: emit_vptr && has_entries && !tcx.sess.opts.unstable_opts.no_trait_vptr, })?; // If we've emitted (fed to `segment_visitor`) a trait that has methods present in the vtable, // we'll need to emit vptrs from now on. - if !emit_vptr_on_new_entry - && has_own_existential_vtable_entries(tcx, inner_most_trait_ref.def_id()) - { - emit_vptr_on_new_entry = true; - } + emit_vptr_on_new_entry |= has_entries; if let Some(next_inner_most_trait_ref) = siblings.find(|&sibling| visited.insert(sibling.upcast(tcx))) diff --git a/tests/ui/traits/object/print_vtable_sizes.stdout b/tests/ui/traits/object/print_vtable_sizes.stdout index b43e168df3f38..4daf476957657 100644 --- a/tests/ui/traits/object/print_vtable_sizes.stdout +++ b/tests/ui/traits/object/print_vtable_sizes.stdout @@ -1,8 +1,8 @@ -print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "E", "entries": "6", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "2", "upcasting_cost_percent": "50" } -print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "G", "entries": "14", "entries_ignoring_upcasting": "11", "entries_for_upcasting": "3", "upcasting_cost_percent": "27.27272727272727" } print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "A", "entries": "6", "entries_ignoring_upcasting": "5", "entries_for_upcasting": "1", "upcasting_cost_percent": "20" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "G", "entries": "13", "entries_ignoring_upcasting": "11", "entries_for_upcasting": "2", "upcasting_cost_percent": "18.181818181818183" } print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "B", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "D", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "E", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "F", "entries": "6", "entries_ignoring_upcasting": "6", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } diff --git a/tests/ui/traits/upcast_reorder.rs b/tests/ui/traits/upcast_reorder.rs new file mode 100644 index 0000000000000..55e6ad4c368d1 --- /dev/null +++ b/tests/ui/traits/upcast_reorder.rs @@ -0,0 +1,29 @@ +//@ run-pass +// +// issue: + +#![feature(trait_upcasting)] + +trait Pollable { + #[allow(unused)] + fn poll(&self) {} +} +trait FileIo: Pollable + Send + Sync { + fn read(&self) {} +} +trait Terminal: Send + Sync + FileIo {} + +struct A; + +impl Pollable for A {} +impl FileIo for A {} +impl Terminal for A {} + +fn main() { + let a = A; + + let b = &a as &dyn Terminal; + let c = b as &dyn FileIo; + + c.read(); +} diff --git a/tests/ui/traits/vtable/multiple-markers.stderr b/tests/ui/traits/vtable/multiple-markers.stderr index 4497c703ae8a1..36ac8b24eb530 100644 --- a/tests/ui/traits/vtable/multiple-markers.stderr +++ b/tests/ui/traits/vtable/multiple-markers.stderr @@ -14,7 +14,6 @@ error: vtable entries for ``: [ MetadataSize, MetadataAlign, Method(::method), - TraitVPtr(), ] --> $DIR/multiple-markers.rs:24:1 | @@ -26,8 +25,6 @@ error: vtable entries for ``: [ MetadataSize, MetadataAlign, Method(::method), - TraitVPtr(), - TraitVPtr(), ] --> $DIR/multiple-markers.rs:27:1 | @@ -39,9 +36,6 @@ error: vtable entries for ``: [ MetadataSize, MetadataAlign, Method(::method), - TraitVPtr(), - TraitVPtr(), - TraitVPtr(), ] --> $DIR/multiple-markers.rs:30:1 |