]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
New upstream version 1.60.0+dfsg1
[rustc.git] / compiler / rustc_const_eval / src / transform / check_consts / qualifs.rs
index 27f2da34262a1f2e851f95a979bd3ed7d54d583d..639b798be5431abad80e703acf5702b10d402d52 100644 (file)
@@ -4,11 +4,12 @@
 
 use rustc_errors::ErrorReported;
 use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::traits::TraitEngine;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
 use rustc_span::DUMMY_SP;
 use rustc_trait_selection::traits::{
-    self, ImplSource, Obligation, ObligationCause, SelectionContext,
+    self, FulfillmentContext, ImplSource, Obligation, ObligationCause, SelectionContext,
 };
 
 use super::ConstCx;
@@ -16,14 +17,14 @@ use super::ConstCx;
 pub fn in_any_value_of_ty<'tcx>(
     cx: &ConstCx<'_, 'tcx>,
     ty: Ty<'tcx>,
-    error_occured: Option<ErrorReported>,
+    tainted_by_errors: Option<ErrorReported>,
 ) -> ConstQualifs {
     ConstQualifs {
         has_mut_interior: HasMutInterior::in_any_value_of_ty(cx, ty),
         needs_drop: NeedsDrop::in_any_value_of_ty(cx, ty),
         needs_non_const_drop: NeedsNonConstDrop::in_any_value_of_ty(cx, ty),
         custom_eq: CustomEq::in_any_value_of_ty(cx, ty),
-        error_occured,
+        tainted_by_errors,
     }
 }
 
@@ -145,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::is_trivially_const_drop(ty) {
+            return false;
         }
 
         let Some(drop_trait) = cx.tcx.lang_items().drop_trait() else {
@@ -161,28 +157,50 @@ impl Qualif for NeedsNonConstDrop {
             // without having the lang item present.
             return false;
         };
-        let trait_ref =
-            ty::TraitRef { def_id: drop_trait, substs: cx.tcx.mk_substs_trait(ty, &[]) };
+
         let obligation = Obligation::new(
             ObligationCause::dummy(),
             cx.param_env,
             ty::Binder::dummy(ty::TraitPredicate {
-                trait_ref,
+                trait_ref: ty::TraitRef {
+                    def_id: drop_trait,
+                    substs: cx.tcx.mk_substs_trait(ty, &[]),
+                },
                 constness: ty::BoundConstness::ConstIfConst,
                 polarity: ty::ImplPolarity::Positive,
             }),
         );
 
-        let implsrc = cx.tcx.infer_ctxt().enter(|infcx| {
+        cx.tcx.infer_ctxt().enter(|infcx| {
             let mut selcx = SelectionContext::new(&infcx);
-            selcx.select(&obligation)
-        });
-        !matches!(
-            implsrc,
-            Ok(Some(
+            let Some(impl_src) = selcx.select(&obligation).ok().flatten() else {
+                // If we couldn't select a const drop candidate, then it's bad
+                return true;
+            };
+
+            if !matches!(
+                impl_src,
                 ImplSource::ConstDrop(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst)
-            ))
-        )
+            ) {
+                // 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();
+            for nested in impl_src.nested_obligations() {
+                fcx.register_predicate_obligation(&infcx, nested);
+            }
+
+            // If we had any errors, then it's bad
+            !fcx.select_all_or_error(&infcx).is_empty()
+        })
     }
 
     fn in_adt_inherently<'tcx>(
@@ -210,8 +228,7 @@ impl Qualif for CustomEq {
         // because that component may be part of an enum variant (e.g.,
         // `Option::<NonStructuralMatchTy>::Some`), in which case some values of this type may be
         // structural-match (`Option::None`).
-        let id = cx.tcx.hir().local_def_id_to_hir_id(cx.def_id());
-        traits::search_for_structural_match_violation(id, cx.body.span, cx.tcx, ty).is_some()
+        traits::search_for_structural_match_violation(cx.body.span, cx.tcx, ty).is_some()
     }
 
     fn in_adt_inherently<'tcx>(
@@ -338,7 +355,7 @@ where
 
     // Check the qualifs of the value of `const` items.
     if let Some(ct) = constant.literal.const_for_ty() {
-        if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs_: _, promoted }) = ct.val {
+        if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) = ct.val() {
             // Use qualifs of the type for the promoted. Promoteds in MIR body should be possible
             // only for `NeedsNonConstDrop` with precise drop checking. This is the only const
             // check performed after the promotion. Verify that with an assertion.