diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs index 08adec96a079b..8d580305baed1 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs @@ -50,7 +50,13 @@ pub trait MetaSized: PointeeSized {} pub trait Sized: MetaSized {} #[lang = "destruct"] -pub trait Destruct {} +pub trait Destruct { + /// Entrypoint for drop + /// + /// Generated by default if not implemented manually. + #[lang = "destruct_drop_in_place"] + unsafe fn drop_in_place(_to_drop: *mut Self); +} #[lang = "tuple_trait"] pub trait Tuple {} diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs index 2d5a29ceb8191..fbd4df8a45ed3 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core.rs @@ -54,7 +54,13 @@ pub trait MetaSized: PointeeSized {} pub trait Sized: MetaSized {} #[lang = "destruct"] -pub trait Destruct {} +pub trait Destruct { + /// Entrypoint for drop + /// + /// Generated by default if not implemented manually. + #[lang = "destruct_drop_in_place"] + unsafe fn drop_in_place(_to_drop: *mut Self); +} #[lang = "tuple_trait"] pub trait Tuple {} diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 7577217401810..8fdc7e9ec1da8 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -430,7 +430,7 @@ fn upstream_monomorphizations_provider( let mut instances: DefIdMap> = Default::default(); - let drop_glue_fn_def_id = tcx.lang_items().drop_glue_fn(); + let drop_in_place_fn_def_id = tcx.lang_items().destruct_drop_in_place(); let async_drop_in_place_fn_def_id = tcx.lang_items().async_drop_in_place_fn(); for &cnum in cnums.iter() { @@ -491,7 +491,7 @@ fn upstream_drop_glue_for_provider<'tcx>( tcx: TyCtxt<'tcx>, args: GenericArgsRef<'tcx>, ) -> Option { - let def_id = tcx.lang_items().drop_glue_fn()?; + let def_id = tcx.lang_items().destruct_drop_in_place()?; tcx.upstream_monomorphizations_for(def_id)?.get(&args).cloned() } diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index e6e0b3726552f..a9a4f3f74bd7d 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -188,6 +188,7 @@ language_item_table! { Drop, sym::drop, drop_trait, Target::Trait, GenericRequirement::None; Destruct, sym::destruct, destruct_trait, Target::Trait, GenericRequirement::None; + DestructDropInPlace, sym::destruct_drop_in_place, destruct_drop_in_place, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; AsyncDrop, sym::async_drop, async_drop_trait, Target::Trait, GenericRequirement::None; AsyncDropInPlace, sym::async_drop_in_place, async_drop_in_place_fn, Target::Fn, GenericRequirement::Exact(1); diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 6a04357827360..a4b1e1d69c087 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -160,7 +160,7 @@ pub enum ShimKind<'tcx> { /// Proxy shim for async drop of future (def_id, proxy_cor_ty, impl_cor_ty) FutureDropPoll(DefId, Ty<'tcx>, Ty<'tcx>), - /// `core::ptr::drop_glue::`. + /// `Destruct::drop_in_place()` /// /// The `DefId` is for `core::ptr::drop_glue`. /// The `Option>` is either `Some(T)`, or `None` for empty drop glue. @@ -786,8 +786,8 @@ impl<'tcx> Instance<'tcx> { } } - pub fn resolve_drop_glue(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> { - let def_id = tcx.require_lang_item(LangItem::DropGlue, DUMMY_SP); + pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> { + let def_id = tcx.require_lang_item(LangItem::DestructDropInPlace, DUMMY_SP); let args = tcx.mk_args(&[ty.into()]); Instance::expect_resolve( tcx, @@ -798,6 +798,16 @@ impl<'tcx> Instance<'tcx> { ) } + pub fn try_resolve_drop_in_place( + tcx: TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + ty: Ty<'tcx>, + ) -> Result>, ErrorGuaranteed> { + let def_id = tcx.require_lang_item(LangItem::DestructDropInPlace, DUMMY_SP); + let args = tcx.mk_args(&[ty.into()]); + Instance::try_resolve(tcx, typing_env, def_id, args) + } + pub fn resolve_async_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> { let def_id = tcx.require_lang_item(LangItem::AsyncDropInPlace, DUMMY_SP); let args = tcx.mk_args(&[ty.into()]); diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 68d6c01f15e92..94ebec730a61f 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1066,6 +1066,9 @@ fn visit_instance_use<'tcx>( /// Returns `true` if we should codegen an instance in the local crate, or returns `false` if we /// can just link to the upstream crate and therefore don't need a mono item. fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> bool { + if let ty::InstanceKind::DropGlue(_, Some(_)) = instance.def { + return instance.upstream_monomorphization(tcx).is_none(); + } let Some(def_id) = instance.def.def_id_if_not_guaranteed_local_codegen() else { return true; }; diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 040f98de7bcfd..7041248654c1a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -472,37 +472,47 @@ where match assemble_from { AssembleCandidatesFrom::All => { - self.assemble_builtin_impl_candidates(goal, &mut candidates)?; - // For performance we only assemble impls if there are no candidates - // which would shadow them. This is necessary to avoid hangs in rayon, - // see trait-system-refactor-initiative#109 for more details. - // - // We always assemble builtin impls as trivial builtin impls have a higher - // priority than where-clauses. - // - // We only do this if any such candidate applies without any constraints - // as we may want to weaken inference guidance in the future and don't want - // to worry about causing major performance regressions when doing so. - // See trait-system-refactor-initiative#226 for some ideas here. - let assemble_impls = match self.typing_mode() { - TypingMode::Coherence => true, - TypingMode::Typeck { .. } - | TypingMode::PostTypeckUntilBorrowck { .. } - | TypingMode::Reflection - | TypingMode::PostBorrowck { .. } - | TypingMode::PostAnalysis - | TypingMode::Codegen - | TypingMode::ErasedNotCoherence(MayBeErased) => !candidates.iter().any(|c| { - matches!( - c.source, - CandidateSource::ParamEnv(ParamEnvSource::NonGlobal) - | CandidateSource::AliasBound(_) - ) && has_no_inference_or_external_constraints(c.result) - }), - }; - if assemble_impls { - self.assemble_impl_candidates(goal, &mut candidates)?; + let trait_def_id = goal.predicate.trait_def_id(self.cx()); + // Check if there are any user defined impls for Destruct. If there are, + // use those, and fallback to builtin drop glue impl if none are present + if self.cx().is_trait_lang_item(trait_def_id, SolverTraitLangItem::Destruct) { + self.assemble_impl_candidates(goal, &mut candidates); + let has_impl_candidate = + candidates.iter().any(|c| matches!(c.source, CandidateSource::Impl(_))); + if !has_impl_candidate { + self.assemble_builtin_impl_candidates(goal, &mut candidates); + } self.assemble_object_bound_candidates(goal, &mut candidates); + } else { + self.assemble_builtin_impl_candidates(goal, &mut candidates); + // For performance we only assemble impls if there are no candidates + // which would shadow them. This is necessary to avoid hangs in rayon, + // see trait-system-refactor-initiative#109 for more details. + // + // We always assemble builtin impls as trivial builtin impls have a higher + // priority than where-clauses. + // + // We only do this if any such candidate applies without any constraints + // as we may want to weaken inference guidance in the future and don't want + // to worry about causing major performance regressions when doing so. + // See trait-system-refactor-initiative#226 for some ideas here. + let assemble_impls = match self.typing_mode() { + TypingMode::Coherence => true, + TypingMode::Analysis { .. } + | TypingMode::Borrowck { .. } + | TypingMode::PostBorrowckAnalysis { .. } + | TypingMode::PostAnalysis => !candidates.iter().any(|c| { + matches!( + c.source, + CandidateSource::ParamEnv(ParamEnvSource::NonGlobal) + | CandidateSource::AliasBound(_) + ) && has_no_inference_or_external_constraints(c.result) + }), + }; + if assemble_impls { + self.assemble_impl_candidates(goal, &mut candidates); + self.assemble_object_bound_candidates(goal, &mut candidates); + } } } AssembleCandidatesFrom::EnvAndBounds => { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index c874c1af265f8..f650d7cbe519c 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -813,6 +813,7 @@ symbols! { derive_from, derive_smart_pointer, destruct, + destruct_drop_in_place, destructuring_assignment, diagnostic, diagnostic_namespace, diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index d4027fcf388b1..5a0d1cbfb3b04 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -114,7 +114,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.assemble_candidates_for_unsizing(obligation, &mut candidates); } Some(LangItem::Destruct) => { - self.assemble_const_destruct_candidates(obligation, &mut candidates); + let before = candidates.vec.len(); + self.assemble_candidates_from_impls(obligation, &mut candidates); + let added_impl = + candidates.vec[before..].iter().any(|c| matches!(c, ImplCandidate(_))); + if !added_impl { + self.assemble_const_destruct_candidates(obligation, &mut candidates); + } } Some(LangItem::TransmuteTrait) => { // User-defined transmutability impls are permitted. diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index b5a82793dcc97..6215583b7479c 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -39,34 +39,7 @@ fn resolve_instance_raw<'tcx>( } else if tcx.is_lang_item(def_id, LangItem::DropGlue) { let ty = args.type_at(0); - let shim = if ty.needs_drop(tcx, typing_env) { - debug!(" => nontrivial drop glue"); - match *ty.kind() { - ty::Coroutine(coroutine_def_id, ..) => { - // FIXME: sync drop of coroutine with async drop (generate both versions?) - // Currently just ignored - if tcx.optimized_mir(coroutine_def_id).coroutine_drop_async().is_some() { - ty::ShimKind::DropGlue(def_id, None) - } else { - ty::ShimKind::DropGlue(def_id, Some(ty)) - } - } - ty::Closure(..) - | ty::CoroutineClosure(..) - | ty::Tuple(..) - | ty::Adt(..) - | ty::Dynamic(..) - | ty::Array(..) - | ty::Slice(..) - | ty::UnsafeBinder(..) => ty::ShimKind::DropGlue(def_id, Some(ty)), - // Drop shims can only be built from ADTs. - _ => return Ok(None), - } - } else { - debug!(" => trivial drop glue"); - ty::ShimKind::DropGlue(def_id, None) - }; - ty::InstanceKind::Shim(shim) + return ty::Instance::try_resolve_drop_in_place(tcx, typing_env, ty); } else if tcx.is_lang_item(def_id, LangItem::AsyncDropInPlace) { let ty = args.type_at(0); @@ -177,6 +150,20 @@ fn resolve_associated_item<'tcx>( if !eligible { return Ok(None); } + if tcx.is_lang_item(trait_ref.def_id, LangItem::Destruct) { + if !tcx.is_lang_item(trait_item_id, LangItem::DestructDropInPlace) { + bug!( + "unexpected associated item for built-in `{trait_ref}`: {}", + tcx.item_name(trait_item_id) + ); + } + + debug!("Got user Destruct impl"); + return Ok(Some(Instance { + def: ty::InstanceKind::Item(leaf_def.item.def_id), + args: rcvr_args, + })); + } let typing_env = typing_env.with_post_analysis_normalized(tcx); let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); @@ -427,6 +414,46 @@ fn resolve_associated_item<'tcx>( } else { bug!("unexpected associated associated item") } + } else if tcx.is_lang_item(trait_ref.def_id, LangItem::Destruct) { + debug!( + "resolving Destruct for ImplSource::Builtin: {:?}, {:?}, {:?}", + typing_env, trait_item_id, rcvr_args + ); + if !tcx.is_lang_item(trait_item_id, LangItem::DestructDropInPlace) { + bug!( + "unexpected associated item for built-in `{trait_ref}`: {}", + tcx.item_name(trait_item_id) + ); + } + + let self_ty = trait_ref.self_ty(); + + let def = if self_ty.needs_drop(tcx, typing_env) { + match *self_ty.kind() { + ty::Coroutine(coroutine_def_id, ..) => { + if tcx.optimized_mir(coroutine_def_id).coroutine_drop_async().is_some() + { + ty::InstanceKind::DropGlue(trait_item_id, None) + } else { + ty::InstanceKind::DropGlue(trait_item_id, Some(self_ty)) + } + } + ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Tuple(..) + | ty::Adt(..) + | ty::Dynamic(..) + | ty::Array(..) + | ty::Slice(..) + | ty::UnsafeBinder(..) => { + ty::InstanceKind::DropGlue(trait_item_id, Some(self_ty)) + } + _ => return Ok(None), + } + } else { + ty::InstanceKind::DropGlue(trait_item_id, None) + }; + Some(ty::Instance { def, args: rcvr_args }) } else { Instance::try_resolve_item_for_coroutine(tcx, trait_item_id, trait_id, rcvr_args) } diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index e3785c92c8d0d..b06003dce1d7d 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -1057,10 +1057,15 @@ marker_impls! { #[unstable(feature = "const_destruct", issue = "133214")] #[rustc_const_unstable(feature = "const_destruct", issue = "133214")] #[lang = "destruct"] -#[diagnostic::on_unimplemented(message = "can't drop `{Self}`")] -#[rustc_deny_explicit_impl] +#[rustc_on_unimplemented(message = "can't drop `{Self}`")] #[rustc_dyn_incompatible_trait] -pub const trait Destruct: PointeeSized {} +pub const trait Destruct: PointeeSized { + /// Entrypoint for drop + /// + /// Generated by default if not implemented manually. + #[lang = "destruct_drop_in_place"] + unsafe fn drop_in_place(_to_drop: *mut Self); +} /// A marker for tuple types. /// diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs index c580841244f1b..8b82fe6bd04c1 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs @@ -2437,7 +2437,13 @@ impl const MyClone for i32 { } } #[lang = "destruct"] -pub trait Destruct {} +pub trait Destruct { + /// Entrypoint for drop + /// + /// Generated by default if not implemented manually. + #[lang = "destruct_drop_in_place"] + unsafe fn drop_in_place(_to_drop: *mut Self); +} "#, ); } diff --git a/tests/auxiliary/minicore.rs b/tests/auxiliary/minicore.rs index e8bfdf80c98e8..065273db84850 100644 --- a/tests/auxiliary/minicore.rs +++ b/tests/auxiliary/minicore.rs @@ -70,7 +70,13 @@ pub trait Sized: MetaSized {} #[lang = "destruct"] #[diagnostic::on_unimplemented(message = "can't drop `{Self}`")] -pub trait Destruct: PointeeSized {} +pub trait Destruct: PointeeSized { + /// Entrypoint for drop + /// + /// Generated by default if not implemented manually. + #[lang = "destruct_drop_in_place"] + unsafe fn drop_in_place(_to_drop: *mut Self); +} #[lang = "legacy_receiver"] pub trait LegacyReceiver {} diff --git a/tests/ui/consts/const-eval/c-variadic-fail.stderr b/tests/ui/consts/const-eval/c-variadic-fail.stderr index ccf2936324a9c..f4a02006129b5 100644 --- a/tests/ui/consts/const-eval/c-variadic-fail.stderr +++ b/tests/ui/consts/const-eval/c-variadic-fail.stderr @@ -464,8 +464,8 @@ LL | drop(ap); | ^^^^^^^^ note: inside `std::mem::drop::>` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL -note: inside `std::ptr::drop_glue::> - shim(Some(VaList<'_>))` - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +note: inside ` as Destruct>::drop_in_place - shim(Some(VaList<'_>))` + --> $SRC_DIR/core/src/marker.rs:LL:COL note: inside ` as Drop>::drop` --> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL @@ -496,8 +496,8 @@ LL | drop(ap); | ^^^^^^^^ note: inside `std::mem::drop::>` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL -note: inside `std::ptr::drop_glue::> - shim(Some(VaList<'_>))` - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +note: inside ` as Destruct>::drop_in_place - shim(Some(VaList<'_>))` + --> $SRC_DIR/core/src/marker.rs:LL:COL note: inside ` as Drop>::drop` --> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL @@ -549,8 +549,8 @@ error[E0080]: pointer not dereferenceable: pointer must point to some allocation LL | } | ^ evaluation of `drop_of_invalid::{constant#0}` failed inside this call | -note: inside `std::ptr::drop_glue::> - shim(Some(VaList<'_>))` - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +note: inside ` as Destruct>::drop_in_place - shim(Some(VaList<'_>))` + --> $SRC_DIR/core/src/marker.rs:LL:COL note: inside ` as Drop>::drop` --> $SRC_DIR/core/src/ffi/va_list.rs:LL:COL diff --git a/tests/ui/consts/required-consts/collect-in-dead-drop.noopt.stderr b/tests/ui/consts/required-consts/collect-in-dead-drop.noopt.stderr index 38e169c97016d..2727672dd4d40 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-drop.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-drop.noopt.stderr @@ -11,7 +11,7 @@ LL | let _ = Fail::::C; | ^^^^^^^^^^^^ note: the above error was encountered while instantiating `fn as Drop>::drop` - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL + --> $SRC_DIR/core/src/marker.rs:LL:COL error: aborting due to 1 previous error diff --git a/tests/ui/consts/required-consts/collect-in-dead-drop.opt.stderr b/tests/ui/consts/required-consts/collect-in-dead-drop.opt.stderr index 38e169c97016d..2727672dd4d40 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-drop.opt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-drop.opt.stderr @@ -11,7 +11,7 @@ LL | let _ = Fail::::C; | ^^^^^^^^^^^^ note: the above error was encountered while instantiating `fn as Drop>::drop` - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL + --> $SRC_DIR/core/src/marker.rs:LL:COL error: aborting due to 1 previous error diff --git a/tests/ui/consts/required-consts/collect-in-dead-move.noopt.stderr b/tests/ui/consts/required-consts/collect-in-dead-move.noopt.stderr index 9f652e26f242f..19b41fb3e3ae6 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-move.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-move.noopt.stderr @@ -11,7 +11,7 @@ LL | let _ = Fail::::C; | ^^^^^^^^^^^^ note: the above error was encountered while instantiating `fn as Drop>::drop` - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL + --> $SRC_DIR/core/src/marker.rs:LL:COL error: aborting due to 1 previous error diff --git a/tests/ui/consts/required-consts/collect-in-dead-move.opt.stderr b/tests/ui/consts/required-consts/collect-in-dead-move.opt.stderr index 9f652e26f242f..19b41fb3e3ae6 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-move.opt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-move.opt.stderr @@ -11,7 +11,7 @@ LL | let _ = Fail::::C; | ^^^^^^^^^^^^ note: the above error was encountered while instantiating `fn as Drop>::drop` - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL + --> $SRC_DIR/core/src/marker.rs:LL:COL error: aborting due to 1 previous error diff --git a/tests/ui/drop/custom_dtor_with_destruct.rs b/tests/ui/drop/custom_dtor_with_destruct.rs new file mode 100644 index 0000000000000..54ca01ca24fa1 --- /dev/null +++ b/tests/ui/drop/custom_dtor_with_destruct.rs @@ -0,0 +1,19 @@ +//@ run-pass +//@ check-stdout +//@ check-run-results + +#![feature(const_destruct)] +use std::marker::Destruct; +struct A { + _a: String, +} + +impl Destruct for A { + unsafe fn drop_in_place(_to_drop: *mut Self) { + println!("Hey i was dropped"); + } +} + +fn main() { + let _a = A { _a: String::new() }; +} diff --git a/tests/ui/drop/custom_dtor_with_destruct.run.stdout b/tests/ui/drop/custom_dtor_with_destruct.run.stdout new file mode 100644 index 0000000000000..e864173b60164 --- /dev/null +++ b/tests/ui/drop/custom_dtor_with_destruct.run.stdout @@ -0,0 +1 @@ +Hey i was dropped diff --git a/tests/ui/traits/const-traits/auxiliary/minicore.rs b/tests/ui/traits/const-traits/auxiliary/minicore.rs index e1d1135e6d4ec..d5d6cfc2cb342 100644 --- a/tests/ui/traits/const-traits/auxiliary/minicore.rs +++ b/tests/ui/traits/const-traits/auxiliary/minicore.rs @@ -122,7 +122,13 @@ impl Receiver for T { } #[lang = "destruct"] -pub const trait Destruct {} +pub const trait Destruct { + /// Entrypoint for drop + /// + /// Generated by default if not implemented manually. + #[lang = "destruct_drop_in_place"] + unsafe fn drop_in_place(_to_drop: *mut Self); +} #[lang = "freeze"] pub unsafe auto trait Freeze {}