diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 4ea21b4d06d..1e02129855e 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -3,6 +3,7 @@ //! See the `Qualif` trait for more info. use rustc_errors::ErrorGuaranteed; +use rustc_hir::LangItem; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::TraitEngine; use rustc_middle::mir::*; @@ -152,18 +153,14 @@ impl Qualif for NeedsNonConstDrop { return false; } - let Some(drop_trait) = cx.tcx.lang_items().drop_trait() else { - // there is no way to define a type that needs non-const drop - // without having the lang item present. - return false; - }; + let destruct = cx.tcx.require_lang_item(LangItem::Destruct, None); let obligation = Obligation::new( ObligationCause::dummy(), cx.param_env, ty::Binder::dummy(ty::TraitPredicate { trait_ref: ty::TraitRef { - def_id: drop_trait, + def_id: destruct, substs: cx.tcx.mk_substs_trait(ty, &[]), }, constness: ty::BoundConstness::ConstIfConst, @@ -174,15 +171,16 @@ impl Qualif for NeedsNonConstDrop { cx.tcx.infer_ctxt().enter(|infcx| { let mut selcx = SelectionContext::new(&infcx); let Some(impl_src) = selcx.select(&obligation).ok().flatten() else { - // If we couldn't select a const drop candidate, then it's bad + // If we couldn't select a const destruct candidate, then it's bad return true; }; if !matches!( impl_src, - ImplSource::ConstDrop(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst) + ImplSource::ConstDestruct(_) + | ImplSource::Param(_, ty::BoundConstness::ConstIfConst) ) { - // If our const drop candidate is not ConstDrop or implied by the param env, + // If our const destruct candidate is not ConstDestruct or implied by the param env, // then it's bad return true; } diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index b299e71c9c4..7c312e1b61d 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -216,6 +216,7 @@ language_item_table! { Freeze, sym::freeze, freeze_trait, Target::Trait, GenericRequirement::Exact(0); Drop, sym::drop, drop_trait, Target::Trait, GenericRequirement::None; + Destruct, sym::destruct, destruct_trait, Target::Trait, GenericRequirement::None; CoerceUnsized, sym::coerce_unsized, coerce_unsized_trait, Target::Trait, GenericRequirement::Minimum(1); DispatchFromDyn, sym::dispatch_from_dyn, dispatch_from_dyn_trait, Target::Trait, GenericRequirement::Minimum(1); diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index 5b6997bf0ee..81d308ee347 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -93,10 +93,6 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { let Trait(trait_predicate) = predicate.kind().skip_binder() else { continue }; - if trait_predicate.is_const_if_const() { - // `~const Drop` definitely have meanings so avoid linting here. - continue; - } let def_id = trait_predicate.trait_ref.def_id; if cx.tcx.lang_items().drop_trait() == Some(def_id) { // Explicitly allow `impl Drop`, a drop-guards-as-Voldemort-type pattern. diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 45610fa77d3..36bbccf0a80 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -577,7 +577,7 @@ pub enum ImplSource<'tcx, N> { TraitAlias(ImplSourceTraitAliasData<'tcx, N>), /// ImplSource for a `const Drop` implementation. - ConstDrop(ImplSourceConstDropData), + ConstDestruct(ImplSourceConstDestructData), } impl<'tcx, N> ImplSource<'tcx, N> { @@ -595,7 +595,7 @@ impl<'tcx, N> ImplSource<'tcx, N> { | ImplSource::Pointee(ImplSourcePointeeData) => Vec::new(), ImplSource::TraitAlias(d) => d.nested, ImplSource::TraitUpcasting(d) => d.nested, - ImplSource::ConstDrop(i) => i.nested, + ImplSource::ConstDestruct(i) => i.nested, } } @@ -613,7 +613,7 @@ impl<'tcx, N> ImplSource<'tcx, N> { | ImplSource::Pointee(ImplSourcePointeeData) => &[], ImplSource::TraitAlias(d) => &d.nested, ImplSource::TraitUpcasting(d) => &d.nested, - ImplSource::ConstDrop(i) => &i.nested, + ImplSource::ConstDestruct(i) => &i.nested, } } @@ -672,9 +672,11 @@ impl<'tcx, N> ImplSource<'tcx, N> { nested: d.nested.into_iter().map(f).collect(), }) } - ImplSource::ConstDrop(i) => ImplSource::ConstDrop(ImplSourceConstDropData { - nested: i.nested.into_iter().map(f).collect(), - }), + ImplSource::ConstDestruct(i) => { + ImplSource::ConstDestruct(ImplSourceConstDestructData { + nested: i.nested.into_iter().map(f).collect(), + }) + } } } } @@ -767,7 +769,7 @@ pub struct ImplSourceDiscriminantKindData; pub struct ImplSourcePointeeData; #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] -pub struct ImplSourceConstDropData { +pub struct ImplSourceConstDestructData { pub nested: Vec, } diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index e18f04d92ee..56d42706f67 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -146,8 +146,8 @@ pub enum SelectionCandidate<'tcx> { BuiltinUnsizeCandidate, - /// Implementation of `const Drop`, optionally from a custom `impl const Drop`. - ConstDropCandidate(Option), + /// Implementation of `const Destruct`, optionally from a custom `impl const Drop`. + ConstDestructCandidate(Option), } /// The result of trait evaluation. The order is important diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs index 6ce9f5eea34..ea706053231 100644 --- a/compiler/rustc_middle/src/traits/structural_impls.rs +++ b/compiler/rustc_middle/src/traits/structural_impls.rs @@ -33,7 +33,7 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> { super::ImplSource::TraitUpcasting(ref d) => write!(f, "{:?}", d), - super::ImplSource::ConstDrop(ref d) => write!(f, "{:?}", d), + super::ImplSource::ConstDestruct(ref d) => write!(f, "{:?}", d), } } } @@ -120,9 +120,9 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitAliasData<'tcx, } } -impl fmt::Debug for traits::ImplSourceConstDropData { +impl fmt::Debug for traits::ImplSourceConstDestructData { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ImplSourceConstDropData(nested={:?})", self.nested) + write!(f, "ImplSourceConstDestructData(nested={:?})", self.nested) } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 83ab761aa55..3124cc5dba8 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -765,6 +765,7 @@ impl<'tcx> TraitPredicate<'tcx> { if unlikely!(Some(self.trait_ref.def_id) == tcx.lang_items().drop_trait()) { // remap without changing constness of this predicate. // this is because `T: ~const Drop` has a different meaning to `T: Drop` + // FIXME(fee1-dead): remove this logic after beta bump param_env.remap_constness_with(self.constness) } else { *param_env = param_env.with_constness(self.constness.and(param_env.constness())) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 523a1066a1c..48ca321b737 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -571,6 +571,7 @@ symbols! { deref_target, derive, derive_default_enum, + destruct, destructuring_assignment, diagnostic, direct, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 614a5e04809..390381752f9 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1569,7 +1569,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( super::ImplSource::AutoImpl(..) | super::ImplSource::Builtin(..) | super::ImplSource::TraitUpcasting(_) - | super::ImplSource::ConstDrop(_) => { + | super::ImplSource::ConstDestruct(_) => { // These traits have no associated types. selcx.tcx().sess.delay_span_bug( obligation.cause.span, @@ -1644,7 +1644,7 @@ fn confirm_select_candidate<'cx, 'tcx>( | super::ImplSource::Builtin(..) | super::ImplSource::TraitUpcasting(_) | super::ImplSource::TraitAlias(..) - | super::ImplSource::ConstDrop(_) => { + | super::ImplSource::ConstDestruct(_) => { // we don't create Select candidates with this kind of resolution span_bug!( obligation.cause.span, 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 d76bcf6807f..c0a283d2eda 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -5,6 +5,7 @@ //! candidates. See the [rustc dev guide] for more details. //! //! [rustc dev guide]:https://rustc-dev-guide.rust-lang.org/traits/resolution.html#candidate-assembly +use hir::LangItem; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::traits::TraitEngine; @@ -307,7 +308,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } else if lang_items.drop_trait() == Some(def_id) && obligation.predicate.is_const_if_const() { - self.assemble_const_drop_candidates(obligation, &mut candidates); + // holds to make it easier to transition + // FIXME(fee1-dead): add a note for selection error of `~const Drop` + // when beta is bumped + // FIXME: remove this when beta is bumped + #[cfg(bootstrap)] + {} + + candidates.vec.push(SelectionCandidate::ConstDestructCandidate(None)) + } else if lang_items.destruct_trait() == Some(def_id) { + self.assemble_const_destruct_candidates(obligation, &mut candidates); } else { if lang_items.clone_trait() == Some(def_id) { // Same builtin conditions as `Copy`, i.e., every type which has builtin support @@ -906,15 +916,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - fn assemble_const_drop_candidates( + fn assemble_const_destruct_candidates( &mut self, obligation: &TraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { - // If the predicate is `~const Drop` in a non-const environment, we don't actually need + // If the predicate is `~const Destruct` in a non-const environment, we don't actually need // to check anything. We'll short-circuit checking any obligations in confirmation, too. - if obligation.param_env.constness() == hir::Constness::NotConst { - candidates.vec.push(ConstDropCandidate(None)); + if !obligation.is_const() { + candidates.vec.push(ConstDestructCandidate(None)); return; } @@ -927,7 +937,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Param(_) | ty::Placeholder(_) | ty::Projection(_) => { - // We don't know if these are `~const Drop`, at least + // We don't know if these are `~const Destruct`, at least // not structurally... so don't push a candidate. } @@ -951,14 +961,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Generator(..) | ty::Tuple(_) | ty::GeneratorWitness(_) => { - // These are built-in, and cannot have a custom `impl const Drop`. - candidates.vec.push(ConstDropCandidate(None)); + // These are built-in, and cannot have a custom `impl const Destruct`. + candidates.vec.push(ConstDestructCandidate(None)); } ty::Adt(..) => { // Find a custom `impl Drop` impl, if it exists let relevant_impl = self.tcx().find_map_relevant_impl( - obligation.predicate.def_id(), + self.tcx().require_lang_item(LangItem::Drop, None), obligation.predicate.skip_binder().trait_ref.self_ty(), Some, ); @@ -966,11 +976,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if let Some(impl_def_id) = relevant_impl { // Check that `impl Drop` is actually const, if there is a custom impl if self.tcx().impl_constness(impl_def_id) == hir::Constness::Const { - candidates.vec.push(ConstDropCandidate(Some(impl_def_id))); + candidates.vec.push(ConstDestructCandidate(Some(impl_def_id))); } } else { // Otherwise check the ADT like a built-in type (structurally) - candidates.vec.push(ConstDropCandidate(None)); + candidates.vec.push(ConstDestructCandidate(None)); } } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 05479899f3a..df760a166e8 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -8,7 +8,6 @@ //! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; -use rustc_hir::Constness; use rustc_index::bit_set::GrowableBitSet; use rustc_infer::infer::InferOk; use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; @@ -29,9 +28,9 @@ use crate::traits::TraitNotObjectSafe; use crate::traits::VtblSegment; use crate::traits::{BuiltinDerivedObligation, ImplDerivedObligation}; use crate::traits::{ - ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData, ImplSourceConstDropData, - ImplSourceDiscriminantKindData, ImplSourceFnPointerData, ImplSourceGeneratorData, - ImplSourceObjectData, ImplSourcePointeeData, ImplSourceTraitAliasData, + ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData, + ImplSourceConstDestructData, ImplSourceDiscriminantKindData, ImplSourceFnPointerData, + ImplSourceGeneratorData, ImplSourceObjectData, ImplSourcePointeeData, ImplSourceTraitAliasData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, }; use crate::traits::{ObjectCastObligation, PredicateObligation, TraitObligation}; @@ -156,9 +155,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(ImplSource::TraitUpcasting(data)) } - ConstDropCandidate(def_id) => { - let data = self.confirm_const_drop_candidate(obligation, def_id)?; - Ok(ImplSource::ConstDrop(data)) + ConstDestructCandidate(def_id) => { + let data = self.confirm_const_destruct_candidate(obligation, def_id)?; + Ok(ImplSource::ConstDestruct(data)) } } } @@ -1037,14 +1036,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(ImplSourceBuiltinData { nested }) } - fn confirm_const_drop_candidate( + fn confirm_const_destruct_candidate( &mut self, obligation: &TraitObligation<'tcx>, impl_def_id: Option, - ) -> Result>, SelectionError<'tcx>> { - // `~const Drop` in a non-const environment is always trivially true, since our type is `Drop` - if obligation.param_env.constness() == Constness::NotConst { - return Ok(ImplSourceConstDropData { nested: vec![] }); + ) -> Result>, SelectionError<'tcx>> { + // `~const Destruct` in a non-const environment is always trivially true, since our type is `Drop` + if !obligation.is_const() { + return Ok(ImplSourceConstDestructData { nested: vec![] }); + } + + let drop_trait = self.tcx().require_lang_item(LangItem::Drop, None); + // FIXME: remove if statement below when beta is bumped + #[cfg(bootstrap)] + {} + + if obligation.predicate.skip_binder().def_id() == drop_trait { + return Ok(ImplSourceConstDestructData { nested: vec![] }); } let tcx = self.tcx(); @@ -1054,9 +1062,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let cause = obligation.derived_cause(BuiltinDerivedObligation); // If we have a custom `impl const Drop`, then - // first check it like a regular impl candidate + // first check it like a regular impl candidate. + // This is copied from confirm_impl_candidate but remaps the predicate to `~const Drop` beforehand. if let Some(impl_def_id) = impl_def_id { - nested.extend(self.confirm_impl_candidate(obligation, impl_def_id).nested); + let obligations = self.infcx.commit_unconditionally(|_| { + let mut new_obligation = obligation.clone(); + new_obligation.predicate = new_obligation.predicate.map_bound(|mut trait_pred| { + trait_pred.trait_ref.def_id = drop_trait; + trait_pred + }); + let substs = self.rematch_impl(impl_def_id, &new_obligation); + debug!(?substs, "impl substs"); + let cause = obligation.derived_cause(ImplDerivedObligation); + ensure_sufficient_stack(|| { + self.vtable_impl( + impl_def_id, + substs, + cause, + new_obligation.recursion_depth + 1, + new_obligation.param_env, + ) + }) + }); + nested.extend(obligations.nested); } // We want to confirm the ADT's fields if we have an ADT @@ -1114,7 +1142,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self_ty .rebind(ty::TraitPredicate { trait_ref: ty::TraitRef { - def_id: self.tcx().require_lang_item(LangItem::Drop, None), + def_id: self + .tcx() + .require_lang_item(LangItem::Destruct, None), substs: self.tcx().mk_substs_trait(nested_ty, &[]), }, constness: ty::BoundConstness::ConstIfConst, @@ -1140,7 +1170,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let predicate = self_ty .rebind(ty::TraitPredicate { trait_ref: ty::TraitRef { - def_id: self.tcx().require_lang_item(LangItem::Drop, None), + def_id: self.tcx().require_lang_item(LangItem::Destruct, None), substs: self.tcx().mk_substs_trait(nested_ty, &[]), }, constness: ty::BoundConstness::ConstIfConst, @@ -1158,6 +1188,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - Ok(ImplSourceConstDropData { nested }) + Ok(ImplSourceConstDestructData { nested }) } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index a1a8497859d..5d07139e87b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1179,7 +1179,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { GeneratorCandidate => {} // FnDef where the function is const FnPointerCandidate { is_const: true } => {} - ConstDropCandidate(_) => {} + ConstDestructCandidate(_) => {} _ => { // reject all other types of candidates continue; @@ -1589,7 +1589,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }; // (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`, - // `DiscriminantKindCandidate`, and `ConstDropCandidate` to anything else. + // `DiscriminantKindCandidate`, and `ConstDestructCandidate` to anything else. // // This is a fix for #53123 and prevents winnowing from accidentally extending the // lifetime of a variable. @@ -1606,7 +1606,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate | PointeeCandidate - | ConstDropCandidate(_), + | ConstDestructCandidate(_), _, ) => true, ( @@ -1614,7 +1614,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate | PointeeCandidate - | ConstDropCandidate(_), + | ConstDestructCandidate(_), ) => false, (ParamCandidate(other), ParamCandidate(victim)) => { diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 295a91959eb..802a59abe5f 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -378,7 +378,7 @@ fn resolve_associated_item<'tcx>( | traits::ImplSource::DiscriminantKind(..) | traits::ImplSource::Pointee(..) | traits::ImplSource::TraitUpcasting(_) - | traits::ImplSource::ConstDrop(_) => None, + | traits::ImplSource::ConstDestruct(_) => None, }) } diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index bd7d721b5e1..44389ee47b0 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -14,6 +14,8 @@ use core::ptr::{self, NonNull}; #[doc(inline)] pub use core::alloc::*; +use core::marker::Destruct; + #[cfg(test)] mod tests; @@ -324,12 +326,16 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { #[cfg_attr(not(test), lang = "box_free")] #[inline] #[rustc_const_unstable(feature = "const_box", issue = "92521")] +#[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping // This signature has to be the same as `Box`, otherwise an ICE will happen. // When an additional parameter to `Box` is added (like `A: Allocator`), this has to be added here as // well. // For example if `Box` is changed to `struct Box(Unique, A)`, // this function has to be changed to `fn box_free(Unique, A)` as well. -pub(crate) const unsafe fn box_free( +pub(crate) const unsafe fn box_free< + T: ?Sized, + A: ~const Allocator + ~const Drop + ~const Destruct, +>( ptr: Unique, alloc: A, ) { diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index 8b13e36c4b3..27e5af4f1be 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -331,6 +331,7 @@ impl Cow<'_, B> { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_deref", issue = "88955")] +#[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping impl const Deref for Cow<'_, B> where B::Owned: ~const Borrow, diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 7dce3db0a47..b5f4c9a237b 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -143,7 +143,7 @@ use core::hash::{Hash, Hasher}; #[cfg(not(no_global_oom_handling))] use core::iter::FromIterator; use core::iter::{FusedIterator, Iterator}; -use core::marker::{Unpin, Unsize}; +use core::marker::{Destruct, Unpin, Unsize}; use core::mem; use core::ops::{ CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Generator, GeneratorState, Receiver, @@ -349,9 +349,10 @@ impl Box { #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[must_use] #[inline] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn new_in(x: T, alloc: A) -> Self where - A: ~const Allocator + ~const Drop, + A: ~const Allocator + ~const Drop + ~const Destruct, { let mut boxed = Self::new_uninit_in(alloc); unsafe { @@ -378,10 +379,11 @@ impl Box { #[unstable(feature = "allocator_api", issue = "32838")] #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn try_new_in(x: T, alloc: A) -> Result where - T: ~const Drop, - A: ~const Allocator + ~const Drop, + T: ~const Drop + ~const Destruct, + A: ~const Allocator + ~const Drop + ~const Destruct, { let mut boxed = Self::try_new_uninit_in(alloc)?; unsafe { @@ -415,9 +417,10 @@ impl Box { #[cfg(not(no_global_oom_handling))] #[must_use] // #[unstable(feature = "new_uninit", issue = "63291")] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn new_uninit_in(alloc: A) -> Box, A> where - A: ~const Allocator + ~const Drop, + A: ~const Allocator + ~const Drop + ~const Destruct, { let layout = Layout::new::>(); // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. @@ -453,9 +456,10 @@ impl Box { #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "new_uninit", issue = "63291")] #[rustc_const_unstable(feature = "const_box", issue = "92521")] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn try_new_uninit_in(alloc: A) -> Result, A>, AllocError> where - A: ~const Allocator + ~const Drop, + A: ~const Allocator + ~const Drop + ~const Destruct, { let layout = Layout::new::>(); let ptr = alloc.allocate(layout)?.cast(); @@ -487,9 +491,10 @@ impl Box { #[cfg(not(no_global_oom_handling))] // #[unstable(feature = "new_uninit", issue = "63291")] #[must_use] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn new_zeroed_in(alloc: A) -> Box, A> where - A: ~const Allocator + ~const Drop, + A: ~const Allocator + ~const Drop + ~const Destruct, { let layout = Layout::new::>(); // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. @@ -525,9 +530,10 @@ impl Box { #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "new_uninit", issue = "63291")] #[rustc_const_unstable(feature = "const_box", issue = "92521")] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn try_new_zeroed_in(alloc: A) -> Result, A>, AllocError> where - A: ~const Allocator + ~const Drop, + A: ~const Allocator + ~const Drop + ~const Destruct, { let layout = Layout::new::>(); let ptr = alloc.allocate_zeroed(layout)?.cast(); @@ -541,9 +547,10 @@ impl Box { #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[must_use] #[inline(always)] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn pin_in(x: T, alloc: A) -> Pin where - A: 'static + ~const Allocator + ~const Drop, + A: 'static + ~const Allocator + ~const Drop + ~const Destruct, { Self::into_pin(Self::new_in(x, alloc)) } @@ -572,9 +579,10 @@ impl Box { #[unstable(feature = "box_into_inner", issue = "80437")] #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn into_inner(boxed: Self) -> T where - Self: ~const Drop, + Self: ~const Drop + ~const Destruct, { *boxed } diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs index d5119d0b7c3..a13593a539d 100644 --- a/library/core/src/bool.rs +++ b/library/core/src/bool.rs @@ -1,5 +1,7 @@ //! impl bool {} +use crate::marker::Destruct; + #[lang = "bool"] impl bool { /// Returns `Some(t)` if the `bool` is [`true`](../std/keyword.true.html), @@ -16,9 +18,10 @@ impl bool { #[unstable(feature = "bool_to_option", issue = "80967")] #[rustc_const_unstable(feature = "const_bool_to_option", issue = "91917")] #[inline] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn then_some(self, t: T) -> Option where - T: ~const Drop, + T: ~const Drop + ~const Destruct, { if self { Some(t) } else { None } } @@ -35,10 +38,11 @@ impl bool { #[stable(feature = "lazy_bool_to_option", since = "1.50.0")] #[rustc_const_unstable(feature = "const_bool_to_option", issue = "91917")] #[inline] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn then(self, f: F) -> Option where F: ~const FnOnce() -> T, - F: ~const Drop, + F: ~const Drop + ~const Destruct, { if self { Some(f()) } else { None } } diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index 1912694412b..cfdc51c71ee 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -36,6 +36,8 @@ #![stable(feature = "rust1", since = "1.0.0")] +use crate::marker::Destruct; + /// A common trait for the ability to explicitly duplicate an object. /// /// Differs from [`Copy`] in that [`Copy`] is implicit and an inexpensive bit-wise copy, while @@ -128,9 +130,10 @@ pub trait Clone: Sized { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[default_method_body_is_const] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping fn clone_from(&mut self, source: &Self) where - Self: ~const Drop, + Self: ~const Drop + ~const Destruct, { *self = source.clone() } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 1d457c2b7d5..22c6c1cd868 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -54,7 +54,7 @@ )] #![allow(missing_docs)] -use crate::marker::DiscriminantKind; +use crate::marker::{Destruct, DiscriminantKind}; use crate::mem; // These imports are used for simplifying intra-doc links @@ -2353,6 +2353,7 @@ pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { #[rustc_const_unstable(feature = "const_eval_select", issue = "none")] #[lang = "const_eval_select"] #[rustc_do_not_const_check] +#[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const unsafe fn const_eval_select( arg: ARG, _called_in_const: F, @@ -2360,7 +2361,7 @@ pub const unsafe fn const_eval_select( ) -> RET where F: ~const FnOnce, - G: FnOnce + ~const Drop, + G: FnOnce + ~const Drop + ~const Destruct, { called_at_rt.call_once(arg) } @@ -2372,6 +2373,7 @@ where )] #[rustc_const_unstable(feature = "const_eval_select", issue = "none")] #[lang = "const_eval_select_ct"] +#[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const unsafe fn const_eval_select_ct( arg: ARG, called_in_const: F, @@ -2379,7 +2381,7 @@ pub const unsafe fn const_eval_select_ct( ) -> RET where F: ~const FnOnce, - G: FnOnce + ~const Drop, + G: FnOnce + ~const Drop + ~const Destruct, { called_in_const.call_once(arg) } diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 82bac2640b4..6b9d6253e42 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -792,6 +792,22 @@ impl Unpin for *const T {} #[stable(feature = "pin_raw", since = "1.38.0")] impl Unpin for *mut T {} +/// A marker for types that can be dropped. +/// +/// This should be used for `~const` bounds, +/// as non-const bounds will always hold for every type. +#[unstable(feature = "const_trait_impl", issue = "67792")] +#[cfg_attr(not(bootstrap), lang = "destruct")] +#[cfg_attr( + not(bootstrap), + rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg,) +)] +pub trait Destruct {} + +#[cfg(bootstrap)] +#[unstable(feature = "const_trait_impl", issue = "67792")] +impl const Destruct for T {} + /// Implementations of `Copy` for primitive types. /// /// Implementations that cannot be described in Rust diff --git a/library/core/src/option.rs b/library/core/src/option.rs index bcba18a4a3e..acab8de8c70 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -503,6 +503,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::iter::{self, FromIterator, FusedIterator, TrustedLen}; +use crate::marker::Destruct; use crate::panicking::{panic, panic_str}; use crate::pin::Pin; use crate::{ @@ -772,9 +773,10 @@ impl Option { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn unwrap_or(self, default: T) -> T where - T: ~const Drop, + T: ~const Drop + ~const Destruct, { match self { Some(x) => x, @@ -794,10 +796,11 @@ impl Option { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn unwrap_or_else(self, f: F) -> T where F: ~const FnOnce() -> T, - F: ~const Drop, + F: ~const Drop + ~const Destruct, { match self { Some(x) => x, @@ -899,10 +902,11 @@ impl Option { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn map(self, f: F) -> Option where F: ~const FnOnce(T) -> U, - F: ~const Drop, + F: ~const Drop + ~const Destruct, { match self { Some(x) => Some(f(x)), @@ -928,10 +932,11 @@ impl Option { #[inline] #[unstable(feature = "result_option_inspect", issue = "91345")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn inspect(self, f: F) -> Self where F: ~const FnOnce(&T), - F: ~const Drop, + F: ~const Drop + ~const Destruct, { if let Some(ref x) = self { f(x); @@ -961,11 +966,12 @@ impl Option { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn map_or(self, default: U, f: F) -> U where F: ~const FnOnce(T) -> U, - F: ~const Drop, - U: ~const Drop, + F: ~const Drop + ~const Destruct, + U: ~const Drop + ~const Destruct, { match self { Some(t) => f(t), @@ -990,12 +996,13 @@ impl Option { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn map_or_else(self, default: D, f: F) -> U where D: ~const FnOnce() -> U, - D: ~const Drop, + D: ~const Drop + ~const Destruct, F: ~const FnOnce(T) -> U, - F: ~const Drop, + F: ~const Drop + ~const Destruct, { match self { Some(t) => f(t), @@ -1027,9 +1034,10 @@ impl Option { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn ok_or(self, err: E) -> Result where - E: ~const Drop, + E: ~const Drop + ~const Destruct, { match self { Some(v) => Ok(v), @@ -1056,10 +1064,11 @@ impl Option { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn ok_or_else(self, err: F) -> Result where F: ~const FnOnce() -> E, - F: ~const Drop, + F: ~const Drop + ~const Destruct, { match self { Some(v) => Ok(v), @@ -1190,10 +1199,11 @@ impl Option { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn and(self, optb: Option) -> Option where - T: ~const Drop, - U: ~const Drop, + T: ~const Drop + ~const Destruct, + U: ~const Drop + ~const Destruct, { match self { Some(_) => optb, @@ -1232,10 +1242,11 @@ impl Option { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn and_then(self, f: F) -> Option where F: ~const FnOnce(T) -> Option, - F: ~const Drop, + F: ~const Drop + ~const Destruct, { match self { Some(x) => f(x), @@ -1270,11 +1281,12 @@ impl Option { #[inline] #[stable(feature = "option_filter", since = "1.27.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn filter

(self, predicate: P) -> Self where - T: ~const Drop, + T: ~const Drop + ~const Destruct, P: ~const FnOnce(&T) -> bool, - P: ~const Drop, + P: ~const Drop + ~const Destruct, { if let Some(x) = self { if predicate(&x) { @@ -1314,9 +1326,10 @@ impl Option { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn or(self, optb: Option) -> Option where - T: ~const Drop, + T: ~const Drop + ~const Destruct, { match self { Some(x) => Some(x), @@ -1340,10 +1353,11 @@ impl Option { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn or_else(self, f: F) -> Option where F: ~const FnOnce() -> Option, - F: ~const Drop, + F: ~const Drop + ~const Destruct, { match self { Some(x) => Some(x), @@ -1375,9 +1389,10 @@ impl Option { #[inline] #[stable(feature = "option_xor", since = "1.37.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn xor(self, optb: Option) -> Option where - T: ~const Drop, + T: ~const Drop + ~const Destruct, { match (self, optb) { (Some(a), None) => Some(a), @@ -1413,9 +1428,10 @@ impl Option { #[inline] #[stable(feature = "option_insert", since = "1.53.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn insert(&mut self, value: T) -> &mut T where - T: ~const Drop, + T: ~const Drop + ~const Destruct, { *self = Some(value); @@ -1446,9 +1462,10 @@ impl Option { #[inline] #[stable(feature = "option_entry", since = "1.20.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn get_or_insert(&mut self, value: T) -> &mut T where - T: ~const Drop, + T: ~const Drop + ~const Destruct, { if let None = *self { *self = Some(value); @@ -1513,10 +1530,11 @@ impl Option { #[inline] #[stable(feature = "option_entry", since = "1.20.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn get_or_insert_with(&mut self, f: F) -> &mut T where F: ~const FnOnce() -> T, - F: ~const Drop, + F: ~const Drop + ~const Destruct, { if let None = *self { // the compiler isn't smart enough to know that we are not dropping a `T` @@ -1627,10 +1645,11 @@ impl Option { /// ``` #[stable(feature = "option_zip_option", since = "1.46.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn zip(self, other: Option) -> Option<(T, U)> where - T: ~const Drop, - U: ~const Drop, + T: ~const Drop + ~const Destruct, + U: ~const Drop + ~const Destruct, { match (self, other) { (Some(a), Some(b)) => Some((a, b)), @@ -1668,12 +1687,13 @@ impl Option { /// ``` #[unstable(feature = "option_zip", issue = "70086")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping pub const fn zip_with(self, other: Option, f: F) -> Option where F: ~const FnOnce(T, U) -> R, - F: ~const Drop, - T: ~const Drop, - U: ~const Drop, + F: ~const Drop + ~const Destruct, + T: ~const Drop + ~const Destruct, + U: ~const Drop + ~const Destruct, { match (self, other) { (Some(a), Some(b)) => Some(f(a, b)), @@ -1860,9 +1880,10 @@ const fn expect_failed(msg: &str) -> ! { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_clone", issue = "91805")] +#[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping impl const Clone for Option where - T: ~const Clone + ~const Drop, + T: ~const Clone + ~const Drop + ~const Destruct, { #[inline] fn clone(&self) -> Self { diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 9a243cbc3a2..afd0c857229 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -490,6 +490,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::iter::{self, FromIterator, FusedIterator, TrustedLen}; +use crate::marker::Destruct; use crate::ops::{self, ControlFlow, Deref, DerefMut}; use crate::{convert, fmt, hint}; @@ -635,7 +636,7 @@ impl Result { #[rustc_const_unstable(feature = "const_result_drop", issue = "92384")] pub const fn ok(self) -> Option where - E: ~const Drop, + E: ~const Drop + ~const Destruct, { match self { Ok(x) => Some(x), @@ -666,7 +667,7 @@ impl Result { #[rustc_const_unstable(feature = "const_result_drop", issue = "92384")] pub const fn err(self) -> Option where - T: ~const Drop, + T: ~const Drop + ~const Destruct, { match self { // FIXME: ~const Drop doesn't quite work right yet @@ -1282,9 +1283,9 @@ impl Result { #[stable(feature = "rust1", since = "1.0.0")] pub const fn and(self, res: Result) -> Result where - T: ~const Drop, - U: ~const Drop, - E: ~const Drop, + T: ~const Drop + ~const Destruct, + U: ~const Drop + ~const Destruct, + E: ~const Drop + ~const Destruct, { match self { // FIXME: ~const Drop doesn't quite work right yet @@ -1367,9 +1368,9 @@ impl Result { #[stable(feature = "rust1", since = "1.0.0")] pub const fn or(self, res: Result) -> Result where - T: ~const Drop, - E: ~const Drop, - F: ~const Drop, + T: ~const Drop + ~const Destruct, + E: ~const Drop + ~const Destruct, + F: ~const Drop + ~const Destruct, { match self { Ok(v) => Ok(v), @@ -1431,8 +1432,8 @@ impl Result { #[stable(feature = "rust1", since = "1.0.0")] pub const fn unwrap_or(self, default: T) -> T where - T: ~const Drop, - E: ~const Drop, + T: ~const Drop + ~const Destruct, + E: ~const Drop + ~const Destruct, { match self { Ok(t) => t, @@ -1802,10 +1803,11 @@ fn unwrap_failed(_msg: &str, _error: &T) -> ! { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_clone", issue = "91805")] +#[cfg_attr(not(bootstrap), allow(drop_bounds))] // FIXME remove `~const Drop` and this attr when bumping impl const Clone for Result where - T: ~const Clone + ~const Drop, - E: ~const Clone + ~const Drop, + T: ~const Clone + ~const Drop + ~const Destruct, + E: ~const Clone + ~const Drop + ~const Destruct, { #[inline] fn clone(&self) -> Self { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 2c61b7468dc..1e3260ce9ae 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -121,11 +121,20 @@ impl Clean> for hir::GenericBound<'_> { hir::GenericBound::Trait(ref t, modifier) => { // `T: ~const Drop` is not equivalent to `T: Drop`, and we don't currently document `~const` bounds // because of its experimental status, so just don't show these. - if Some(t.trait_ref.trait_def_id().unwrap()) == cx.tcx.lang_items().drop_trait() - && hir::TraitBoundModifier::MaybeConst == modifier + // `T: ~const Destruct` is hidden because `T: Destruct` is a no-op. + if modifier == hir::TraitBoundModifier::MaybeConst + && [cx.tcx.lang_items().drop_trait(), cx.tcx.lang_items().destruct_trait()] + .iter() + .any(|tr| *tr == Some(t.trait_ref.trait_def_id().unwrap())) { return None; } + + #[cfg(bootstrap)] + { + // FIXME: remove `lang_items().drop_trait()` from above logic, + // as well as the comment about `~const Drop` because it was renamed to `Destruct`. + } GenericBound::TraitBound(t.clean(cx), modifier) } }) @@ -306,12 +315,21 @@ impl<'a> Clean> for ty::PolyTraitPredicate<'a> { fn clean(&self, cx: &mut DocContext<'_>) -> Option { // `T: ~const Drop` is not equivalent to `T: Drop`, and we don't currently document `~const` bounds // because of its experimental status, so just don't show these. + // `T: ~const Destruct` is hidden because `T: Destruct` is a no-op. if self.skip_binder().constness == ty::BoundConstness::ConstIfConst - && Some(self.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().drop_trait() + && [cx.tcx.lang_items().drop_trait(), cx.tcx.lang_items().destruct_trait()] + .iter() + .any(|tr| *tr == Some(self.skip_binder().def_id())) { return None; } + #[cfg(bootstrap)] + { + // FIXME: remove `lang_items().drop_trait()` from above logic, + // as well as the comment about `~const Drop` because it was renamed to `Destruct`. + } + let poly_trait_ref = self.map_bound(|pred| pred.trait_ref); Some(WherePredicate::BoundPredicate { ty: poly_trait_ref.skip_binder().self_ty().clean(cx), diff --git a/src/test/ui/consts/const-block-const-bound.rs b/src/test/ui/consts/const-block-const-bound.rs index 1ccd0ee9370..42aa0216b87 100644 --- a/src/test/ui/consts/const-block-const-bound.rs +++ b/src/test/ui/consts/const-block-const-bound.rs @@ -1,7 +1,9 @@ #![allow(unused)] #![feature(const_trait_impl, inline_const, negative_impls)] -const fn f(x: T) {} +use std::marker::Destruct; + +const fn f(x: T) {} struct UnconstDrop; @@ -16,8 +18,8 @@ impl !Drop for NonDrop {} fn main() { const { f(UnconstDrop); - //~^ ERROR the trait bound `UnconstDrop: ~const Drop` is not satisfied + //~^ ERROR can't drop f(NonDrop); - //~^ ERROR the trait bound `NonDrop: ~const Drop` is not satisfied + //~^ ERROR can't drop } } diff --git a/src/test/ui/consts/const-block-const-bound.stderr b/src/test/ui/consts/const-block-const-bound.stderr index b5f5694ba83..87ca771e54e 100644 --- a/src/test/ui/consts/const-block-const-bound.stderr +++ b/src/test/ui/consts/const-block-const-bound.stderr @@ -1,16 +1,17 @@ -error[E0277]: the trait bound `UnconstDrop: ~const Drop` is not satisfied - --> $DIR/const-block-const-bound.rs:18:11 +error[E0277]: can't drop `UnconstDrop` in const contexts + --> $DIR/const-block-const-bound.rs:20:11 | LL | f(UnconstDrop); - | - ^^^^^^^^^^^ expected an implementor of trait `~const Drop` + | - ^^^^^^^^^^^ expected an implementor of trait `~const Destruct` | | | required by a bound introduced by this call | + = note: the trait bound `UnconstDrop: ~const Destruct` is not satisfied note: required by a bound in `f` - --> $DIR/const-block-const-bound.rs:4:15 + --> $DIR/const-block-const-bound.rs:6:15 | -LL | const fn f(x: T) {} - | ^^^^^^^^^^^ required by this bound in `f` +LL | const fn f(x: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `f` help: consider borrowing here | LL | f(&UnconstDrop); @@ -18,19 +19,20 @@ LL | f(&UnconstDrop); LL | f(&mut UnconstDrop); | ++++ -error[E0277]: the trait bound `NonDrop: ~const Drop` is not satisfied - --> $DIR/const-block-const-bound.rs:20:11 +error[E0277]: can't drop `NonDrop` in const contexts + --> $DIR/const-block-const-bound.rs:22:11 | LL | f(NonDrop); - | - ^^^^^^^ expected an implementor of trait `~const Drop` + | - ^^^^^^^ expected an implementor of trait `~const Destruct` | | | required by a bound introduced by this call | + = note: the trait bound `NonDrop: ~const Destruct` is not satisfied note: required by a bound in `f` - --> $DIR/const-block-const-bound.rs:4:15 + --> $DIR/const-block-const-bound.rs:6:15 | -LL | const fn f(x: T) {} - | ^^^^^^^^^^^ required by this bound in `f` +LL | const fn f(x: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `f` help: consider borrowing here | LL | f(&NonDrop); diff --git a/src/test/ui/intrinsics/const-eval-select-bad.stderr b/src/test/ui/intrinsics/const-eval-select-bad.stderr index 06a7a2f63cf..c03688d03b6 100644 --- a/src/test/ui/intrinsics/const-eval-select-bad.stderr +++ b/src/test/ui/intrinsics/const-eval-select-bad.stderr @@ -48,7 +48,7 @@ LL | const_eval_select((), 42, 0xDEADBEEF); note: required by a bound in `const_eval_select` --> $SRC_DIR/core/src/intrinsics.rs:LL:COL | -LL | G: FnOnce + ~const Drop, +LL | G: FnOnce + ~const Drop + ~const Destruct, | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select` error[E0271]: type mismatch resolving ` bool {bar} as FnOnce<(i32,)>>::Output == i32` @@ -60,7 +60,7 @@ LL | const_eval_select((1,), foo, bar); note: required by a bound in `const_eval_select` --> $SRC_DIR/core/src/intrinsics.rs:LL:COL | -LL | G: FnOnce + ~const Drop, +LL | G: FnOnce + ~const Drop + ~const Destruct, | ^^^^^^^^^^^^ required by this bound in `const_eval_select` error[E0631]: type mismatch in function arguments diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop-bound.rs index a1cfee6b6e7..948f0efbcfc 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-bound.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-bound.rs @@ -3,7 +3,9 @@ #![feature(const_trait_impl)] #![feature(const_precise_live_drops)] -const fn foo(res: Result) -> Option where E: ~const Drop { +use std::marker::Destruct; + +const fn foo(res: Result) -> Option where E: ~const Destruct { match res { Ok(t) => Some(t), Err(_e) => None, @@ -12,7 +14,11 @@ const fn foo(res: Result) -> Option where E: ~const Drop { pub struct Foo(T); -const fn baz(res: Result, Foo>) -> Option> { +const fn baz(res: Result, Foo>) -> Option> +where + T: ~const Destruct, + E: ~const Destruct, +{ foo(res) } diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr index d88bcdc89ad..fedb1ffdea9 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr @@ -1,17 +1,18 @@ -error[E0277]: the trait bound `NonTrivialDrop: ~const Drop` is not satisfied +error[E0277]: can't drop `NonTrivialDrop` in const contexts --> $DIR/const-drop-fail.rs:43:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call ... LL | NonTrivialDrop, - | ^^^^^^^^^^^^^^ expected an implementor of trait `~const Drop` + | ^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct` | + = note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied note: required by a bound in `check` --> $DIR/const-drop-fail.rs:34:19 | -LL | const fn check(_: T) {} - | ^^^^^^^^^^^ required by this bound in `check` +LL | const fn check(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `check` help: consider borrowing here | LL | &NonTrivialDrop, @@ -19,16 +20,16 @@ LL | &NonTrivialDrop, LL | &mut NonTrivialDrop, | ++++ -error[E0277]: the trait bound `NonTrivialDrop: ~const Drop` is not satisfied in `ConstImplWithDropGlue` +error[E0277]: can't drop `NonTrivialDrop` in const contexts --> $DIR/const-drop-fail.rs:45:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call ... LL | ConstImplWithDropGlue(NonTrivialDrop), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Drop` is not implemented for `NonTrivialDrop` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Destruct` is not implemented for `NonTrivialDrop` | -note: the trait `Drop` is implemented for `NonTrivialDrop`, but that implementation is not `const` +note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const` --> $DIR/const-drop-fail.rs:45:5 | LL | ConstImplWithDropGlue(NonTrivialDrop), @@ -41,28 +42,24 @@ LL | struct ConstImplWithDropGlue(NonTrivialDrop); note: required by a bound in `check` --> $DIR/const-drop-fail.rs:34:19 | -LL | const fn check(_: T) {} - | ^^^^^^^^^^^ required by this bound in `check` +LL | const fn check(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `check` -error[E0277]: the trait bound `ConstDropImplWithBounds: ~const Drop` is not satisfied +error[E0277]: the trait bound `ConstDropImplWithBounds: ~const Destruct` is not satisfied --> $DIR/const-drop-fail.rs:47:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call ... LL | ConstDropImplWithBounds::(PhantomData), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `~const Drop` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct` | -note: required because of the requirements on the impl of `~const Drop` for `ConstDropImplWithBounds` - --> $DIR/const-drop-fail.rs:28:25 - | -LL | impl const Drop for ConstDropImplWithBounds { - | ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds` note: required by a bound in `check` --> $DIR/const-drop-fail.rs:34:19 | -LL | const fn check(_: T) {} - | ^^^^^^^^^^^ required by this bound in `check` +LL | const fn check(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `check` help: consider borrowing here | LL | &ConstDropImplWithBounds::(PhantomData), diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs index 49968b47dbe..001dd430a86 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs @@ -3,7 +3,7 @@ #![feature(const_mut_refs)] #![cfg_attr(precise, feature(const_precise_live_drops))] -use std::marker::PhantomData; +use std::marker::{Destruct, PhantomData}; struct NonTrivialDrop; @@ -31,7 +31,7 @@ impl const Drop for ConstDropImplWithBounds { } } -const fn check(_: T) {} +const fn check(_: T) {} macro_rules! check_all { ($($exp:expr),*$(,)?) => {$( @@ -41,9 +41,9 @@ macro_rules! check_all { check_all! { NonTrivialDrop, - //~^ ERROR the trait bound + //~^ ERROR can't drop ConstImplWithDropGlue(NonTrivialDrop), - //~^ ERROR the trait bound + //~^ ERROR can't drop ConstDropImplWithBounds::(PhantomData), //~^ ERROR the trait bound } diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr index d88bcdc89ad..fedb1ffdea9 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr @@ -1,17 +1,18 @@ -error[E0277]: the trait bound `NonTrivialDrop: ~const Drop` is not satisfied +error[E0277]: can't drop `NonTrivialDrop` in const contexts --> $DIR/const-drop-fail.rs:43:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call ... LL | NonTrivialDrop, - | ^^^^^^^^^^^^^^ expected an implementor of trait `~const Drop` + | ^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct` | + = note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied note: required by a bound in `check` --> $DIR/const-drop-fail.rs:34:19 | -LL | const fn check(_: T) {} - | ^^^^^^^^^^^ required by this bound in `check` +LL | const fn check(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `check` help: consider borrowing here | LL | &NonTrivialDrop, @@ -19,16 +20,16 @@ LL | &NonTrivialDrop, LL | &mut NonTrivialDrop, | ++++ -error[E0277]: the trait bound `NonTrivialDrop: ~const Drop` is not satisfied in `ConstImplWithDropGlue` +error[E0277]: can't drop `NonTrivialDrop` in const contexts --> $DIR/const-drop-fail.rs:45:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call ... LL | ConstImplWithDropGlue(NonTrivialDrop), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Drop` is not implemented for `NonTrivialDrop` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Destruct` is not implemented for `NonTrivialDrop` | -note: the trait `Drop` is implemented for `NonTrivialDrop`, but that implementation is not `const` +note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const` --> $DIR/const-drop-fail.rs:45:5 | LL | ConstImplWithDropGlue(NonTrivialDrop), @@ -41,28 +42,24 @@ LL | struct ConstImplWithDropGlue(NonTrivialDrop); note: required by a bound in `check` --> $DIR/const-drop-fail.rs:34:19 | -LL | const fn check(_: T) {} - | ^^^^^^^^^^^ required by this bound in `check` +LL | const fn check(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `check` -error[E0277]: the trait bound `ConstDropImplWithBounds: ~const Drop` is not satisfied +error[E0277]: the trait bound `ConstDropImplWithBounds: ~const Destruct` is not satisfied --> $DIR/const-drop-fail.rs:47:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call ... LL | ConstDropImplWithBounds::(PhantomData), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `~const Drop` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct` | -note: required because of the requirements on the impl of `~const Drop` for `ConstDropImplWithBounds` - --> $DIR/const-drop-fail.rs:28:25 - | -LL | impl const Drop for ConstDropImplWithBounds { - | ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds` note: required by a bound in `check` --> $DIR/const-drop-fail.rs:34:19 | -LL | const fn check(_: T) {} - | ^^^^^^^^^^^ required by this bound in `check` +LL | const fn check(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `check` help: consider borrowing here | LL | &ConstDropImplWithBounds::(PhantomData), diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs index 20b9d772147..f50e70939df 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs @@ -5,6 +5,8 @@ #![feature(never_type)] #![cfg_attr(precise, feature(const_precise_live_drops))] +use std::marker::Destruct; + struct S<'a>(&'a mut u8); impl<'a> const Drop for S<'a> { @@ -13,7 +15,7 @@ impl<'a> const Drop for S<'a> { } } -const fn a(_: T) {} +const fn a(_: T) {} const fn b() -> u8 { let mut c = 0; diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-92111.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-92111.rs index da7147acdd7..96a3e386e6e 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/issue-92111.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/issue-92111.rs @@ -1,16 +1,11 @@ // Regression test for #92111. // -// The issue was that we normalize trait bounds before caching -// results of selection. Checking that `impl Tr for S` requires -// checking `S: !Drop` because it cannot overlap with the blanket -// impl. Then we save the (unsatisfied) result from checking `S: Drop`. -// Then the call to `a` checks whether `S: ~const Drop` but we normalize -// it to `S: Drop` which the cache claims to be unsatisfied. -// // check-pass #![feature(const_trait_impl)] +use std::marker::Destruct; + pub trait Tr {} #[allow(drop_bounds)] @@ -21,7 +16,7 @@ pub struct S(i32); impl Tr for S {} -const fn a(t: T) {} +const fn a(t: T) {} fn main() { a(S(0));