about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-12-04 17:48:19 +0000
committerbors <bors@rust-lang.org>2019-12-04 17:48:19 +0000
commit6d77e45f01079fe3d40180b3e256e414ab379f63 (patch)
tree6ebdc54c14baad74166c12baf04a690d8f197f4f
parentc4f130493564b23e78628af25201e7e2260849f6 (diff)
parentaf8f1416e1bc004c15f2cb305bbc26e0af5478e1 (diff)
downloadrust-6d77e45f01079fe3d40180b3e256e414ab379f63.tar.gz
rust-6d77e45f01079fe3d40180b3e256e414ab379f63.zip
Auto merge of #66866 - oli-obk:const_fn_memoization, r=RalfJung
Only memoize const fn calls during const eval

Miri and other engines may want to execute the function in order to detect UB inside of them.

r? @RalfJung
-rw-r--r--src/librustc_mir/const_eval.rs18
-rw-r--r--src/librustc_mir/interpret/machine.rs2
-rw-r--r--src/librustc_mir/interpret/terminator.rs17
-rw-r--r--src/librustc_mir/transform/const_prop.rs2
4 files changed, 20 insertions, 19 deletions
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index a3eac1eecf0..968a8a71ba0 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -328,20 +328,32 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         false // for now, we don't enforce validity
     }
 
-    fn find_fn(
+    fn find_mir_or_eval_fn(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx>],
         ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>,
         _unwind: Option<mir::BasicBlock> // unwinding is not supported in consts
     ) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>> {
-        debug!("eval_fn_call: {:?}", instance);
+        debug!("find_mir_or_eval_fn: {:?}", instance);
+
         // Only check non-glue functions
         if let ty::InstanceDef::Item(def_id) = instance.def {
             // Execution might have wandered off into other crates, so we cannot do a stability-
             // sensitive check here.  But we can at least rule out functions that are not const
             // at all.
-            if !ecx.tcx.is_const_fn_raw(def_id) {
+            if ecx.tcx.is_const_fn_raw(def_id) {
+                // If this function is a `const fn` then as an optimization we can query this
+                // evaluation immediately.
+                //
+                // For the moment we only do this for functions which take no arguments
+                // (or all arguments are ZSTs) so that we don't memoize too much.
+                if args.iter().all(|a| a.layout.is_zst()) {
+                    let gid = GlobalId { instance, promoted: None };
+                    ecx.eval_const_fn_call(gid, ret)?;
+                    return Ok(None);
+                }
+            } else {
                 // Some functions we support even if they are non-const -- but avoid testing
                 // that for const fn!  We certainly do *not* want to actually call the fn
                 // though, so be sure we return here.
diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs
index 2ecc8d88ad3..74206ad2873 100644
--- a/src/librustc_mir/interpret/machine.rs
+++ b/src/librustc_mir/interpret/machine.rs
@@ -146,7 +146,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
     /// nor just jump to `ret`, but instead push their own stack frame.)
     /// Passing `dest`and `ret` in the same `Option` proved very annoying when only one of them
     /// was used.
-    fn find_fn(
+    fn find_mir_or_eval_fn(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx, Self::PointerTag>],
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index 06c3969fbc5..b8dc15f451d 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -266,20 +266,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             ty::InstanceDef::DropGlue(..) |
             ty::InstanceDef::CloneShim(..) |
             ty::InstanceDef::Item(_) => {
-                // If this function is a `const fn` then as an optimization we can query this
-                // evaluation immediately.
-                //
-                // For the moment we only do this for functions which take no arguments
-                // (or all arguments are ZSTs) so that we don't memoize too much.
-                if self.tcx.is_const_fn_raw(instance.def.def_id()) &&
-                   args.iter().all(|a| a.layout.is_zst())
-                {
-                    let gid = GlobalId { instance, promoted: None };
-                    return self.eval_const_fn_call(gid, ret);
-                }
-
                 // We need MIR for this fn
-                let body = match M::find_fn(self, instance, args, ret, unwind)? {
+                let body = match M::find_mir_or_eval_fn(self, instance, args, ret, unwind)? {
                     Some(body) => body,
                     None => return Ok(()),
                 };
@@ -445,7 +433,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
     /// Evaluate a const function where all arguments (if any) are zero-sized types.
     /// The evaluation is memoized thanks to the query system.
-    fn eval_const_fn_call(
+    // FIXME: Consider moving this to `const_eval.rs`.
+    pub (crate) fn eval_const_fn_call(
         &mut self,
         gid: GlobalId<'tcx>,
         ret: Option<(PlaceTy<'tcx, M::PointerTag>, mir::BasicBlock)>,
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index a99ca71d167..95de635d634 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -128,7 +128,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
         false
     }
 
-    fn find_fn(
+    fn find_mir_or_eval_fn(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _instance: ty::Instance<'tcx>,
         _args: &[OpTy<'tcx>],