Skip to content

Commit ec41fda

Browse files
author
David Haig
committed
Squash
1 parent 96ad8e5 commit ec41fda

File tree

13 files changed

+192
-33
lines changed

13 files changed

+192
-33
lines changed

src/librustc/mir/interpret/error.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,8 @@ pub enum PanicInfo<O> {
266266
RemainderByZero,
267267
GeneratorResumedAfterReturn,
268268
GeneratorResumedAfterPanic,
269+
AsyncResumedAfterReturn,
270+
AsyncResumedAfterPanic,
269271
}
270272

271273
/// Type for MIR `Assert` terminator error messages.
@@ -304,6 +306,10 @@ impl<O> PanicInfo<O> {
304306
"generator resumed after completion",
305307
GeneratorResumedAfterPanic =>
306308
"generator resumed after panicking",
309+
AsyncResumedAfterReturn =>
310+
"`async fn` resumed after completion",
311+
AsyncResumedAfterPanic =>
312+
"`async fn` resumed after panic",
307313
Panic { .. } | BoundsCheck { .. } =>
308314
bug!("Unexpected PanicInfo"),
309315
}

src/librustc/mir/mod.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
77
use crate::hir::def::{CtorKind, Namespace};
88
use crate::hir::def_id::DefId;
9-
use crate::hir;
9+
use crate::hir::GeneratorKind;
1010
use crate::mir::interpret::{GlobalAlloc, PanicInfo, Scalar};
1111
use crate::mir::visit::MirVisitable;
1212
use crate::ty::adjustment::PointerCast;
@@ -117,6 +117,10 @@ pub struct Body<'tcx> {
117117
/// The layout of a generator. Produced by the state transformation.
118118
pub generator_layout: Option<GeneratorLayout<'tcx>>,
119119

120+
/// If this is a generator then record the type of source expression that caused this generator
121+
/// to be created.
122+
pub generator_kind: Option<GeneratorKind>,
123+
120124
/// Declarations of locals.
121125
///
122126
/// The first local is the return value pointer, followed by `arg_count`
@@ -170,6 +174,7 @@ impl<'tcx> Body<'tcx> {
170174
var_debug_info: Vec<VarDebugInfo<'tcx>>,
171175
span: Span,
172176
control_flow_destroyed: Vec<(Span, String)>,
177+
generator_kind : Option<GeneratorKind>,
173178
) -> Self {
174179
// We need `arg_count` locals, and one for the return place.
175180
assert!(
@@ -187,6 +192,7 @@ impl<'tcx> Body<'tcx> {
187192
yield_ty: None,
188193
generator_drop: None,
189194
generator_layout: None,
195+
generator_kind,
190196
local_decls,
191197
user_type_annotations,
192198
arg_count,
@@ -2975,7 +2981,8 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
29752981
index: index.fold_with(folder),
29762982
},
29772983
Panic { .. } | Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero |
2978-
GeneratorResumedAfterReturn | GeneratorResumedAfterPanic =>
2984+
GeneratorResumedAfterReturn | GeneratorResumedAfterPanic |
2985+
AsyncResumedAfterReturn | AsyncResumedAfterPanic =>
29792986
msg.clone(),
29802987
};
29812988
Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup }
@@ -3021,7 +3028,8 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
30213028
len.visit_with(visitor) || index.visit_with(visitor),
30223029
Panic { .. } | Overflow(_) | OverflowNeg |
30233030
DivisionByZero | RemainderByZero |
3024-
GeneratorResumedAfterReturn | GeneratorResumedAfterPanic =>
3031+
GeneratorResumedAfterReturn | GeneratorResumedAfterPanic |
3032+
AsyncResumedAfterReturn | AsyncResumedAfterPanic =>
30253033
false
30263034
}
30273035
} else {

src/librustc/mir/visit.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,8 @@ macro_rules! make_mir_visitor {
517517
self.visit_operand(index, location);
518518
}
519519
Panic { .. } | Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero |
520-
GeneratorResumedAfterReturn | GeneratorResumedAfterPanic => {
520+
GeneratorResumedAfterReturn | GeneratorResumedAfterPanic |
521+
AsyncResumedAfterReturn | AsyncResumedAfterPanic => {
521522
// Nothing to visit
522523
}
523524
}

src/librustc_mir/build/mod.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::hair::{LintLevel, BindingMode, PatKind};
55
use crate::transform::MirSource;
66
use crate::util as mir_util;
77
use rustc::hir;
8-
use rustc::hir::Node;
8+
use rustc::hir::{Node, GeneratorKind};
99
use rustc::hir::def_id::DefId;
1010
use rustc::middle::lang_items;
1111
use rustc::middle::region;
@@ -279,7 +279,7 @@ struct Builder<'a, 'tcx> {
279279

280280
fn_span: Span,
281281
arg_count: usize,
282-
is_generator: bool,
282+
generator_kind: Option<GeneratorKind>,
283283

284284
/// The current set of scopes, updated as we traverse;
285285
/// see the `scope` module for more details.
@@ -570,7 +570,7 @@ where
570570
safety,
571571
return_ty,
572572
return_ty_span,
573-
body.generator_kind.is_some());
573+
body.generator_kind);
574574

575575
let call_site_scope = region::Scope {
576576
id: body.value.hir_id.local_id,
@@ -647,7 +647,7 @@ fn construct_const<'a, 'tcx>(
647647
Safety::Safe,
648648
const_ty,
649649
const_ty_span,
650-
false,
650+
None,
651651
);
652652

653653
let mut block = START_BLOCK;
@@ -678,7 +678,7 @@ fn construct_error<'a, 'tcx>(
678678
let owner_id = hir.tcx().hir().body_owner(body_id);
679679
let span = hir.tcx().hir().span(owner_id);
680680
let ty = hir.tcx().types.err;
681-
let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, span, false);
681+
let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, span, None);
682682
let source_info = builder.source_info(span);
683683
builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
684684
builder.finish()
@@ -691,15 +691,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
691691
safety: Safety,
692692
return_ty: Ty<'tcx>,
693693
return_span: Span,
694-
is_generator: bool)
694+
generator_kind: Option<GeneratorKind>)
695695
-> Builder<'a, 'tcx> {
696696
let lint_level = LintLevel::Explicit(hir.root_lint_level);
697697
let mut builder = Builder {
698698
hir,
699699
cfg: CFG { basic_blocks: IndexVec::new() },
700700
fn_span: span,
701701
arg_count,
702-
is_generator,
702+
generator_kind,
703703
scopes: Default::default(),
704704
block_context: BlockContext::new(),
705705
source_scopes: IndexVec::new(),
@@ -748,6 +748,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
748748
self.var_debug_info,
749749
self.fn_span,
750750
self.hir.control_flow_destroyed(),
751+
self.generator_kind
751752
)
752753
}
753754

src/librustc_mir/build/scope.rs

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ use syntax_pos::{DUMMY_SP, Span};
9191
use rustc_data_structures::fx::FxHashMap;
9292
use std::collections::hash_map::Entry;
9393
use std::mem;
94+
use rustc::hir::GeneratorKind;
9495

9596
#[derive(Debug)]
9697
struct Scope {
@@ -219,7 +220,12 @@ impl Scope {
219220
/// `storage_only` controls whether to invalidate only drop paths that run `StorageDead`.
220221
/// `this_scope_only` controls whether to invalidate only drop paths that refer to the current
221222
/// top-of-scope (as opposed to dependent scopes).
222-
fn invalidate_cache(&mut self, storage_only: bool, is_generator: bool, this_scope_only: bool) {
223+
fn invalidate_cache(
224+
&mut self,
225+
storage_only: bool,
226+
generator_kind: Option<GeneratorKind>,
227+
this_scope_only: bool
228+
) {
223229
// FIXME: maybe do shared caching of `cached_exits` etc. to handle functions
224230
// with lots of `try!`?
225231

@@ -229,7 +235,7 @@ impl Scope {
229235
// the current generator drop and unwind refer to top-of-scope
230236
self.cached_generator_drop = None;
231237

232-
let ignore_unwinds = storage_only && !is_generator;
238+
let ignore_unwinds = storage_only && generator_kind.is_none();
233239
if !ignore_unwinds {
234240
self.cached_unwind.invalidate();
235241
}
@@ -481,7 +487,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
481487

482488
unpack!(block = build_scope_drops(
483489
&mut self.cfg,
484-
self.is_generator,
490+
self.generator_kind,
485491
&scope,
486492
block,
487493
unwind_to,
@@ -574,7 +580,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
574580

575581
unpack!(block = build_scope_drops(
576582
&mut self.cfg,
577-
self.is_generator,
583+
self.generator_kind,
578584
scope,
579585
block,
580586
unwind_to,
@@ -625,7 +631,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
625631

626632
unpack!(block = build_scope_drops(
627633
&mut self.cfg,
628-
self.is_generator,
634+
self.generator_kind,
629635
scope,
630636
block,
631637
unwind_to,
@@ -809,7 +815,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
809815
// invalidating caches of each scope visited. This way bare minimum of the
810816
// caches gets invalidated. i.e., if a new drop is added into the middle scope, the
811817
// cache of outer scope stays intact.
812-
scope.invalidate_cache(!needs_drop, self.is_generator, this_scope);
818+
scope.invalidate_cache(!needs_drop, self.generator_kind, this_scope);
813819
if this_scope {
814820
let region_scope_span = region_scope.span(self.hir.tcx(),
815821
&self.hir.region_scope_tree);
@@ -958,7 +964,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
958964
}
959965
}
960966

961-
top_scope.invalidate_cache(true, self.is_generator, true);
967+
top_scope.invalidate_cache(true, self.generator_kind, true);
962968
} else {
963969
bug!("Expected as_local_operand to produce a temporary");
964970
}
@@ -1016,7 +1022,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
10161022

10171023
for scope in self.scopes.top_scopes(first_uncached) {
10181024
target = build_diverge_scope(&mut self.cfg, scope.region_scope_span,
1019-
scope, target, generator_drop, self.is_generator);
1025+
scope, target, generator_drop, self.generator_kind);
10201026
}
10211027

10221028
target
@@ -1079,14 +1085,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
10791085
assert_eq!(top_scope.region_scope, region_scope);
10801086

10811087
top_scope.drops.clear();
1082-
top_scope.invalidate_cache(false, self.is_generator, true);
1088+
top_scope.invalidate_cache(false, self.generator_kind, true);
10831089
}
10841090
}
10851091

10861092
/// Builds drops for pop_scope and exit_scope.
10871093
fn build_scope_drops<'tcx>(
10881094
cfg: &mut CFG<'tcx>,
1089-
is_generator: bool,
1095+
generator_kind: Option<GeneratorKind>,
10901096
scope: &Scope,
10911097
mut block: BasicBlock,
10921098
last_unwind_to: BasicBlock,
@@ -1130,7 +1136,7 @@ fn build_scope_drops<'tcx>(
11301136
continue;
11311137
}
11321138

1133-
let unwind_to = get_unwind_to(scope, is_generator, drop_idx, generator_drop)
1139+
let unwind_to = get_unwind_to(scope, generator_kind, drop_idx, generator_drop)
11341140
.unwrap_or(last_unwind_to);
11351141

11361142
let next = cfg.start_new_block();
@@ -1156,19 +1162,19 @@ fn build_scope_drops<'tcx>(
11561162

11571163
fn get_unwind_to(
11581164
scope: &Scope,
1159-
is_generator: bool,
1165+
generator_kind: Option<GeneratorKind>,
11601166
unwind_from: usize,
11611167
generator_drop: bool,
11621168
) -> Option<BasicBlock> {
11631169
for drop_idx in (0..unwind_from).rev() {
11641170
let drop_data = &scope.drops[drop_idx];
1165-
match (is_generator, &drop_data.kind) {
1166-
(true, DropKind::Storage) => {
1171+
match (generator_kind, &drop_data.kind) {
1172+
(Some(_), DropKind::Storage) => {
11671173
return Some(drop_data.cached_block.get(generator_drop).unwrap_or_else(|| {
11681174
span_bug!(drop_data.span, "cached block not present for {:?}", drop_data)
11691175
}));
11701176
}
1171-
(false, DropKind::Value) => {
1177+
(None, DropKind::Value) => {
11721178
return Some(drop_data.cached_block.get(generator_drop).unwrap_or_else(|| {
11731179
span_bug!(drop_data.span, "cached block not present for {:?}", drop_data)
11741180
}));
@@ -1184,7 +1190,7 @@ fn build_diverge_scope<'tcx>(cfg: &mut CFG<'tcx>,
11841190
scope: &mut Scope,
11851191
mut target: BasicBlock,
11861192
generator_drop: bool,
1187-
is_generator: bool)
1193+
generator_kind: Option<GeneratorKind>)
11881194
-> BasicBlock
11891195
{
11901196
// Build up the drops in **reverse** order. The end result will
@@ -1224,7 +1230,7 @@ fn build_diverge_scope<'tcx>(cfg: &mut CFG<'tcx>,
12241230
// match the behavior of clang, but on inspection eddyb says
12251231
// this is not what clang does.
12261232
match drop_data.kind {
1227-
DropKind::Storage if is_generator => {
1233+
DropKind::Storage if generator_kind.is_some() => {
12281234
storage_deads.push(Statement {
12291235
source_info: source_info(drop_data.span),
12301236
kind: StatementKind::StorageDead(drop_data.local)

src/librustc_mir/interpret/terminator.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
144144
RemainderByZero => err_panic!(RemainderByZero),
145145
GeneratorResumedAfterReturn => err_panic!(GeneratorResumedAfterReturn),
146146
GeneratorResumedAfterPanic => err_panic!(GeneratorResumedAfterPanic),
147+
AsyncResumedAfterReturn => err_panic!(AsyncResumedAfterReturn),
148+
AsyncResumedAfterPanic => err_panic!(AsyncResumedAfterPanic),
147149
Panic { .. } => bug!("`Panic` variant cannot occur in MIR"),
148150
}
149151
.into());

src/librustc_mir/shim.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
208208
vec![],
209209
span,
210210
vec![],
211+
None,
211212
);
212213

213214
if let Some(..) = ty {
@@ -374,6 +375,7 @@ impl CloneShimBuilder<'tcx> {
374375
vec![],
375376
self.span,
376377
vec![],
378+
None,
377379
)
378380
}
379381

@@ -834,6 +836,7 @@ fn build_call_shim<'tcx>(
834836
vec![],
835837
span,
836838
vec![],
839+
None,
837840
);
838841
if let Abi::RustCall = sig.abi {
839842
body.spread_arg = Some(Local::new(sig.inputs().len()));
@@ -920,6 +923,7 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &Body<'_> {
920923
vec![],
921924
span,
922925
vec![],
926+
None,
923927
);
924928

925929
crate::util::dump_mir(

src/librustc_mir/transform/const_prop.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
9191
Default::default(),
9292
tcx.def_span(source.def_id()),
9393
Default::default(),
94+
body.generator_kind,
9495
);
9596

9697
// FIXME(oli-obk, eddyb) Optimize locals (or even local paths) to hold

src/librustc_mir/transform/generator.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
//! Otherwise it drops all the values in scope at the last suspension point.
5151
5252
use rustc::hir;
53-
use rustc::hir::def_id::DefId;
53+
use rustc::hir::{def_id::DefId, GeneratorKind};
5454
use rustc::mir::*;
5555
use rustc::mir::visit::{PlaceContext, Visitor, MutVisitor};
5656
use rustc::ty::{self, TyCtxt, AdtDef, Ty};
@@ -1058,14 +1058,27 @@ fn create_generator_resume_function<'tcx>(
10581058
use rustc::mir::interpret::PanicInfo::{
10591059
GeneratorResumedAfterPanic,
10601060
GeneratorResumedAfterReturn,
1061+
AsyncResumedAfterReturn,
1062+
AsyncResumedAfterPanic,
10611063
};
10621064

10631065
// Jump to the entry point on the unresumed
10641066
cases.insert(0, (UNRESUMED, BasicBlock::new(0)));
1065-
// Panic when resumed on the returned state
1066-
cases.insert(1, (RETURNED, insert_panic_block(tcx, body, GeneratorResumedAfterReturn)));
1067-
// Panic when resumed on the poisoned state
1068-
cases.insert(2, (POISONED, insert_panic_block(tcx, body, GeneratorResumedAfterPanic)));
1067+
1068+
// Panic when resumed on the returned or poisoned state
1069+
match body.generator_kind {
1070+
Some(GeneratorKind::Async(_)) => {
1071+
cases.insert(1, (RETURNED, insert_panic_block(tcx, body, AsyncResumedAfterReturn)));
1072+
cases.insert(2, (POISONED, insert_panic_block(tcx, body, AsyncResumedAfterPanic)));
1073+
},
1074+
Some(GeneratorKind::Gen) => {
1075+
cases.insert(1, (RETURNED, insert_panic_block(tcx, body, GeneratorResumedAfterReturn)));
1076+
cases.insert(2, (POISONED, insert_panic_block(tcx, body, GeneratorResumedAfterPanic)));
1077+
},
1078+
None => {
1079+
// N/A because we would never create a resume function if there was no generator_kind
1080+
}
1081+
};
10691082

10701083
insert_switch(body, cases, &transform, TerminatorKind::Unreachable);
10711084

0 commit comments

Comments
 (0)