Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-ty/src/mir/eval.rs25
-rw-r--r--crates/hir-ty/src/mir/eval/tests.rs51
2 files changed, 71 insertions, 5 deletions
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index c69febd019..855dafe2d9 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -3046,7 +3046,7 @@ impl<'a, 'db: 'a> Evaluator<'a, 'db> {
ty: Ty<'db>,
locals: &Locals<'a>,
addr: Address,
- _metadata: &[u8],
+ metadata: &[u8],
span: MirSpan,
) -> Result<'db, ()> {
let Some(drop_fn) = self.lang_items().Drop_drop else {
@@ -3056,13 +3056,23 @@ impl<'a, 'db: 'a> Evaluator<'a, 'db> {
};
let generic_args = GenericArgs::new_from_slice(&[ty.into()]);
- if let Ok(MirOrDynIndex::Mir(body)) =
- self.get_mir_or_dyn_index(drop_fn, generic_args, locals, span)
+ let (drop_impl, drop_args) = self.db.lookup_impl_method(
+ ParamEnvAndCrate { param_env: self.param_env.param_env, krate: self.crate_id },
+ drop_fn,
+ generic_args,
+ );
+ if let Either::Left(drop_impl) = drop_impl
+ && matches!(drop_impl.lookup(self.db).container, ItemContainerId::ImplId(_))
+ && let Ok(body) = self.db.monomorphized_mir_body(
+ drop_impl.into(),
+ drop_args.store(),
+ self.param_env.store(),
+ )
{
self.exec_looked_up_function(
body,
locals,
- drop_fn,
+ drop_impl,
iter::once(IntervalOrOwned::Owned(addr.to_bytes().to_vec())),
span,
Interval { addr: Address::Invalid(0), size: 0 },
@@ -3103,6 +3113,12 @@ impl<'a, 'db: 'a> Evaluator<'a, 'db> {
AdtId::EnumId(_) => (),
}
}
+ TyKind::Dynamic(..) => {
+ if !metadata.is_empty() {
+ let concrete_ty = self.vtable_map.ty_of_bytes(metadata)?;
+ self.run_drop_glue_deep(concrete_ty, locals, addr, &[], span)?;
+ }
+ }
TyKind::Bool
| TyKind::Char
| TyKind::Int(_)
@@ -3125,7 +3141,6 @@ impl<'a, 'db: 'a> Evaluator<'a, 'db> {
| TyKind::Error(_)
| TyKind::Param(_)
| TyKind::Placeholder(_)
- | TyKind::Dynamic(..)
| TyKind::FnPtr(..)
| TyKind::Bound(..)
| TyKind::Infer(..)
diff --git a/crates/hir-ty/src/mir/eval/tests.rs b/crates/hir-ty/src/mir/eval/tests.rs
index 0e94a5b92d..ccc4815d6c 100644
--- a/crates/hir-ty/src/mir/eval/tests.rs
+++ b/crates/hir-ty/src/mir/eval/tests.rs
@@ -230,6 +230,28 @@ fn main() {
}
#[test]
+fn drop_glue_for_type_without_drop_impl_does_not_recurse() {
+ check_pass(
+ r#"
+//- minicore: drop, pin
+
+struct HasDrop;
+impl Drop for HasDrop {
+ fn drop(&mut self) {}
+}
+
+struct WithDropGlue {
+ field: HasDrop,
+}
+
+fn main() {
+ let _c = WithDropGlue { field: HasDrop };
+}
+ "#,
+ );
+}
+
+#[test]
fn drop_if_let() {
check_pass(
r#"
@@ -359,6 +381,35 @@ fn main() {
}
#[test]
+fn drop_glue_for_trait_object() {
+ check_panic(
+ r#"
+//- minicore: manually_drop, coerce_unsized, fmt, panic, drop, pin
+use core::mem::ManuallyDrop;
+use core::ptr::drop_in_place;
+
+struct X;
+impl Drop for X {
+ fn drop(&mut self) {
+ panic!("concrete drop ran");
+ }
+}
+
+trait T {}
+impl T for X {}
+
+fn main() {
+ let mut x = ManuallyDrop::new(X);
+ let p = &mut x as *mut ManuallyDrop<X> as *mut X;
+ let obj: &mut dyn T = unsafe { &mut *p };
+ drop_in_place(obj);
+}
+ "#,
+ "concrete drop ran",
+ );
+}
+
+#[test]
fn manually_drop() {
check_pass(
r#"