Skip to content

Commit

Permalink
Don't incorrectly mark blocks in generator drop shims as cleanup
Browse files Browse the repository at this point in the history
This also ensure that dropping a generator won't leak upvars if dropping
one of them panics
  • Loading branch information
matthewjasper committed Mar 3, 2019
1 parent 2131b15 commit 8a78019
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 24 deletions.
46 changes: 22 additions & 24 deletions src/librustc_mir/transform/generator.rs
Expand Up @@ -592,8 +592,15 @@ fn elaborate_generator_drops<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let param_env = tcx.param_env(def_id);
let gen = self_arg();

for block in mir.basic_blocks().indices() {
let (target, unwind, source_info) = match mir.basic_blocks()[block].terminator() {
let mut elaborator = DropShimElaborator {
mir: mir,
patch: MirPatch::new(mir),
tcx,
param_env
};

for (block, block_data) in mir.basic_blocks().iter_enumerated() {
let (target, unwind, source_info) = match block_data.terminator() {
&Terminator {
source_info,
kind: TerminatorKind::Drop {
Expand All @@ -604,31 +611,22 @@ fn elaborate_generator_drops<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
} if local == gen => (target, unwind, source_info),
_ => continue,
};
let unwind = if let Some(unwind) = unwind {
Unwind::To(unwind)
} else {
let unwind = if block_data.is_cleanup {
Unwind::InCleanup
} else {
Unwind::To(unwind.unwrap_or_else(|| elaborator.patch.resume_block()))
};
let patch = {
let mut elaborator = DropShimElaborator {
mir: &mir,
patch: MirPatch::new(mir),
tcx,
param_env
};
elaborate_drop(
&mut elaborator,
source_info,
&Place::Base(PlaceBase::Local(gen)),
(),
target,
unwind,
block
);
elaborator.patch
};
patch.apply(mir);
elaborate_drop(
&mut elaborator,
source_info,
&Place::Base(PlaceBase::Local(gen)),
(),
target,
unwind,
block,
);
}
elaborator.patch.apply(mir);
}

fn create_generator_drop_shim<'a, 'tcx>(
Expand Down
43 changes: 43 additions & 0 deletions src/test/mir-opt/generator-drop-cleanup.rs
@@ -0,0 +1,43 @@
#![feature(generators, generator_trait)]

// Regression test for #58892, generator drop shims should not have blocks
// spuriously marked as cleanup

fn main() {
let gen = || {
yield;
};
}

// END RUST SOURCE

// START rustc.main-{{closure}}.generator_drop.0.mir
// bb0: {
// switchInt(((*_1).0: u32)) -> [0u32: bb4, 3u32: bb7, otherwise: bb8];
// }
// bb1: {
// goto -> bb5;
// }
// bb2: {
// return;
// }
// bb3: {
// return;
// }
// bb4: {
// goto -> bb6;
// }
// bb5: {
// goto -> bb2;
// }
// bb6: {
// goto -> bb3;
// }
// bb7: {
// StorageLive(_3);
// goto -> bb1;
// }
// bb8: {
// return;
// }
// END rustc.main-{{closure}}.generator_drop.0.mir

0 comments on commit 8a78019

Please sign in to comment.