diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 34fc81a495e24..7b3739a7a097a 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -69,6 +69,17 @@ impl<'tcx> HasLocalDecls<'tcx> for Mir<'tcx> { } } +/// The various "big phases" that MIR goes through. +/// +/// Warning: ordering of variants is significant +#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub enum MirPhase { + Build, + Const, + Validated, + Optimized, +} + /// Lowered representation of a single function. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Mir<'tcx> { @@ -76,6 +87,8 @@ pub struct Mir<'tcx> { /// that indexes into this vector. basic_blocks: IndexVec>, + pub phase: MirPhase, + /// List of source scopes; these are referenced by statements /// and used for debuginfo. Indexed by a `SourceScope`. pub source_scopes: IndexVec, @@ -151,6 +164,7 @@ impl<'tcx> Mir<'tcx> { ); Mir { + phase: MirPhase::Build, basic_blocks, source_scopes, source_scope_local_data, @@ -368,6 +382,7 @@ pub enum Safety { } impl_stable_hash_for!(struct Mir<'tcx> { + phase, basic_blocks, source_scopes, source_scope_local_data, @@ -616,6 +631,13 @@ impl_stable_hash_for!(enum self::ImplicitSelfKind { None }); +impl_stable_hash_for!(enum self::MirPhase { + Build, + Const, + Validated, + Optimized, +}); + mod binding_form_impl { use ich::StableHashingContext; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; @@ -2777,6 +2799,7 @@ pub enum ClosureOutlivesSubject<'tcx> { CloneTypeFoldableAndLiftImpls! { BlockTailInfo, + MirPhase, Mutability, SourceInfo, UpvarDecl, @@ -2789,6 +2812,7 @@ CloneTypeFoldableAndLiftImpls! { BraceStructTypeFoldableImpl! { impl<'tcx> TypeFoldable<'tcx> for Mir<'tcx> { + phase, basic_blocks, source_scopes, source_scope_local_data, diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index d18836999dccf..61e150ea12a22 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -11,7 +11,7 @@ use borrow_check::nll::type_check; use build; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; -use rustc::mir::{Mir, Promoted}; +use rustc::mir::{Mir, MirPhase, Promoted}; use rustc::ty::TyCtxt; use rustc::ty::query::Providers; use rustc::ty::steal::Steal; @@ -155,9 +155,22 @@ pub trait MirPass { mir: &mut Mir<'tcx>); } -pub macro run_passes($tcx:ident, $mir:ident, $def_id:ident, $suite_index:expr; $($pass:expr,)*) {{ +pub macro run_passes( + $tcx:ident, + $mir:ident, + $def_id:ident, + $suite_index:expr, + $mir_phase:expr; + $($pass:expr,)* +) {{ let suite_index: usize = $suite_index; let run_passes = |mir: &mut _, promoted| { + let mir: &mut Mir<'_> = mir; + + if mir.phase >= $mir_phase { + return; + } + let source = MirSource { def_id: $def_id, promoted @@ -175,6 +188,8 @@ pub macro run_passes($tcx:ident, $mir:ident, $def_id:ident, $suite_index:expr; $ index += 1; }; $(run_pass(&$pass);)* + + mir.phase = $mir_phase; }; run_passes(&mut $mir, None); @@ -192,7 +207,7 @@ fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Stea let _ = tcx.unsafety_check_result(def_id); let mut mir = tcx.mir_built(def_id).steal(); - run_passes![tcx, mir, def_id, 0; + run_passes![tcx, mir, def_id, 0, MirPhase::Const; // Remove all `EndRegion` statements that are not involved in borrows. cleanup_post_borrowck::CleanEndRegions, @@ -214,7 +229,7 @@ fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx } let mut mir = tcx.mir_const(def_id).steal(); - run_passes![tcx, mir, def_id, 1; + run_passes![tcx, mir, def_id, 1, MirPhase::Validated; // What we need to run borrowck etc. qualify_consts::QualifyAndPromoteConstants, simplify::SimplifyCfg::new("qualify-consts"), @@ -232,7 +247,7 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx } let mut mir = tcx.mir_validated(def_id).steal(); - run_passes![tcx, mir, def_id, 2; + run_passes![tcx, mir, def_id, 2, MirPhase::Optimized; // Remove all things not needed by analysis no_landing_pads::NoLandingPads, simplify_branches::SimplifyBranches::new("initial"), diff --git a/src/test/ui/issues/issue-50411.rs b/src/test/ui/issues/issue-50411.rs new file mode 100644 index 0000000000000..26154771ace8f --- /dev/null +++ b/src/test/ui/issues/issue-50411.rs @@ -0,0 +1,8 @@ +// Regression test for #50411: the MIR inliner was causing problems +// here because it would inline promoted code (which had already had +// elaborate-drops invoked on it) and then try to elaboate drops a +// second time. Uncool. + +fn main() { + let _ = (0 .. 1).filter(|_| [1].iter().all(|_| true)).count(); +}