Skip to content

Conversation

zachs18
Copy link
Contributor

@zachs18 zachs18 commented Aug 24, 2025

When determining if a non-first supertrait vptr can be omitted from a subtrait vtable, check if the supertrait or any of its (transitive) supertraits have methods, instead of only checking if the supertrait itself has methods.

This fixes the soundness issue where a vptr would be omitted for a supertrait with no methods but that itself had a supertrait with methods, while still optimizing the case where the supertrait is "truly" empty (it has no own vtable entries, and none of its (transitive) supertraits have any own vtable entries).

Fixes #145752


Old description:

Treat all non-auto traits as non-empty (possibly having methods) for purposes of determining if we need to emit a vptr for a non-direct supertrait (and for new "sibling" entries after a direct or non-direct supertrait).

This fixes (I believe) the soundness issue, but regresses vtable sizes and possibly upcasting perf in some cases when using trait hierarchies with empty non-auto traits (see tests/ui/traits/vtable/multiple-markers.stderr) since we use vptrs in some cases where we could re-use the vtable.

Fixes #145752

Re-opens (not anymore) #114942

Should not affect #131813 (i.e. the soundness issue is still fixed, though the relevant vtables in the trait Evil example will be larger now)

cc implementation history #131864 #113856


It should be possible to check if a trait has any methods from itself or supertraits (instead of just from itself), but to fix the immediate soundness issue, just assume any non-auto trait could have methods. A more optimistic check can be implemented later (or if someone does it soon it could just supercede this PR 😄). Done in latest push

@rustbot label A-dyn-trait F-trait_upcasting

@rustbot
Copy link
Collaborator

rustbot commented Aug 24, 2025

r? @SparrowLii

rustbot has assigned @SparrowLii.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. A-dyn-trait Area: trait objects, vtable layout F-trait_upcasting `#![feature(trait_upcasting)]` labels Aug 24, 2025
@jieyouxu
Copy link
Member

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rust-bors

This comment has been minimized.

rust-bors bot added a commit that referenced this pull request Aug 24, 2025
Only consider auto traits empty for the purposes of omitting vptrs from subtrait vtables.
@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Aug 24, 2025
@rust-bors
Copy link

rust-bors bot commented Aug 24, 2025

☀️ Try build successful (CI)
Build commit: b128140 (b1281401f3d41c9a4c5290caa55cd74176ccc2be, parent: f6d23413c399fb530be362ebcf25a4e788e16137)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (b128140): comparison URL.

Overall result: no relevant changes - no action needed

Benchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf.

@bors rollup=never
@rustbot label: -S-waiting-on-perf -perf-regression

Instruction count

This benchmark run did not return any relevant results for this metric.

Max RSS (memory usage)

Results (primary 6.0%, secondary 0.4%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
6.0% [6.0%, 6.0%] 1
Regressions ❌
(secondary)
1.6% [1.3%, 2.0%] 2
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-2.2% [-2.2%, -2.2%] 1
All ❌✅ (primary) 6.0% [6.0%, 6.0%] 1

Cycles

This benchmark run did not return any relevant results for this metric.

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 468.54s -> 466.319s (-0.47%)
Artifact size: 378.30 MiB -> 378.29 MiB (-0.00%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Aug 24, 2025
@@ -153,16 +153,26 @@ 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);
Copy link
Member

@compiler-errors compiler-errors Aug 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you would like to look at if any of the supertraits (including the trait itself) has entries, you can do something like:

let has_entries = elaborate::supertrait_def_ids(tcx, inner_most_trait_ref.def_id).any(|def_id| has_own_existential_vtable_entries(tcx, def_id));

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! This is a much better solution

@zachs18 zachs18 force-pushed the only-consider-auto-traits-empty branch from bae9ed3 to 904e83c Compare August 25, 2025 21:16
@zachs18 zachs18 changed the title Only consider auto traits empty for the purposes of omitting vptrs from subtrait vtables. When determining if a trait has no entries for the purposes of omitting vptrs from subtrait vtables, consider a its transitive supertraits' entries, instead of just its own entries. Aug 25, 2025
@zachs18 zachs18 changed the title When determining if a trait has no entries for the purposes of omitting vptrs from subtrait vtables, consider a its transitive supertraits' entries, instead of just its own entries. When determining if a trait has no entries for the purposes of omitting vptrs from subtrait vtables, consider its transitive supertraits' entries, instead of just its own entries. Aug 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-dyn-trait Area: trait objects, vtable layout F-trait_upcasting `#![feature(trait_upcasting)]` S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

SIGSEGV without unsafe when passing &dyn Trait to &dyn ParentTrait
6 participants