]> git.lizzy.rs Git - rust.git/commitdiff
Remove the `self.mir` field from `ConstPropagator`
authorWesley Wiser <wwiser@gmail.com>
Mon, 29 Apr 2019 22:32:35 +0000 (18:32 -0400)
committerWesley Wiser <wwiser@gmail.com>
Thu, 2 May 2019 11:02:34 +0000 (07:02 -0400)
src/librustc_mir/transform/const_prop.rs
src/test/ui/consts/const-err.stderr

index 2465adf46cdf436781ddef8c5b36154a38fbf54d..2d89f73a95f6913c7dc588445d15aeaf6c867337 100644 (file)
@@ -1,18 +1,19 @@
 //! Propagates constants for early reporting of statically known
 //! assertion failures
 
-
 use rustc::hir::def::Def;
-use rustc::mir::{Constant, Location, Place, PlaceBase, Mir, Operand, Rvalue, Local};
-use rustc::mir::{NullOp, UnOp, StatementKind, Statement, LocalKind, Static, StaticKind};
-use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
+use rustc::mir::{
+    Constant, Location, Place, PlaceBase, Mir, Operand, Rvalue, Local,
+    NullOp, UnOp, StatementKind, Statement, LocalKind, Static, StaticKind,
+    TerminatorKind, Terminator,  ClearCrossCrate, SourceInfo, BinOp, ProjectionElem,
+    SourceScope, SourceScopeLocalData, LocalDecl, Promoted,
+};
 use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext};
 use rustc::mir::interpret::{InterpError, Scalar, GlobalId, EvalResult};
-use rustc::ty::{self, Instance, Ty, TyCtxt};
-use syntax::source_map::{Span, DUMMY_SP};
+use rustc::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
+use syntax::source_map::DUMMY_SP;
 use rustc::ty::subst::InternalSubsts;
 use rustc_data_structures::indexed_vec::IndexVec;
-use rustc::ty::ParamEnv;
 use rustc::ty::layout::{
     LayoutOf, TyLayout, LayoutError,
     HasTyCtxt, TargetDataLayout, HasDataLayout,
@@ -62,21 +63,33 @@ fn run_pass<'a, 'tcx>(&self,
         let mut optimization_finder = ConstPropagator::new(mir, tcx, source);
         optimization_finder.visit_mir(mir);
 
+        // put back the data we stole from `mir`
+        std::mem::replace(
+            &mut mir.source_scope_local_data,
+            optimization_finder.source_scope_local_data
+        );
+        std::mem::replace(
+            &mut mir.promoted,
+            optimization_finder.promoted
+        );
+
         trace!("ConstProp done for {:?}", source.def_id());
     }
 }
 
-type Const<'tcx> = (OpTy<'tcx>, Span);
+type Const<'tcx> = OpTy<'tcx>;
 
 /// Finds optimization opportunities on the MIR.
 struct ConstPropagator<'a, 'mir, 'tcx:'a+'mir> {
     ecx: InterpretCx<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>,
-    mir: &'mir Mir<'tcx>,
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     source: MirSource<'tcx>,
     places: IndexVec<Local, Option<Const<'tcx>>>,
     can_const_prop: IndexVec<Local, bool>,
     param_env: ParamEnv<'tcx>,
+    source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
+    local_decls: IndexVec<Local, LocalDecl<'tcx>>,
+    promoted: IndexVec<Promoted, Mir<'tcx>>,
 }
 
 impl<'a, 'b, 'tcx> LayoutOf for ConstPropagator<'a, 'b, 'tcx> {
@@ -104,20 +117,33 @@ fn tcx<'c>(&'c self) -> TyCtxt<'c, 'tcx, 'tcx> {
 
 impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
     fn new(
-        mir: &'mir Mir<'tcx>,
+        mir: &mut Mir<'tcx>,
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
         source: MirSource<'tcx>,
     ) -> ConstPropagator<'a, 'mir, 'tcx> {
         let param_env = tcx.param_env(source.def_id());
         let ecx = mk_eval_cx(tcx, tcx.def_span(source.def_id()), param_env);
+        let can_const_prop = CanConstProp::check(mir);
+        let source_scope_local_data = std::mem::replace(
+            &mut mir.source_scope_local_data,
+            ClearCrossCrate::Clear
+        );
+        let promoted = std::mem::replace(
+            &mut mir.promoted,
+            IndexVec::new()
+        );
+
         ConstPropagator {
             ecx,
-            mir,
             tcx,
             source,
             param_env,
-            can_const_prop: CanConstProp::check(mir),
+            can_const_prop,
             places: IndexVec::from_elem(None, &mir.local_decls),
+            source_scope_local_data,
+            //FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_mir()` needs it
+            local_decls: mir.local_decls.clone(),
+            promoted,
         }
     }
 
@@ -130,7 +156,7 @@ fn use_ecx<F, T>(
         F: FnOnce(&mut Self) -> EvalResult<'tcx, T>,
     {
         self.ecx.tcx.span = source_info.span;
-        let lint_root = match self.mir.source_scope_local_data {
+        let lint_root = match self.source_scope_local_data {
             ClearCrossCrate::Set(ref ivs) => {
                 //FIXME(#51314): remove this check
                 if source_info.scope.index() >= ivs.len() {
@@ -252,12 +278,11 @@ fn use_ecx<F, T>(
     fn eval_constant(
         &mut self,
         c: &Constant<'tcx>,
-        source_info: SourceInfo,
     ) -> Option<Const<'tcx>> {
-        self.ecx.tcx.span = source_info.span;
+        self.ecx.tcx.span = c.span;
         match self.ecx.eval_const_to_op(*c.literal, None) {
             Ok(op) => {
-                Some((op, c.span))
+                Some(op)
             },
             Err(error) => {
                 let err = error_to_const_error(&self.ecx, error);
@@ -273,11 +298,11 @@ fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option
             Place::Projection(ref proj) => match proj.elem {
                 ProjectionElem::Field(field, _) => {
                     trace!("field proj on {:?}", proj.base);
-                    let (base, span) = self.eval_place(&proj.base, source_info)?;
+                    let base = self.eval_place(&proj.base, source_info)?;
                     let res = self.use_ecx(source_info, |this| {
                         this.ecx.operand_field(base, field.index() as u64)
                     })?;
-                    Some((res, span))
+                    Some(res)
                 },
                 // We could get more projections by using e.g., `operand_projection`,
                 // but we do not even have the stack frame set up properly so
@@ -301,11 +326,11 @@ fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option
                 // 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 res = self.use_ecx(source_info, |this| {
-                    let mir = &this.mir.promoted[promoted];
+                    let mir = &this.promoted[promoted];
                     eval_promoted(this.tcx, cid, mir, this.param_env)
                 })?;
                 trace!("evaluated promoted {:?} to {:?}", promoted, res);
-                Some((res.into(), source_info.span))
+                Some(res.into())
             },
             _ => None,
         }
@@ -313,7 +338,7 @@ fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option
 
     fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
         match *op {
-            Operand::Constant(ref c) => self.eval_constant(c, source_info),
+            Operand::Constant(ref c) => self.eval_constant(c),
             | Operand::Move(ref place)
             | Operand::Copy(ref place) => self.eval_place(place, source_info),
         }
@@ -337,18 +362,18 @@ fn const_prop(
             Rvalue::Discriminant(..) => None,
 
             Rvalue::Cast(kind, ref operand, _) => {
-                let (op, span) = self.eval_operand(operand, source_info)?;
+                let op = self.eval_operand(operand, source_info)?;
                 self.use_ecx(source_info, |this| {
                     let dest = this.ecx.allocate(place_layout, MemoryKind::Stack);
                     this.ecx.cast(op, kind, dest.into())?;
-                    Ok((dest.into(), span))
+                    Ok(dest.into())
                 })
             }
 
             // FIXME(oli-obk): evaluate static/constant slice lengths
             Rvalue::Len(_) => None,
             Rvalue::NullaryOp(NullOp::SizeOf, ty) => {
-                type_size_of(self.tcx, self.param_env, ty).and_then(|n| Some((
+                type_size_of(self.tcx, self.param_env, ty).and_then(|n| Some(
                     ImmTy {
                         imm: Immediate::Scalar(
                             Scalar::Bits {
@@ -357,9 +382,8 @@ fn const_prop(
                             }.into()
                         ),
                         layout: self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
-                    }.into(),
-                    span,
-                )))
+                    }.into()
+                ))
             }
             Rvalue::UnaryOp(op, ref arg) => {
                 let def_id = if self.tcx.is_closure(self.source.def_id()) {
@@ -373,7 +397,7 @@ fn const_prop(
                     return None;
                 }
 
-                let (arg, _) = self.eval_operand(arg, source_info)?;
+                let arg = self.eval_operand(arg, source_info)?;
                 let val = self.use_ecx(source_info, |this| {
                     let prim = this.ecx.read_immediate(arg)?;
                     match op {
@@ -395,7 +419,7 @@ fn const_prop(
                     imm: Immediate::Scalar(val.into()),
                     layout: place_layout,
                 };
-                Some((res.into(), span))
+                Some(res.into())
             }
             Rvalue::CheckedBinaryOp(op, ref left, ref right) |
             Rvalue::BinaryOp(op, ref left, ref right) => {
@@ -413,20 +437,20 @@ fn const_prop(
                 }
 
                 let r = self.use_ecx(source_info, |this| {
-                    this.ecx.read_immediate(right.0)
+                    this.ecx.read_immediate(right)
                 })?;
                 if op == BinOp::Shr || op == BinOp::Shl {
-                    let left_ty = left.ty(self.mir, self.tcx);
+                    let left_ty = left.ty(&self.local_decls, self.tcx);
                     let left_bits = self
                         .tcx
                         .layout_of(self.param_env.and(left_ty))
                         .unwrap()
                         .size
                         .bits();
-                    let right_size = right.0.layout.size;
+                    let right_size = right.layout.size;
                     let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size));
                     if r_bits.ok().map_or(false, |b| b >= left_bits as u128) {
-                        let source_scope_local_data = match self.mir.source_scope_local_data {
+                        let source_scope_local_data = match self.source_scope_local_data {
                             ClearCrossCrate::Set(ref data) => data,
                             ClearCrossCrate::Clear => return None,
                         };
@@ -446,7 +470,7 @@ fn const_prop(
                 }
                 let left = self.eval_operand(left, source_info)?;
                 let l = self.use_ecx(source_info, |this| {
-                    this.ecx.read_immediate(left.0)
+                    this.ecx.read_immediate(left)
                 })?;
                 trace!("const evaluating {:?} for {:?} and {:?}", op, left, right);
                 let (val, overflow) = self.use_ecx(source_info, |this| {
@@ -469,7 +493,7 @@ fn const_prop(
                     imm: val,
                     layout: place_layout,
                 };
-                Some((res.into(), span))
+                Some(res.into())
             },
         }
     }
@@ -544,8 +568,7 @@ fn visit_constant(
     ) {
         trace!("visit_constant: {:?}", constant);
         self.super_constant(constant, location);
-        let source_info = *self.mir.source_info(location);
-        self.eval_constant(constant, source_info);
+        self.eval_constant(constant);
     }
 
     fn visit_statement(
@@ -556,7 +579,7 @@ fn visit_statement(
         trace!("visit_statement: {:?}", statement);
         if let StatementKind::Assign(ref place, ref rval) = statement.kind {
             let place_ty: Ty<'tcx> = place
-                .ty(&self.mir.local_decls, self.tcx)
+                .ty(&self.local_decls, self.tcx)
                 .ty;
             if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) {
                 if let Some(value) = self.const_prop(rval, place_layout, statement.source_info) {
@@ -574,18 +597,18 @@ fn visit_statement(
         self.super_statement(statement, location);
     }
 
-    fn visit_terminator_kind(
+    fn visit_terminator(
         &mut self,
-        kind: &TerminatorKind<'tcx>,
+        terminator: &Terminator<'tcx>,
         location: Location,
     ) {
-        self.super_terminator_kind(kind, location);
-        let source_info = *self.mir.source_info(location);
-        if let TerminatorKind::Assert { expected, msg, cond, .. } = kind {
-            if let Some(value) = self.eval_operand(cond, source_info) {
+        self.super_terminator(terminator, location);
+        let source_info = terminator.source_info;;
+        if let TerminatorKind::Assert { expected, msg, cond, .. } = &terminator.kind {
+            if let Some(value) = self.eval_operand(&cond, source_info) {
                 trace!("assertion on {:?} should be {:?}", value, expected);
                 let expected = ScalarMaybeUndef::from(Scalar::from_bool(*expected));
-                if expected != self.ecx.read_scalar(value.0).unwrap() {
+                if expected != self.ecx.read_scalar(value).unwrap() {
                     // poison all places this operand references so that further code
                     // doesn't use the invalid value
                     match cond {
@@ -600,12 +623,7 @@ fn visit_terminator_kind(
                         },
                         Operand::Constant(_) => {}
                     }
-                    let span = self.mir[location.block]
-                        .terminator
-                        .as_ref()
-                        .unwrap()
-                        .source_info
-                        .span;
+                    let span = terminator.source_info.span;
                     let hir_id = self
                         .tcx
                         .hir()
@@ -621,7 +639,7 @@ fn visit_terminator_kind(
                             let len = self
                                 .eval_operand(len, source_info)
                                 .expect("len must be const");
-                            let len = match self.ecx.read_scalar(len.0) {
+                            let len = match self.ecx.read_scalar(len) {
                                 Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
                                     bits, ..
                                 })) => bits,
@@ -630,7 +648,7 @@ fn visit_terminator_kind(
                             let index = self
                                 .eval_operand(index, source_info)
                                 .expect("index must be const");
-                            let index = match self.ecx.read_scalar(index.0) {
+                            let index = match self.ecx.read_scalar(index) {
                                 Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
                                     bits, ..
                                 })) => bits,
index 0ee9ecdef451dc9cbbc9046b337674e9e25f2c9e..429e2ae7600d679aed49d60442425b8428d8c40b 100644 (file)
@@ -13,11 +13,17 @@ LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
 error[E0080]: erroneous constant used
-  --> $DIR/const-err.rs:14:15
+  --> $DIR/const-err.rs:14:16
    |
 LL |     black_box((FOO, FOO));
-   |               ^^^^^^^^^^ referenced constant has errors
+   |                ^^^ referenced constant has errors
 
-error: aborting due to previous error
+error[E0080]: erroneous constant used
+  --> $DIR/const-err.rs:14:21
+   |
+LL |     black_box((FOO, FOO));
+   |                     ^^^ referenced constant has errors
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.