Report errors in statics during collecting instead of translating
This commit is contained in:
committed by
Oliver Schneider
parent
df6b40e342
commit
5b247b9bbe
@@ -9,10 +9,7 @@
|
|||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
use middle::const_val::ConstVal;
|
|
||||||
use ty::{self, BoundRegion, Region, Ty, TyCtxt};
|
use ty::{self, BoundRegion, Region, Ty, TyCtxt};
|
||||||
use mir::interpret::{Value, PrimVal};
|
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use syntax::abi;
|
use syntax::abi;
|
||||||
use syntax::ast;
|
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::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::TyForeign(def_id) => format!("extern type `{}`", tcx.item_path_str(def_id)),
|
||||||
ty::TyArray(_, n) => {
|
ty::TyArray(_, n) => {
|
||||||
match n.val {
|
match n.val.to_raw_bits() {
|
||||||
ConstVal::Value(Value::ByVal(PrimVal::Bytes(n))) =>
|
Some(n) => format!("array of {} elements", n),
|
||||||
format!("array of {} elements", n),
|
|
||||||
_ => "array".to_string(),
|
_ => "array".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -201,9 +201,10 @@ use rustc::ty::subst::{Substs, Kind};
|
|||||||
use rustc::ty::{self, TypeFoldable, Ty, TyCtxt};
|
use rustc::ty::{self, TypeFoldable, Ty, TyCtxt};
|
||||||
use rustc::ty::adjustment::CustomCoerceUnsized;
|
use rustc::ty::adjustment::CustomCoerceUnsized;
|
||||||
use rustc::session::config;
|
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::visit::Visitor as MirVisitor;
|
||||||
use rustc::mir::mono::MonoItem;
|
use rustc::mir::mono::MonoItem;
|
||||||
|
use rustc::mir::interpret::GlobalId;
|
||||||
|
|
||||||
use monomorphize::{self, Instance};
|
use monomorphize::{self, Instance};
|
||||||
use rustc::util::nodemap::{FxHashSet, FxHashMap, DefIdMap};
|
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;
|
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) => {
|
MonoItem::Fn(instance) => {
|
||||||
// Sanity check whether this ended up being collected accidentally
|
// 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));
|
recursion_depths));
|
||||||
check_type_length_limit(tcx, instance);
|
check_type_length_limit(tcx, instance);
|
||||||
|
|
||||||
collect_neighbours(tcx, instance, false, &mut neighbors);
|
collect_neighbours(tcx, instance, &mut neighbors);
|
||||||
}
|
}
|
||||||
MonoItem::GlobalAsm(..) => {
|
MonoItem::GlobalAsm(..) => {
|
||||||
recursion_depth_reset = None;
|
recursion_depth_reset = None;
|
||||||
@@ -499,7 +512,6 @@ struct MirNeighborCollector<'a, 'tcx: 'a> {
|
|||||||
mir: &'a mir::Mir<'tcx>,
|
mir: &'a mir::Mir<'tcx>,
|
||||||
output: &'a mut Vec<MonoItem<'tcx>>,
|
output: &'a mut Vec<MonoItem<'tcx>>,
|
||||||
param_substs: &'tcx Substs<'tcx>,
|
param_substs: &'tcx Substs<'tcx>,
|
||||||
const_context: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
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) {
|
fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, location: Location) {
|
||||||
debug!("visiting const {:?} @ {:?}", *constant, location);
|
debug!("visiting const {:?} @ {:?}", *constant, location);
|
||||||
|
|
||||||
match constant.val {
|
collect_const(self.tcx, constant, self.param_substs, self.output);
|
||||||
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),
|
|
||||||
_ => {},
|
|
||||||
}
|
|
||||||
|
|
||||||
self.super_const(constant);
|
self.super_const(constant);
|
||||||
}
|
}
|
||||||
@@ -605,30 +597,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
|||||||
mir::TerminatorKind::Call { ref func, .. } => {
|
mir::TerminatorKind::Call { ref func, .. } => {
|
||||||
let callee_ty = func.ty(self.mir, tcx);
|
let callee_ty = func.ty(self.mir, tcx);
|
||||||
let callee_ty = tcx.trans_apply_param_substs(self.param_substs, &callee_ty);
|
let callee_ty = tcx.trans_apply_param_substs(self.param_substs, &callee_ty);
|
||||||
|
visit_fn_use(self.tcx, callee_ty, true, &mut self.output);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mir::TerminatorKind::Drop { ref location, .. } |
|
mir::TerminatorKind::Drop { ref location, .. } |
|
||||||
mir::TerminatorKind::DropAndReplace { ref location, .. } => {
|
mir::TerminatorKind::DropAndReplace { ref location, .. } => {
|
||||||
@@ -1117,7 +1086,14 @@ fn collect_miri<'a, 'tcx>(
|
|||||||
alloc_id: AllocId,
|
alloc_id: AllocId,
|
||||||
output: &mut Vec<MonoItem<'tcx>>,
|
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);
|
trace!("collecting {:?} with {:#?}", alloc_id, alloc);
|
||||||
for &inner in alloc.relocations.values() {
|
for &inner in alloc.relocations.values() {
|
||||||
collect_miri(tcx, inner, output);
|
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
|
/// Scan the MIR in order to find function calls, closures, and drop-glue
|
||||||
fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
instance: Instance<'tcx>,
|
instance: Instance<'tcx>,
|
||||||
const_context: bool,
|
|
||||||
output: &mut Vec<MonoItem<'tcx>>)
|
output: &mut Vec<MonoItem<'tcx>>)
|
||||||
{
|
{
|
||||||
let mir = tcx.instance_mir(instance.def);
|
let mir = tcx.instance_mir(instance.def);
|
||||||
|
|
||||||
let mut visitor = MirNeighborCollector {
|
MirNeighborCollector {
|
||||||
tcx,
|
tcx,
|
||||||
mir: &mir,
|
mir: &mir,
|
||||||
output,
|
output,
|
||||||
param_substs: instance.substs,
|
param_substs: instance.substs,
|
||||||
const_context,
|
}.visit_mir(&mir);
|
||||||
};
|
let param_env = ty::ParamEnv::empty(traits::Reveal::All);
|
||||||
|
for (i, promoted) in mir.promoted.iter().enumerate() {
|
||||||
visitor.visit_mir(&mir);
|
use rustc_data_structures::indexed_vec::Idx;
|
||||||
for promoted in &mir.promoted {
|
let cid = GlobalId {
|
||||||
visitor.mir = promoted;
|
instance,
|
||||||
visitor.visit_mir(promoted);
|
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);
|
printer.push_def_path(def_id, &mut output);
|
||||||
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)
|
collector::collect_crate_mono_items(tcx, collection_mode)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
tcx.sess.abort_if_errors();
|
||||||
|
|
||||||
::rustc_mir::monomorphize::assert_symbols_are_distinct(tcx, items.iter());
|
::rustc_mir::monomorphize::assert_symbols_are_distinct(tcx, items.iter());
|
||||||
|
|
||||||
let strategy = if tcx.sess.opts.incremental.is_some() {
|
let strategy = if tcx.sess.opts.incremental.is_some() {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// error-pattern:; 1518599999
|
// error-pattern:; 1518600000
|
||||||
|
|
||||||
fn generic<T: Copy>(t: T) {
|
fn generic<T: Copy>(t: T) {
|
||||||
let s: [T; 1518600000] = [t; 1518600000];
|
let s: [T; 1518600000] = [t; 1518600000];
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
static FOO: i32 = [][0]; //~ ERROR E0080
|
static FOO: i32 = [][0];
|
||||||
|
//~^ ERROR E0080
|
||||||
|
//~| ERROR E0080
|
||||||
|
|
||||||
fn main() {}
|
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
|
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
|
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
|
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
|
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
|
error[E0080]: constant evaluation error
|
||||||
|
|||||||
Reference in New Issue
Block a user