diff options
| author | 许杰友 Jieyou Xu (Joe) <39484203+jieyouxu@users.noreply.github.com> | 2024-10-18 14:52:25 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-10-18 14:52:25 +0100 |
| commit | 765e8c75b0b3dcfd9bb4de67c5a199d4c58f2db5 (patch) | |
| tree | 23505354072a3a4027b84438d70eb0310b8dcbd0 /compiler/rustc_trait_selection/src | |
| parent | 39af44dae986e91c8c7ea1a994781e8fb7fb6751 (diff) | |
| parent | 781bff049905d325bb877935978f1bce8ea6af86 (diff) | |
| download | rust-765e8c75b0b3dcfd9bb4de67c5a199d4c58f2db5.tar.gz rust-765e8c75b0b3dcfd9bb4de67c5a199d4c58f2db5.zip | |
Rollup merge of #131864 - lrh2000:upcast_reorder, r=WaffleLapkin
Never emit `vptr` for empty/auto traits Emiting `vptr`s for empty/auto traits is unnecessary (#114942) and causes unsoundness in `trait_upcasting` (#131813). This PR should ensure that we never emit vtables for such traits. See the linked issues for more details. I'm not sure if I can add tests for the vtable layout. So this PR only adds tests for the soundness hole (i.e., the segmentation fault will disappear after this PR). Fixes #114942 Fixes #131813 Cc #65991 (tracking issue for `trait_upcasting`) r? `@WaffleLapkin` (per https://github.com/rust-lang/rust/issues/131813#issuecomment-2419969745)
Diffstat (limited to 'compiler/rustc_trait_selection/src')
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/vtable.rs | 11 |
1 files changed, 5 insertions, 6 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 6e6f948a2cd..ed221e2a183 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))) |
