Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit c5441ac

Browse files
committed
Call destructors when dyn* object goes out of scope
1 parent 549c105 commit c5441ac

File tree

8 files changed

+59
-18
lines changed

8 files changed

+59
-18
lines changed

compiler/rustc_codegen_ssa/src/meth.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,15 +86,14 @@ fn expect_dyn_trait_in_self<'tcx>(ty: Ty<'tcx>) -> ty::PolyExistentialTraitRef<'
8686
/// The `trait_ref` encodes the erased self type. Hence if we are
8787
/// making an object `Foo<dyn Trait>` from a value of type `Foo<T>`, then
8888
/// `trait_ref` would map `T: Trait`.
89+
#[instrument(level = "debug", skip(cx))]
8990
pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
9091
cx: &Cx,
9192
ty: Ty<'tcx>,
9293
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
9394
) -> Cx::Value {
9495
let tcx = cx.tcx();
9596

96-
debug!("get_vtable(ty={:?}, trait_ref={:?})", ty, trait_ref);
97-
9897
// Check the cache.
9998
if let Some(&val) = cx.vtables().borrow().get(&(ty, trait_ref)) {
10099
return val;

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_index::vec::Idx;
1616
use rustc_middle::mir::{self, AssertKind, SwitchTargets};
1717
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
1818
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
19-
use rustc_middle::ty::{self, Instance, Ty, TypeVisitable, TraitObjectRepresentation};
19+
use rustc_middle::ty::{self, Instance, TraitObjectRepresentation, Ty, TypeVisitable};
2020
use rustc_span::source_map::Span;
2121
use rustc_span::{sym, Symbol};
2222
use rustc_symbol_mangling::typeid::typeid_for_fnabi;
@@ -451,7 +451,27 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
451451
// (data, vtable) // an equivalent Rust `*mut dyn Trait`
452452
//
453453
// SO THEN WE CAN USE THE ABOVE CODE.
454-
todo!()
454+
let virtual_drop = Instance {
455+
def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0),
456+
substs: drop_fn.substs,
457+
};
458+
debug!("ty = {:?}", ty);
459+
debug!("drop_fn = {:?}", drop_fn);
460+
debug!("args = {:?}", args);
461+
let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty());
462+
let data = args[0];
463+
let data_ty = bx.cx().backend_type(place.layout);
464+
let vtable_ptr =
465+
bx.gep(data_ty, data, &[bx.cx().const_i32(0), bx.cx().const_i32(1)]);
466+
let vtable = bx.load(bx.type_i8p(), vtable_ptr, abi::Align::ONE);
467+
// Truncate vtable off of args list
468+
args = &args[..1];
469+
debug!("args' = {:?}", args);
470+
(
471+
meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE)
472+
.get_fn(&mut bx, vtable, ty, &fn_abi),
473+
fn_abi,
474+
)
455475
}
456476
_ => (bx.get_fn_addr(drop_fn), bx.fn_abi_of_instance(drop_fn, ty::List::empty())),
457477
};

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ use super::{FunctionCx, LocalRef};
44

55
use crate::base;
66
use crate::common::{self, IntPredicate};
7+
use crate::meth::get_vtable;
78
use crate::traits::*;
89
use crate::MemFlags;
910

1011
use rustc_middle::mir;
1112
use rustc_middle::mir::Operand;
1213
use rustc_middle::ty::cast::{CastTy, IntTy};
1314
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
15+
use rustc_middle::ty::TraitObjectRepresentation;
1416
use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt};
1517
use rustc_span::source_map::{Span, DUMMY_SP};
1618

@@ -271,14 +273,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
271273
bug!("unexpected non-pair operand");
272274
}
273275
}
274-
#[allow(unreachable_code, unused)] // FIXME: remove this
275276
mir::CastKind::DynStar => {
276277
let data = match operand.val {
277278
OperandValue::Ref(_, _, _) => todo!(),
278-
OperandValue::Immediate(_) => todo!(),
279+
OperandValue::Immediate(v) => v,
279280
OperandValue::Pair(_, _) => todo!(),
280281
};
281-
let vtable = todo!();
282+
// FIXME: find the real vtable!
283+
let trait_ref = if let ty::Dynamic(data, _, TraitObjectRepresentation::Sized) = cast.ty.kind() {
284+
data.principal()
285+
} else {
286+
bug!("Only valid to do a DynStar cast into a DynStar type")
287+
};
288+
let vtable = get_vtable(bx.cx(), source.ty(self.mir, bx.tcx()), trait_ref);
282289
OperandValue::Pair(data, vtable)
283290
}
284291
mir::CastKind::Pointer(

compiler/rustc_middle/src/ty/layout.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2751,6 +2751,7 @@ impl<'tcx> ty::Instance<'tcx> {
27512751
// for `Instance` (e.g. typeck would use `Ty::fn_sig` instead),
27522752
// or should go through `FnAbi` instead, to avoid losing any
27532753
// adjustments `fn_abi_of_instance` might be performing.
2754+
#[tracing::instrument(level = "debug", skip(tcx, param_env))]
27542755
fn fn_sig_for_fn_abi(
27552756
&self,
27562757
tcx: TyCtxt<'tcx>,
@@ -2897,6 +2898,7 @@ impl<'tcx> ty::Instance<'tcx> {
28972898
/// with `-Cpanic=abort` will look like they can't unwind when in fact they
28982899
/// might (from a foreign exception or similar).
28992900
#[inline]
2901+
#[tracing::instrument(level = "debug", skip(tcx))]
29002902
pub fn fn_can_unwind<'tcx>(tcx: TyCtxt<'tcx>, fn_def_id: Option<DefId>, abi: SpecAbi) -> bool {
29012903
if let Some(did) = fn_def_id {
29022904
// Special attribute for functions which can't unwind.
@@ -3113,6 +3115,7 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> {
31133115
/// NB: that includes virtual calls, which are represented by "direct calls"
31143116
/// to an `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`).
31153117
#[inline]
3118+
#[tracing::instrument(level = "debug", skip(self))]
31163119
fn fn_abi_of_instance(
31173120
&self,
31183121
instance: ty::Instance<'tcx>,
@@ -3259,6 +3262,10 @@ pub fn adjust_for_rust_scalar<'tcx>(
32593262
impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
32603263
// FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
32613264
// arguments of this method, into a separate `struct`.
3265+
#[tracing::instrument(
3266+
level = "debug",
3267+
skip(self, caller_location, fn_def_id, force_thin_self_ptr)
3268+
)]
32623269
fn fn_abi_new_uncached(
32633270
&self,
32643271
sig: ty::PolyFnSig<'tcx>,
@@ -3268,8 +3275,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
32683275
// FIXME(eddyb) replace this with something typed, like an `enum`.
32693276
force_thin_self_ptr: bool,
32703277
) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
3271-
debug!("fn_abi_new_uncached({:?}, {:?})", sig, extra_args);
3272-
32733278
let sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, sig);
32743279

32753280
let conv = conv_from_spec_abi(self.tcx(), sig.abi);
@@ -3312,6 +3317,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
33123317
let rust_abi = matches!(sig.abi, RustIntrinsic | PlatformIntrinsic | Rust | RustCall);
33133318

33143319
let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, FnAbiError<'tcx>> {
3320+
let span = tracing::debug_span!("arg_of");
3321+
let _entered = span.enter();
33153322
let is_return = arg_idx.is_none();
33163323

33173324
let layout = self.layout_of(ty)?;
@@ -3368,6 +3375,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
33683375
Ok(self.tcx.arena.alloc(fn_abi))
33693376
}
33703377

3378+
#[tracing::instrument(level = "debug", skip(self))]
33713379
fn fn_abi_adjust_for_abi(
33723380
&self,
33733381
fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>,
@@ -3442,6 +3450,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
34423450
}
34433451
}
34443452

3453+
#[tracing::instrument(level = "debug", skip(cx))]
34453454
fn make_thin_self_ptr<'tcx>(
34463455
cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>),
34473456
layout: TyAndLayout<'tcx>,
@@ -3453,7 +3462,7 @@ fn make_thin_self_ptr<'tcx>(
34533462
tcx.mk_mut_ptr(layout.ty)
34543463
} else {
34553464
match layout.abi {
3456-
Abi::ScalarPair(..) => (),
3465+
Abi::ScalarPair(..) | Abi::Scalar(..) => (),
34573466
_ => bug!("receiver type has unsupported layout: {:?}", layout),
34583467
}
34593468

compiler/rustc_middle/src/ty/normalize_erasing_regions.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ impl<'tcx> TyCtxt<'tcx> {
3636
///
3737
/// This should only be used outside of type inference. For example,
3838
/// it assumes that normalization will succeed.
39+
#[tracing::instrument(level = "debug", skip(self, param_env))]
3940
pub fn normalize_erasing_regions<T>(self, param_env: ty::ParamEnv<'tcx>, value: T) -> T
4041
where
4142
T: TypeFoldable<'tcx>,
@@ -100,6 +101,7 @@ impl<'tcx> TyCtxt<'tcx> {
100101
/// N.B., currently, higher-ranked type bounds inhibit
101102
/// normalization. Therefore, each time we erase them in
102103
/// codegen, we need to normalize the contents.
104+
#[tracing::instrument(level = "debug", skip(self, param_env))]
103105
pub fn normalize_erasing_late_bound_regions<T>(
104106
self,
105107
param_env: ty::ParamEnv<'tcx>,

compiler/rustc_mir_build/src/build/expr/as_rvalue.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -216,10 +216,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
216216
};
217217
let from_ty = CastTy::from_ty(ty);
218218
let cast_ty = CastTy::from_ty(expr.ty);
219-
debug!(
220-
"ExprKind::Cast from_ty={from_ty:?}, cast_ty={:?}/{cast_ty:?}",
221-
expr.ty,
222-
);
219+
debug!("ExprKind::Cast from_ty={from_ty:?}, cast_ty={:?}/{cast_ty:?}", expr.ty,);
223220
let cast_kind = match (from_ty, cast_ty) {
224221
(Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => {
225222
CastKind::PointerExposeAddress

compiler/rustc_monomorphize/src/collector.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,8 @@ use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCast};
189189
use rustc_middle::ty::print::with_no_trimmed_paths;
190190
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
191191
use rustc_middle::ty::{
192-
self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitable, VtblEntry,
192+
self, GenericParamDefKind, Instance, TraitObjectRepresentation, Ty, TyCtxt, TypeFoldable,
193+
TypeVisitable, VtblEntry,
193194
};
194195
use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyContext};
195196
use rustc_session::config::EntryFnType;
@@ -689,7 +690,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
689690
mir::CastKind::Pointer(PointerCast::Unsize),
690691
ref operand,
691692
target_ty,
692-
) => {
693+
)
694+
| mir::Rvalue::Cast(mir::CastKind::DynStar, ref operand, target_ty) => {
693695
let target_ty = self.monomorphize(target_ty);
694696
let source_ty = operand.ty(self.body, self.tcx);
695697
let source_ty = self.monomorphize(source_ty);
@@ -698,7 +700,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
698700
// This could also be a different Unsize instruction, like
699701
// from a fixed sized array to a slice. But we are only
700702
// interested in things that produce a vtable.
701-
if target_ty.is_trait() && !source_ty.is_trait() {
703+
if (target_ty.is_trait() || target_ty.is_dyn_star()) && !source_ty.is_trait() {
702704
create_mono_items_for_vtable_methods(
703705
self.tcx,
704706
target_ty,
@@ -1112,6 +1114,11 @@ fn find_vtable_types_for_unsizing<'tcx>(
11121114
ptr_vtable(source_ty.boxed_ty(), target_ty.boxed_ty())
11131115
}
11141116

1117+
// T as dyn* Trait
1118+
(_, &ty::Dynamic(_, _, TraitObjectRepresentation::Sized)) => {
1119+
ptr_vtable(source_ty, target_ty)
1120+
}
1121+
11151122
(&ty::Adt(source_adt_def, source_substs), &ty::Adt(target_adt_def, target_substs)) => {
11161123
assert_eq!(source_adt_def, target_adt_def);
11171124

src/test/ui/dyn-star/make-dyn-star.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use std::fmt::Debug;
55

66
fn make_dyn_star(i: usize) {
7-
let dyn_i: dyn* Debug = i as dyn* Debug;
7+
let _dyn_i: dyn* Debug = i as dyn* Debug;
88
}
99

1010
fn main() {

0 commit comments

Comments
 (0)