Skip to content

Commit 1ca83c6

Browse files
committed
Use trait select logic instead of query
1 parent f0a5212 commit 1ca83c6

File tree

5 files changed

+101
-32
lines changed

5 files changed

+101
-32
lines changed

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

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -988,14 +988,12 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
988988

989989
let mut err_span = self.span;
990990

991-
// Check to see if the type of this place can ever have a drop impl. If not, this
992-
// `Drop` terminator is frivolous.
993-
let ty_needs_drop = dropped_place
994-
.ty(self.body, self.tcx)
995-
.ty
996-
.needs_non_const_drop(self.tcx, self.param_env);
997-
998-
if !ty_needs_drop {
991+
let ty_needs_non_const_drop = qualifs::NeedsNonConstDrop::in_any_value_of_ty(
992+
self.ccx,
993+
dropped_place.ty(self.body, self.tcx).ty,
994+
);
995+
996+
if !ty_needs_non_const_drop {
999997
return;
1000998
}
1001999

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

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@
33
//! See the `Qualif` trait for more info.
44
55
use rustc_errors::ErrorReported;
6+
use rustc_hir as hir;
7+
use rustc_infer::infer::TyCtxtInferExt;
68
use rustc_middle::mir::*;
79
use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
810
use rustc_span::DUMMY_SP;
9-
use rustc_trait_selection::traits;
11+
use rustc_trait_selection::traits::{
12+
self, ImplSource, Obligation, ObligationCause, SelectionContext,
13+
};
1014

1115
use super::ConstCx;
1216

@@ -108,7 +112,28 @@ impl Qualif for NeedsNonConstDrop {
108112
}
109113

110114
fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
111-
ty.needs_drop(cx.tcx, cx.param_env)
115+
let trait_ref = ty::TraitRef {
116+
def_id: cx.tcx.require_lang_item(hir::LangItem::Drop, None),
117+
substs: cx.tcx.mk_substs_trait(ty, &[]),
118+
};
119+
let obligation = Obligation::new(
120+
ObligationCause::dummy(),
121+
cx.param_env,
122+
ty::Binder::dummy(ty::TraitPredicate {
123+
trait_ref,
124+
constness: ty::BoundConstness::ConstIfConst,
125+
}),
126+
);
127+
128+
let implsrc = cx.tcx.infer_ctxt().enter(|infcx| {
129+
let mut selcx = SelectionContext::with_constness(&infcx, hir::Constness::Const);
130+
selcx.select(&obligation)
131+
});
132+
match implsrc {
133+
Ok(Some(ImplSource::ConstDrop(_)))
134+
| Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => false,
135+
_ => true,
136+
}
112137
}
113138

114139
fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, _: SubstsRef<'tcx>) -> bool {

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

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
283283
if self.is_in_const_context {
284284
self.assemble_const_drop_candidates(obligation, &mut candidates)?;
285285
} else {
286+
debug!("passing ~const Drop bound; in non-const context");
286287
// `~const Drop` when we are not in a const context has no effect.
287288
candidates.vec.push(ConstDropCandidate)
288289
}
@@ -821,6 +822,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
821822
let mut stack: Vec<(Ty<'tcx>, usize)> = vec![(obligation.self_ty().skip_binder(), 0)];
822823

823824
while let Some((ty, depth)) = stack.pop() {
825+
let mut noreturn = false;
826+
824827
self.check_recursion_depth(depth, obligation)?;
825828
let mut copy_candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
826829
let mut copy_obligation =
@@ -836,8 +839,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
836839
let copy_conditions = self.copy_clone_conditions(&copy_obligation);
837840
self.assemble_builtin_bound_candidates(copy_conditions, &mut copy_candidates);
838841
if !copy_candidates.vec.is_empty() {
839-
continue;
842+
noreturn = true;
840843
}
844+
debug!(?copy_candidates.vec, "assemble_const_drop_candidates - copy");
841845

842846
match ty.kind() {
843847
ty::Int(_)
@@ -857,22 +861,28 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
857861

858862
ty::Adt(def, subst) => {
859863
let mut set = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
860-
self.assemble_candidates_from_impls(obligation, &mut set);
861-
if set
862-
.vec
863-
.into_iter()
864-
.find(|candidate| {
865-
if let SelectionCandidate::ImplCandidate(did) = candidate {
866-
matches!(self.tcx().impl_constness(*did), hir::Constness::NotConst)
867-
} else {
868-
false
869-
}
870-
})
871-
.is_none()
872-
{
873-
// could not find a const impl for Drop, iterate over its fields.
874-
stack
875-
.extend(def.all_fields().map(|f| (f.ty(self.tcx(), subst), depth + 1)));
864+
self.assemble_candidates_from_impls(
865+
&obligation.with(obligation.predicate.map_bound(|mut pred| {
866+
pred.trait_ref.substs = self.tcx().mk_substs_trait(ty, &[]);
867+
pred
868+
})),
869+
&mut set,
870+
);
871+
stack.extend(def.all_fields().map(|f| (f.ty(self.tcx(), subst), depth + 1)));
872+
873+
debug!(?set.vec, "assemble_const_drop_candidates - ty::Adt");
874+
if set.vec.into_iter().any(|candidate| {
875+
if let SelectionCandidate::ImplCandidate(did) = candidate {
876+
matches!(self.tcx().impl_constness(did), hir::Constness::NotConst)
877+
} else {
878+
false
879+
}
880+
}) {
881+
if !noreturn {
882+
// has non-const Drop
883+
return Ok(());
884+
}
885+
debug!("not returning");
876886
}
877887
}
878888

@@ -903,8 +913,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
903913
| ty::Infer(_)
904914
| ty::Placeholder(_)
905915
| ty::Projection(..)
906-
| ty::Param(..) => return Ok(()),
916+
| ty::Param(..) => {
917+
if !noreturn {
918+
return Ok(());
919+
}
920+
debug!("not returning");
921+
}
907922
}
923+
debug!(?stack, "assemble_const_drop_candidates - in loop");
908924
}
909925
// all types have passed.
910926
candidates.vec.push(ConstDropCandidate);

src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,19 @@ impl const Drop for ConstImplWithDropGlue {
1616
fn drop(&mut self) {}
1717
}
1818

19-
const fn check<T: ~const Drop>() {}
19+
const fn check<T: ~const Drop>(_: T) {}
2020

2121
macro_rules! check_all {
22-
($($T:ty),*$(,)?) => {$(
23-
const _: () = check::<$T>();
22+
($($exp:expr),*$(,)?) => {$(
23+
const _: () = check($exp);
2424
)*};
2525
}
2626

2727
check_all! {
28-
ConstImplWithDropGlue,
28+
NonTrivialDrop,
29+
//~^ ERROR the trait bound
30+
ConstImplWithDropGlue(NonTrivialDrop),
31+
//~^ ERROR the trait bound
2932
}
3033

3134
fn main() {}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error[E0277]: the trait bound `NonTrivialDrop: Drop` is not satisfied
2+
--> $DIR/const-drop-fail.rs:28:5
3+
|
4+
LL | NonTrivialDrop,
5+
| ^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `NonTrivialDrop`
6+
|
7+
note: required by a bound in `check`
8+
--> $DIR/const-drop-fail.rs:19:19
9+
|
10+
LL | const fn check<T: ~const Drop>(_: T) {}
11+
| ^^^^^^^^^^^ required by this bound in `check`
12+
13+
error[E0277]: the trait bound `ConstImplWithDropGlue: Drop` is not satisfied
14+
--> $DIR/const-drop-fail.rs:30:5
15+
|
16+
LL | ConstImplWithDropGlue(NonTrivialDrop),
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `ConstImplWithDropGlue`
18+
|
19+
note: required by a bound in `check`
20+
--> $DIR/const-drop-fail.rs:19:19
21+
|
22+
LL | const fn check<T: ~const Drop>(_: T) {}
23+
| ^^^^^^^^^^^ required by this bound in `check`
24+
25+
error: aborting due to 2 previous errors
26+
27+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)