about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDeadbeef <ent3rm4n@gmail.com>2021-09-02 10:59:53 +0000
committerDeadbeef <ent3rm4n@gmail.com>2021-09-09 05:21:32 +0000
commit1ca83c6451783aaa77aa69643b70b22ef9e9a01a (patch)
tree1c8d6ae32eb0353472adbb255bce0d408278482c
parentf0a52128ee2d522e12893637428d88a3287c818e (diff)
downloadrust-1ca83c6451783aaa77aa69643b70b22ef9e9a01a.tar.gz
rust-1ca83c6451783aaa77aa69643b70b22ef9e9a01a.zip
Use trait select logic instead of query
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs14
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs29
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs52
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs11
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stderr27
5 files changed, 101 insertions, 32 deletions
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 13345183124..f1c7d3035b9 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -988,14 +988,12 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
 
                 let mut err_span = self.span;
 
-                // Check to see if the type of this place can ever have a drop impl. If not, this
-                // `Drop` terminator is frivolous.
-                let ty_needs_drop = dropped_place
-                    .ty(self.body, self.tcx)
-                    .ty
-                    .needs_non_const_drop(self.tcx, self.param_env);
-
-                if !ty_needs_drop {
+                let ty_needs_non_const_drop = qualifs::NeedsNonConstDrop::in_any_value_of_ty(
+                    self.ccx,
+                    dropped_place.ty(self.body, self.tcx).ty,
+                );
+
+                if !ty_needs_non_const_drop {
                     return;
                 }
 
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index 50b691dffe8..ea8f0a29181 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -3,10 +3,14 @@
 //! See the `Qualif` trait for more info.
 
 use rustc_errors::ErrorReported;
+use rustc_hir as hir;
+use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
 use rustc_span::DUMMY_SP;
-use rustc_trait_selection::traits;
+use rustc_trait_selection::traits::{
+    self, ImplSource, Obligation, ObligationCause, SelectionContext,
+};
 
 use super::ConstCx;
 
@@ -108,7 +112,28 @@ impl Qualif for NeedsNonConstDrop {
     }
 
     fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
-        ty.needs_drop(cx.tcx, cx.param_env)
+        let trait_ref = ty::TraitRef {
+            def_id: cx.tcx.require_lang_item(hir::LangItem::Drop, None),
+            substs: cx.tcx.mk_substs_trait(ty, &[]),
+        };
+        let obligation = Obligation::new(
+            ObligationCause::dummy(),
+            cx.param_env,
+            ty::Binder::dummy(ty::TraitPredicate {
+                trait_ref,
+                constness: ty::BoundConstness::ConstIfConst,
+            }),
+        );
+
+        let implsrc = cx.tcx.infer_ctxt().enter(|infcx| {
+            let mut selcx = SelectionContext::with_constness(&infcx, hir::Constness::Const);
+            selcx.select(&obligation)
+        });
+        match implsrc {
+            Ok(Some(ImplSource::ConstDrop(_)))
+            | Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => false,
+            _ => true,
+        }
     }
 
     fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, _: SubstsRef<'tcx>) -> bool {
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index ffaef566cd5..6d64dc8254b 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -283,6 +283,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             if self.is_in_const_context {
                 self.assemble_const_drop_candidates(obligation, &mut candidates)?;
             } else {
+                debug!("passing ~const Drop bound; in non-const context");
                 // `~const Drop` when we are not in a const context has no effect.
                 candidates.vec.push(ConstDropCandidate)
             }
@@ -821,6 +822,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let mut stack: Vec<(Ty<'tcx>, usize)> = vec![(obligation.self_ty().skip_binder(), 0)];
 
         while let Some((ty, depth)) = stack.pop() {
+            let mut noreturn = false;
+
             self.check_recursion_depth(depth, obligation)?;
             let mut copy_candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
             let mut copy_obligation =
@@ -836,8 +839,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             let copy_conditions = self.copy_clone_conditions(&copy_obligation);
             self.assemble_builtin_bound_candidates(copy_conditions, &mut copy_candidates);
             if !copy_candidates.vec.is_empty() {
-                continue;
+                noreturn = true;
             }
+            debug!(?copy_candidates.vec, "assemble_const_drop_candidates - copy");
 
             match ty.kind() {
                 ty::Int(_)
@@ -857,22 +861,28 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
                 ty::Adt(def, subst) => {
                     let mut set = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
-                    self.assemble_candidates_from_impls(obligation, &mut set);
-                    if set
-                        .vec
-                        .into_iter()
-                        .find(|candidate| {
-                            if let SelectionCandidate::ImplCandidate(did) = candidate {
-                                matches!(self.tcx().impl_constness(*did), hir::Constness::NotConst)
-                            } else {
-                                false
-                            }
-                        })
-                        .is_none()
-                    {
-                        // could not find a const impl for Drop, iterate over its fields.
-                        stack
-                            .extend(def.all_fields().map(|f| (f.ty(self.tcx(), subst), depth + 1)));
+                    self.assemble_candidates_from_impls(
+                        &obligation.with(obligation.predicate.map_bound(|mut pred| {
+                            pred.trait_ref.substs = self.tcx().mk_substs_trait(ty, &[]);
+                            pred
+                        })),
+                        &mut set,
+                    );
+                    stack.extend(def.all_fields().map(|f| (f.ty(self.tcx(), subst), depth + 1)));
+
+                    debug!(?set.vec, "assemble_const_drop_candidates - ty::Adt");
+                    if set.vec.into_iter().any(|candidate| {
+                        if let SelectionCandidate::ImplCandidate(did) = candidate {
+                            matches!(self.tcx().impl_constness(did), hir::Constness::NotConst)
+                        } else {
+                            false
+                        }
+                    }) {
+                        if !noreturn {
+                            // has non-const Drop
+                            return Ok(());
+                        }
+                        debug!("not returning");
                     }
                 }
 
@@ -903,8 +913,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 | ty::Infer(_)
                 | ty::Placeholder(_)
                 | ty::Projection(..)
-                | ty::Param(..) => return Ok(()),
+                | ty::Param(..) => {
+                    if !noreturn {
+                        return Ok(());
+                    }
+                    debug!("not returning");
+                }
             }
+            debug!(?stack, "assemble_const_drop_candidates - in loop");
         }
         // all types have passed.
         candidates.vec.push(ConstDropCandidate);
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs
index a79b67fb0db..17442e1b05a 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs
@@ -16,16 +16,19 @@ impl const Drop for ConstImplWithDropGlue {
     fn drop(&mut self) {}
 }
 
-const fn check<T: ~const Drop>() {}
+const fn check<T: ~const Drop>(_: T) {}
 
 macro_rules! check_all {
-    ($($T:ty),*$(,)?) => {$(
-        const _: () = check::<$T>();
+    ($($exp:expr),*$(,)?) => {$(
+        const _: () = check($exp);
     )*};
 }
 
 check_all! {
-    ConstImplWithDropGlue,
+    NonTrivialDrop,
+    //~^ ERROR the trait bound
+    ConstImplWithDropGlue(NonTrivialDrop),
+    //~^ ERROR the trait bound
 }
 
 fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stderr
new file mode 100644
index 00000000000..e962503d7df
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stderr
@@ -0,0 +1,27 @@
+error[E0277]: the trait bound `NonTrivialDrop: Drop` is not satisfied
+  --> $DIR/const-drop-fail.rs:28:5
+   |
+LL |     NonTrivialDrop,
+   |     ^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `NonTrivialDrop`
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:19:19
+   |
+LL | const fn check<T: ~const Drop>(_: T) {}
+   |                   ^^^^^^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `ConstImplWithDropGlue: Drop` is not satisfied
+  --> $DIR/const-drop-fail.rs:30:5
+   |
+LL |     ConstImplWithDropGlue(NonTrivialDrop),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `ConstImplWithDropGlue`
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:19:19
+   |
+LL | const fn check<T: ~const Drop>(_: T) {}
+   |                   ^^^^^^^^^^^ required by this bound in `check`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.