Rollup merge of #127856 - RalfJung:interpret-cast-sanity, r=oli-obk
interpret: add sanity check in dyn upcast to double-check what codegen does For dyn receiver calls, we already have two codepaths: look up the function to call by indexing into the vtable, or alternatively resolve the DefId given the dynamic type of the receiver. With debug assertions enabled, the interpreter does both and compares the results. (Without debug assertions we always use the vtable as it is simpler.) This PR does the same for dyn trait upcasts. However, for casts *not* using the vtable is the easier thing to do, so now the vtable path is the debug-assertion-only path. In particular, there are cases where the vtable does not contain a pointer for upcasts but instead reuses the old pointer: when the supertrait vtable is a prefix of the larger vtable. We don't want to expose this optimization and detect UB if people do a transmute assuming this optimization, so we cannot in general use the vtable indexing path. r? ``@oli-obk``
This commit is contained in:
commit
9f8c618a90
15 changed files with 245 additions and 254 deletions
|
@ -364,7 +364,9 @@ pub(crate) fn first_method_vtable_slot<'tcx>(tcx: TyCtxt<'tcx>, key: ty::TraitRe
|
|||
}
|
||||
|
||||
/// Given a `dyn Subtrait` and `dyn Supertrait` trait object, find the slot of
|
||||
/// // the trait vptr in the subtrait's vtable.
|
||||
/// the trait vptr in the subtrait's vtable.
|
||||
///
|
||||
/// A return value of `None` means that the original vtable can be reused.
|
||||
pub(crate) fn supertrait_vtable_slot<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
key: (
|
||||
|
@ -373,8 +375,17 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
|
|||
),
|
||||
) -> Option<usize> {
|
||||
debug_assert!(!key.has_non_region_infer() && !key.has_non_region_param());
|
||||
|
||||
let (source, target) = key;
|
||||
|
||||
// If the target principal is `None`, we can just return `None`.
|
||||
let ty::Dynamic(target, _, _) = *target.kind() else {
|
||||
bug!();
|
||||
};
|
||||
let target_principal = tcx
|
||||
.normalize_erasing_regions(ty::ParamEnv::reveal_all(), target.principal()?)
|
||||
.with_self_ty(tcx, tcx.types.trait_object_dummy_self);
|
||||
|
||||
// Given that we have a target principal, it is a bug for there not to be a source principal.
|
||||
let ty::Dynamic(source, _, _) = *source.kind() else {
|
||||
bug!();
|
||||
};
|
||||
|
@ -382,13 +393,6 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
|
|||
.normalize_erasing_regions(ty::ParamEnv::reveal_all(), source.principal().unwrap())
|
||||
.with_self_ty(tcx, tcx.types.trait_object_dummy_self);
|
||||
|
||||
let ty::Dynamic(target, _, _) = *target.kind() else {
|
||||
bug!();
|
||||
};
|
||||
let target_principal = tcx
|
||||
.normalize_erasing_regions(ty::ParamEnv::reveal_all(), target.principal().unwrap())
|
||||
.with_self_ty(tcx, tcx.types.trait_object_dummy_self);
|
||||
|
||||
let vtable_segment_callback = {
|
||||
let mut vptr_offset = 0;
|
||||
move |segment| {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue