Skip to content

Commit 9280445

Browse files
committed
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.
2 parents c99b42c + fe5b813 commit 9280445

File tree

32 files changed

+308
-187
lines changed

32 files changed

+308
-187
lines changed

compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs

+7-9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
//! See the `Qualif` trait for more info.
44
55
use rustc_errors::ErrorGuaranteed;
6+
use rustc_hir::LangItem;
67
use rustc_infer::infer::TyCtxtInferExt;
78
use rustc_infer::traits::TraitEngine;
89
use rustc_middle::mir::*;
@@ -152,18 +153,14 @@ impl Qualif for NeedsNonConstDrop {
152153
return false;
153154
}
154155

155-
let Some(drop_trait) = cx.tcx.lang_items().drop_trait() else {
156-
// there is no way to define a type that needs non-const drop
157-
// without having the lang item present.
158-
return false;
159-
};
156+
let destruct = cx.tcx.require_lang_item(LangItem::Destruct, None);
160157

161158
let obligation = Obligation::new(
162159
ObligationCause::dummy(),
163160
cx.param_env,
164161
ty::Binder::dummy(ty::TraitPredicate {
165162
trait_ref: ty::TraitRef {
166-
def_id: drop_trait,
163+
def_id: destruct,
167164
substs: cx.tcx.mk_substs_trait(ty, &[]),
168165
},
169166
constness: ty::BoundConstness::ConstIfConst,
@@ -174,15 +171,16 @@ impl Qualif for NeedsNonConstDrop {
174171
cx.tcx.infer_ctxt().enter(|infcx| {
175172
let mut selcx = SelectionContext::new(&infcx);
176173
let Some(impl_src) = selcx.select(&obligation).ok().flatten() else {
177-
// If we couldn't select a const drop candidate, then it's bad
174+
// If we couldn't select a const destruct candidate, then it's bad
178175
return true;
179176
};
180177

181178
if !matches!(
182179
impl_src,
183-
ImplSource::ConstDrop(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst)
180+
ImplSource::ConstDestruct(_)
181+
| ImplSource::Param(_, ty::BoundConstness::ConstIfConst)
184182
) {
185-
// If our const drop candidate is not ConstDrop or implied by the param env,
183+
// If our const destruct candidate is not ConstDestruct or implied by the param env,
186184
// then it's bad
187185
return true;
188186
}

compiler/rustc_hir/src/lang_items.rs

+1
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ language_item_table! {
216216
Freeze, sym::freeze, freeze_trait, Target::Trait, GenericRequirement::Exact(0);
217217

218218
Drop, sym::drop, drop_trait, Target::Trait, GenericRequirement::None;
219+
Destruct, sym::destruct, destruct_trait, Target::Trait, GenericRequirement::None;
219220

220221
CoerceUnsized, sym::coerce_unsized, coerce_unsized_trait, Target::Trait, GenericRequirement::Minimum(1);
221222
DispatchFromDyn, sym::dispatch_from_dyn, dispatch_from_dyn_trait, Target::Trait, GenericRequirement::Minimum(1);

compiler/rustc_lint/src/traits.rs

-4
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,6 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
9393
let Trait(trait_predicate) = predicate.kind().skip_binder() else {
9494
continue
9595
};
96-
if trait_predicate.is_const_if_const() {
97-
// `~const Drop` definitely have meanings so avoid linting here.
98-
continue;
99-
}
10096
let def_id = trait_predicate.trait_ref.def_id;
10197
if cx.tcx.lang_items().drop_trait() == Some(def_id) {
10298
// Explicitly allow `impl Drop`, a drop-guards-as-Voldemort-type pattern.

compiler/rustc_middle/src/traits/mod.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ pub enum ImplSource<'tcx, N> {
577577
TraitAlias(ImplSourceTraitAliasData<'tcx, N>),
578578

579579
/// ImplSource for a `const Drop` implementation.
580-
ConstDrop(ImplSourceConstDropData<N>),
580+
ConstDestruct(ImplSourceConstDestructData<N>),
581581
}
582582

583583
impl<'tcx, N> ImplSource<'tcx, N> {
@@ -595,7 +595,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
595595
| ImplSource::Pointee(ImplSourcePointeeData) => Vec::new(),
596596
ImplSource::TraitAlias(d) => d.nested,
597597
ImplSource::TraitUpcasting(d) => d.nested,
598-
ImplSource::ConstDrop(i) => i.nested,
598+
ImplSource::ConstDestruct(i) => i.nested,
599599
}
600600
}
601601

@@ -613,7 +613,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
613613
| ImplSource::Pointee(ImplSourcePointeeData) => &[],
614614
ImplSource::TraitAlias(d) => &d.nested,
615615
ImplSource::TraitUpcasting(d) => &d.nested,
616-
ImplSource::ConstDrop(i) => &i.nested,
616+
ImplSource::ConstDestruct(i) => &i.nested,
617617
}
618618
}
619619

@@ -672,9 +672,11 @@ impl<'tcx, N> ImplSource<'tcx, N> {
672672
nested: d.nested.into_iter().map(f).collect(),
673673
})
674674
}
675-
ImplSource::ConstDrop(i) => ImplSource::ConstDrop(ImplSourceConstDropData {
676-
nested: i.nested.into_iter().map(f).collect(),
677-
}),
675+
ImplSource::ConstDestruct(i) => {
676+
ImplSource::ConstDestruct(ImplSourceConstDestructData {
677+
nested: i.nested.into_iter().map(f).collect(),
678+
})
679+
}
678680
}
679681
}
680682
}
@@ -767,7 +769,7 @@ pub struct ImplSourceDiscriminantKindData;
767769
pub struct ImplSourcePointeeData;
768770

769771
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
770-
pub struct ImplSourceConstDropData<N> {
772+
pub struct ImplSourceConstDestructData<N> {
771773
pub nested: Vec<N>,
772774
}
773775

compiler/rustc_middle/src/traits/select.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,8 @@ pub enum SelectionCandidate<'tcx> {
146146

147147
BuiltinUnsizeCandidate,
148148

149-
/// Implementation of `const Drop`, optionally from a custom `impl const Drop`.
150-
ConstDropCandidate(Option<DefId>),
149+
/// Implementation of `const Destruct`, optionally from a custom `impl const Drop`.
150+
ConstDestructCandidate(Option<DefId>),
151151
}
152152

153153
/// The result of trait evaluation. The order is important

compiler/rustc_middle/src/traits/structural_impls.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> {
3333

3434
super::ImplSource::TraitUpcasting(ref d) => write!(f, "{:?}", d),
3535

36-
super::ImplSource::ConstDrop(ref d) => write!(f, "{:?}", d),
36+
super::ImplSource::ConstDestruct(ref d) => write!(f, "{:?}", d),
3737
}
3838
}
3939
}
@@ -120,9 +120,9 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitAliasData<'tcx,
120120
}
121121
}
122122

123-
impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceConstDropData<N> {
123+
impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceConstDestructData<N> {
124124
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125-
write!(f, "ImplSourceConstDropData(nested={:?})", self.nested)
125+
write!(f, "ImplSourceConstDestructData(nested={:?})", self.nested)
126126
}
127127
}
128128

compiler/rustc_middle/src/ty/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,7 @@ impl<'tcx> TraitPredicate<'tcx> {
765765
if unlikely!(Some(self.trait_ref.def_id) == tcx.lang_items().drop_trait()) {
766766
// remap without changing constness of this predicate.
767767
// this is because `T: ~const Drop` has a different meaning to `T: Drop`
768+
// FIXME(fee1-dead): remove this logic after beta bump
768769
param_env.remap_constness_with(self.constness)
769770
} else {
770771
*param_env = param_env.with_constness(self.constness.and(param_env.constness()))

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,7 @@ symbols! {
571571
deref_target,
572572
derive,
573573
derive_default_enum,
574+
destruct,
574575
destructuring_assignment,
575576
diagnostic,
576577
direct,

compiler/rustc_trait_selection/src/traits/project.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1569,7 +1569,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
15691569
super::ImplSource::AutoImpl(..)
15701570
| super::ImplSource::Builtin(..)
15711571
| super::ImplSource::TraitUpcasting(_)
1572-
| super::ImplSource::ConstDrop(_) => {
1572+
| super::ImplSource::ConstDestruct(_) => {
15731573
// These traits have no associated types.
15741574
selcx.tcx().sess.delay_span_bug(
15751575
obligation.cause.span,
@@ -1644,7 +1644,7 @@ fn confirm_select_candidate<'cx, 'tcx>(
16441644
| super::ImplSource::Builtin(..)
16451645
| super::ImplSource::TraitUpcasting(_)
16461646
| super::ImplSource::TraitAlias(..)
1647-
| super::ImplSource::ConstDrop(_) => {
1647+
| super::ImplSource::ConstDestruct(_) => {
16481648
// we don't create Select candidates with this kind of resolution
16491649
span_bug!(
16501650
obligation.cause.span,

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

+21-11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
//! candidates. See the [rustc dev guide] for more details.
66
//!
77
//! [rustc dev guide]:https://rustc-dev-guide.rust-lang.org/traits/resolution.html#candidate-assembly
8+
use hir::LangItem;
89
use rustc_hir as hir;
910
use rustc_hir::def_id::DefId;
1011
use rustc_infer::traits::TraitEngine;
@@ -307,7 +308,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
307308
} else if lang_items.drop_trait() == Some(def_id)
308309
&& obligation.predicate.is_const_if_const()
309310
{
310-
self.assemble_const_drop_candidates(obligation, &mut candidates);
311+
// holds to make it easier to transition
312+
// FIXME(fee1-dead): add a note for selection error of `~const Drop`
313+
// when beta is bumped
314+
// FIXME: remove this when beta is bumped
315+
#[cfg(bootstrap)]
316+
{}
317+
318+
candidates.vec.push(SelectionCandidate::ConstDestructCandidate(None))
319+
} else if lang_items.destruct_trait() == Some(def_id) {
320+
self.assemble_const_destruct_candidates(obligation, &mut candidates);
311321
} else {
312322
if lang_items.clone_trait() == Some(def_id) {
313323
// Same builtin conditions as `Copy`, i.e., every type which has builtin support
@@ -906,15 +916,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
906916
}
907917
}
908918

909-
fn assemble_const_drop_candidates(
919+
fn assemble_const_destruct_candidates(
910920
&mut self,
911921
obligation: &TraitObligation<'tcx>,
912922
candidates: &mut SelectionCandidateSet<'tcx>,
913923
) {
914-
// If the predicate is `~const Drop` in a non-const environment, we don't actually need
924+
// If the predicate is `~const Destruct` in a non-const environment, we don't actually need
915925
// to check anything. We'll short-circuit checking any obligations in confirmation, too.
916-
if obligation.param_env.constness() == hir::Constness::NotConst {
917-
candidates.vec.push(ConstDropCandidate(None));
926+
if !obligation.is_const() {
927+
candidates.vec.push(ConstDestructCandidate(None));
918928
return;
919929
}
920930

@@ -927,7 +937,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
927937
| ty::Param(_)
928938
| ty::Placeholder(_)
929939
| ty::Projection(_) => {
930-
// We don't know if these are `~const Drop`, at least
940+
// We don't know if these are `~const Destruct`, at least
931941
// not structurally... so don't push a candidate.
932942
}
933943

@@ -951,26 +961,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
951961
| ty::Generator(..)
952962
| ty::Tuple(_)
953963
| ty::GeneratorWitness(_) => {
954-
// These are built-in, and cannot have a custom `impl const Drop`.
955-
candidates.vec.push(ConstDropCandidate(None));
964+
// These are built-in, and cannot have a custom `impl const Destruct`.
965+
candidates.vec.push(ConstDestructCandidate(None));
956966
}
957967

958968
ty::Adt(..) => {
959969
// Find a custom `impl Drop` impl, if it exists
960970
let relevant_impl = self.tcx().find_map_relevant_impl(
961-
obligation.predicate.def_id(),
971+
self.tcx().require_lang_item(LangItem::Drop, None),
962972
obligation.predicate.skip_binder().trait_ref.self_ty(),
963973
Some,
964974
);
965975

966976
if let Some(impl_def_id) = relevant_impl {
967977
// Check that `impl Drop` is actually const, if there is a custom impl
968978
if self.tcx().impl_constness(impl_def_id) == hir::Constness::Const {
969-
candidates.vec.push(ConstDropCandidate(Some(impl_def_id)));
979+
candidates.vec.push(ConstDestructCandidate(Some(impl_def_id)));
970980
}
971981
} else {
972982
// Otherwise check the ADT like a built-in type (structurally)
973-
candidates.vec.push(ConstDropCandidate(None));
983+
candidates.vec.push(ConstDestructCandidate(None));
974984
}
975985
}
976986

compiler/rustc_trait_selection/src/traits/select/confirmation.rs

+47-17
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
//! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
99
use rustc_data_structures::stack::ensure_sufficient_stack;
1010
use rustc_hir::lang_items::LangItem;
11-
use rustc_hir::Constness;
1211
use rustc_index::bit_set::GrowableBitSet;
1312
use rustc_infer::infer::InferOk;
1413
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
@@ -29,9 +28,9 @@ use crate::traits::TraitNotObjectSafe;
2928
use crate::traits::VtblSegment;
3029
use crate::traits::{BuiltinDerivedObligation, ImplDerivedObligation};
3130
use crate::traits::{
32-
ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData, ImplSourceConstDropData,
33-
ImplSourceDiscriminantKindData, ImplSourceFnPointerData, ImplSourceGeneratorData,
34-
ImplSourceObjectData, ImplSourcePointeeData, ImplSourceTraitAliasData,
31+
ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData,
32+
ImplSourceConstDestructData, ImplSourceDiscriminantKindData, ImplSourceFnPointerData,
33+
ImplSourceGeneratorData, ImplSourceObjectData, ImplSourcePointeeData, ImplSourceTraitAliasData,
3534
ImplSourceTraitUpcastingData, ImplSourceUserDefinedData,
3635
};
3736
use crate::traits::{ObjectCastObligation, PredicateObligation, TraitObligation};
@@ -156,9 +155,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
156155
Ok(ImplSource::TraitUpcasting(data))
157156
}
158157

159-
ConstDropCandidate(def_id) => {
160-
let data = self.confirm_const_drop_candidate(obligation, def_id)?;
161-
Ok(ImplSource::ConstDrop(data))
158+
ConstDestructCandidate(def_id) => {
159+
let data = self.confirm_const_destruct_candidate(obligation, def_id)?;
160+
Ok(ImplSource::ConstDestruct(data))
162161
}
163162
}
164163
}
@@ -1037,14 +1036,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10371036
Ok(ImplSourceBuiltinData { nested })
10381037
}
10391038

1040-
fn confirm_const_drop_candidate(
1039+
fn confirm_const_destruct_candidate(
10411040
&mut self,
10421041
obligation: &TraitObligation<'tcx>,
10431042
impl_def_id: Option<DefId>,
1044-
) -> Result<ImplSourceConstDropData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
1045-
// `~const Drop` in a non-const environment is always trivially true, since our type is `Drop`
1046-
if obligation.param_env.constness() == Constness::NotConst {
1047-
return Ok(ImplSourceConstDropData { nested: vec![] });
1043+
) -> Result<ImplSourceConstDestructData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
1044+
// `~const Destruct` in a non-const environment is always trivially true, since our type is `Drop`
1045+
if !obligation.is_const() {
1046+
return Ok(ImplSourceConstDestructData { nested: vec![] });
1047+
}
1048+
1049+
let drop_trait = self.tcx().require_lang_item(LangItem::Drop, None);
1050+
// FIXME: remove if statement below when beta is bumped
1051+
#[cfg(bootstrap)]
1052+
{}
1053+
1054+
if obligation.predicate.skip_binder().def_id() == drop_trait {
1055+
return Ok(ImplSourceConstDestructData { nested: vec![] });
10481056
}
10491057

10501058
let tcx = self.tcx();
@@ -1054,9 +1062,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10541062
let cause = obligation.derived_cause(BuiltinDerivedObligation);
10551063

10561064
// If we have a custom `impl const Drop`, then
1057-
// first check it like a regular impl candidate
1065+
// first check it like a regular impl candidate.
1066+
// This is copied from confirm_impl_candidate but remaps the predicate to `~const Drop` beforehand.
10581067
if let Some(impl_def_id) = impl_def_id {
1059-
nested.extend(self.confirm_impl_candidate(obligation, impl_def_id).nested);
1068+
let obligations = self.infcx.commit_unconditionally(|_| {
1069+
let mut new_obligation = obligation.clone();
1070+
new_obligation.predicate = new_obligation.predicate.map_bound(|mut trait_pred| {
1071+
trait_pred.trait_ref.def_id = drop_trait;
1072+
trait_pred
1073+
});
1074+
let substs = self.rematch_impl(impl_def_id, &new_obligation);
1075+
debug!(?substs, "impl substs");
1076+
let cause = obligation.derived_cause(ImplDerivedObligation);
1077+
ensure_sufficient_stack(|| {
1078+
self.vtable_impl(
1079+
impl_def_id,
1080+
substs,
1081+
cause,
1082+
new_obligation.recursion_depth + 1,
1083+
new_obligation.param_env,
1084+
)
1085+
})
1086+
});
1087+
nested.extend(obligations.nested);
10601088
}
10611089

10621090
// We want to confirm the ADT's fields if we have an ADT
@@ -1114,7 +1142,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11141142
self_ty
11151143
.rebind(ty::TraitPredicate {
11161144
trait_ref: ty::TraitRef {
1117-
def_id: self.tcx().require_lang_item(LangItem::Drop, None),
1145+
def_id: self
1146+
.tcx()
1147+
.require_lang_item(LangItem::Destruct, None),
11181148
substs: self.tcx().mk_substs_trait(nested_ty, &[]),
11191149
},
11201150
constness: ty::BoundConstness::ConstIfConst,
@@ -1140,7 +1170,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11401170
let predicate = self_ty
11411171
.rebind(ty::TraitPredicate {
11421172
trait_ref: ty::TraitRef {
1143-
def_id: self.tcx().require_lang_item(LangItem::Drop, None),
1173+
def_id: self.tcx().require_lang_item(LangItem::Destruct, None),
11441174
substs: self.tcx().mk_substs_trait(nested_ty, &[]),
11451175
},
11461176
constness: ty::BoundConstness::ConstIfConst,
@@ -1158,6 +1188,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11581188
}
11591189
}
11601190

1161-
Ok(ImplSourceConstDropData { nested })
1191+
Ok(ImplSourceConstDestructData { nested })
11621192
}
11631193
}

0 commit comments

Comments
 (0)