about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-11-29 18:11:33 +0000
committerbors <bors@rust-lang.org>2019-11-29 18:11:33 +0000
commit25d8a9494ca6d77361e47c1505ecf640b168819e (patch)
tree01cf867d7bd46c03741be57376bb6e28bf011f08
parentd99e0c6d02b159f305474f58c8c38027bb06e051 (diff)
parent851492c3724204834d833f940ed5447813fda672 (diff)
downloadrust-25d8a9494ca6d77361e47c1505ecf640b168819e.tar.gz
rust-25d8a9494ca6d77361e47c1505ecf640b168819e.zip
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
-rw-r--r--src/librustc/mir/interpret/error.rs14
-rw-r--r--src/librustc/mir/mod.rs22
-rw-r--r--src/librustc/mir/visit.rs2
-rw-r--r--src/librustc_mir/build/mod.rs15
-rw-r--r--src/librustc_mir/build/scope.rs40
-rw-r--r--src/librustc_mir/interpret/terminator.rs6
-rw-r--r--src/librustc_mir/shim.rs55
-rw-r--r--src/librustc_mir/transform/const_prop.rs1
-rw-r--r--src/librustc_mir/transform/generator.rs19
-rw-r--r--src/librustc_mir/transform/promote_consts.rs1
-rw-r--r--src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs46
-rw-r--r--src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs52
-rw-r--r--src/test/ui/async-await/issues/issue-65419/issue-65419-generator-resume-after-completion.rs25
13 files changed, 232 insertions, 66 deletions
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index 7fb669314eb..98e6770c70d 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -13,7 +13,7 @@ use rustc_macros::HashStable;
 use rustc_target::spec::abi::Abi;
 use syntax_pos::{Pos, Span};
 use syntax::symbol::Symbol;
-
+use hir::GeneratorKind;
 use std::{fmt, env};
 
 use rustc_error_codes::*;
@@ -264,8 +264,8 @@ pub enum PanicInfo<O> {
     OverflowNeg,
     DivisionByZero,
     RemainderByZero,
-    GeneratorResumedAfterReturn,
-    GeneratorResumedAfterPanic,
+    ResumedAfterReturn(GeneratorKind),
+    ResumedAfterPanic(GeneratorKind),
 }
 
 /// Type for MIR `Assert` terminator error messages.
@@ -300,10 +300,14 @@ impl<O> PanicInfo<O> {
                 "attempt to divide by zero",
             RemainderByZero =>
                 "attempt to calculate the remainder with a divisor of zero",
-            GeneratorResumedAfterReturn =>
+            ResumedAfterReturn(GeneratorKind::Gen) =>
                 "generator resumed after completion",
-            GeneratorResumedAfterPanic =>
+            ResumedAfterReturn(GeneratorKind::Async(_)) =>
+                "`async fn` resumed after completion",
+            ResumedAfterPanic(GeneratorKind::Gen) =>
                 "generator resumed after panicking",
+            ResumedAfterPanic(GeneratorKind::Async(_)) =>
+                "`async fn` resumed after panicking",
             Panic { .. } | BoundsCheck { .. } =>
                 bug!("Unexpected PanicInfo"),
         }
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index c745dd9444c..8c1690a177b 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -6,7 +6,7 @@
 
 use crate::hir::def::{CtorKind, Namespace};
 use crate::hir::def_id::DefId;
-use crate::hir;
+use crate::hir::{self, GeneratorKind};
 use crate::mir::interpret::{GlobalAlloc, PanicInfo, Scalar};
 use crate::mir::visit::MirVisitable;
 use crate::ty::adjustment::PointerCast;
@@ -117,6 +117,10 @@ pub struct Body<'tcx> {
     /// The layout of a generator. Produced by the state transformation.
     pub generator_layout: Option<GeneratorLayout<'tcx>>,
 
+    /// If this is a generator then record the type of source expression that caused this generator
+    /// to be created.
+    pub generator_kind: Option<GeneratorKind>,
+
     /// Declarations of locals.
     ///
     /// The first local is the return value pointer, followed by `arg_count`
@@ -170,6 +174,7 @@ impl<'tcx> Body<'tcx> {
         var_debug_info: Vec<VarDebugInfo<'tcx>>,
         span: Span,
         control_flow_destroyed: Vec<(Span, String)>,
+        generator_kind : Option<GeneratorKind>,
     ) -> Self {
         // We need `arg_count` locals, and one for the return place.
         assert!(
@@ -187,6 +192,7 @@ impl<'tcx> Body<'tcx> {
             yield_ty: None,
             generator_drop: None,
             generator_layout: None,
+            generator_kind,
             local_decls,
             user_type_annotations,
             arg_count,
@@ -2975,7 +2981,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
                             index: index.fold_with(folder),
                         },
                     Panic { .. } | Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero |
-                    GeneratorResumedAfterReturn | GeneratorResumedAfterPanic =>
+                    ResumedAfterReturn(_) | ResumedAfterPanic(_)  =>
                         msg.clone(),
                 };
                 Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup }
@@ -3021,7 +3027,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
                             len.visit_with(visitor) || index.visit_with(visitor),
                         Panic { .. } | Overflow(_) | OverflowNeg |
                         DivisionByZero | RemainderByZero |
-                        GeneratorResumedAfterReturn | GeneratorResumedAfterPanic =>
+                        ResumedAfterReturn(_) | ResumedAfterPanic(_) =>
                             false
                     }
                 } else {
@@ -3040,6 +3046,16 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
     }
 }
 
+impl<'tcx> TypeFoldable<'tcx> for GeneratorKind {
+    fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
+        *self
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
+        false
+    }
+}
+
 impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
         Place {
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 464d4c74366..58c12ef2501 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -517,7 +517,7 @@ macro_rules! make_mir_visitor {
                         self.visit_operand(index, location);
                     }
                     Panic { .. } | Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero |
-                    GeneratorResumedAfterReturn | GeneratorResumedAfterPanic => {
+                    ResumedAfterReturn(_) | ResumedAfterPanic(_) => {
                         // Nothing to visit
                     }
                 }
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 180f2cc089f..91ddd5a5623 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -5,7 +5,7 @@ use crate::hair::{LintLevel, BindingMode, PatKind};
 use crate::transform::MirSource;
 use crate::util as mir_util;
 use rustc::hir;
-use rustc::hir::Node;
+use rustc::hir::{Node, GeneratorKind};
 use rustc::hir::def_id::DefId;
 use rustc::middle::lang_items;
 use rustc::middle::region;
@@ -279,7 +279,7 @@ struct Builder<'a, 'tcx> {
 
     fn_span: Span,
     arg_count: usize,
-    is_generator: bool,
+    generator_kind: Option<GeneratorKind>,
 
     /// The current set of scopes, updated as we traverse;
     /// see the `scope` module for more details.
@@ -570,7 +570,7 @@ where
         safety,
         return_ty,
         return_ty_span,
-        body.generator_kind.is_some());
+        body.generator_kind);
 
     let call_site_scope = region::Scope {
         id: body.value.hir_id.local_id,
@@ -647,7 +647,7 @@ fn construct_const<'a, 'tcx>(
         Safety::Safe,
         const_ty,
         const_ty_span,
-        false,
+        None,
     );
 
     let mut block = START_BLOCK;
@@ -678,7 +678,7 @@ fn construct_error<'a, 'tcx>(
     let owner_id = hir.tcx().hir().body_owner(body_id);
     let span = hir.tcx().hir().span(owner_id);
     let ty = hir.tcx().types.err;
-    let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, span, false);
+    let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, span, None);
     let source_info = builder.source_info(span);
     builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
     builder.finish()
@@ -691,7 +691,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
            safety: Safety,
            return_ty: Ty<'tcx>,
            return_span: Span,
-           is_generator: bool)
+           generator_kind: Option<GeneratorKind>)
            -> Builder<'a, 'tcx> {
         let lint_level = LintLevel::Explicit(hir.root_lint_level);
         let mut builder = Builder {
@@ -699,7 +699,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             cfg: CFG { basic_blocks: IndexVec::new() },
             fn_span: span,
             arg_count,
-            is_generator,
+            generator_kind,
             scopes: Default::default(),
             block_context: BlockContext::new(),
             source_scopes: IndexVec::new(),
@@ -748,6 +748,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             self.var_debug_info,
             self.fn_span,
             self.hir.control_flow_destroyed(),
+            self.generator_kind
         )
     }
 
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index 1b3d8641f20..bb25b285269 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -91,6 +91,7 @@ use syntax_pos::{DUMMY_SP, Span};
 use rustc_data_structures::fx::FxHashMap;
 use std::collections::hash_map::Entry;
 use std::mem;
+use rustc::hir::GeneratorKind;
 
 #[derive(Debug)]
 struct Scope {
@@ -219,7 +220,12 @@ impl Scope {
     /// `storage_only` controls whether to invalidate only drop paths that run `StorageDead`.
     /// `this_scope_only` controls whether to invalidate only drop paths that refer to the current
     /// top-of-scope (as opposed to dependent scopes).
-    fn invalidate_cache(&mut self, storage_only: bool, is_generator: bool, this_scope_only: bool) {
+    fn invalidate_cache(
+        &mut self,
+        storage_only: bool,
+        generator_kind: Option<GeneratorKind>,
+        this_scope_only: bool
+    ) {
         // FIXME: maybe do shared caching of `cached_exits` etc. to handle functions
         // with lots of `try!`?
 
@@ -229,7 +235,7 @@ impl Scope {
         // the current generator drop and unwind refer to top-of-scope
         self.cached_generator_drop = None;
 
-        let ignore_unwinds = storage_only && !is_generator;
+        let ignore_unwinds = storage_only && generator_kind.is_none();
         if !ignore_unwinds {
             self.cached_unwind.invalidate();
         }
@@ -481,7 +487,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
         unpack!(block = build_scope_drops(
             &mut self.cfg,
-            self.is_generator,
+            self.generator_kind,
             &scope,
             block,
             unwind_to,
@@ -574,7 +580,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
             unpack!(block = build_scope_drops(
                 &mut self.cfg,
-                self.is_generator,
+                self.generator_kind,
                 scope,
                 block,
                 unwind_to,
@@ -625,7 +631,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
             unpack!(block = build_scope_drops(
                 &mut self.cfg,
-                self.is_generator,
+                self.generator_kind,
                 scope,
                 block,
                 unwind_to,
@@ -809,7 +815,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             // invalidating caches of each scope visited. This way bare minimum of the
             // caches gets invalidated. i.e., if a new drop is added into the middle scope, the
             // cache of outer scope stays intact.
-            scope.invalidate_cache(!needs_drop, self.is_generator, this_scope);
+            scope.invalidate_cache(!needs_drop, self.generator_kind, this_scope);
             if this_scope {
                 let region_scope_span = region_scope.span(self.hir.tcx(),
                                                           &self.hir.region_scope_tree);
@@ -958,7 +964,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         }
                     }
 
-                    top_scope.invalidate_cache(true, self.is_generator, true);
+                    top_scope.invalidate_cache(true, self.generator_kind, true);
                 } else {
                     bug!("Expected as_local_operand to produce a temporary");
                 }
@@ -1016,7 +1022,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
         for scope in self.scopes.top_scopes(first_uncached) {
             target = build_diverge_scope(&mut self.cfg, scope.region_scope_span,
-                                         scope, target, generator_drop, self.is_generator);
+                                         scope, target, generator_drop, self.generator_kind);
         }
 
         target
@@ -1079,14 +1085,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         assert_eq!(top_scope.region_scope, region_scope);
 
         top_scope.drops.clear();
-        top_scope.invalidate_cache(false, self.is_generator, true);
+        top_scope.invalidate_cache(false, self.generator_kind, true);
     }
 }
 
 /// Builds drops for pop_scope and exit_scope.
 fn build_scope_drops<'tcx>(
     cfg: &mut CFG<'tcx>,
-    is_generator: bool,
+    generator_kind: Option<GeneratorKind>,
     scope: &Scope,
     mut block: BasicBlock,
     last_unwind_to: BasicBlock,
@@ -1130,7 +1136,7 @@ fn build_scope_drops<'tcx>(
                     continue;
                 }
 
-                let unwind_to = get_unwind_to(scope, is_generator, drop_idx, generator_drop)
+                let unwind_to = get_unwind_to(scope, generator_kind, drop_idx, generator_drop)
                     .unwrap_or(last_unwind_to);
 
                 let next = cfg.start_new_block();
@@ -1156,19 +1162,19 @@ fn build_scope_drops<'tcx>(
 
 fn get_unwind_to(
     scope: &Scope,
-    is_generator: bool,
+    generator_kind: Option<GeneratorKind>,
     unwind_from: usize,
     generator_drop: bool,
 ) -> Option<BasicBlock> {
     for drop_idx in (0..unwind_from).rev() {
         let drop_data = &scope.drops[drop_idx];
-        match (is_generator, &drop_data.kind) {
-            (true, DropKind::Storage) => {
+        match (generator_kind, &drop_data.kind) {
+            (Some(_), DropKind::Storage) => {
                 return Some(drop_data.cached_block.get(generator_drop).unwrap_or_else(|| {
                     span_bug!(drop_data.span, "cached block not present for {:?}", drop_data)
                 }));
             }
-            (false, DropKind::Value) => {
+            (None, DropKind::Value) => {
                 return Some(drop_data.cached_block.get(generator_drop).unwrap_or_else(|| {
                     span_bug!(drop_data.span, "cached block not present for {:?}", drop_data)
                 }));
@@ -1184,7 +1190,7 @@ fn build_diverge_scope<'tcx>(cfg: &mut CFG<'tcx>,
                              scope: &mut Scope,
                              mut target: BasicBlock,
                              generator_drop: bool,
-                             is_generator: bool)
+                             generator_kind: Option<GeneratorKind>)
                              -> BasicBlock
 {
     // Build up the drops in **reverse** order. The end result will
@@ -1224,7 +1230,7 @@ fn build_diverge_scope<'tcx>(cfg: &mut CFG<'tcx>,
         // match the behavior of clang, but on inspection eddyb says
         // this is not what clang does.
         match drop_data.kind {
-            DropKind::Storage if is_generator => {
+            DropKind::Storage if generator_kind.is_some() => {
                 storage_deads.push(Statement {
                     source_info: source_info(drop_data.span),
                     kind: StatementKind::StorageDead(drop_data.local)
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index 7285836d1c3..50cd3188510 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -142,8 +142,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         OverflowNeg => err_panic!(OverflowNeg),
                         DivisionByZero => err_panic!(DivisionByZero),
                         RemainderByZero => err_panic!(RemainderByZero),
-                        GeneratorResumedAfterReturn => err_panic!(GeneratorResumedAfterReturn),
-                        GeneratorResumedAfterPanic => err_panic!(GeneratorResumedAfterPanic),
+                        ResumedAfterReturn(generator_kind)
+                            => err_panic!(ResumedAfterReturn(*generator_kind)),
+                        ResumedAfterPanic(generator_kind)
+                            => err_panic!(ResumedAfterPanic(*generator_kind)),
                         Panic { .. } => bug!("`Panic` variant cannot occur in MIR"),
                     }
                     .into());
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index b5cb6a92816..08af271ff46 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -196,19 +196,14 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
     block(&mut blocks, TerminatorKind::Goto { target: return_block });
     block(&mut blocks, TerminatorKind::Return);
 
-    let mut body = Body::new(
+    let mut body = new_body(
         blocks,
         IndexVec::from_elem_n(
-            SourceScopeData { span: span, parent_scope: None }, 1
+            SourceScopeData { span, parent_scope: None }, 1
         ),
-        ClearCrossCrate::Clear,
         local_decls_for_sig(&sig, span),
-        IndexVec::new(),
         sig.inputs().len(),
-        vec![],
-        span,
-        vec![],
-    );
+        span);
 
     if let Some(..) = ty {
         // The first argument (index 0), but add 1 for the return value.
@@ -247,6 +242,27 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
     body
 }
 
+fn new_body<'tcx>(
+    basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
+    source_scopes: IndexVec<SourceScope, SourceScopeData>,
+    local_decls: IndexVec<Local, LocalDecl<'tcx>>,
+    arg_count: usize,
+    span: Span,
+) -> Body<'tcx> {
+    Body::new(
+        basic_blocks,
+        source_scopes,
+        ClearCrossCrate::Clear,
+        local_decls,
+        IndexVec::new(),
+        arg_count,
+        vec![],
+        span,
+        vec![],
+        None,
+    )
+}
+
 pub struct DropShimElaborator<'a, 'tcx> {
     pub body: &'a Body<'tcx>,
     pub patch: MirPatch<'tcx>,
@@ -362,18 +378,14 @@ impl CloneShimBuilder<'tcx> {
     }
 
     fn into_mir(self) -> Body<'tcx> {
-        Body::new(
+        new_body(
             self.blocks,
             IndexVec::from_elem_n(
                 SourceScopeData { span: self.span, parent_scope: None }, 1
             ),
-            ClearCrossCrate::Clear,
             self.local_decls,
-            IndexVec::new(),
             self.sig.inputs().len(),
-            vec![],
             self.span,
-            vec![],
         )
     }
 
@@ -822,19 +834,16 @@ fn build_call_shim<'tcx>(
         block(&mut blocks, vec![], TerminatorKind::Resume, true);
     }
 
-    let mut body = Body::new(
+    let mut body = new_body(
         blocks,
         IndexVec::from_elem_n(
-            SourceScopeData { span: span, parent_scope: None }, 1
+            SourceScopeData { span, parent_scope: None }, 1
         ),
-        ClearCrossCrate::Clear,
         local_decls,
-        IndexVec::new(),
         sig.inputs().len(),
-        vec![],
         span,
-        vec![],
     );
+
     if let Abi::RustCall = sig.abi {
         body.spread_arg = Some(Local::new(sig.inputs().len()));
     }
@@ -908,18 +917,14 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &Body<'_> {
         is_cleanup: false
     };
 
-    let body = Body::new(
+    let body = new_body(
         IndexVec::from_elem_n(start_block, 1),
         IndexVec::from_elem_n(
-            SourceScopeData { span: span, parent_scope: None }, 1
+            SourceScopeData { span, parent_scope: None }, 1
         ),
-        ClearCrossCrate::Clear,
         local_decls,
-        IndexVec::new(),
         sig.inputs().len(),
-        vec![],
         span,
-        vec![],
     );
 
     crate::util::dump_mir(
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 8de16308e83..d2740cf3771 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -91,6 +91,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
                 Default::default(),
                 tcx.def_span(source.def_id()),
                 Default::default(),
+                body.generator_kind,
             );
 
         // FIXME(oli-obk, eddyb) Optimize locals (or even local paths) to hold
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index a904c6a3ada..5d88629435b 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -1056,16 +1056,23 @@ fn create_generator_resume_function<'tcx>(
     let mut cases = create_cases(body, &transform, |point| Some(point.resume));
 
     use rustc::mir::interpret::PanicInfo::{
-        GeneratorResumedAfterPanic,
-        GeneratorResumedAfterReturn,
+        ResumedAfterPanic,
+        ResumedAfterReturn,
     };
 
     // Jump to the entry point on the unresumed
     cases.insert(0, (UNRESUMED, BasicBlock::new(0)));
-    // Panic when resumed on the returned state
-    cases.insert(1, (RETURNED, insert_panic_block(tcx, body, GeneratorResumedAfterReturn)));
-    // Panic when resumed on the poisoned state
-    cases.insert(2, (POISONED, insert_panic_block(tcx, body, GeneratorResumedAfterPanic)));
+
+    // Panic when resumed on the returned or poisoned state
+    let generator_kind = body.generator_kind.unwrap();
+    cases.insert(1, (RETURNED, insert_panic_block(
+        tcx,
+        body,
+        ResumedAfterReturn(generator_kind))));
+    cases.insert(2, (POISONED, insert_panic_block(
+        tcx,
+        body,
+        ResumedAfterPanic(generator_kind))));
 
     insert_switch(body, cases, &transform, TerminatorKind::Unreachable);
 
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index d927ac27fd7..cc6108c7dc0 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -1088,6 +1088,7 @@ pub fn promote_candidates<'tcx>(
                 vec![],
                 body.span,
                 vec![],
+                body.generator_kind,
             ),
             tcx,
             source: body,
diff --git a/src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs b/src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs
new file mode 100644
index 00000000000..ade386a605d
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs
@@ -0,0 +1,46 @@
+// issue 65419 - Attempting to run an async fn after completion mentions generators when it should
+// be talking about `async fn`s instead.
+
+// run-fail
+// error-pattern: thread 'main' panicked at '`async fn` resumed after completion'
+// edition:2018
+// ignore-wasm no panic or subprocess support
+// ignore-emscripten no panic or subprocess support
+
+#![feature(generators, generator_trait)]
+
+async fn foo() {
+}
+
+fn main() {
+    let mut future = Box::pin(foo());
+    executor::block_on(future.as_mut());
+    executor::block_on(future.as_mut());
+}
+
+mod executor {
+    use core::{
+        future::Future,
+        pin::Pin,
+        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+    };
+
+    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+
+        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+            |_| unimplemented!("clone"),
+            |_| unimplemented!("wake"),
+            |_| unimplemented!("wake_by_ref"),
+            |_| (),
+        );
+        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+        let mut context = Context::from_waker(&waker);
+
+        loop {
+            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+                break val;
+            }
+        }
+    }
+}
diff --git a/src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs b/src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs
new file mode 100644
index 00000000000..f8caebcb876
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs
@@ -0,0 +1,52 @@
+// issue 65419 - Attempting to run an async fn after completion mentions generators when it should
+// be talking about `async fn`s instead. Should also test what happens when it panics.
+
+// run-fail
+// error-pattern: thread 'main' panicked at '`async fn` resumed after panicking'
+// edition:2018
+// ignore-wasm no panic or subprocess support
+// ignore-emscripten no panic or subprocess support
+
+#![feature(generators, generator_trait)]
+
+use std::panic;
+
+async fn foo() {
+    panic!();
+}
+
+fn main() {
+    let mut future = Box::pin(foo());
+    panic::catch_unwind(panic::AssertUnwindSafe(|| {
+        executor::block_on(future.as_mut());
+    }));
+
+    executor::block_on(future.as_mut());
+}
+
+mod executor {
+    use core::{
+        future::Future,
+        pin::Pin,
+        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+    };
+
+    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+
+        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+            |_| unimplemented!("clone"),
+            |_| unimplemented!("wake"),
+            |_| unimplemented!("wake_by_ref"),
+            |_| (),
+        );
+        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+        let mut context = Context::from_waker(&waker);
+
+        loop {
+            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+                break val;
+            }
+        }
+    }
+}
diff --git a/src/test/ui/async-await/issues/issue-65419/issue-65419-generator-resume-after-completion.rs b/src/test/ui/async-await/issues/issue-65419/issue-65419-generator-resume-after-completion.rs
new file mode 100644
index 00000000000..23e3483e01c
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-65419/issue-65419-generator-resume-after-completion.rs
@@ -0,0 +1,25 @@
+// issue 65419 - Attempting to run an `async fn` after completion mentions generators when it should
+// be talking about `async fn`s instead. Regression test added to make sure generators still
+// panic when resumed after completion.
+
+// run-fail
+// error-pattern:generator resumed after completion
+// edition:2018
+// ignore-wasm no panic or subprocess support
+// ignore-emscripten no panic or subprocess support
+
+#![feature(generators, generator_trait)]
+
+use std::{
+    ops::Generator,
+    pin::Pin,
+};
+
+fn main() {
+    let mut g = || {
+        yield;
+    };
+    Pin::new(&mut g).resume(); // Yields once.
+    Pin::new(&mut g).resume(); // Completes here.
+    Pin::new(&mut g).resume(); // Panics here.
+}