Skip to content

Commit 37e1d29

Browse files
nikomatsakiswesleywiser
authored andcommitted
Don't rerun Mir passes when inlining
When inlining a function using the Mir inliner, we shouldn't rerun the various Mir passes on it because the Mir has already been lowered and that wil break various early Mir passes. The issue in rust-lang#50411 is that we've inlined a function with promotions whose Mir has already been lowered. The promotions are then copied into the local function and we begin to run passes on their lowered Mir which causes the ICE. Fixes rust-lang#50411
1 parent 22cc2ae commit 37e1d29

File tree

3 files changed

+60
-5
lines changed

3 files changed

+60
-5
lines changed

src/librustc/mir/mod.rs

+29
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,31 @@ impl<'tcx> HasLocalDecls<'tcx> for Mir<'tcx> {
6969
}
7070
}
7171

72+
/// The various "big phases" that MIR goes through.
73+
///
74+
/// Warning: ordering of variants is significant
75+
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)]
76+
pub enum MirPhase {
77+
Build,
78+
Const,
79+
Validated,
80+
Optimized,
81+
}
82+
7283
/// Lowered representation of a single function.
7384
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
7485
pub struct Mir<'tcx> {
7586
/// List of basic blocks. References to basic block use a newtyped index type `BasicBlock`
7687
/// that indexes into this vector.
7788
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
7889

90+
/// Records how far through the "desugaring and optimization" process this particular
91+
/// MIR has traversed. This is particularly useful when inlining, since in that context
92+
/// we instantiate the promoted constants and add them to our promoted vector -- but those
93+
/// promoted items have already been optimized, whereas ours have not. This field allows
94+
/// us to see the difference and forego optimization on the inlined promoted items.
95+
pub phase: MirPhase,
96+
7997
/// List of source scopes; these are referenced by statements
8098
/// and used for debuginfo. Indexed by a `SourceScope`.
8199
pub source_scopes: IndexVec<SourceScope, SourceScopeData>,
@@ -151,6 +169,7 @@ impl<'tcx> Mir<'tcx> {
151169
);
152170

153171
Mir {
172+
phase: MirPhase::Build,
154173
basic_blocks,
155174
source_scopes,
156175
source_scope_local_data,
@@ -368,6 +387,7 @@ pub enum Safety {
368387
}
369388

370389
impl_stable_hash_for!(struct Mir<'tcx> {
390+
phase,
371391
basic_blocks,
372392
source_scopes,
373393
source_scope_local_data,
@@ -616,6 +636,13 @@ impl_stable_hash_for!(enum self::ImplicitSelfKind {
616636
None
617637
});
618638

639+
impl_stable_hash_for!(enum self::MirPhase {
640+
Build,
641+
Const,
642+
Validated,
643+
Optimized,
644+
});
645+
619646
mod binding_form_impl {
620647
use ich::StableHashingContext;
621648
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
@@ -2777,6 +2804,7 @@ pub enum ClosureOutlivesSubject<'tcx> {
27772804

27782805
CloneTypeFoldableAndLiftImpls! {
27792806
BlockTailInfo,
2807+
MirPhase,
27802808
Mutability,
27812809
SourceInfo,
27822810
UpvarDecl,
@@ -2789,6 +2817,7 @@ CloneTypeFoldableAndLiftImpls! {
27892817

27902818
BraceStructTypeFoldableImpl! {
27912819
impl<'tcx> TypeFoldable<'tcx> for Mir<'tcx> {
2820+
phase,
27922821
basic_blocks,
27932822
source_scopes,
27942823
source_scope_local_data,

src/librustc_mir/transform/mod.rs

+20-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use borrow_check::nll::type_check;
1212
use build;
1313
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
14-
use rustc::mir::{Mir, Promoted};
14+
use rustc::mir::{Mir, MirPhase, Promoted};
1515
use rustc::ty::TyCtxt;
1616
use rustc::ty::query::Providers;
1717
use rustc::ty::steal::Steal;
@@ -155,9 +155,22 @@ pub trait MirPass {
155155
mir: &mut Mir<'tcx>);
156156
}
157157

158-
pub macro run_passes($tcx:ident, $mir:ident, $def_id:ident, $suite_index:expr; $($pass:expr,)*) {{
158+
pub macro run_passes(
159+
$tcx:ident,
160+
$mir:ident,
161+
$def_id:ident,
162+
$suite_index:expr,
163+
$mir_phase:expr;
164+
$($pass:expr,)*
165+
) {{
159166
let suite_index: usize = $suite_index;
160167
let run_passes = |mir: &mut _, promoted| {
168+
let mir: &mut Mir<'_> = mir;
169+
170+
if mir.phase >= $mir_phase {
171+
return;
172+
}
173+
161174
let source = MirSource {
162175
def_id: $def_id,
163176
promoted
@@ -175,6 +188,8 @@ pub macro run_passes($tcx:ident, $mir:ident, $def_id:ident, $suite_index:expr; $
175188
index += 1;
176189
};
177190
$(run_pass(&$pass);)*
191+
192+
mir.phase = $mir_phase;
178193
};
179194

180195
run_passes(&mut $mir, None);
@@ -192,7 +207,7 @@ fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Stea
192207
let _ = tcx.unsafety_check_result(def_id);
193208

194209
let mut mir = tcx.mir_built(def_id).steal();
195-
run_passes![tcx, mir, def_id, 0;
210+
run_passes![tcx, mir, def_id, 0, MirPhase::Const;
196211
// Remove all `EndRegion` statements that are not involved in borrows.
197212
cleanup_post_borrowck::CleanEndRegions,
198213

@@ -214,7 +229,7 @@ fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
214229
}
215230

216231
let mut mir = tcx.mir_const(def_id).steal();
217-
run_passes![tcx, mir, def_id, 1;
232+
run_passes![tcx, mir, def_id, 1, MirPhase::Validated;
218233
// What we need to run borrowck etc.
219234
qualify_consts::QualifyAndPromoteConstants,
220235
simplify::SimplifyCfg::new("qualify-consts"),
@@ -232,7 +247,7 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
232247
}
233248

234249
let mut mir = tcx.mir_validated(def_id).steal();
235-
run_passes![tcx, mir, def_id, 2;
250+
run_passes![tcx, mir, def_id, 2, MirPhase::Optimized;
236251
// Remove all things not needed by analysis
237252
no_landing_pads::NoLandingPads,
238253
simplify_branches::SimplifyBranches::new("initial"),

src/test/ui/issues/issue-50411.rs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Regression test for #50411: the MIR inliner was causing problems
2+
// here because it would inline promoted code (which had already had
3+
// elaborate-drops invoked on it) and then try to elaboate drops a
4+
// second time. Uncool.
5+
6+
// compile-flags:-Zmir-opt-level=3
7+
// compile-pass
8+
9+
fn main() {
10+
let _ = (0 .. 1).filter(|_| [1].iter().all(|_| true)).count();
11+
}

0 commit comments

Comments
 (0)