about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-01-18 17:01:52 -0800
committerMichael Goulet <michael@errs.io>2022-01-18 17:01:52 -0800
commitba87be05cfa8f9a02d673a64aa2ee83976d80e60 (patch)
treea66d71d29d35fceed9131b245af9a02e3132ea2a /compiler
parent33e5efbd586cbdc683cb54949fe163755c57e9e8 (diff)
downloadrust-ba87be05cfa8f9a02d673a64aa2ee83976d80e60.tar.gz
rust-ba87be05cfa8f9a02d673a64aa2ee83976d80e60.zip
Short-circuit some trivially const Drop types
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs19
-rw-r--r--compiler/rustc_middle/src/ty/util.rs36
2 files changed, 45 insertions, 10 deletions
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 1269f2207d5..8dfdbf5d9dd 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -146,15 +146,10 @@ impl Qualif for NeedsNonConstDrop {
         qualifs.needs_non_const_drop
     }
 
-    fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, mut ty: Ty<'tcx>) -> bool {
-        // Avoid selecting for simple cases.
-        match ty::util::needs_drop_components(ty, &cx.tcx.data_layout).as_deref() {
-            Ok([]) => return false,
-            Err(ty::util::AlwaysRequiresDrop) => return true,
-            // If we've got a single component, select with that
-            // to increase the chance that we hit the selection cache.
-            Ok([t]) => ty = t,
-            Ok([..]) => {}
+    fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
+        // Avoid selecting for simple cases, such as builtin types.
+        if ty::util::trivial_const_drop(ty) {
+            return false;
         }
 
         let Some(drop_trait) = cx.tcx.lang_items().drop_trait() else {
@@ -187,11 +182,15 @@ impl Qualif for NeedsNonConstDrop {
                 impl_src,
                 ImplSource::ConstDrop(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst)
             ) {
-                // If our const drop candidate is not ConstDrop or implied by param,
+                // If our const drop candidate is not ConstDrop or implied by the param env,
                 // then it's bad
                 return true;
             }
 
+            if impl_src.borrow_nested_obligations().is_empty() {
+                return false;
+            }
+
             // If we successfully found one, then select all of the predicates
             // implied by our const drop impl.
             let mut fcx = FulfillmentContext::new();
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 8793264a47f..71e9197e4f5 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -1041,6 +1041,42 @@ pub fn needs_drop_components<'tcx>(
     }
 }
 
+pub fn trivial_const_drop<'tcx>(ty: Ty<'tcx>) -> bool {
+    match *ty.kind() {
+        ty::Bool
+        | ty::Char
+        | ty::Int(_)
+        | ty::Uint(_)
+        | ty::Float(_)
+        | ty::Infer(ty::IntVar(_))
+        | ty::Infer(ty::FloatVar(_))
+        | ty::Str
+        | ty::RawPtr(_)
+        | ty::Ref(..)
+        | ty::FnDef(..)
+        | ty::FnPtr(_) => true,
+
+        ty::Opaque(..)
+        | ty::Dynamic(..)
+        | ty::Error(_)
+        | ty::Bound(..)
+        | ty::Param(_)
+        | ty::Placeholder(_)
+        | ty::Never
+        | ty::Foreign(_)
+        | ty::Projection(_)
+        | ty::Infer(_) => false,
+
+        // Not trivial because they have components, and instead of looking inside,
+        // we'll just perform trait selection.
+        ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(_) | ty::Adt(..) => false,
+
+        ty::Array(ty, _) | ty::Slice(ty) => trivial_const_drop(ty),
+
+        ty::Tuple(tys) => tys.iter().all(|ty| trivial_const_drop(ty.expect_ty())),
+    }
+}
+
 // Does the equivalent of
 // ```
 // let v = self.iter().map(|p| p.fold_with(folder)).collect::<SmallVec<[_; 8]>>();