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. //! See the `Qualif` trait for more info.
use rustc_errors::ErrorGuaranteed; use rustc_errors::ErrorGuaranteed;
use rustc_hir::LangItem;
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::TraitEngine; use rustc_infer::traits::TraitEngine;
use rustc_middle::mir::*; use rustc_middle::mir::*;
@ -152,18 +153,14 @@ impl Qualif for NeedsNonConstDrop {
return false; return false;
} }
let Some(drop_trait) = cx.tcx.lang_items().drop_trait() else { let destruct = cx.tcx.require_lang_item(LangItem::Destruct, None);
// there is no way to define a type that needs non-const drop
// without having the lang item present.
return false;
};
let obligation = Obligation::new( let obligation = Obligation::new(
ObligationCause::dummy(), ObligationCause::dummy(),
cx.param_env, cx.param_env,
ty::Binder::dummy(ty::TraitPredicate { ty::Binder::dummy(ty::TraitPredicate {
trait_ref: ty::TraitRef { trait_ref: ty::TraitRef {
def_id: drop_trait, def_id: destruct,
substs: cx.tcx.mk_substs_trait(ty, &[]), substs: cx.tcx.mk_substs_trait(ty, &[]),
}, },
constness: ty::BoundConstness::ConstIfConst, constness: ty::BoundConstness::ConstIfConst,
@ -174,15 +171,16 @@ impl Qualif for NeedsNonConstDrop {
cx.tcx.infer_ctxt().enter(|infcx| { cx.tcx.infer_ctxt().enter(|infcx| {
let mut selcx = SelectionContext::new(&infcx); let mut selcx = SelectionContext::new(&infcx);
let Some(impl_src) = selcx.select(&obligation).ok().flatten() else { 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; return true;
}; };
if !matches!( if !matches!(
impl_src, 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 // then it's bad
return true; return true;
} }

View File

@ -216,6 +216,7 @@ language_item_table! {
Freeze, sym::freeze, freeze_trait, Target::Trait, GenericRequirement::Exact(0); Freeze, sym::freeze, freeze_trait, Target::Trait, GenericRequirement::Exact(0);
Drop, sym::drop, drop_trait, Target::Trait, GenericRequirement::None; 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); 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); 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 { let Trait(trait_predicate) = predicate.kind().skip_binder() else {
continue 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; let def_id = trait_predicate.trait_ref.def_id;
if cx.tcx.lang_items().drop_trait() == Some(def_id) { if cx.tcx.lang_items().drop_trait() == Some(def_id) {
// Explicitly allow `impl Drop`, a drop-guards-as-Voldemort-type pattern. // 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>), TraitAlias(ImplSourceTraitAliasData<'tcx, N>),
/// ImplSource for a `const Drop` implementation. /// ImplSource for a `const Drop` implementation.
ConstDrop(ImplSourceConstDropData<N>), ConstDestruct(ImplSourceConstDestructData<N>),
} }
impl<'tcx, N> ImplSource<'tcx, N> { impl<'tcx, N> ImplSource<'tcx, N> {
@ -595,7 +595,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
| ImplSource::Pointee(ImplSourcePointeeData) => Vec::new(), | ImplSource::Pointee(ImplSourcePointeeData) => Vec::new(),
ImplSource::TraitAlias(d) => d.nested, ImplSource::TraitAlias(d) => d.nested,
ImplSource::TraitUpcasting(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::Pointee(ImplSourcePointeeData) => &[],
ImplSource::TraitAlias(d) => &d.nested, ImplSource::TraitAlias(d) => &d.nested,
ImplSource::TraitUpcasting(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(), nested: d.nested.into_iter().map(f).collect(),
}) })
} }
ImplSource::ConstDrop(i) => ImplSource::ConstDrop(ImplSourceConstDropData { ImplSource::ConstDestruct(i) => {
nested: i.nested.into_iter().map(f).collect(), ImplSource::ConstDestruct(ImplSourceConstDestructData {
}), nested: i.nested.into_iter().map(f).collect(),
})
}
} }
} }
} }
@ -767,7 +769,7 @@ pub struct ImplSourceDiscriminantKindData;
pub struct ImplSourcePointeeData; pub struct ImplSourcePointeeData;
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
pub struct ImplSourceConstDropData<N> { pub struct ImplSourceConstDestructData<N> {
pub nested: Vec<N>, pub nested: Vec<N>,
} }

View File

@ -146,8 +146,8 @@ pub enum SelectionCandidate<'tcx> {
BuiltinUnsizeCandidate, BuiltinUnsizeCandidate,
/// Implementation of `const Drop`, optionally from a custom `impl const Drop`. /// Implementation of `const Destruct`, optionally from a custom `impl const Drop`.
ConstDropCandidate(Option<DefId>), ConstDestructCandidate(Option<DefId>),
} }
/// The result of trait evaluation. The order is important /// 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::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 { 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()) { if unlikely!(Some(self.trait_ref.def_id) == tcx.lang_items().drop_trait()) {
// remap without changing constness of this predicate. // remap without changing constness of this predicate.
// this is because `T: ~const Drop` has a different meaning to `T: Drop` // 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) param_env.remap_constness_with(self.constness)
} else { } else {
*param_env = param_env.with_constness(self.constness.and(param_env.constness())) *param_env = param_env.with_constness(self.constness.and(param_env.constness()))

View File

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

View File

@ -1569,7 +1569,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
super::ImplSource::AutoImpl(..) super::ImplSource::AutoImpl(..)
| super::ImplSource::Builtin(..) | super::ImplSource::Builtin(..)
| super::ImplSource::TraitUpcasting(_) | super::ImplSource::TraitUpcasting(_)
| super::ImplSource::ConstDrop(_) => { | super::ImplSource::ConstDestruct(_) => {
// These traits have no associated types. // These traits have no associated types.
selcx.tcx().sess.delay_span_bug( selcx.tcx().sess.delay_span_bug(
obligation.cause.span, obligation.cause.span,
@ -1644,7 +1644,7 @@ fn confirm_select_candidate<'cx, 'tcx>(
| super::ImplSource::Builtin(..) | super::ImplSource::Builtin(..)
| super::ImplSource::TraitUpcasting(_) | super::ImplSource::TraitUpcasting(_)
| super::ImplSource::TraitAlias(..) | super::ImplSource::TraitAlias(..)
| super::ImplSource::ConstDrop(_) => { | super::ImplSource::ConstDestruct(_) => {
// we don't create Select candidates with this kind of resolution // we don't create Select candidates with this kind of resolution
span_bug!( span_bug!(
obligation.cause.span, obligation.cause.span,

View File

@ -5,6 +5,7 @@
//! candidates. See the [rustc dev guide] for more details. //! candidates. See the [rustc dev guide] for more details.
//! //!
//! [rustc dev guide]:https://rustc-dev-guide.rust-lang.org/traits/resolution.html#candidate-assembly //! [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 as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_infer::traits::TraitEngine; use rustc_infer::traits::TraitEngine;
@ -307,7 +308,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
} else if lang_items.drop_trait() == Some(def_id) } else if lang_items.drop_trait() == Some(def_id)
&& obligation.predicate.is_const_if_const() && 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 { } else {
if lang_items.clone_trait() == Some(def_id) { if lang_items.clone_trait() == Some(def_id) {
// Same builtin conditions as `Copy`, i.e., every type which has builtin support // 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, &mut self,
obligation: &TraitObligation<'tcx>, obligation: &TraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'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. // to check anything. We'll short-circuit checking any obligations in confirmation, too.
if obligation.param_env.constness() == hir::Constness::NotConst { if !obligation.is_const() {
candidates.vec.push(ConstDropCandidate(None)); candidates.vec.push(ConstDestructCandidate(None));
return; return;
} }
@ -927,7 +937,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Param(_) | ty::Param(_)
| ty::Placeholder(_) | ty::Placeholder(_)
| ty::Projection(_) => { | 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. // not structurally... so don't push a candidate.
} }
@ -951,14 +961,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Generator(..) | ty::Generator(..)
| ty::Tuple(_) | ty::Tuple(_)
| ty::GeneratorWitness(_) => { | ty::GeneratorWitness(_) => {
// These are built-in, and cannot have a custom `impl const Drop`. // These are built-in, and cannot have a custom `impl const Destruct`.
candidates.vec.push(ConstDropCandidate(None)); candidates.vec.push(ConstDestructCandidate(None));
} }
ty::Adt(..) => { ty::Adt(..) => {
// Find a custom `impl Drop` impl, if it exists // Find a custom `impl Drop` impl, if it exists
let relevant_impl = self.tcx().find_map_relevant_impl( 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(), obligation.predicate.skip_binder().trait_ref.self_ty(),
Some, Some,
); );
@ -966,11 +976,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if let Some(impl_def_id) = relevant_impl { if let Some(impl_def_id) = relevant_impl {
// Check that `impl Drop` is actually const, if there is a custom 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 { 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 { } else {
// Otherwise check the ADT like a built-in type (structurally) // 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 //! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_hir::Constness;
use rustc_index::bit_set::GrowableBitSet; use rustc_index::bit_set::GrowableBitSet;
use rustc_infer::infer::InferOk; use rustc_infer::infer::InferOk;
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
@ -29,9 +28,9 @@ use crate::traits::TraitNotObjectSafe;
use crate::traits::VtblSegment; use crate::traits::VtblSegment;
use crate::traits::{BuiltinDerivedObligation, ImplDerivedObligation}; use crate::traits::{BuiltinDerivedObligation, ImplDerivedObligation};
use crate::traits::{ use crate::traits::{
ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData, ImplSourceConstDropData, ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData,
ImplSourceDiscriminantKindData, ImplSourceFnPointerData, ImplSourceGeneratorData, ImplSourceConstDestructData, ImplSourceDiscriminantKindData, ImplSourceFnPointerData,
ImplSourceObjectData, ImplSourcePointeeData, ImplSourceTraitAliasData, ImplSourceGeneratorData, ImplSourceObjectData, ImplSourcePointeeData, ImplSourceTraitAliasData,
ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData,
}; };
use crate::traits::{ObjectCastObligation, PredicateObligation, TraitObligation}; use crate::traits::{ObjectCastObligation, PredicateObligation, TraitObligation};
@ -156,9 +155,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Ok(ImplSource::TraitUpcasting(data)) Ok(ImplSource::TraitUpcasting(data))
} }
ConstDropCandidate(def_id) => { ConstDestructCandidate(def_id) => {
let data = self.confirm_const_drop_candidate(obligation, def_id)?; let data = self.confirm_const_destruct_candidate(obligation, def_id)?;
Ok(ImplSource::ConstDrop(data)) Ok(ImplSource::ConstDestruct(data))
} }
} }
} }
@ -1037,14 +1036,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Ok(ImplSourceBuiltinData { nested }) Ok(ImplSourceBuiltinData { nested })
} }
fn confirm_const_drop_candidate( fn confirm_const_destruct_candidate(
&mut self, &mut self,
obligation: &TraitObligation<'tcx>, obligation: &TraitObligation<'tcx>,
impl_def_id: Option<DefId>, impl_def_id: Option<DefId>,
) -> Result<ImplSourceConstDropData<PredicateObligation<'tcx>>, SelectionError<'tcx>> { ) -> Result<ImplSourceConstDestructData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
// `~const Drop` in a non-const environment is always trivially true, since our type is `Drop` // `~const Destruct` in a non-const environment is always trivially true, since our type is `Drop`
if obligation.param_env.constness() == Constness::NotConst { if !obligation.is_const() {
return Ok(ImplSourceConstDropData { nested: vec![] }); 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(); let tcx = self.tcx();
@ -1054,9 +1062,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let cause = obligation.derived_cause(BuiltinDerivedObligation); let cause = obligation.derived_cause(BuiltinDerivedObligation);
// If we have a custom `impl const Drop`, then // 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 { 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 // 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 self_ty
.rebind(ty::TraitPredicate { .rebind(ty::TraitPredicate {
trait_ref: ty::TraitRef { 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, &[]), substs: self.tcx().mk_substs_trait(nested_ty, &[]),
}, },
constness: ty::BoundConstness::ConstIfConst, constness: ty::BoundConstness::ConstIfConst,
@ -1140,7 +1170,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let predicate = self_ty let predicate = self_ty
.rebind(ty::TraitPredicate { .rebind(ty::TraitPredicate {
trait_ref: ty::TraitRef { 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, &[]), substs: self.tcx().mk_substs_trait(nested_ty, &[]),
}, },
constness: ty::BoundConstness::ConstIfConst, 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 => {} GeneratorCandidate => {}
// FnDef where the function is const // FnDef where the function is const
FnPointerCandidate { is_const: true } => {} FnPointerCandidate { is_const: true } => {}
ConstDropCandidate(_) => {} ConstDestructCandidate(_) => {}
_ => { _ => {
// reject all other types of candidates // reject all other types of candidates
continue; continue;
@ -1589,7 +1589,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}; };
// (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`, // (*) 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 // This is a fix for #53123 and prevents winnowing from accidentally extending the
// lifetime of a variable. // lifetime of a variable.
@ -1606,7 +1606,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
BuiltinCandidate { has_nested: false } BuiltinCandidate { has_nested: false }
| DiscriminantKindCandidate | DiscriminantKindCandidate
| PointeeCandidate | PointeeCandidate
| ConstDropCandidate(_), | ConstDestructCandidate(_),
_, _,
) => true, ) => true,
( (
@ -1614,7 +1614,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
BuiltinCandidate { has_nested: false } BuiltinCandidate { has_nested: false }
| DiscriminantKindCandidate | DiscriminantKindCandidate
| PointeeCandidate | PointeeCandidate
| ConstDropCandidate(_), | ConstDestructCandidate(_),
) => false, ) => false,
(ParamCandidate(other), ParamCandidate(victim)) => { (ParamCandidate(other), ParamCandidate(victim)) => {

View File

@ -378,7 +378,7 @@ fn resolve_associated_item<'tcx>(
| traits::ImplSource::DiscriminantKind(..) | traits::ImplSource::DiscriminantKind(..)
| traits::ImplSource::Pointee(..) | traits::ImplSource::Pointee(..)
| traits::ImplSource::TraitUpcasting(_) | traits::ImplSource::TraitUpcasting(_)
| traits::ImplSource::ConstDrop(_) => None, | traits::ImplSource::ConstDestruct(_) => None,
}) })
} }

View File

@ -14,6 +14,8 @@ use core::ptr::{self, NonNull};
#[doc(inline)] #[doc(inline)]
pub use core::alloc::*; pub use core::alloc::*;
use core::marker::Destruct;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@ -324,12 +326,16 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
#[cfg_attr(not(test), lang = "box_free")] #[cfg_attr(not(test), lang = "box_free")]
#[inline] #[inline]
#[rustc_const_unstable(feature = "const_box", issue = "92521")] #[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. // 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 // When an additional parameter to `Box` is added (like `A: Allocator`), this has to be added here as
// well. // well.
// For example if `Box` is changed to `struct Box<T: ?Sized, A: Allocator>(Unique<T>, A)`, // 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. // 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>, ptr: Unique<T>,
alloc: A, alloc: A,
) { ) {

View File

@ -331,6 +331,7 @@ impl<B: ?Sized + ToOwned> Cow<'_, B> {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_deref", issue = "88955")] #[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> impl<B: ?Sized + ToOwned> const Deref for Cow<'_, B>
where where
B::Owned: ~const Borrow<B>, B::Owned: ~const Borrow<B>,

View File

@ -143,7 +143,7 @@ use core::hash::{Hash, Hasher};
#[cfg(not(no_global_oom_handling))] #[cfg(not(no_global_oom_handling))]
use core::iter::FromIterator; use core::iter::FromIterator;
use core::iter::{FusedIterator, Iterator}; use core::iter::{FusedIterator, Iterator};
use core::marker::{Unpin, Unsize}; use core::marker::{Destruct, Unpin, Unsize};
use core::mem; use core::mem;
use core::ops::{ use core::ops::{
CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Generator, GeneratorState, Receiver, 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")] #[rustc_const_unstable(feature = "const_box", issue = "92521")]
#[must_use] #[must_use]
#[inline] #[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 pub const fn new_in(x: T, alloc: A) -> Self
where where
A: ~const Allocator + ~const Drop, A: ~const Allocator + ~const Drop + ~const Destruct,
{ {
let mut boxed = Self::new_uninit_in(alloc); let mut boxed = Self::new_uninit_in(alloc);
unsafe { unsafe {
@ -378,10 +379,11 @@ impl<T, A: Allocator> Box<T, A> {
#[unstable(feature = "allocator_api", issue = "32838")] #[unstable(feature = "allocator_api", issue = "32838")]
#[rustc_const_unstable(feature = "const_box", issue = "92521")] #[rustc_const_unstable(feature = "const_box", issue = "92521")]
#[inline] #[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> pub const fn try_new_in(x: T, alloc: A) -> Result<Self, AllocError>
where where
T: ~const Drop, T: ~const Drop + ~const Destruct,
A: ~const Allocator + ~const Drop, A: ~const Allocator + ~const Drop + ~const Destruct,
{ {
let mut boxed = Self::try_new_uninit_in(alloc)?; let mut boxed = Self::try_new_uninit_in(alloc)?;
unsafe { unsafe {
@ -415,9 +417,10 @@ impl<T, A: Allocator> Box<T, A> {
#[cfg(not(no_global_oom_handling))] #[cfg(not(no_global_oom_handling))]
#[must_use] #[must_use]
// #[unstable(feature = "new_uninit", issue = "63291")] // #[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> pub const fn new_uninit_in(alloc: A) -> Box<mem::MaybeUninit<T>, A>
where where
A: ~const Allocator + ~const Drop, A: ~const Allocator + ~const Drop + ~const Destruct,
{ {
let layout = Layout::new::<mem::MaybeUninit<T>>(); let layout = Layout::new::<mem::MaybeUninit<T>>();
// NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. // 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 = "allocator_api", issue = "32838")]
// #[unstable(feature = "new_uninit", issue = "63291")] // #[unstable(feature = "new_uninit", issue = "63291")]
#[rustc_const_unstable(feature = "const_box", issue = "92521")] #[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> pub const fn try_new_uninit_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError>
where where
A: ~const Allocator + ~const Drop, A: ~const Allocator + ~const Drop + ~const Destruct,
{ {
let layout = Layout::new::<mem::MaybeUninit<T>>(); let layout = Layout::new::<mem::MaybeUninit<T>>();
let ptr = alloc.allocate(layout)?.cast(); let ptr = alloc.allocate(layout)?.cast();
@ -487,9 +491,10 @@ impl<T, A: Allocator> Box<T, A> {
#[cfg(not(no_global_oom_handling))] #[cfg(not(no_global_oom_handling))]
// #[unstable(feature = "new_uninit", issue = "63291")] // #[unstable(feature = "new_uninit", issue = "63291")]
#[must_use] #[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> pub const fn new_zeroed_in(alloc: A) -> Box<mem::MaybeUninit<T>, A>
where where
A: ~const Allocator + ~const Drop, A: ~const Allocator + ~const Drop + ~const Destruct,
{ {
let layout = Layout::new::<mem::MaybeUninit<T>>(); let layout = Layout::new::<mem::MaybeUninit<T>>();
// NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. // 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 = "allocator_api", issue = "32838")]
// #[unstable(feature = "new_uninit", issue = "63291")] // #[unstable(feature = "new_uninit", issue = "63291")]
#[rustc_const_unstable(feature = "const_box", issue = "92521")] #[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> pub const fn try_new_zeroed_in(alloc: A) -> Result<Box<mem::MaybeUninit<T>, A>, AllocError>
where where
A: ~const Allocator + ~const Drop, A: ~const Allocator + ~const Drop + ~const Destruct,
{ {
let layout = Layout::new::<mem::MaybeUninit<T>>(); let layout = Layout::new::<mem::MaybeUninit<T>>();
let ptr = alloc.allocate_zeroed(layout)?.cast(); 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")] #[rustc_const_unstable(feature = "const_box", issue = "92521")]
#[must_use] #[must_use]
#[inline(always)] #[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> pub const fn pin_in(x: T, alloc: A) -> Pin<Self>
where where
A: 'static + ~const Allocator + ~const Drop, A: 'static + ~const Allocator + ~const Drop + ~const Destruct,
{ {
Self::into_pin(Self::new_in(x, alloc)) 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")] #[unstable(feature = "box_into_inner", issue = "80437")]
#[rustc_const_unstable(feature = "const_box", issue = "92521")] #[rustc_const_unstable(feature = "const_box", issue = "92521")]
#[inline] #[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 pub const fn into_inner(boxed: Self) -> T
where where
Self: ~const Drop, Self: ~const Drop + ~const Destruct,
{ {
*boxed *boxed
} }

View File

@ -1,5 +1,7 @@
//! impl bool {} //! impl bool {}
use crate::marker::Destruct;
#[lang = "bool"] #[lang = "bool"]
impl bool { impl bool {
/// Returns `Some(t)` if the `bool` is [`true`](../std/keyword.true.html), /// 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")] #[unstable(feature = "bool_to_option", issue = "80967")]
#[rustc_const_unstable(feature = "const_bool_to_option", issue = "91917")] #[rustc_const_unstable(feature = "const_bool_to_option", issue = "91917")]
#[inline] #[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> pub const fn then_some<T>(self, t: T) -> Option<T>
where where
T: ~const Drop, T: ~const Drop + ~const Destruct,
{ {
if self { Some(t) } else { None } if self { Some(t) } else { None }
} }
@ -35,10 +38,11 @@ impl bool {
#[stable(feature = "lazy_bool_to_option", since = "1.50.0")] #[stable(feature = "lazy_bool_to_option", since = "1.50.0")]
#[rustc_const_unstable(feature = "const_bool_to_option", issue = "91917")] #[rustc_const_unstable(feature = "const_bool_to_option", issue = "91917")]
#[inline] #[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> pub const fn then<T, F>(self, f: F) -> Option<T>
where where
F: ~const FnOnce() -> T, F: ~const FnOnce() -> T,
F: ~const Drop, F: ~const Drop + ~const Destruct,
{ {
if self { Some(f()) } else { None } if self { Some(f()) } else { None }
} }

View File

@ -36,6 +36,8 @@
#![stable(feature = "rust1", since = "1.0.0")] #![stable(feature = "rust1", since = "1.0.0")]
use crate::marker::Destruct;
/// A common trait for the ability to explicitly duplicate an object. /// 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 /// Differs from [`Copy`] in that [`Copy`] is implicit and an inexpensive bit-wise copy, while
@ -128,9 +130,10 @@ pub trait Clone: Sized {
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[default_method_body_is_const] #[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) fn clone_from(&mut self, source: &Self)
where where
Self: ~const Drop, Self: ~const Drop + ~const Destruct,
{ {
*self = source.clone() *self = source.clone()
} }

View File

@ -54,7 +54,7 @@
)] )]
#![allow(missing_docs)] #![allow(missing_docs)]
use crate::marker::DiscriminantKind; use crate::marker::{Destruct, DiscriminantKind};
use crate::mem; use crate::mem;
// These imports are used for simplifying intra-doc links // 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")] #[rustc_const_unstable(feature = "const_eval_select", issue = "none")]
#[lang = "const_eval_select"] #[lang = "const_eval_select"]
#[rustc_do_not_const_check] #[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>( pub const unsafe fn const_eval_select<ARG, F, G, RET>(
arg: ARG, arg: ARG,
_called_in_const: F, _called_in_const: F,
@ -2360,7 +2361,7 @@ pub const unsafe fn const_eval_select<ARG, F, G, RET>(
) -> RET ) -> RET
where where
F: ~const FnOnce<ARG, Output = RET>, 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) called_at_rt.call_once(arg)
} }
@ -2372,6 +2373,7 @@ where
)] )]
#[rustc_const_unstable(feature = "const_eval_select", issue = "none")] #[rustc_const_unstable(feature = "const_eval_select", issue = "none")]
#[lang = "const_eval_select_ct"] #[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>( pub const unsafe fn const_eval_select_ct<ARG, F, G, RET>(
arg: ARG, arg: ARG,
called_in_const: F, called_in_const: F,
@ -2379,7 +2381,7 @@ pub const unsafe fn const_eval_select_ct<ARG, F, G, RET>(
) -> RET ) -> RET
where where
F: ~const FnOnce<ARG, Output = RET>, 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) 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")] #[stable(feature = "pin_raw", since = "1.38.0")]
impl<T: ?Sized> Unpin for *mut T {} 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 of `Copy` for primitive types.
/// ///
/// Implementations that cannot be described in Rust /// Implementations that cannot be described in Rust

View File

@ -503,6 +503,7 @@
#![stable(feature = "rust1", since = "1.0.0")] #![stable(feature = "rust1", since = "1.0.0")]
use crate::iter::{self, FromIterator, FusedIterator, TrustedLen}; use crate::iter::{self, FromIterator, FusedIterator, TrustedLen};
use crate::marker::Destruct;
use crate::panicking::{panic, panic_str}; use crate::panicking::{panic, panic_str};
use crate::pin::Pin; use crate::pin::Pin;
use crate::{ use crate::{
@ -772,9 +773,10 @@ impl<T> Option<T> {
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] #[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 pub const fn unwrap_or(self, default: T) -> T
where where
T: ~const Drop, T: ~const Drop + ~const Destruct,
{ {
match self { match self {
Some(x) => x, Some(x) => x,
@ -794,10 +796,11 @@ impl<T> Option<T> {
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] #[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 pub const fn unwrap_or_else<F>(self, f: F) -> T
where where
F: ~const FnOnce() -> T, F: ~const FnOnce() -> T,
F: ~const Drop, F: ~const Drop + ~const Destruct,
{ {
match self { match self {
Some(x) => x, Some(x) => x,
@ -899,10 +902,11 @@ impl<T> Option<T> {
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] #[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> pub const fn map<U, F>(self, f: F) -> Option<U>
where where
F: ~const FnOnce(T) -> U, F: ~const FnOnce(T) -> U,
F: ~const Drop, F: ~const Drop + ~const Destruct,
{ {
match self { match self {
Some(x) => Some(f(x)), Some(x) => Some(f(x)),
@ -928,10 +932,11 @@ impl<T> Option<T> {
#[inline] #[inline]
#[unstable(feature = "result_option_inspect", issue = "91345")] #[unstable(feature = "result_option_inspect", issue = "91345")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] #[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 pub const fn inspect<F>(self, f: F) -> Self
where where
F: ~const FnOnce(&T), F: ~const FnOnce(&T),
F: ~const Drop, F: ~const Drop + ~const Destruct,
{ {
if let Some(ref x) = self { if let Some(ref x) = self {
f(x); f(x);
@ -961,11 +966,12 @@ impl<T> Option<T> {
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] #[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 pub const fn map_or<U, F>(self, default: U, f: F) -> U
where where
F: ~const FnOnce(T) -> U, F: ~const FnOnce(T) -> U,
F: ~const Drop, F: ~const Drop + ~const Destruct,
U: ~const Drop, U: ~const Drop + ~const Destruct,
{ {
match self { match self {
Some(t) => f(t), Some(t) => f(t),
@ -990,12 +996,13 @@ impl<T> Option<T> {
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] #[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 pub const fn map_or_else<U, D, F>(self, default: D, f: F) -> U
where where
D: ~const FnOnce() -> U, D: ~const FnOnce() -> U,
D: ~const Drop, D: ~const Drop + ~const Destruct,
F: ~const FnOnce(T) -> U, F: ~const FnOnce(T) -> U,
F: ~const Drop, F: ~const Drop + ~const Destruct,
{ {
match self { match self {
Some(t) => f(t), Some(t) => f(t),
@ -1027,9 +1034,10 @@ impl<T> Option<T> {
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] #[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> pub const fn ok_or<E>(self, err: E) -> Result<T, E>
where where
E: ~const Drop, E: ~const Drop + ~const Destruct,
{ {
match self { match self {
Some(v) => Ok(v), Some(v) => Ok(v),
@ -1056,10 +1064,11 @@ impl<T> Option<T> {
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] #[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> pub const fn ok_or_else<E, F>(self, err: F) -> Result<T, E>
where where
F: ~const FnOnce() -> E, F: ~const FnOnce() -> E,
F: ~const Drop, F: ~const Drop + ~const Destruct,
{ {
match self { match self {
Some(v) => Ok(v), Some(v) => Ok(v),
@ -1190,10 +1199,11 @@ impl<T> Option<T> {
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] #[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> pub const fn and<U>(self, optb: Option<U>) -> Option<U>
where where
T: ~const Drop, T: ~const Drop + ~const Destruct,
U: ~const Drop, U: ~const Drop + ~const Destruct,
{ {
match self { match self {
Some(_) => optb, Some(_) => optb,
@ -1232,10 +1242,11 @@ impl<T> Option<T> {
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] #[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> pub const fn and_then<U, F>(self, f: F) -> Option<U>
where where
F: ~const FnOnce(T) -> Option<U>, F: ~const FnOnce(T) -> Option<U>,
F: ~const Drop, F: ~const Drop + ~const Destruct,
{ {
match self { match self {
Some(x) => f(x), Some(x) => f(x),
@ -1270,11 +1281,12 @@ impl<T> Option<T> {
#[inline] #[inline]
#[stable(feature = "option_filter", since = "1.27.0")] #[stable(feature = "option_filter", since = "1.27.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] #[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 pub const fn filter<P>(self, predicate: P) -> Self
where where
T: ~const Drop, T: ~const Drop + ~const Destruct,
P: ~const FnOnce(&T) -> bool, P: ~const FnOnce(&T) -> bool,
P: ~const Drop, P: ~const Drop + ~const Destruct,
{ {
if let Some(x) = self { if let Some(x) = self {
if predicate(&x) { if predicate(&x) {
@ -1314,9 +1326,10 @@ impl<T> Option<T> {
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] #[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> pub const fn or(self, optb: Option<T>) -> Option<T>
where where
T: ~const Drop, T: ~const Drop + ~const Destruct,
{ {
match self { match self {
Some(x) => Some(x), Some(x) => Some(x),
@ -1340,10 +1353,11 @@ impl<T> Option<T> {
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] #[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> pub const fn or_else<F>(self, f: F) -> Option<T>
where where
F: ~const FnOnce() -> Option<T>, F: ~const FnOnce() -> Option<T>,
F: ~const Drop, F: ~const Drop + ~const Destruct,
{ {
match self { match self {
Some(x) => Some(x), Some(x) => Some(x),
@ -1375,9 +1389,10 @@ impl<T> Option<T> {
#[inline] #[inline]
#[stable(feature = "option_xor", since = "1.37.0")] #[stable(feature = "option_xor", since = "1.37.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] #[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> pub const fn xor(self, optb: Option<T>) -> Option<T>
where where
T: ~const Drop, T: ~const Drop + ~const Destruct,
{ {
match (self, optb) { match (self, optb) {
(Some(a), None) => Some(a), (Some(a), None) => Some(a),
@ -1413,9 +1428,10 @@ impl<T> Option<T> {
#[inline] #[inline]
#[stable(feature = "option_insert", since = "1.53.0")] #[stable(feature = "option_insert", since = "1.53.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] #[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 pub const fn insert(&mut self, value: T) -> &mut T
where where
T: ~const Drop, T: ~const Drop + ~const Destruct,
{ {
*self = Some(value); *self = Some(value);
@ -1446,9 +1462,10 @@ impl<T> Option<T> {
#[inline] #[inline]
#[stable(feature = "option_entry", since = "1.20.0")] #[stable(feature = "option_entry", since = "1.20.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] #[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 pub const fn get_or_insert(&mut self, value: T) -> &mut T
where where
T: ~const Drop, T: ~const Drop + ~const Destruct,
{ {
if let None = *self { if let None = *self {
*self = Some(value); *self = Some(value);
@ -1513,10 +1530,11 @@ impl<T> Option<T> {
#[inline] #[inline]
#[stable(feature = "option_entry", since = "1.20.0")] #[stable(feature = "option_entry", since = "1.20.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] #[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 pub const fn get_or_insert_with<F>(&mut self, f: F) -> &mut T
where where
F: ~const FnOnce() -> T, F: ~const FnOnce() -> T,
F: ~const Drop, F: ~const Drop + ~const Destruct,
{ {
if let None = *self { if let None = *self {
// the compiler isn't smart enough to know that we are not dropping a `T` // 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")] #[stable(feature = "option_zip_option", since = "1.46.0")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] #[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)> pub const fn zip<U>(self, other: Option<U>) -> Option<(T, U)>
where where
T: ~const Drop, T: ~const Drop + ~const Destruct,
U: ~const Drop, U: ~const Drop + ~const Destruct,
{ {
match (self, other) { match (self, other) {
(Some(a), Some(b)) => Some((a, b)), (Some(a), Some(b)) => Some((a, b)),
@ -1668,12 +1687,13 @@ impl<T> Option<T> {
/// ``` /// ```
#[unstable(feature = "option_zip", issue = "70086")] #[unstable(feature = "option_zip", issue = "70086")]
#[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] #[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> pub const fn zip_with<U, F, R>(self, other: Option<U>, f: F) -> Option<R>
where where
F: ~const FnOnce(T, U) -> R, F: ~const FnOnce(T, U) -> R,
F: ~const Drop, F: ~const Drop + ~const Destruct,
T: ~const Drop, T: ~const Drop + ~const Destruct,
U: ~const Drop, U: ~const Drop + ~const Destruct,
{ {
match (self, other) { match (self, other) {
(Some(a), Some(b)) => Some(f(a, b)), (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")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_clone", issue = "91805")] #[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> impl<T> const Clone for Option<T>
where where
T: ~const Clone + ~const Drop, T: ~const Clone + ~const Drop + ~const Destruct,
{ {
#[inline] #[inline]
fn clone(&self) -> Self { fn clone(&self) -> Self {

View File

@ -490,6 +490,7 @@
#![stable(feature = "rust1", since = "1.0.0")] #![stable(feature = "rust1", since = "1.0.0")]
use crate::iter::{self, FromIterator, FusedIterator, TrustedLen}; use crate::iter::{self, FromIterator, FusedIterator, TrustedLen};
use crate::marker::Destruct;
use crate::ops::{self, ControlFlow, Deref, DerefMut}; use crate::ops::{self, ControlFlow, Deref, DerefMut};
use crate::{convert, fmt, hint}; use crate::{convert, fmt, hint};
@ -635,7 +636,7 @@ impl<T, E> Result<T, E> {
#[rustc_const_unstable(feature = "const_result_drop", issue = "92384")] #[rustc_const_unstable(feature = "const_result_drop", issue = "92384")]
pub const fn ok(self) -> Option<T> pub const fn ok(self) -> Option<T>
where where
E: ~const Drop, E: ~const Drop + ~const Destruct,
{ {
match self { match self {
Ok(x) => Some(x), Ok(x) => Some(x),
@ -666,7 +667,7 @@ impl<T, E> Result<T, E> {
#[rustc_const_unstable(feature = "const_result_drop", issue = "92384")] #[rustc_const_unstable(feature = "const_result_drop", issue = "92384")]
pub const fn err(self) -> Option<E> pub const fn err(self) -> Option<E>
where where
T: ~const Drop, T: ~const Drop + ~const Destruct,
{ {
match self { match self {
// FIXME: ~const Drop doesn't quite work right yet // 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")] #[stable(feature = "rust1", since = "1.0.0")]
pub const fn and<U>(self, res: Result<U, E>) -> Result<U, E> pub const fn and<U>(self, res: Result<U, E>) -> Result<U, E>
where where
T: ~const Drop, T: ~const Drop + ~const Destruct,
U: ~const Drop, U: ~const Drop + ~const Destruct,
E: ~const Drop, E: ~const Drop + ~const Destruct,
{ {
match self { match self {
// FIXME: ~const Drop doesn't quite work right yet // 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")] #[stable(feature = "rust1", since = "1.0.0")]
pub const fn or<F>(self, res: Result<T, F>) -> Result<T, F> pub const fn or<F>(self, res: Result<T, F>) -> Result<T, F>
where where
T: ~const Drop, T: ~const Drop + ~const Destruct,
E: ~const Drop, E: ~const Drop + ~const Destruct,
F: ~const Drop, F: ~const Drop + ~const Destruct,
{ {
match self { match self {
Ok(v) => Ok(v), Ok(v) => Ok(v),
@ -1431,8 +1432,8 @@ impl<T, E> Result<T, E> {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub const fn unwrap_or(self, default: T) -> T pub const fn unwrap_or(self, default: T) -> T
where where
T: ~const Drop, T: ~const Drop + ~const Destruct,
E: ~const Drop, E: ~const Drop + ~const Destruct,
{ {
match self { match self {
Ok(t) => t, Ok(t) => t,
@ -1802,10 +1803,11 @@ fn unwrap_failed<T>(_msg: &str, _error: &T) -> ! {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_clone", issue = "91805")] #[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> impl<T, E> const Clone for Result<T, E>
where where
T: ~const Clone + ~const Drop, T: ~const Clone + ~const Drop + ~const Destruct,
E: ~const Clone + ~const Drop, E: ~const Clone + ~const Drop + ~const Destruct,
{ {
#[inline] #[inline]
fn clone(&self) -> Self { fn clone(&self) -> Self {

View File

@ -121,11 +121,20 @@ impl Clean<Option<GenericBound>> for hir::GenericBound<'_> {
hir::GenericBound::Trait(ref t, modifier) => { hir::GenericBound::Trait(ref t, modifier) => {
// `T: ~const Drop` is not equivalent to `T: Drop`, and we don't currently document `~const` bounds // `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. // 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() // `T: ~const Destruct` is hidden because `T: Destruct` is a no-op.
&& hir::TraitBoundModifier::MaybeConst == modifier 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; 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) 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> { 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 // `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. // 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 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; 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); let poly_trait_ref = self.map_bound(|pred| pred.trait_ref);
Some(WherePredicate::BoundPredicate { Some(WherePredicate::BoundPredicate {
ty: poly_trait_ref.skip_binder().self_ty().clean(cx), ty: poly_trait_ref.skip_binder().self_ty().clean(cx),

View File

@ -1,7 +1,9 @@
#![allow(unused)] #![allow(unused)]
#![feature(const_trait_impl, inline_const, negative_impls)] #![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; struct UnconstDrop;
@ -16,8 +18,8 @@ impl !Drop for NonDrop {}
fn main() { fn main() {
const { const {
f(UnconstDrop); f(UnconstDrop);
//~^ ERROR the trait bound `UnconstDrop: ~const Drop` is not satisfied //~^ ERROR can't drop
f(NonDrop); 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 error[E0277]: can't drop `UnconstDrop` in const contexts
--> $DIR/const-block-const-bound.rs:18:11 --> $DIR/const-block-const-bound.rs:20:11
| |
LL | f(UnconstDrop); 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 | 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` 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) {} LL | const fn f<T: ~const Destruct>(x: T) {}
| ^^^^^^^^^^^ required by this bound in `f` | ^^^^^^^^^^^^^^^ required by this bound in `f`
help: consider borrowing here help: consider borrowing here
| |
LL | f(&UnconstDrop); LL | f(&UnconstDrop);
@ -18,19 +19,20 @@ LL | f(&UnconstDrop);
LL | f(&mut UnconstDrop); LL | f(&mut UnconstDrop);
| ++++ | ++++
error[E0277]: the trait bound `NonDrop: ~const Drop` is not satisfied error[E0277]: can't drop `NonDrop` in const contexts
--> $DIR/const-block-const-bound.rs:20:11 --> $DIR/const-block-const-bound.rs:22:11
| |
LL | f(NonDrop); 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 | 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` 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) {} LL | const fn f<T: ~const Destruct>(x: T) {}
| ^^^^^^^^^^^ required by this bound in `f` | ^^^^^^^^^^^^^^^ required by this bound in `f`
help: consider borrowing here help: consider borrowing here
| |
LL | f(&NonDrop); LL | f(&NonDrop);

View File

@ -48,7 +48,7 @@ LL | const_eval_select((), 42, 0xDEADBEEF);
note: required by a bound in `const_eval_select` note: required by a bound in `const_eval_select`
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL --> $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` | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
error[E0271]: type mismatch resolving `<fn(i32) -> bool {bar} as FnOnce<(i32,)>>::Output == i32` 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` note: required by a bound in `const_eval_select`
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL --> $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` | ^^^^^^^^^^^^ required by this bound in `const_eval_select`
error[E0631]: type mismatch in function arguments error[E0631]: type mismatch in function arguments

View File

@ -3,7 +3,9 @@
#![feature(const_trait_impl)] #![feature(const_trait_impl)]
#![feature(const_precise_live_drops)] #![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 { match res {
Ok(t) => Some(t), Ok(t) => Some(t),
Err(_e) => None, 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); 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) 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 --> $DIR/const-drop-fail.rs:43:5
| |
LL | const _: () = check($exp); LL | const _: () = check($exp);
| ----- required by a bound introduced by this call | ----- required by a bound introduced by this call
... ...
LL | NonTrivialDrop, 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` note: required by a bound in `check`
--> $DIR/const-drop-fail.rs:34:19 --> $DIR/const-drop-fail.rs:34:19
| |
LL | const fn check<T: ~const Drop>(_: T) {} LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^ required by this bound in `check` | ^^^^^^^^^^^^^^^ required by this bound in `check`
help: consider borrowing here help: consider borrowing here
| |
LL | &NonTrivialDrop, LL | &NonTrivialDrop,
@ -19,16 +20,16 @@ LL | &NonTrivialDrop,
LL | &mut 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 --> $DIR/const-drop-fail.rs:45:5
| |
LL | const _: () = check($exp); LL | const _: () = check($exp);
| ----- required by a bound introduced by this call | ----- required by a bound introduced by this call
... ...
LL | ConstImplWithDropGlue(NonTrivialDrop), 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 --> $DIR/const-drop-fail.rs:45:5
| |
LL | ConstImplWithDropGlue(NonTrivialDrop), LL | ConstImplWithDropGlue(NonTrivialDrop),
@ -41,28 +42,24 @@ LL | struct ConstImplWithDropGlue(NonTrivialDrop);
note: required by a bound in `check` note: required by a bound in `check`
--> $DIR/const-drop-fail.rs:34:19 --> $DIR/const-drop-fail.rs:34:19
| |
LL | const fn check<T: ~const Drop>(_: T) {} LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^ required by this bound in `check` | ^^^^^^^^^^^^^^^ 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 --> $DIR/const-drop-fail.rs:47:5
| |
LL | const _: () = check($exp); LL | const _: () = check($exp);
| ----- required by a bound introduced by this call | ----- required by a bound introduced by this call
... ...
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), 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>` = note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds<NonTrivialDrop>`
--> $DIR/const-drop-fail.rs:28:25
|
LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
| ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `check` note: required by a bound in `check`
--> $DIR/const-drop-fail.rs:34:19 --> $DIR/const-drop-fail.rs:34:19
| |
LL | const fn check<T: ~const Drop>(_: T) {} LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^ required by this bound in `check` | ^^^^^^^^^^^^^^^ required by this bound in `check`
help: consider borrowing here help: consider borrowing here
| |
LL | &ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), LL | &ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),

View File

@ -3,7 +3,7 @@
#![feature(const_mut_refs)] #![feature(const_mut_refs)]
#![cfg_attr(precise, feature(const_precise_live_drops))] #![cfg_attr(precise, feature(const_precise_live_drops))]
use std::marker::PhantomData; use std::marker::{Destruct, PhantomData};
struct NonTrivialDrop; 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 { macro_rules! check_all {
($($exp:expr),*$(,)?) => {$( ($($exp:expr),*$(,)?) => {$(
@ -41,9 +41,9 @@ macro_rules! check_all {
check_all! { check_all! {
NonTrivialDrop, NonTrivialDrop,
//~^ ERROR the trait bound //~^ ERROR can't drop
ConstImplWithDropGlue(NonTrivialDrop), ConstImplWithDropGlue(NonTrivialDrop),
//~^ ERROR the trait bound //~^ ERROR can't drop
ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
//~^ ERROR the trait bound //~^ 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 --> $DIR/const-drop-fail.rs:43:5
| |
LL | const _: () = check($exp); LL | const _: () = check($exp);
| ----- required by a bound introduced by this call | ----- required by a bound introduced by this call
... ...
LL | NonTrivialDrop, 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` note: required by a bound in `check`
--> $DIR/const-drop-fail.rs:34:19 --> $DIR/const-drop-fail.rs:34:19
| |
LL | const fn check<T: ~const Drop>(_: T) {} LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^ required by this bound in `check` | ^^^^^^^^^^^^^^^ required by this bound in `check`
help: consider borrowing here help: consider borrowing here
| |
LL | &NonTrivialDrop, LL | &NonTrivialDrop,
@ -19,16 +20,16 @@ LL | &NonTrivialDrop,
LL | &mut 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 --> $DIR/const-drop-fail.rs:45:5
| |
LL | const _: () = check($exp); LL | const _: () = check($exp);
| ----- required by a bound introduced by this call | ----- required by a bound introduced by this call
... ...
LL | ConstImplWithDropGlue(NonTrivialDrop), 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 --> $DIR/const-drop-fail.rs:45:5
| |
LL | ConstImplWithDropGlue(NonTrivialDrop), LL | ConstImplWithDropGlue(NonTrivialDrop),
@ -41,28 +42,24 @@ LL | struct ConstImplWithDropGlue(NonTrivialDrop);
note: required by a bound in `check` note: required by a bound in `check`
--> $DIR/const-drop-fail.rs:34:19 --> $DIR/const-drop-fail.rs:34:19
| |
LL | const fn check<T: ~const Drop>(_: T) {} LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^ required by this bound in `check` | ^^^^^^^^^^^^^^^ 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 --> $DIR/const-drop-fail.rs:47:5
| |
LL | const _: () = check($exp); LL | const _: () = check($exp);
| ----- required by a bound introduced by this call | ----- required by a bound introduced by this call
... ...
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), 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>` = note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds<NonTrivialDrop>`
--> $DIR/const-drop-fail.rs:28:25
|
LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
| ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `check` note: required by a bound in `check`
--> $DIR/const-drop-fail.rs:34:19 --> $DIR/const-drop-fail.rs:34:19
| |
LL | const fn check<T: ~const Drop>(_: T) {} LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^ required by this bound in `check` | ^^^^^^^^^^^^^^^ required by this bound in `check`
help: consider borrowing here help: consider borrowing here
| |
LL | &ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), LL | &ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),

View File

@ -5,6 +5,8 @@
#![feature(never_type)] #![feature(never_type)]
#![cfg_attr(precise, feature(const_precise_live_drops))] #![cfg_attr(precise, feature(const_precise_live_drops))]
use std::marker::Destruct;
struct S<'a>(&'a mut u8); struct S<'a>(&'a mut u8);
impl<'a> const Drop for S<'a> { 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 { const fn b() -> u8 {
let mut c = 0; let mut c = 0;

View File

@ -1,16 +1,11 @@
// Regression test for #92111. // 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 // check-pass
#![feature(const_trait_impl)] #![feature(const_trait_impl)]
use std::marker::Destruct;
pub trait Tr {} pub trait Tr {}
#[allow(drop_bounds)] #[allow(drop_bounds)]
@ -21,7 +16,7 @@ pub struct S(i32);
impl Tr for S {} impl Tr for S {}
const fn a<T: ~const Drop>(t: T) {} const fn a<T: ~const Destruct>(t: T) {}
fn main() { fn main() {
a(S(0)); a(S(0));