]> git.lizzy.rs Git - rust.git/commitdiff
Allow `Validator` to get qualifs for the return place
authorDylan MacKenzie <ecstaticmorse@gmail.com>
Mon, 28 Oct 2019 17:24:29 +0000 (10:24 -0700)
committerDylan MacKenzie <ecstaticmorse@gmail.com>
Fri, 15 Nov 2019 18:33:32 +0000 (10:33 -0800)
src/librustc_mir/transform/check_consts/validation.rs

index 74b22d8e14366af24025dabaf7fd15ac9fdad5cc..53fb0bab80f83425dda94733906d145cb46cf50d 100644 (file)
@@ -17,7 +17,7 @@
 use super::ops::{self, NonConstOp};
 use super::qualifs::{HasMutInterior, NeedsDrop};
 use super::resolver::FlowSensitiveAnalysis;
-use super::{ConstKind, Item, Qualif, is_lang_panic_fn};
+use super::{ConstKind, Item, Qualif, QualifSet, is_lang_panic_fn};
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub enum CheckOpResult {
@@ -85,6 +85,19 @@ fn needs_drop_lazy_seek(&mut self, local: Local, location: Location) -> bool {
             || self.indirectly_mutable(local, location)
     }
 
+    /// Returns `true` if `local` is `HasMutInterior` at the given `Location`.
+    ///
+    /// Only updates the cursor if absolutely necessary.
+    fn has_mut_interior_lazy_seek(&mut self, local: Local, location: Location) -> bool {
+        if !self.has_mut_interior.in_any_value_of_ty.contains(local) {
+            return false;
+        }
+
+        self.has_mut_interior.cursor.seek_before(location);
+        self.has_mut_interior.cursor.get().contains(local)
+            || self.indirectly_mutable(local, location)
+    }
+
     /// Returns `true` if `local` is `HasMutInterior`, but requires the `has_mut_interior` and
     /// `indirectly_mutable` cursors to be updated beforehand.
     fn has_mut_interior_eager_seek(&self, local: Local) -> bool {
@@ -95,6 +108,37 @@ fn has_mut_interior_eager_seek(&self, local: Local) -> bool {
         self.has_mut_interior.cursor.get().contains(local)
             || self.indirectly_mutable.get().contains(local)
     }
+
+    fn in_return_place(&mut self, item: &Item<'_, 'tcx>) -> QualifSet {
+        // Find the `Return` terminator if one exists.
+        //
+        // If no `Return` terminator exists, this MIR is divergent. Just return the conservative
+        // qualifs for the return type.
+        let return_block = item.body
+            .basic_blocks()
+            .iter_enumerated()
+            .find(|(_, block)| {
+                match block.terminator().kind {
+                    TerminatorKind::Return => true,
+                    _ => false,
+                }
+            })
+            .map(|(bb, _)| bb);
+
+        let return_block = match return_block {
+            None => return QualifSet::in_any_value_of_ty(item, item.body.return_ty()),
+            Some(bb) => bb,
+        };
+
+        let return_loc = item.body.terminator_loc(return_block);
+
+        let mut qualifs = QualifSet::default();
+
+        qualifs.set::<NeedsDrop>(self.needs_drop_lazy_seek(RETURN_PLACE, return_loc));
+        qualifs.set::<HasMutInterior>(self.has_mut_interior_lazy_seek(RETURN_PLACE, return_loc));
+
+        qualifs
+    }
 }
 
 pub struct Validator<'a, 'mir, 'tcx> {