mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-28 15:43:21 +00:00
address review comments
This commit is contained in:
parent
881249aa46
commit
d84658e317
@ -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));
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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),
|
||||
|
@ -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() {
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user