diff options
| author | Ariel Ben-Yehuda <ariel.byd@gmail.com> | 2016-02-13 01:01:08 +0200 |
|---|---|---|
| committer | Ariel Ben-Yehuda <ariel.byd@gmail.com> | 2016-02-20 13:17:30 +0200 |
| commit | d84658e317ac5b881a46e27204a1cb9f4ac1b691 (patch) | |
| tree | 41ae067131a3a89ad1e3f0be1a16b553ed4efa08 | |
| parent | 881249aa463db43e41e4d5f98d6f71f2970f8965 (diff) | |
| download | rust-d84658e317ac5b881a46e27204a1cb9f4ac1b691.tar.gz rust-d84658e317ac5b881a46e27204a1cb9f4ac1b691.zip | |
address review comments
| -rw-r--r-- | src/librustc/mir/mir_map.rs | 4 | ||||
| -rw-r--r-- | src/librustc_mir/build/expr/as_rvalue.rs | 4 | ||||
| -rw-r--r-- | src/librustc_mir/transform/clear_dead_blocks.rs | 30 | ||||
| -rw-r--r-- | src/librustc_mir/transform/type_check.rs | 22 | ||||
| -rw-r--r-- | src/test/run-pass/mir_augmented_assignments.rs | 6 |
5 files changed, 50 insertions, 16 deletions
diff --git a/src/librustc/mir/mir_map.rs b/src/librustc/mir/mir_map.rs index 82bd2caaac1..32e78b04676 100644 --- a/src/librustc/mir/mir_map.rs +++ b/src/librustc/mir/mir_map.rs @@ -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)); diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 53b106d6d86..2338d7df01a 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -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) { diff --git a/src/librustc_mir/transform/clear_dead_blocks.rs b/src/librustc_mir/transform/clear_dead_blocks.rs index 2c08b6b0b81..b35d8c08f5d 100644 --- a/src/librustc_mir/transform/clear_dead_blocks.rs +++ b/src/librustc_mir/transform/clear_dead_blocks.rs @@ -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), diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 4e94c76c7e8..0e97e362906 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -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() { diff --git a/src/test/run-pass/mir_augmented_assignments.rs b/src/test/run-pass/mir_augmented_assignments.rs index cadfce367a4..c85ac458edd 100644 --- a/src/test/run-pass/mir_augmented_assignments.rs +++ b/src/test/run-pass/mir_augmented_assignments.rs @@ -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 { |
