about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Schneider <git-no-reply-9879165716479413131@oli-obk.de>2018-01-27 17:15:40 +0100
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>2018-03-08 08:34:12 +0100
commit5b247b9bbe7252db2d22d3ec4be172c73f1f94e9 (patch)
treec0d1a8f54cf9294314e8e410d4b477aa0ca33736
parentdf6b40e342879169962295e27f1f878998f22bc3 (diff)
downloadrust-5b247b9bbe7252db2d22d3ec4be172c73f1f94e9.tar.gz
rust-5b247b9bbe7252db2d22d3ec4be172c73f1f94e9.zip
Report errors in statics during collecting instead of translating
-rw-r--r--src/librustc/ty/error.rs8
-rw-r--r--src/librustc_mir/monomorphize/collector.rs157
-rw-r--r--src/librustc_trans/base.rs2
-rw-r--r--src/test/compile-fail/huge-array.rs2
-rw-r--r--src/test/ui/const-eval/index_out_of_bound.rs4
-rw-r--r--src/test/ui/const-fn-error.stderr12
6 files changed, 116 insertions, 69 deletions
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index 5dc78d84da8..b50b9cb43d3 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -9,10 +9,7 @@
 // except according to those terms.
 
 use hir::def_id::DefId;
-use middle::const_val::ConstVal;
 use ty::{self, BoundRegion, Region, Ty, TyCtxt};
-use mir::interpret::{Value, PrimVal};
-
 use std::fmt;
 use syntax::abi;
 use syntax::ast;
@@ -185,9 +182,8 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
             ty::TyAdt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)),
             ty::TyForeign(def_id) => format!("extern type `{}`", tcx.item_path_str(def_id)),
             ty::TyArray(_, n) => {
-                match n.val {
-                    ConstVal::Value(Value::ByVal(PrimVal::Bytes(n))) =>
-                        format!("array of {} elements", n),
+                match n.val.to_raw_bits() {
+                    Some(n) => format!("array of {} elements", n),
                     _ => "array".to_string(),
                 }
             }
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 3d393b5696a..a6df0465789 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -201,9 +201,10 @@ use rustc::ty::subst::{Substs, Kind};
 use rustc::ty::{self, TypeFoldable, Ty, TyCtxt};
 use rustc::ty::adjustment::CustomCoerceUnsized;
 use rustc::session::config;
-use rustc::mir::{self, Location};
+use rustc::mir::{self, Location, Promoted};
 use rustc::mir::visit::Visitor as MirVisitor;
 use rustc::mir::mono::MonoItem;
+use rustc::mir::interpret::GlobalId;
 
 use monomorphize::{self, Instance};
 use rustc::util::nodemap::{FxHashSet, FxHashMap, DefIdMap};
@@ -378,7 +379,19 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
             recursion_depth_reset = None;
 
-            collect_neighbours(tcx, instance, true, &mut neighbors);
+            let cid = GlobalId {
+                instance,
+                promoted: None,
+            };
+            let param_env = ty::ParamEnv::empty(traits::Reveal::All);
+
+            match tcx.const_eval(param_env.and(cid)) {
+                Ok(val) => collect_const(tcx, val, instance.substs, &mut neighbors),
+                Err(err) => {
+                    let span = tcx.def_span(def_id);
+                    err.report(tcx, span, "static");
+                }
+            }
         }
         MonoItem::Fn(instance) => {
             // Sanity check whether this ended up being collected accidentally
@@ -390,7 +403,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                                recursion_depths));
             check_type_length_limit(tcx, instance);
 
-            collect_neighbours(tcx, instance, false, &mut neighbors);
+            collect_neighbours(tcx, instance, &mut neighbors);
         }
         MonoItem::GlobalAsm(..) => {
             recursion_depth_reset = None;
@@ -499,7 +512,6 @@ struct MirNeighborCollector<'a, 'tcx: 'a> {
     mir: &'a mir::Mir<'tcx>,
     output: &'a mut Vec<MonoItem<'tcx>>,
     param_substs: &'tcx Substs<'tcx>,
-    const_context: bool,
 }
 
 impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
@@ -569,27 +581,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
     fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, location: Location) {
         debug!("visiting const {:?} @ {:?}", *constant, location);
 
-        match constant.val {
-            ConstVal::Unevaluated(def_id, substs) => {
-                let substs = self.tcx.trans_apply_param_substs(self.param_substs,
-                                                            &substs);
-                let instance = ty::Instance::resolve(self.tcx,
-                                                    ty::ParamEnv::empty(traits::Reveal::All),
-                                                    def_id,
-                                                    substs).unwrap();
-                collect_neighbours(self.tcx, instance, true, self.output);
-            },
-            ConstVal::Value(Value::ByValPair(PrimVal::Ptr(a), PrimVal::Ptr(b))) => {
-                collect_miri(self.tcx, a.alloc_id, self.output);
-                collect_miri(self.tcx, b.alloc_id, self.output);
-            }
-            ConstVal::Value(Value::ByValPair(_, PrimVal::Ptr(ptr))) |
-            ConstVal::Value(Value::ByValPair(PrimVal::Ptr(ptr), _)) |
-            ConstVal::Value(Value::ByVal(PrimVal::Ptr(ptr))) |
-            ConstVal::Value(Value::ByRef(Pointer { primval: PrimVal::Ptr(ptr) }, _)) =>
-                collect_miri(self.tcx, ptr.alloc_id, self.output),
-            _ => {},
-        }
+        collect_const(self.tcx, constant, self.param_substs, self.output);
 
         self.super_const(constant);
     }
@@ -605,30 +597,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
             mir::TerminatorKind::Call { ref func, .. } => {
                 let callee_ty = func.ty(self.mir, tcx);
                 let callee_ty = tcx.trans_apply_param_substs(self.param_substs, &callee_ty);
-
-                let constness = match (self.const_context, &callee_ty.sty) {
-                    (true, &ty::TyFnDef(def_id, substs)) if self.tcx.is_const_fn(def_id) => {
-                        let instance =
-                            ty::Instance::resolve(self.tcx,
-                                                  ty::ParamEnv::empty(traits::Reveal::All),
-                                                  def_id,
-                                                  substs).unwrap();
-                        Some(instance)
-                    }
-                    _ => None
-                };
-
-                if let Some(const_fn_instance) = constness {
-                    // If this is a const fn, called from a const context, we
-                    // have to visit its body in order to find any fn reifications
-                    // it might contain.
-                    collect_neighbours(self.tcx,
-                                       const_fn_instance,
-                                       true,
-                                       self.output);
-                } else {
-                    visit_fn_use(self.tcx, callee_ty, true, &mut self.output);
-                }
+                visit_fn_use(self.tcx, callee_ty, true, &mut self.output);
             }
             mir::TerminatorKind::Drop { ref location, .. } |
             mir::TerminatorKind::DropAndReplace { ref location, .. } => {
@@ -1117,7 +1086,14 @@ fn collect_miri<'a, 'tcx>(
     alloc_id: AllocId,
     output: &mut Vec<MonoItem<'tcx>>,
 ) {
-    if let Some(alloc) = tcx.interpret_interner.get_alloc(alloc_id) {
+    if let Some(did) = tcx.interpret_interner.get_corresponding_static_def_id(alloc_id) {
+        let instance = Instance::mono(tcx, did);
+        if should_monomorphize_locally(tcx, &instance) {
+            trace!("collecting static {:?}", did);
+            let node_id = tcx.hir.as_local_node_id(did).unwrap();
+            output.push(MonoItem::Static(node_id));
+        }
+    } else if let Some(alloc) = tcx.interpret_interner.get_alloc(alloc_id) {
         trace!("collecting {:?} with {:#?}", alloc_id, alloc);
         for &inner in alloc.relocations.values() {
             collect_miri(tcx, inner, output);
@@ -1135,23 +1111,29 @@ fn collect_miri<'a, 'tcx>(
 /// Scan the MIR in order to find function calls, closures, and drop-glue
 fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 instance: Instance<'tcx>,
-                                const_context: bool,
                                 output: &mut Vec<MonoItem<'tcx>>)
 {
     let mir = tcx.instance_mir(instance.def);
 
-    let mut visitor = MirNeighborCollector {
+    MirNeighborCollector {
         tcx,
         mir: &mir,
         output,
         param_substs: instance.substs,
-        const_context,
-    };
-
-    visitor.visit_mir(&mir);
-    for promoted in &mir.promoted {
-        visitor.mir = promoted;
-        visitor.visit_mir(promoted);
+    }.visit_mir(&mir);
+    let param_env = ty::ParamEnv::empty(traits::Reveal::All);
+    for (i, promoted) in mir.promoted.iter().enumerate() {
+        use rustc_data_structures::indexed_vec::Idx;
+        let cid = GlobalId {
+            instance,
+            promoted: Some(Promoted::new(i)),
+        };
+        match tcx.const_eval(param_env.and(cid)) {
+            Ok(val) => collect_const(tcx, val, instance.substs, output),
+            Err(err) => {
+                err.report(tcx, promoted.span, "promoted");
+            }
+        }
     }
 }
 
@@ -1163,3 +1145,60 @@ fn def_id_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     printer.push_def_path(def_id, &mut output);
     output
 }
+
+fn collect_const<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    constant: &ty::Const<'tcx>,
+    param_substs: &'tcx Substs<'tcx>,
+    output: &mut Vec<MonoItem<'tcx>>,
+) {
+    debug!("visiting const {:?}", *constant);
+
+    let val = match constant.val {
+        ConstVal::Unevaluated(def_id, substs) => {
+            let param_env = ty::ParamEnv::empty(traits::Reveal::All);
+            let substs = tcx.trans_apply_param_substs(param_substs,
+                                                        &substs);
+            let instance = ty::Instance::resolve(tcx,
+                                                param_env,
+                                                def_id,
+                                                substs).unwrap();
+
+            let cid = GlobalId {
+                instance,
+                promoted: None,
+            };
+            match tcx.const_eval(param_env.and(cid)) {
+                Ok(val) => val.val,
+                Err(err) => {
+                    let span = tcx.def_span(def_id);
+                    err.report(tcx, span, "constant");
+                    return;
+                }
+            }
+        },
+        _ => constant.val,
+    };
+    match val {
+        ConstVal::Unevaluated(..) => bug!("const eval yielded unevaluated const"),
+        ConstVal::Value(Value::ByValPair(PrimVal::Ptr(a), PrimVal::Ptr(b))) => {
+            collect_miri(tcx, a.alloc_id, output);
+            collect_miri(tcx, b.alloc_id, output);
+        }
+        ConstVal::Value(Value::ByValPair(_, PrimVal::Ptr(ptr))) |
+        ConstVal::Value(Value::ByValPair(PrimVal::Ptr(ptr), _)) |
+        ConstVal::Value(Value::ByVal(PrimVal::Ptr(ptr))) =>
+            collect_miri(tcx, ptr.alloc_id, output),
+        ConstVal::Value(Value::ByRef(Pointer { primval: PrimVal::Ptr(ptr) }, _)) => {
+            // by ref should only collect the inner allocation, not the value itself
+            let alloc = tcx
+                .interpret_interner
+                .get_alloc(ptr.alloc_id)
+                .expect("ByRef to extern static is not allowed");
+            for &inner in alloc.relocations.values() {
+                collect_miri(tcx, inner, output);
+            }
+        }
+        _ => {},
+    }
+}
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index bae9fe8bd1b..49a5b7ac8b9 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -972,6 +972,8 @@ fn collect_and_partition_translation_items<'a, 'tcx>(
             collector::collect_crate_mono_items(tcx, collection_mode)
     });
 
+    tcx.sess.abort_if_errors();
+
     ::rustc_mir::monomorphize::assert_symbols_are_distinct(tcx, items.iter());
 
     let strategy = if tcx.sess.opts.incremental.is_some() {
diff --git a/src/test/compile-fail/huge-array.rs b/src/test/compile-fail/huge-array.rs
index 029e9651cb3..7de84802e1d 100644
--- a/src/test/compile-fail/huge-array.rs
+++ b/src/test/compile-fail/huge-array.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:; 1518599999
+// error-pattern:; 1518600000
 
 fn generic<T: Copy>(t: T) {
     let s: [T; 1518600000] = [t; 1518600000];
diff --git a/src/test/ui/const-eval/index_out_of_bound.rs b/src/test/ui/const-eval/index_out_of_bound.rs
index 0109f72aa1d..632804f2fd3 100644
--- a/src/test/ui/const-eval/index_out_of_bound.rs
+++ b/src/test/ui/const-eval/index_out_of_bound.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-static FOO: i32 = [][0]; //~ ERROR E0080
+static FOO: i32 = [][0];
+//~^ ERROR E0080
+//~| ERROR E0080
 
 fn main() {}
diff --git a/src/test/ui/const-fn-error.stderr b/src/test/ui/const-fn-error.stderr
index 26c238992ab..f7ce0565c85 100644
--- a/src/test/ui/const-fn-error.stderr
+++ b/src/test/ui/const-fn-error.stderr
@@ -20,15 +20,23 @@ error[E0016]: blocks in constant functions are limited to items and tail express
    |                   ^
 
 error[E0015]: calls in constant functions are limited to constant functions, struct and enum constructors
-  --> $DIR/const-fn-error.rs:17:14
+  --> $DIR/const-fn-error.rs:18:14
    |
+<<<<<<< HEAD
 LL |     for i in 0..x { //~ ERROR calls in constant functions
+=======
+18 |     for i in 0..x {
+>>>>>>> Report errors in statics during collecting instead of translating
    |              ^^^^
 
 error[E0019]: constant function contains unimplemented expression type
-  --> $DIR/const-fn-error.rs:17:14
+  --> $DIR/const-fn-error.rs:18:14
    |
+<<<<<<< HEAD
 LL |     for i in 0..x { //~ ERROR calls in constant functions
+=======
+18 |     for i in 0..x {
+>>>>>>> Report errors in statics during collecting instead of translating
    |              ^^^^
 
 error[E0080]: constant evaluation error