diff options
| author | Oliver Schneider <git-no-reply-9879165716479413131@oli-obk.de> | 2018-01-27 17:15:40 +0100 |
|---|---|---|
| committer | Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> | 2018-03-08 08:34:12 +0100 |
| commit | 5b247b9bbe7252db2d22d3ec4be172c73f1f94e9 (patch) | |
| tree | c0d1a8f54cf9294314e8e410d4b477aa0ca33736 | |
| parent | df6b40e342879169962295e27f1f878998f22bc3 (diff) | |
| download | rust-5b247b9bbe7252db2d22d3ec4be172c73f1f94e9.tar.gz rust-5b247b9bbe7252db2d22d3ec4be172c73f1f94e9.zip | |
Report errors in statics during collecting instead of translating
| -rw-r--r-- | src/librustc/ty/error.rs | 8 | ||||
| -rw-r--r-- | src/librustc_mir/monomorphize/collector.rs | 157 | ||||
| -rw-r--r-- | src/librustc_trans/base.rs | 2 | ||||
| -rw-r--r-- | src/test/compile-fail/huge-array.rs | 2 | ||||
| -rw-r--r-- | src/test/ui/const-eval/index_out_of_bound.rs | 4 | ||||
| -rw-r--r-- | src/test/ui/const-fn-error.stderr | 12 |
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 |
