Auto merge of #94901 - fee1-dead:destructable, r=oli-obk

Rename `~const Drop` to `~const Destruct`

r? `@oli-obk`

Completely switching to `~const Destructible` would be rather complicated, so it seems best to add it for now and wait for it to be backported to beta in the next release.

The rationale is to prevent complications such as #92149 and #94803 by introducing an entirely new trait. And `~const Destructible` reads a bit better than `~const Drop`. Name Bikesheddable.
This commit is contained in:
bors 2022-03-23 14:04:38 +00:00
commit 9280445570
32 changed files with 308 additions and 187 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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.

View File

@ -577,7 +577,7 @@ pub enum ImplSource<'tcx, N> {
TraitAlias(ImplSourceTraitAliasData<'tcx, N>),
/// ImplSource for a `const Drop` implementation.
ConstDrop(ImplSourceConstDropData<N>),
ConstDestruct(ImplSourceConstDestructData<N>),
}
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<N> {
pub struct ImplSourceConstDestructData<N> {
pub nested: Vec<N>,
}

View File

@ -146,8 +146,8 @@ pub enum SelectionCandidate<'tcx> {
BuiltinUnsizeCandidate,
/// Implementation of `const Drop`, optionally from a custom `impl const Drop`.
ConstDropCandidate(Option<DefId>),
/// Implementation of `const Destruct`, optionally from a custom `impl const Drop`.
ConstDestructCandidate(Option<DefId>),
}
/// The result of trait evaluation. The order is important

View File

@ -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<N: fmt::Debug> fmt::Debug for traits::ImplSourceConstDropData<N> {
impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceConstDestructData<N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ImplSourceConstDropData(nested={:?})", self.nested)
write!(f, "ImplSourceConstDestructData(nested={:?})", self.nested)
}
}

View File

@ -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()))

View File

@ -571,6 +571,7 @@ symbols! {
deref_target,
derive,
derive_default_enum,
destruct,
destructuring_assignment,
diagnostic,
direct,

View File

@ -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,

View File

@ -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));
}
}

View File

@ -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<DefId>,
) -> Result<ImplSourceConstDropData<PredicateObligation<'tcx>>, 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<ImplSourceConstDestructData<PredicateObligation<'tcx>>, 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 })
}
}

View File

@ -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)) => {

View File

@ -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,
})
}

View File

@ -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<T: ?Sized, A: Allocator>(Unique<T>, A)`,
// this function has to be changed to `fn box_free<T: ?Sized, A: Allocator>(Unique<T>, A)` as well.
pub(crate) const unsafe fn box_free<T: ?Sized, A: ~const Allocator + ~const Drop>(
pub(crate) const unsafe fn box_free<
T: ?Sized,
A: ~const Allocator + ~const Drop + ~const Destruct,
>(
ptr: Unique<T>,
alloc: A,
) {

View File

@ -331,6 +331,7 @@ impl<B: ?Sized + ToOwned> 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<B: ?Sized + ToOwned> const Deref for Cow<'_, B>
where
B::Owned: ~const Borrow<B>,

View File

@ -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<T, A: Allocator> Box<T, A> {
#[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<T, A: Allocator> Box<T, A> {
#[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<Self, AllocError>
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<T, A: Allocator> Box<T, A> {
#[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<mem::MaybeUninit<T>, A>
where
A: ~const Allocator + ~const Drop,
A: ~const Allocator + ~const Drop + ~const Destruct,
{
let layout = Layout::new::<mem::MaybeUninit<T>>();
// NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable.
@ -453,9 +456,10 @@ impl<T, A: Allocator> Box<T, A> {
#[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<Box<mem::MaybeUninit<T>, A>, AllocError>
where
A: ~const Allocator + ~const Drop,
A: ~const Allocator + ~const Drop + ~const Destruct,
{
let layout = Layout::new::<mem::MaybeUninit<T>>();
let ptr = alloc.allocate(layout)?.cast();
@ -487,9 +491,10 @@ impl<T, A: Allocator> Box<T, A> {
#[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<mem::MaybeUninit<T>, A>
where
A: ~const Allocator + ~const Drop,
A: ~const Allocator + ~const Drop + ~const Destruct,
{
let layout = Layout::new::<mem::MaybeUninit<T>>();
// NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable.
@ -525,9 +530,10 @@ impl<T, A: Allocator> Box<T, A> {
#[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<Box<mem::MaybeUninit<T>, A>, AllocError>
where
A: ~const Allocator + ~const Drop,
A: ~const Allocator + ~const Drop + ~const Destruct,
{
let layout = Layout::new::<mem::MaybeUninit<T>>();
let ptr = alloc.allocate_zeroed(layout)?.cast();
@ -541,9 +547,10 @@ impl<T, A: Allocator> Box<T, A> {
#[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<Self>
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<T, A: Allocator> Box<T, A> {
#[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
}

View File

@ -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<T>(self, t: T) -> Option<T>
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<T, F>(self, f: F) -> Option<T>
where
F: ~const FnOnce() -> T,
F: ~const Drop,
F: ~const Drop + ~const Destruct,
{
if self { Some(f()) } else { None }
}

View File

@ -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()
}

View File

@ -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<T>(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, F, G, RET>(
arg: ARG,
_called_in_const: F,
@ -2360,7 +2361,7 @@ pub const unsafe fn const_eval_select<ARG, F, G, RET>(
) -> RET
where
F: ~const FnOnce<ARG, Output = RET>,
G: FnOnce<ARG, Output = RET> + ~const Drop,
G: FnOnce<ARG, Output = RET> + ~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, F, G, RET>(
arg: ARG,
called_in_const: F,
@ -2379,7 +2381,7 @@ pub const unsafe fn const_eval_select_ct<ARG, F, G, RET>(
) -> RET
where
F: ~const FnOnce<ARG, Output = RET>,
G: FnOnce<ARG, Output = RET> + ~const Drop,
G: FnOnce<ARG, Output = RET> + ~const Drop + ~const Destruct,
{
called_in_const.call_once(arg)
}

View File

@ -792,6 +792,22 @@ impl<T: ?Sized> Unpin for *const T {}
#[stable(feature = "pin_raw", since = "1.38.0")]
impl<T: ?Sized> 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<T: ?Sized> const Destruct for T {}
/// Implementations of `Copy` for primitive types.
///
/// Implementations that cannot be described in Rust

View File

@ -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<T> Option<T> {
#[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<T> Option<T> {
#[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<F>(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<T> Option<T> {
#[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<U, F>(self, f: F) -> Option<U>
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<T> Option<T> {
#[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<F>(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<T> Option<T> {
#[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<U, F>(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<T> Option<T> {
#[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<U, D, F>(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<T> Option<T> {
#[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<E>(self, err: E) -> Result<T, E>
where
E: ~const Drop,
E: ~const Drop + ~const Destruct,
{
match self {
Some(v) => Ok(v),
@ -1056,10 +1064,11 @@ impl<T> Option<T> {
#[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<E, F>(self, err: F) -> Result<T, E>
where
F: ~const FnOnce() -> E,
F: ~const Drop,
F: ~const Drop + ~const Destruct,
{
match self {
Some(v) => Ok(v),
@ -1190,10 +1199,11 @@ impl<T> Option<T> {
#[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<U>(self, optb: Option<U>) -> Option<U>
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<T> Option<T> {
#[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<U, F>(self, f: F) -> Option<U>
where
F: ~const FnOnce(T) -> Option<U>,
F: ~const Drop,
F: ~const Drop + ~const Destruct,
{
match self {
Some(x) => f(x),
@ -1270,11 +1281,12 @@ impl<T> Option<T> {
#[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<P>(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<T> Option<T> {
#[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<T>) -> Option<T>
where
T: ~const Drop,
T: ~const Drop + ~const Destruct,
{
match self {
Some(x) => Some(x),
@ -1340,10 +1353,11 @@ impl<T> Option<T> {
#[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<F>(self, f: F) -> Option<T>
where
F: ~const FnOnce() -> Option<T>,
F: ~const Drop,
F: ~const Drop + ~const Destruct,
{
match self {
Some(x) => Some(x),
@ -1375,9 +1389,10 @@ impl<T> Option<T> {
#[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<T>) -> Option<T>
where
T: ~const Drop,
T: ~const Drop + ~const Destruct,
{
match (self, optb) {
(Some(a), None) => Some(a),
@ -1413,9 +1428,10 @@ impl<T> Option<T> {
#[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<T> Option<T> {
#[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<T> Option<T> {
#[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<F>(&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<T> Option<T> {
/// ```
#[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<U>(self, other: Option<U>) -> 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<T> Option<T> {
/// ```
#[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<U, F, R>(self, other: Option<U>, f: F) -> Option<R>
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<T> const Clone for Option<T>
where
T: ~const Clone + ~const Drop,
T: ~const Clone + ~const Drop + ~const Destruct,
{
#[inline]
fn clone(&self) -> Self {

View File

@ -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<T, E> Result<T, E> {
#[rustc_const_unstable(feature = "const_result_drop", issue = "92384")]
pub const fn ok(self) -> Option<T>
where
E: ~const Drop,
E: ~const Drop + ~const Destruct,
{
match self {
Ok(x) => Some(x),
@ -666,7 +667,7 @@ impl<T, E> Result<T, E> {
#[rustc_const_unstable(feature = "const_result_drop", issue = "92384")]
pub const fn err(self) -> Option<E>
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<T, E> Result<T, E> {
#[stable(feature = "rust1", since = "1.0.0")]
pub const fn and<U>(self, res: Result<U, E>) -> Result<U, E>
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<T, E> Result<T, E> {
#[stable(feature = "rust1", since = "1.0.0")]
pub const fn or<F>(self, res: Result<T, F>) -> Result<T, F>
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<T, E> Result<T, E> {
#[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<T>(_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<T, E> const Clone for Result<T, E>
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 {

View File

@ -121,11 +121,20 @@ impl Clean<Option<GenericBound>> 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<Option<WherePredicate>> for ty::PolyTraitPredicate<'a> {
fn clean(&self, cx: &mut DocContext<'_>) -> Option<WherePredicate> {
// `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),

View File

@ -1,7 +1,9 @@
#![allow(unused)]
#![feature(const_trait_impl, inline_const, negative_impls)]
const fn f<T: ~const Drop>(x: T) {}
use std::marker::Destruct;
const fn f<T: ~const Destruct>(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
}
}

View File

@ -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<T: ~const Drop>(x: T) {}
| ^^^^^^^^^^^ required by this bound in `f`
LL | const fn f<T: ~const Destruct>(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<T: ~const Drop>(x: T) {}
| ^^^^^^^^^^^ required by this bound in `f`
LL | const fn f<T: ~const Destruct>(x: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `f`
help: consider borrowing here
|
LL | f(&NonDrop);

View File

@ -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<ARG, Output = RET> + ~const Drop,
LL | G: FnOnce<ARG, Output = RET> + ~const Drop + ~const Destruct,
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
error[E0271]: type mismatch resolving `<fn(i32) -> 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<ARG, Output = RET> + ~const Drop,
LL | G: FnOnce<ARG, Output = RET> + ~const Drop + ~const Destruct,
| ^^^^^^^^^^^^ required by this bound in `const_eval_select`
error[E0631]: type mismatch in function arguments

View File

@ -3,7 +3,9 @@
#![feature(const_trait_impl)]
#![feature(const_precise_live_drops)]
const fn foo<T, E>(res: Result<T, E>) -> Option<T> where E: ~const Drop {
use std::marker::Destruct;
const fn foo<T, E>(res: Result<T, E>) -> Option<T> where E: ~const Destruct {
match res {
Ok(t) => Some(t),
Err(_e) => None,
@ -12,7 +14,11 @@ const fn foo<T, E>(res: Result<T, E>) -> Option<T> where E: ~const Drop {
pub struct Foo<T>(T);
const fn baz<T: ~const Drop, E: ~const Drop>(res: Result<Foo<T>, Foo<E>>) -> Option<Foo<T>> {
const fn baz<T, E>(res: Result<Foo<T>, Foo<E>>) -> Option<Foo<T>>
where
T: ~const Destruct,
E: ~const Destruct,
{
foo(res)
}

View File

@ -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: ~const Drop>(_: T) {}
| ^^^^^^^^^^^ required by this bound in `check`
LL | const fn check<T: ~const Destruct>(_: 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: ~const Drop>(_: T) {}
| ^^^^^^^^^^^ required by this bound in `check`
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `check`
error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: ~const Drop` is not satisfied
error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: ~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::<NonTrivialDrop>(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<NonTrivialDrop>`
--> $DIR/const-drop-fail.rs:28:25
|
LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
| ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds<NonTrivialDrop>`
note: required by a bound in `check`
--> $DIR/const-drop-fail.rs:34:19
|
LL | const fn check<T: ~const Drop>(_: T) {}
| ^^^^^^^^^^^ required by this bound in `check`
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `check`
help: consider borrowing here
|
LL | &ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),

View File

@ -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<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
}
}
const fn check<T: ~const Drop>(_: T) {}
const fn check<T: ~const Destruct>(_: 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::<NonTrivialDrop>(PhantomData),
//~^ ERROR the trait bound
}

View File

@ -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: ~const Drop>(_: T) {}
| ^^^^^^^^^^^ required by this bound in `check`
LL | const fn check<T: ~const Destruct>(_: 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: ~const Drop>(_: T) {}
| ^^^^^^^^^^^ required by this bound in `check`
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `check`
error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: ~const Drop` is not satisfied
error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: ~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::<NonTrivialDrop>(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<NonTrivialDrop>`
--> $DIR/const-drop-fail.rs:28:25
|
LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
| ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds<NonTrivialDrop>`
note: required by a bound in `check`
--> $DIR/const-drop-fail.rs:34:19
|
LL | const fn check<T: ~const Drop>(_: T) {}
| ^^^^^^^^^^^ required by this bound in `check`
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `check`
help: consider borrowing here
|
LL | &ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),

View File

@ -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 Drop>(_: T) {}
const fn a<T: ~const Destruct>(_: T) {}
const fn b() -> u8 {
let mut c = 0;

View File

@ -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: ~const Drop>(t: T) {}
const fn a<T: ~const Destruct>(t: T) {}
fn main() {
a(S(0));