未验证 提交 5b247b9b 编写于 作者: O Oliver Schneider 提交者: Oliver Schneider

Report errors in statics during collecting instead of translating

上级 df6b40e3
......@@ -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 @@ pub fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
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(),
}
}
......
......@@ -201,9 +201,10 @@
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 @@ fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
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 @@ fn visit_terminator_kind(&mut self,
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);
}
}
_ => {},
}
}
......@@ -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() {
......
......@@ -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];
......
......@@ -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() {}
......@@ -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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册