]> git.lizzy.rs Git - rust.git/commitdiff
Compute the ParamEnv only once and use it to call tcx.const_eval
authorOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Wed, 31 Jan 2018 08:31:24 +0000 (09:31 +0100)
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Thu, 8 Mar 2018 07:34:15 +0000 (08:34 +0100)
src/librustc_mir/interpret/const_eval.rs
src/librustc_mir/transform/const_prop.rs

index e216f5c4d8a8218c8803f93cb3680b58dac85f8a..b141106aa60f551785a0d9b89426a0087c0b78c8 100644 (file)
@@ -61,7 +61,7 @@ pub fn eval_body_with_mir<'a, 'mir, 'tcx>(
     mir: &'mir mir::Mir<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
 ) -> Option<(Value, Pointer, Ty<'tcx>)> {
-    let (res, ecx) = eval_body_and_ecx(tcx, cid, Some(mir), param_env);
+    let (res, ecx, _) = eval_body_and_ecx(tcx, cid, Some(mir), param_env);
     match res {
         Ok(val) => Some(val),
         Err(mut err) => {
@@ -76,7 +76,7 @@ pub fn eval_body<'a, 'tcx>(
     cid: GlobalId<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
 ) -> Option<(Value, Pointer, Ty<'tcx>)> {
-    let (res, ecx) = eval_body_and_ecx(tcx, cid, None, param_env);
+    let (res, ecx, _) = eval_body_and_ecx(tcx, cid, None, param_env);
     match res {
         Ok(val) => Some(val),
         Err(mut err) => {
@@ -91,9 +91,12 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
     cid: GlobalId<'tcx>,
     mir: Option<&'mir mir::Mir<'tcx>>,
     param_env: ty::ParamEnv<'tcx>,
-) -> (EvalResult<'tcx, (Value, Pointer, Ty<'tcx>)>, EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>) {
+) -> (EvalResult<'tcx, (Value, Pointer, Ty<'tcx>)>, EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>, Span) {
     debug!("eval_body: {:?}, {:?}", cid, param_env);
     let mut ecx = EvalContext::new(tcx, param_env, CompileTimeEvaluator, ());
+    // we start out with the best span we have
+    // and try improving it down the road when more information is available
+    let mut span = tcx.def_span(cid.instance.def_id());
     let res = (|| {
         let mut mir = match mir {
             Some(mir) => mir,
@@ -102,6 +105,7 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
         if let Some(index) = cid.promoted {
             mir = &mir.promoted[index];
         }
+        span = mir.span;
         let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?;
         let alloc = tcx.interpret_interner.get_cached(cid.instance.def_id());
         let alloc = match alloc {
@@ -120,8 +124,7 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
                 if tcx.is_static(cid.instance.def_id()).is_some() {
                     tcx.interpret_interner.cache(cid.instance.def_id(), ptr.alloc_id);
                 }
-                let span = tcx.def_span(cid.instance.def_id());
-                let internally_mutable = !layout.ty.is_freeze(tcx, param_env, span);
+                let internally_mutable = !layout.ty.is_freeze(tcx, param_env, mir.span);
                 let mutability = tcx.is_static(cid.instance.def_id());
                 let mutability = if mutability == Some(hir::Mutability::MutMutable) || internally_mutable {
                     Mutability::Mutable
@@ -152,7 +155,7 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
         };
         Ok((value, ptr, layout.ty))
     })();
-    (res, ecx)
+    (res, ecx, span)
 }
 
 pub struct CompileTimeEvaluator;
@@ -499,7 +502,7 @@ pub fn const_eval_provider<'a, 'tcx>(
         }
     };
 
-    let (res, ecx) = eval_body_and_ecx(tcx, cid, None, key.param_env);
+    let (res, ecx, span) = eval_body_and_ecx(tcx, cid, None, key.param_env);
     res.map(|(miri_value, _, miri_ty)| {
         tcx.mk_const(ty::Const {
             val: ConstVal::Value(miri_value),
@@ -509,7 +512,6 @@ pub fn const_eval_provider<'a, 'tcx>(
         if tcx.is_static(def_id).is_some() {
             ecx.report(&mut err, true, None);
         }
-        let span = ecx.frame().span;
         ConstEvalErr {
             kind: err.into(),
             span,
index 09c72c4bf9387ff09c1efe837df0fd525105c8c7..d3ab494139a502b3a01eb514c3667c5ea2bfa056 100644 (file)
 use rustc::middle::const_val::ConstVal;
 use rustc::ty::{TyCtxt, self, Instance};
 use rustc::mir::interpret::{Value, PrimVal, GlobalId};
-use interpret::{eval_body_with_mir, eval_body, mk_borrowck_eval_cx, unary_op, ValTy};
+use interpret::{eval_body_with_mir, mk_borrowck_eval_cx, unary_op, ValTy};
 use transform::{MirPass, MirSource};
 use syntax::codemap::Span;
 use rustc::ty::subst::Substs;
 use rustc_data_structures::indexed_vec::IndexVec;
+use rustc::ty::ParamEnv;
 
 pub struct ConstProp;
 
@@ -56,6 +57,7 @@ struct ConstPropagator<'b, 'a, 'tcx:'a+'b> {
     source: MirSource,
     places: IndexVec<Local, Option<Const<'tcx>>>,
     can_const_prop: IndexVec<Local, bool>,
+    param_env: ParamEnv<'tcx>,
 }
 
 impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
@@ -64,24 +66,40 @@ fn new(
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
         source: MirSource,
     ) -> ConstPropagator<'b, 'a, 'tcx> {
+        let param_env = tcx.param_env(source.def_id);
         ConstPropagator {
             mir,
             tcx,
             source,
+            param_env,
             can_const_prop: CanConstProp::check(mir),
             places: IndexVec::from_elem(None, &mir.local_decls),
         }
     }
 
+    fn const_eval(&self, cid: GlobalId<'tcx>, span: Span) -> Option<Const<'tcx>> {
+        let value = match self.tcx.const_eval(self.param_env.and(cid)) {
+            Ok(val) => val,
+            // FIXME: report some errors
+            Err(_) => return None,
+        };
+        let val = match value.val {
+            ConstVal::Value(v) => v,
+            _ => bug!("eval produced: {:?}", value),
+        };
+        let val = (val, value.ty, span);
+        trace!("evaluated {:?} to {:?}", cid, val);
+        Some(val)
+    }
+
     fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'tcx>> {
         match c.literal {
             Literal::Value { value } => match value.val {
                 ConstVal::Value(v) => Some((v, value.ty, c.span)),
                 ConstVal::Unevaluated(did, substs) => {
-                    let param_env = self.tcx.param_env(self.source.def_id);
                     let instance = Instance::resolve(
                         self.tcx,
-                        param_env,
+                        self.param_env,
                         did,
                         substs,
                     )?;
@@ -89,10 +107,7 @@ fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'tcx>> {
                         instance,
                         promoted: None,
                     };
-                    let (value, _, ty) = eval_body(self.tcx, cid, param_env)?;
-                    let val = (value, ty, c.span);
-                    trace!("evaluated {:?} to {:?}", c, val);
-                    Some(val)
+                    self.const_eval(cid, c.span)
                 },
             },
             // evaluate the promoted and replace the constant with the evaluated result
@@ -108,8 +123,9 @@ fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'tcx>> {
                     instance,
                     promoted: Some(index),
                 };
-                let param_env = self.tcx.param_env(self.source.def_id);
-                let (value, _, ty) = eval_body_with_mir(self.tcx, cid, self.mir, param_env)?;
+                // cannot use `const_eval` here, because that would require having the MIR
+                // for the current function available, but we're producing said MIR right now
+                let (value, _, ty) = eval_body_with_mir(self.tcx, cid, self.mir, self.param_env)?;
                 let val = (value, ty, c.span);
                 trace!("evaluated {:?} to {:?}", c, val);
                 Some(val)