address review comments

This commit is contained in:
Ariel Ben-Yehuda 2016-02-13 01:01:08 +02:00
parent 881249aa46
commit d84658e317
5 changed files with 50 additions and 16 deletions

View File

@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use dep_graph::DepNode;
use util::nodemap::NodeMap;
use mir::repr::Mir;
use mir::transform::MirPass;
@ -23,6 +24,9 @@ impl<'tcx> MirMap<'tcx> {
if passes.is_empty() { return; }
for (&id, mir) in &mut self.map {
let did = tcx.map.local_def_id(id);
let _task = tcx.dep_graph.in_task(DepNode::MirMapConstruction(did));
let param_env = ty::ParameterEnvironment::for_item(tcx, id);
let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env));

View File

@ -153,6 +153,10 @@ impl<'a,'tcx> Builder<'a,'tcx> {
let fields = if let Some(FruInfo { base, field_types }) = base {
let base = unpack!(block = this.as_lvalue(block, base));
// MIR does not natively support FRU, so for each
// base-supplied field, generate an operand that
// reads it from the base.
field_names.into_iter()
.zip(field_types.into_iter())
.map(|(n, ty)| match fields_map.get(&n) {

View File

@ -8,12 +8,29 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! A pass that erases the contents of dead blocks. This is required
//! because rustc allows for ill-typed block terminators in dead
//! blocks.
//! A pass that erases the contents of dead blocks. This pass must
//! run before any analysis passes because some of the dead blocks
//! can be ill-typed.
//!
//! This pass does not renumber or remove the blocks, to have the
//! MIR better match the source.
//! The main problem is that typeck lets most blocks whose end is not
//! reachable have an arbitrary return type, rather than having the
//! usual () return type (as a note, typeck's notion of reachability
//! is in fact slightly weaker than MIR CFG reachability - see #31617).
//!
//! A standard example of the situation is:
//! ```rust
//! fn example() {
//! let _a: char = { return; };
//! }
//! ```
//!
//! Here the block (`{ return; }`) has the return type `char`,
//! rather than `()`, but the MIR we naively generate still contains
//! the `_a = ()` write in the unreachable block "after" the return.
//!
//! As we have to run this pass even when we want to debug the MIR,
//! this pass just replaces the blocks with empty "return" blocks
//! and does not renumber anything.
use rustc::middle::infer;
use rustc::mir::repr::*;
@ -43,8 +60,9 @@ impl ClearDeadBlocks {
}
}
for (block, seen) in mir.basic_blocks.iter_mut().zip(seen) {
for (n, (block, seen)) in mir.basic_blocks.iter_mut().zip(seen).enumerate() {
if !seen {
info!("clearing block #{}: {:?}", n, block);
*block = BasicBlockData {
statements: vec![],
terminator: Some(Terminator::Return),

View File

@ -48,8 +48,11 @@ enum FieldAccessError {
OutOfRange { field_count: usize }
}
/// Verifies that MIR types are sane to not crash further
/// checks.
/// Verifies that MIR types are sane to not crash further checks.
///
/// The sanitize_XYZ methods here take an MIR object and compute its
/// type, calling `span_mirbug` and returning an error type if there
/// is a problem.
struct TypeVerifier<'a, 'b: 'a, 'tcx: 'b> {
cx: &'a mut TypeChecker<'b, 'tcx>,
mir: &'a Mir<'tcx>,
@ -119,11 +122,11 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
}
fn sanitize_type(&mut self, parent: &fmt::Debug, ty: Ty<'tcx>) -> Ty<'tcx> {
if !(ty.needs_infer() || ty.has_escaping_regions() ||
ty.references_error()) {
return ty;
if ty.needs_infer() || ty.has_escaping_regions() || ty.references_error() {
span_mirbug_and_err!(self, parent, "bad type {:?}", ty)
} else {
ty
}
span_mirbug_and_err!(self, parent, "bad type {:?}", ty)
}
fn sanitize_lvalue(&mut self, lvalue: &Lvalue<'tcx>) -> LvalueTy<'tcx> {
@ -225,7 +228,8 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
}
_ => LvalueTy::Ty {
ty: span_mirbug_and_err!(
self, lvalue, "can't downcast {:?}", base_ty)
self, lvalue, "can't downcast {:?} as {:?}",
base_ty, adt_def1)
}
},
ProjectionElem::Field(field, fty) => {
@ -467,8 +471,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
args: &[Operand<'tcx>])
{
debug!("check_call_inputs({:?}, {:?})", sig, args);
if sig.inputs.len() > args.len() ||
(sig.inputs.len() < args.len() && !sig.variadic) {
if args.len() < sig.inputs.len() ||
(args.len() > sig.inputs.len() && !sig.variadic) {
span_mirbug!(self, term, "call to {:?} with wrong # of args", sig);
}
for (n, (fn_arg, op_arg)) in sig.inputs.iter().zip(args).enumerate() {

View File

@ -77,7 +77,10 @@ fn main_mir() {
assert_eq!(x, Int(0));
// indexed LHS
let mut v = vec![Int(1), Int(2)];
// FIXME(mir-drop): use the vec![..] macro
let mut v = Vec::new();
v.push(Int(1));
v.push(Int(2));
v[0] += Int(2);
assert_eq!(v[0], Int(3));
@ -87,6 +90,7 @@ fn main_mir() {
assert_eq!(array[0], 1);
assert_eq!(array[1], 2);
assert_eq!(array[2], 3);
}
impl AddAssign for Int {