about summary refs log tree commit diff
path: root/compiler/rustc_const_eval/src
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-11-19 17:18:54 +0000
committerMichael Goulet <michael@errs.io>2024-11-22 16:54:41 +0000
commitaf0d566e76a709caa2a89123202f583cbcc877e2 (patch)
tree423a4b388450803052248d342deebf74eeab3d5f /compiler/rustc_const_eval/src
parent20882608529a969bd878ad787cf0038716c021df (diff)
downloadrust-af0d566e76a709caa2a89123202f583cbcc877e2.tar.gz
rust-af0d566e76a709caa2a89123202f583cbcc877e2.zip
Deduplicate checking drop terminator
Diffstat (limited to 'compiler/rustc_const_eval/src')
-rw-r--r--compiler/rustc_const_eval/src/check_consts/check.rs75
-rw-r--r--compiler/rustc_const_eval/src/check_consts/ops.rs2
-rw-r--r--compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs57
-rw-r--r--compiler/rustc_const_eval/src/check_consts/qualifs.rs9
-rw-r--r--compiler/rustc_const_eval/src/errors.rs2
5 files changed, 53 insertions, 92 deletions
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index a088a210e26..9f21c864487 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -324,14 +324,6 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
         }
     }
 
-    /// Emits an error at the given `span` if an expression cannot be evaluated in the current
-    /// context. This is meant for use in a post-const-checker pass such as the const precise
-    /// live drops lint.
-    pub fn check_op_spanned_post<O: NonConstOp<'tcx>>(mut self, op: O, span: Span) {
-        self.check_op_spanned(op, span);
-        assert!(self.secondary_errors.is_empty());
-    }
-
     fn check_static(&mut self, def_id: DefId, span: Span) {
         if self.tcx.is_thread_local_static(def_id) {
             self.tcx.dcx().span_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef`");
@@ -429,6 +421,43 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
 
         true
     }
+
+    pub fn check_drop_terminator(
+        &mut self,
+        dropped_place: Place<'tcx>,
+        location: Location,
+        terminator_span: Span,
+    ) {
+        let ty_of_dropped_place = dropped_place.ty(self.body, self.tcx).ty;
+
+        let needs_drop = if let Some(local) = dropped_place.as_local() {
+            self.qualifs.needs_drop(self.ccx, local, location)
+        } else {
+            qualifs::NeedsDrop::in_any_value_of_ty(self.ccx, ty_of_dropped_place)
+        };
+        // If this type doesn't need a drop at all, then there's nothing to enforce.
+        if !needs_drop {
+            return;
+        }
+
+        let mut err_span = self.span;
+        let needs_non_const_drop = if let Some(local) = dropped_place.as_local() {
+            // Use the span where the local was declared as the span of the drop error.
+            err_span = self.body.local_decls[local].source_info.span;
+            self.qualifs.needs_non_const_drop(self.ccx, local, location)
+        } else {
+            qualifs::NeedsNonConstDrop::in_any_value_of_ty(self.ccx, ty_of_dropped_place)
+        };
+
+        self.check_op_spanned(
+            ops::LiveDrop {
+                dropped_at: terminator_span,
+                dropped_ty: ty_of_dropped_place,
+                needs_non_const_drop,
+            },
+            err_span,
+        );
+    }
 }
 
 impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
@@ -874,35 +903,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                     return;
                 }
 
-                let mut err_span = self.span;
-                let ty_of_dropped_place = dropped_place.ty(self.body, self.tcx).ty;
-
-                let needs_drop = if let Some(local) = dropped_place.as_local() {
-                    self.qualifs.needs_drop(self.ccx, local, location)
-                } else {
-                    qualifs::NeedsDrop::in_any_value_of_ty(self.ccx, ty_of_dropped_place)
-                };
-                // If this type doesn't need a drop at all, then there's nothing to enforce.
-                if !needs_drop {
-                    return;
-                }
-
-                let needs_non_const_drop = if let Some(local) = dropped_place.as_local() {
-                    // Use the span where the local was declared as the span of the drop error.
-                    err_span = self.body.local_decls[local].source_info.span;
-                    self.qualifs.needs_non_const_drop(self.ccx, local, location)
-                } else {
-                    qualifs::NeedsNonConstDrop::in_any_value_of_ty(self.ccx, ty_of_dropped_place)
-                };
-
-                self.check_op_spanned(
-                    ops::LiveDrop {
-                        dropped_at: Some(terminator.source_info.span),
-                        dropped_ty: ty_of_dropped_place,
-                        needs_non_const_drop,
-                    },
-                    err_span,
-                );
+                self.check_drop_terminator(*dropped_place, location, terminator.source_info.span);
             }
 
             TerminatorKind::InlineAsm { .. } => self.check_op(ops::InlineAsm),
diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs
index c8d6358161f..ab81e60a33f 100644
--- a/compiler/rustc_const_eval/src/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/check_consts/ops.rs
@@ -459,7 +459,7 @@ impl<'tcx> NonConstOp<'tcx> for InlineAsm {
 
 #[derive(Debug)]
 pub(crate) struct LiveDrop<'tcx> {
-    pub dropped_at: Option<Span>,
+    pub dropped_at: Span,
     pub dropped_ty: Ty<'tcx>,
     pub needs_non_const_drop: bool,
 }
diff --git a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs
index c3a9aad6421..951e19b470b 100644
--- a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs
+++ b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs
@@ -5,11 +5,7 @@ use rustc_span::symbol::sym;
 use tracing::trace;
 
 use super::ConstCx;
-use super::check::Qualifs;
-use super::ops::{self};
-use super::qualifs::{NeedsNonConstDrop, Qualif};
 use crate::check_consts::check::Checker;
-use crate::check_consts::qualifs::NeedsDrop;
 use crate::check_consts::rustc_allow_const_fn_unstable;
 
 /// Returns `true` if we should use the more precise live drop checker that runs after drop
@@ -46,23 +42,16 @@ pub fn check_live_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>) {
         return;
     }
 
-    let mut visitor = CheckLiveDrops { ccx: &ccx, qualifs: Qualifs::default() };
+    // I know it's not great to be creating a new const checker, but I'd
+    // rather use it so we can deduplicate the error emitting logic that
+    // it contains.
+    let mut visitor = CheckLiveDrops { checker: Checker::new(&ccx) };
 
     visitor.visit_body(body);
 }
 
 struct CheckLiveDrops<'mir, 'tcx> {
-    ccx: &'mir ConstCx<'mir, 'tcx>,
-    qualifs: Qualifs<'mir, 'tcx>,
-}
-
-// So we can access `body` and `tcx`.
-impl<'mir, 'tcx> std::ops::Deref for CheckLiveDrops<'mir, 'tcx> {
-    type Target = ConstCx<'mir, 'tcx>;
-
-    fn deref(&self) -> &Self::Target {
-        self.ccx
-    }
+    checker: Checker<'mir, 'tcx>,
 }
 
 impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> {
@@ -82,38 +71,10 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> {
 
         match &terminator.kind {
             mir::TerminatorKind::Drop { place: dropped_place, .. } => {
-                let ty_of_dropped_place = dropped_place.ty(self.body, self.tcx).ty;
-
-                let needs_drop = if let Some(local) = dropped_place.as_local() {
-                    self.qualifs.needs_drop(self.ccx, local, location)
-                } else {
-                    NeedsDrop::in_any_value_of_ty(self.ccx, ty_of_dropped_place)
-                };
-                // If this type doesn't need a drop at all, then there's nothing to enforce.
-                if !needs_drop {
-                    return;
-                }
-
-                let mut err_span = terminator.source_info.span;
-
-                let needs_non_const_drop = if let Some(local) = dropped_place.as_local() {
-                    // Use the span where the local was declared as the span of the drop error.
-                    err_span = self.body.local_decls[local].source_info.span;
-                    self.qualifs.needs_non_const_drop(self.ccx, local, location)
-                } else {
-                    NeedsNonConstDrop::in_any_value_of_ty(self.ccx, ty_of_dropped_place)
-                };
-
-                // I know it's not great to be creating a new const checker, but I'd
-                // rather use it so we can deduplicate the error emitting logic that
-                // it contains.
-                Checker::new(self.ccx).check_op_spanned_post(
-                    ops::LiveDrop {
-                        dropped_at: Some(terminator.source_info.span),
-                        dropped_ty: ty_of_dropped_place,
-                        needs_non_const_drop,
-                    },
-                    err_span,
+                self.checker.check_drop_terminator(
+                    *dropped_place,
+                    location,
+                    terminator.source_info.span,
                 );
             }
 
diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs
index 29fd3aa7d4d..accce883e39 100644
--- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs
@@ -306,11 +306,10 @@ where
             return false;
         }
 
-        // This is currently unconditionally true for all qualifs, since we do
-        // not recurse into the pointer of a deref projection, but that may change
-        // in the future. If that changes, each qualif should be required to
-        // specify whether it operates structurally for deref projections, just like
-        // we do for `Qualif::is_structural_in_adt`.
+        // `Deref` currently unconditionally "qualifies" if `in_any_value_of_ty` returns true,
+        // i.e., we treat all qualifs as non-structural for deref projections. Generally,
+        // we can say very little about `*ptr` even if we know that `ptr` satisfies all
+        // sorts of properties.
         if matches!(elem, ProjectionElem::Deref) {
             // We have to assume that this qualifies.
             return true;
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index 604e5ed61a3..80236ee05b7 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -411,7 +411,7 @@ pub struct LiveDrop<'tcx> {
     pub kind: ConstContext,
     pub dropped_ty: Ty<'tcx>,
     #[label(const_eval_dropped_at_label)]
-    pub dropped_at: Option<Span>,
+    pub dropped_at: Span,
 }
 
 #[derive(Diagnostic)]