]> git.lizzy.rs Git - rust.git/commitdiff
Merge const linting pass into const prop
authorOliver Schneider <public.oliver.schneider@kit.edu>
Mon, 29 Jan 2018 14:10:26 +0000 (15:10 +0100)
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Thu, 8 Mar 2018 07:34:14 +0000 (08:34 +0100)
src/librustc_driver/driver.rs
src/librustc_mir/check_const_err.rs [deleted file]
src/librustc_mir/lib.rs
src/librustc_mir/transform/const_prop.rs

index f232d039f6641c0a35ef06db7bca9a3d199b7b1a..65649c82da6ffecc59ed278f3a0687a523cf4cce 100644 (file)
@@ -1087,13 +1087,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(trans: &TransCrate,
             stability::check_unused_or_stable_features(tcx)
         });
 
-
-        time(time_passes,
-             "MIR linting",
-             || for def_id in tcx.body_owners() {
-                 mir::check_const_err::check(tcx, def_id)
-             });
-
         time(time_passes, "lint checking", || lint::check_crate(tcx));
 
         return Ok(f(tcx, analysis, rx, tcx.sess.compile_status()));
diff --git a/src/librustc_mir/check_const_err.rs b/src/librustc_mir/check_const_err.rs
deleted file mode 100644 (file)
index 9827dd5..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Lints statically known runtime failures
-
-use rustc::mir::*;
-use rustc::hir;
-use rustc::hir::map::Node;
-use rustc::mir::visit::Visitor;
-use rustc::mir::interpret::{Value, PrimVal, GlobalId};
-use rustc::middle::const_val::{ConstVal, ConstEvalErr, ErrKind};
-use rustc::hir::def::Def;
-use rustc::traits;
-use interpret::eval_body_with_mir;
-use rustc::ty::{TyCtxt, ParamEnv};
-use rustc::ty::Instance;
-use rustc::ty::layout::LayoutOf;
-use rustc::hir::def_id::DefId;
-use rustc::ty::subst::Substs;
-
-fn is_const<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool {
-    if let Some(node) = tcx.hir.get_if_local(def_id) {
-        match node {
-            Node::NodeItem(&hir::Item {
-                node: hir::ItemConst(..), ..
-            }) => true,
-            _ => false
-        }
-    } else {
-        match tcx.describe_def(def_id) {
-            Some(Def::Const(_)) => true,
-            _ => false
-        }
-    }
-}
-
-pub fn check<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
-    let mir = &tcx.optimized_mir(def_id);
-    let substs = Substs::identity_for_item(tcx, def_id);
-    let instance = Instance::new(def_id, substs);
-    let param_env = tcx.param_env(def_id);
-
-    if is_const(tcx, def_id) {
-        let cid = GlobalId {
-            instance,
-            promoted: None,
-        };
-        eval_body_with_mir(tcx, cid, mir, param_env);
-    }
-
-    ConstErrVisitor {
-        tcx,
-        mir,
-    }.visit_mir(mir);
-    let outer_def_id = if tcx.is_closure(def_id) {
-        tcx.closure_base_def_id(def_id)
-    } else {
-        def_id
-    };
-    let generics = tcx.generics_of(outer_def_id);
-    // FIXME: miri should be able to eval stuff that doesn't need info
-    // from the generics
-    if generics.parent_types as usize + generics.types.len() > 0 {
-        return;
-    }
-    for i in 0.. mir.promoted.len() {
-        use rustc_data_structures::indexed_vec::Idx;
-        let cid = GlobalId {
-            instance,
-            promoted: Some(Promoted::new(i)),
-        };
-        eval_body_with_mir(tcx, cid, mir, param_env);
-    }
-}
-
-struct ConstErrVisitor<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
-}
-
-impl<'a, 'tcx> ConstErrVisitor<'a, 'tcx> {
-    fn eval_op(&self, op: &Operand<'tcx>) -> Option<u128> {
-        let op = match *op {
-            Operand::Constant(ref c) => c,
-            _ => return None,
-        };
-        match op.literal {
-            Literal::Value { value } => match value.val {
-                ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))) => Some(b),
-                _ => return None,
-            },
-            _ => None,
-        }
-    }
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for ConstErrVisitor<'a, 'tcx> {
-    fn visit_terminator(&mut self,
-                        block: BasicBlock,
-                        terminator: &Terminator<'tcx>,
-                        location: Location) {
-        self.super_terminator(block, terminator, location);
-        match terminator.kind {
-            TerminatorKind::Assert { ref cond, expected, ref msg, .. } => {
-                let cond = match self.eval_op(cond) {
-                    Some(val) => val,
-                    None => return,
-                };
-                if (cond == 1) == expected {
-                    return;
-                }
-                assert!(cond <= 1);
-                // If we know we always panic, and the error message
-                // is also constant, then we can produce a warning.
-
-                let kind = match *msg {
-                    AssertMessage::BoundsCheck { ref len, ref index } => {
-                        let len = match self.eval_op(len) {
-                            Some(val) => val,
-                            None => return,
-                        };
-                        let index = match self.eval_op(index) {
-                            Some(val) => val,
-                            None => return,
-                        };
-                        ErrKind::IndexOutOfBounds {
-                            len: len as u64,
-                            index: index as u64
-                        }
-                    }
-                    AssertMessage::Math(ref err) => ErrKind::Math(err.clone()),
-                    AssertMessage::GeneratorResumedAfterReturn |
-                    // FIXME(oli-obk): can we report a const_err warning here?
-                    AssertMessage::GeneratorResumedAfterPanic => return,
-                };
-                let span = terminator.source_info.span;
-                let msg = ConstEvalErr{ span, kind };
-                let scope_info = match self.mir.visibility_scope_info {
-                    ClearCrossCrate::Set(ref data) => data,
-                    ClearCrossCrate::Clear => return,
-                };
-                let node_id = scope_info[terminator.source_info.scope].lint_root;
-                self.tcx.lint_node(::rustc::lint::builtin::CONST_ERR,
-                            node_id,
-                            msg.span,
-                            &msg.description().into_oneline().into_owned());
-            },
-            _ => {},
-        }
-    }
-    fn visit_rvalue(&mut self,
-                    rvalue: &Rvalue<'tcx>,
-                    location: Location) {
-        self.super_rvalue(rvalue, location);
-        use rustc::mir::BinOp;
-        match *rvalue {
-            Rvalue::BinaryOp(BinOp::Shr, ref lop, ref rop) |
-            Rvalue::BinaryOp(BinOp::Shl, ref lop, ref rop) => {
-                let val = match self.eval_op(rop) {
-                    Some(val) => val,
-                    None => return,
-                };
-                let ty = lop.ty(self.mir, self.tcx);
-                let param_env = ParamEnv::empty(traits::Reveal::All);
-                let bits = (self.tcx, param_env).layout_of(ty).unwrap().size.bits();
-                if val >= bits as u128 {
-                    let data = &self.mir[location.block];
-                    let stmt_idx = location.statement_index;
-                    let source_info = if stmt_idx < data.statements.len() {
-                        data.statements[stmt_idx].source_info
-                    } else {
-                        data.terminator().source_info
-                    };
-                    let span = source_info.span;
-                    let scope_info = match self.mir.visibility_scope_info {
-                        ClearCrossCrate::Set(ref data) => data,
-                        ClearCrossCrate::Clear => return,
-                    };
-                    let node_id = scope_info[source_info.scope].lint_root;
-                    self.tcx.lint_node(
-                        ::rustc::lint::builtin::EXCEEDING_BITSHIFTS,
-                        node_id,
-                        span,
-                        "bitshift exceeds the type's number of bits");
-                }
-            }
-            _ => {}
-        }
-    }
-}
index f6b38dcc00150c6467f9545cf5d45fbb737aa583..c31e95fd826c686026b4ab9d83aa3727addebfab 100644 (file)
@@ -71,7 +71,6 @@
 pub mod util;
 pub mod interpret;
 pub mod monomorphize;
-pub mod check_const_err;
 
 pub use hair::pattern::check_crate as matchck_crate;
 use rustc::ty::maps::Providers;
index 3b37e755af38829df5e09710e0606d731e7e248c..35fce184bebe8e610fe702cda8bda91df4b422a7 100644 (file)
@@ -212,8 +212,30 @@ fn const_prop(
                 let instance = Instance::new(self.source.def_id, substs);
                 let ecx = mk_borrowck_eval_cx(self.tcx, instance, self.mir, span).unwrap();
 
-                let l = ecx.value_to_primval(ValTy { value: left.0, ty: left.1 }).ok()?;
                 let r = ecx.value_to_primval(ValTy { value: right.0, ty: right.1 }).ok()?;
+                let param_env = ParamEnv::empty(traits::Reveal::All);
+                let bits = (self.tcx, param_env).layout_of(left.ty).unwrap().size.bits();
+                if r >= bits as u128 {
+                    let data = &self.mir[location.block];
+                    let stmt_idx = location.statement_index;
+                    let source_info = if stmt_idx < data.statements.len() {
+                        data.statements[stmt_idx].source_info
+                    } else {
+                        data.terminator().source_info
+                    };
+                    let span = source_info.span;
+                    let scope_info = match self.mir.visibility_scope_info {
+                        ClearCrossCrate::Set(ref data) => data,
+                        ClearCrossCrate::Clear => return,
+                    };
+                    let node_id = scope_info[source_info.scope].lint_root;
+                    self.tcx.lint_node(
+                        ::rustc::lint::builtin::EXCEEDING_BITSHIFTS,
+                        node_id,
+                        span,
+                        "bitshift exceeds the type's number of bits");
+                }
+                let l = ecx.value_to_primval(ValTy { value: left.0, ty: left.1 }).ok()?;
                 trace!("const evaluating {:?} for {:?} and {:?}", op, left, right);
                 match ecx.binary_op(op, l, left.1, r, right.1) {
                     Ok((val, overflow)) => {