diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs index 08adec96a079b..dac03ab7894bf 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_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 5e152af835613..4fec900f86b7c 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -730,7 +730,7 @@ pub(crate) fn codegen_drop<'tcx>( unwind: UnwindAction, ) { let ty = drop_place.layout().ty; - let drop_instance = Instance::resolve_drop_glue(fx.tcx, ty); + let drop_instance = Instance::resolve_drop_in_place(fx.tcx, ty); let ret_block = fx.get_block(target); // AsyncDropGlueCtorShim can't be here diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs index 2d5a29ceb8191..c3a64c326be55 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..4862cff31c3fd 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() { @@ -438,7 +438,7 @@ fn upstream_monomorphizations_provider( let (def_id, args) = match *exported_symbol { ExportedSymbol::Generic(def_id, args) => (def_id, args), ExportedSymbol::DropGlue(ty) => { - if let Some(drop_in_place_fn_def_id) = drop_glue_fn_def_id { + if let Some(drop_in_place_fn_def_id) = drop_in_place_fn_def_id { (drop_in_place_fn_def_id, tcx.mk_args(&[ty.into()])) } else { // `drop_glue` does not exist, don't try to use it. @@ -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() } @@ -613,7 +613,7 @@ pub(crate) fn symbol_name_for_instance_in_crate<'tcx>( } ExportedSymbol::DropGlue(ty) => rustc_symbol_mangling::symbol_name_for_instance_in_crate( tcx, - Instance::resolve_drop_glue(tcx, ty), + Instance::resolve_drop_in_place(tcx, ty), instantiating_crate, ), ExportedSymbol::AsyncDropGlueCtorShim(ty) => { diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 20d6c01f12f73..6e1a308c2ad22 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -644,7 +644,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ) -> MergingSucc { let ty = location.ty(self.mir, bx.tcx()).ty; let ty = self.monomorphize(ty); - let drop_fn = Instance::resolve_drop_glue(bx.tcx(), ty); + let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty); if let ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_, None)) = drop_fn.def { // we don't actually need to drop anything. diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 80cd892c799cd..243264b82fd62 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -927,7 +927,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { _ => { debug_assert_eq!( instance, - ty::Instance::resolve_drop_glue(*self.tcx, place.layout.ty) + ty::Instance::resolve_drop_in_place(*self.tcx, place.layout.ty) ); place } @@ -935,7 +935,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let instance = { let _trace = enter_trace_span!(M, resolve::resolve_drop_glue, ty = ?place.layout.ty); - ty::Instance::resolve_drop_glue(*self.tcx, place.layout.ty) + ty::Instance::resolve_drop_in_place(*self.tcx, place.layout.ty) }; let fn_abi = self.fn_abi_of_instance_no_deduced_attrs(instance, ty::List::empty())?; diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index dd2477503fd6d..c77100f096611 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -606,7 +606,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let instance = { let _trace = enter_trace_span!(M, resolve::resolve_drop_glue, ty = ?place.layout.ty); - Instance::resolve_drop_glue(*self.tcx, place.layout.ty) + Instance::resolve_drop_in_place(*self.tcx, place.layout.ty) }; if let ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_, None)) = instance.def { // This is the branch we enter if and only if the dropped type has no drop glue 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/middle/exported_symbols.rs b/compiler/rustc_middle/src/middle/exported_symbols.rs index e23ad3c832ef7..39de26b66a1be 100644 --- a/compiler/rustc_middle/src/middle/exported_symbols.rs +++ b/compiler/rustc_middle/src/middle/exported_symbols.rs @@ -66,7 +66,7 @@ impl<'tcx> ExportedSymbol<'tcx> { tcx.symbol_name(ty::Instance::new_raw(def_id, args)) } ExportedSymbol::DropGlue(ty) => { - tcx.symbol_name(ty::Instance::resolve_drop_glue(tcx, ty)) + tcx.symbol_name(ty::Instance::resolve_drop_in_place(tcx, ty)) } ExportedSymbol::AsyncDropGlueCtorShim(ty) => { tcx.symbol_name(ty::Instance::resolve_async_drop_in_place(tcx, ty)) 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_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index fb56bda7d4562..26d950b26986f 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -122,7 +122,7 @@ pub(super) fn vtable_allocation_provider<'tcx>( let scalar = match *entry { VtblEntry::MetadataDropInPlace => { if ty.needs_drop(tcx, ty::TypingEnv::fully_monomorphized()) { - let instance = ty::Instance::resolve_drop_glue(tcx, ty); + let instance = ty::Instance::resolve_drop_in_place(tcx, ty); let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance, CTFE_ALLOC_SALT); let fn_ptr = Pointer::from(fn_alloc_id); Scalar::from_pointer(fn_ptr, &tcx) diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index e7c2fb54b2909..889ca37f3ff1b 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -129,7 +129,7 @@ impl RemoveNoopLandingPads { extra.typing_env, ty::EarlyBinder::bind(extra.tcx, ty), ); - let drop_fn = Instance::resolve_drop_glue(extra.tcx, ty); + let drop_fn = Instance::resolve_drop_in_place(extra.tcx, ty); if let ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_, None)) = drop_fn.def { // no need to drop anything, if all of our successors are also no-op then we // can be skipped. diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 68d6c01f15e92..7ccfebee89f2c 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -946,7 +946,7 @@ fn visit_drop_use<'tcx>( source: Span, output: &mut MonoItems<'tcx>, ) { - let instance = Instance::resolve_drop_glue(tcx, ty); + let instance = Instance::resolve_drop_in_place(tcx, ty); visit_instance_use(tcx, instance, is_direct_call, source, output); } @@ -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::Shim(ty::ShimKind::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..ac6b086b351d5 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,50 @@ 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 { + 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::Typeck { .. } + | TypingMode::PostTypeckUntilBorrowck { .. } + | TypingMode::PostBorrowck { .. } + | TypingMode::Reflection + | TypingMode::PostAnalysis + | TypingMode::Codegen + | TypingMode::ErasedNotCoherence(_) => !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_public_bridge/src/context/impls.rs b/compiler/rustc_public_bridge/src/context/impls.rs index 6b12da9d9c4ed..c9715443a6757 100644 --- a/compiler/rustc_public_bridge/src/context/impls.rs +++ b/compiler/rustc_public_bridge/src/context/impls.rs @@ -699,7 +699,7 @@ impl<'tcx, B: Bridge> CompilerCtxt<'tcx, B> { /// Resolve an instance for drop_in_place for the given type. pub fn resolve_drop_in_place(&self, internal_ty: Ty<'tcx>) -> Instance<'tcx> { - let instance = Instance::resolve_drop_glue(self.tcx, internal_ty); + let instance = Instance::resolve_drop_in_place(self.tcx, internal_ty); instance } 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..bff78f7be8ce9 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); @@ -190,6 +163,24 @@ fn resolve_associated_item<'tcx>( ); let args = infcx.tcx.erase_and_anonymize_regions(args); + 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) + ); + } + + // `Destruct` isn't object-safe and has no specialization concerns here, + // so the checks below (dyn-Trait overlap, defaultness, args-compatibility, + // compare_impl_item) don't apply so we build the Instance directly. + debug!("Got user Destruct impl"); + return Ok(Some(Instance { + def: ty::InstanceKind::Item(leaf_def.item.def_id), + args, + })); + } + // HACK: We may have overlapping `dyn Trait` built-in impls and // user-provided blanket impls. Detect that case here, and return // ambiguity. @@ -427,6 +418,52 @@ 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, ..) => { + // 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::InstanceKind::Shim(ty::ShimKind::DropGlue(trait_item_id, None)) + } else { + ty::InstanceKind::Shim(ty::ShimKind::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::Shim(ty::ShimKind::DropGlue( + trait_item_id, + Some(self_ty), + )), + _ => return Ok(None), + } + } else { + ty::InstanceKind::Shim(ty::ShimKind::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..034576580edad 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..431e7ab898b2c 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..adff947955cb6 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..3c2793c204ade --- /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..0f425e6fc5ec6 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 {}