Skip to content

Commit a1132b3

Browse files
committed
Auto merge of #66321 - ninjasource:async-fn-resume-after-completion, r=oli-obk
Async fn resume after completion #65419 -- Attempting to run an async fn after completion mentions generators Not yet ready for review - work in progress Just need to run the tests on a proper build server
2 parents 861e96f + 6531ba8 commit a1132b3

13 files changed

+226
-66
lines changed

src/librustc/mir/interpret/error.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_macros::HashStable;
1313
use rustc_target::spec::abi::Abi;
1414
use syntax_pos::{Pos, Span};
1515
use syntax::symbol::Symbol;
16-
16+
use hir::GeneratorKind;
1717
use std::{fmt, env};
1818

1919
use rustc_error_codes::*;
@@ -264,8 +264,8 @@ pub enum PanicInfo<O> {
264264
OverflowNeg,
265265
DivisionByZero,
266266
RemainderByZero,
267-
GeneratorResumedAfterReturn,
268-
GeneratorResumedAfterPanic,
267+
ResumedAfterReturn(GeneratorKind),
268+
ResumedAfterPanic(GeneratorKind),
269269
}
270270

271271
/// Type for MIR `Assert` terminator error messages.
@@ -300,10 +300,14 @@ impl<O> PanicInfo<O> {
300300
"attempt to divide by zero",
301301
RemainderByZero =>
302302
"attempt to calculate the remainder with a divisor of zero",
303-
GeneratorResumedAfterReturn =>
303+
ResumedAfterReturn(GeneratorKind::Gen) =>
304304
"generator resumed after completion",
305-
GeneratorResumedAfterPanic =>
305+
ResumedAfterReturn(GeneratorKind::Async(_)) =>
306+
"`async fn` resumed after completion",
307+
ResumedAfterPanic(GeneratorKind::Gen) =>
306308
"generator resumed after panicking",
309+
ResumedAfterPanic(GeneratorKind::Async(_)) =>
310+
"`async fn` resumed after panicking",
307311
Panic { .. } | BoundsCheck { .. } =>
308312
bug!("Unexpected PanicInfo"),
309313
}

src/librustc/mir/mod.rs

+19-3
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::{self, 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,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
29752981
index: index.fold_with(folder),
29762982
},
29772983
Panic { .. } | Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero |
2978-
GeneratorResumedAfterReturn | GeneratorResumedAfterPanic =>
2984+
ResumedAfterReturn(_) | ResumedAfterPanic(_) =>
29792985
msg.clone(),
29802986
};
29812987
Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup }
@@ -3021,7 +3027,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
30213027
len.visit_with(visitor) || index.visit_with(visitor),
30223028
Panic { .. } | Overflow(_) | OverflowNeg |
30233029
DivisionByZero | RemainderByZero |
3024-
GeneratorResumedAfterReturn | GeneratorResumedAfterPanic =>
3030+
ResumedAfterReturn(_) | ResumedAfterPanic(_) =>
30253031
false
30263032
}
30273033
} else {
@@ -3040,6 +3046,16 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
30403046
}
30413047
}
30423048

3049+
impl<'tcx> TypeFoldable<'tcx> for GeneratorKind {
3050+
fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
3051+
*self
3052+
}
3053+
3054+
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
3055+
false
3056+
}
3057+
}
3058+
30433059
impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
30443060
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
30453061
Place {

src/librustc/mir/visit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ macro_rules! make_mir_visitor {
517517
self.visit_operand(index, location);
518518
}
519519
Panic { .. } | Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero |
520-
GeneratorResumedAfterReturn | GeneratorResumedAfterPanic => {
520+
ResumedAfterReturn(_) | ResumedAfterPanic(_) => {
521521
// Nothing to visit
522522
}
523523
}

src/librustc_mir/build/mod.rs

+8-7
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

+23-17
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

+4-2
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
142142
OverflowNeg => err_panic!(OverflowNeg),
143143
DivisionByZero => err_panic!(DivisionByZero),
144144
RemainderByZero => err_panic!(RemainderByZero),
145-
GeneratorResumedAfterReturn => err_panic!(GeneratorResumedAfterReturn),
146-
GeneratorResumedAfterPanic => err_panic!(GeneratorResumedAfterPanic),
145+
ResumedAfterReturn(generator_kind)
146+
=> err_panic!(ResumedAfterReturn(*generator_kind)),
147+
ResumedAfterPanic(generator_kind)
148+
=> err_panic!(ResumedAfterPanic(*generator_kind)),
147149
Panic { .. } => bug!("`Panic` variant cannot occur in MIR"),
148150
}
149151
.into());

0 commit comments

Comments
 (0)