]> git.lizzy.rs Git - rust.git/commitdiff
Avoid `GenFuture` shim when compiling async constructs
authorArpad Borsos <swatinem@swatinem.de>
Fri, 18 Nov 2022 21:56:22 +0000 (22:56 +0100)
committerArpad Borsos <swatinem@swatinem.de>
Thu, 24 Nov 2022 09:04:27 +0000 (10:04 +0100)
Previously, async constructs would be lowered to "normal" generators,
with an additional `from_generator` / `GenFuture` shim in between to
convert from `Generator` to `Future`.

The compiler will now special-case these generators internally so that
async constructs will *directly* implement `Future` without the need
to go through the `from_generator` / `GenFuture` shim.

The primary motivation for this change was hiding this implementation
detail in stack traces and debuginfo, but it can in theory also help
the optimizer as there is less abstractions to see through.

41 files changed:
compiler/rustc_ast_lowering/src/expr.rs
compiler/rustc_borrowck/src/diagnostics/region_errors.rs
compiler/rustc_borrowck/src/type_check/mod.rs
compiler/rustc_const_eval/src/transform/check_consts/check.rs
compiler/rustc_hir/src/lang_items.rs
compiler/rustc_hir_typeck/src/check.rs
compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
compiler/rustc_lint/src/unused.rs
compiler/rustc_middle/src/traits/mod.rs
compiler/rustc_middle/src/traits/select.rs
compiler/rustc_middle/src/traits/structural_impls.rs
compiler/rustc_middle/src/ty/print/pretty.rs
compiler/rustc_mir_transform/src/generator.rs
compiler/rustc_resolve/src/late.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
compiler/rustc_trait_selection/src/traits/project.rs
compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
compiler/rustc_trait_selection/src/traits/select/confirmation.rs
compiler/rustc_trait_selection/src/traits/select/mod.rs
compiler/rustc_trait_selection/src/traits/util.rs
compiler/rustc_traits/src/chalk/lowering.rs
compiler/rustc_ty_utils/src/instance.rs
library/core/src/future/mod.rs
library/core/src/task/poll.rs
src/test/codegen/async-fn-debug-awaitee-field.rs
src/test/run-make/coverage-reports/expected_show_coverage.async2.txt
src/test/ui/async-await/async-block-control-flow-static-semantics.stderr
src/test/ui/async-await/async-borrowck-escaping-block-error.stderr
src/test/ui/async-await/generator-desc.stderr
src/test/ui/async-await/issue-68112.drop_tracking.stderr
src/test/ui/async-await/issue-68112.no_drop_tracking.stderr
src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
src/test/ui/async-await/issues/issue-78938-async-block.stderr
src/test/ui/async-await/try-on-option-in-async.stderr
src/test/ui/chalkify/bugs/async.stderr
src/test/ui/lazy-type-alias-impl-trait/freeze_cycle.rs
src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
src/tools/clippy/clippy_lints/src/doc.rs
src/tools/clippy/clippy_lints/src/manual_async_fn.rs
src/tools/clippy/tests/ui/author/blocks.stdout

index a00100ee0a8458f506a7eb1d4d14056e832fd219..b222ef4a88924edd01d6c81c05a894ddd9524db6 100644 (file)
@@ -149,7 +149,7 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
                     *capture_clause,
                     *closure_node_id,
                     None,
-                    block.span,
+                    e.span,
                     hir::AsyncGeneratorKind::Block,
                     |this| this.with_new_scopes(|this| this.lower_block_expr(block)),
                 ),
@@ -569,12 +569,12 @@ fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
         }
     }
 
-    /// Lower an `async` construct to a generator that is then wrapped so it implements `Future`.
+    /// Lower an `async` construct to a generator that implements `Future`.
     ///
     /// This results in:
     ///
     /// ```text
-    /// std::future::from_generator(static move? |_task_context| -> <ret_ty> {
+    /// std::future::identity_future(static move? |_task_context| -> <ret_ty> {
     ///     <body>
     /// })
     /// ```
@@ -589,12 +589,14 @@ pub(super) fn make_async_expr(
     ) -> hir::ExprKind<'hir> {
         let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span)));
 
-        // Resume argument type. We let the compiler infer this to simplify the lowering. It is
-        // fully constrained by `future::from_generator`.
+        // Resume argument type: `ResumeTy`
+        let unstable_span =
+            self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
+        let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span, None);
         let input_ty = hir::Ty {
             hir_id: self.next_id(),
-            kind: hir::TyKind::Infer,
-            span: self.lower_span(span),
+            kind: hir::TyKind::Path(resume_ty),
+            span: unstable_span,
         };
 
         // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
@@ -677,16 +679,24 @@ pub(super) fn make_async_expr(
 
         let generator = hir::Expr { hir_id, kind: generator_kind, span: self.lower_span(span) };
 
-        // `future::from_generator`:
-        let gen_future = self.expr_lang_item_path(
+        // FIXME(swatinem):
+        // For some reason, the async block needs to flow through *any*
+        // call (like the identity function), as otherwise type and lifetime
+        // inference have a hard time figuring things out.
+        // Without this, we would get:
+        // E0720 in src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs
+        // E0700 in src/test/ui/self/self_lifetime-async.rs
+
+        // `future::identity_future`:
+        let identity_future = self.expr_lang_item_path(
             unstable_span,
-            hir::LangItem::FromGenerator,
+            hir::LangItem::IdentityFuture,
             AttrVec::new(),
             None,
         );
 
-        // `future::from_generator(generator)`:
-        hir::ExprKind::Call(self.arena.alloc(gen_future), arena_vec![self; generator])
+        // `future::identity_future(generator)`:
+        hir::ExprKind::Call(self.arena.alloc(identity_future), arena_vec![self; generator])
     }
 
     /// Desugar `<expr>.await` into:
@@ -990,7 +1000,7 @@ fn lower_expr_async_closure(
             }
 
             // Transform `async |x: u8| -> X { ... }` into
-            // `|x: u8| future_from_generator(|| -> X { ... })`.
+            // `|x: u8| identity_future(|| -> X { ... })`.
             let body_id = this.lower_fn_body(&outer_decl, |this| {
                 let async_ret_ty = if let FnRetTy::Ty(ty) = &decl.output {
                     let itctx = ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock);
index 76f249dac5181439f4a437402e0d0aa68a38eb0a..534675f1dc042c5bab0df36fdba6fc4b860d2a9c 100644 (file)
@@ -21,7 +21,7 @@
 use rustc_middle::ty::Region;
 use rustc_middle::ty::TypeVisitor;
 use rustc_middle::ty::{self, RegionVid, Ty};
-use rustc_span::symbol::{kw, sym, Ident};
+use rustc_span::symbol::{kw, Ident};
 use rustc_span::Span;
 
 use crate::borrowck_errors;
@@ -514,8 +514,11 @@ fn report_fnmut_error(
             span: *span,
             ty_err: match output_ty.kind() {
                 ty::Closure(_, _) => FnMutReturnTypeErr::ReturnClosure { span: *span },
-                ty::Adt(def, _)
-                    if self.infcx.tcx.is_diagnostic_item(sym::gen_future, def.did()) =>
+                ty::Generator(def, ..)
+                    if matches!(
+                        self.infcx.tcx.generator_kind(def),
+                        Some(hir::GeneratorKind::Async(_))
+                    ) =>
                 {
                     FnMutReturnTypeErr::ReturnAsyncBlock { span: *span }
                 }
@@ -927,10 +930,14 @@ fn suggest_move_on_borrowing_closure(&self, diag: &mut Diagnostic) {
                     // only when the block is a closure
                     if let hir::ExprKind::Closure(hir::Closure {
                         capture_clause: hir::CaptureBy::Ref,
+                        body,
                         ..
                     }) = expr.kind
                     {
-                        closure_span = Some(expr.span.shrink_to_lo());
+                        let body = map.body(*body);
+                        if !matches!(body.generator_kind, Some(hir::GeneratorKind::Async(..))) {
+                            closure_span = Some(expr.span.shrink_to_lo());
+                        }
                     }
                 }
             }
index 7467212bed883aa2827db09a19c1093b9c7a97cf..b268eac97d0b07a075bb100e816655d45028d008 100644 (file)
@@ -2588,7 +2588,6 @@ fn prove_aggregate_predicates(
             }
 
             // For closures, we have some **extra requirements** we
-            //
             // have to check. In particular, in their upvars and
             // signatures, closures often reference various regions
             // from the surrounding function -- we call those the
index 36956f5dd6d96da367c9e11fa5d362a3101d4beb..4564a6c4f2f4e3f37f47ceee09ba266cbe4a914a 100644 (file)
@@ -449,8 +449,17 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
             | Rvalue::CopyForDeref(..)
             | Rvalue::Repeat(..)
             | Rvalue::Discriminant(..)
-            | Rvalue::Len(_)
-            | Rvalue::Aggregate(..) => {}
+            | Rvalue::Len(_) => {}
+
+            Rvalue::Aggregate(ref kind, ..) => {
+                if let AggregateKind::Generator(def_id, ..) = kind.as_ref() {
+                    if let Some(generator_kind) = self.tcx.generator_kind(def_id.to_def_id()) {
+                        if matches!(generator_kind, hir::GeneratorKind::Async(..)) {
+                            self.check_op(ops::Generator(generator_kind));
+                        }
+                    }
+                }
+            }
 
             Rvalue::Ref(_, kind @ BorrowKind::Mut { .. }, ref place)
             | Rvalue::Ref(_, kind @ BorrowKind::Unique, ref place) => {
@@ -889,14 +898,6 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
                     return;
                 }
 
-                // `async` blocks get lowered to `std::future::from_generator(/* a closure */)`.
-                let is_async_block = Some(callee) == tcx.lang_items().from_generator_fn();
-                if is_async_block {
-                    let kind = hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block);
-                    self.check_op(ops::Generator(kind));
-                    return;
-                }
-
                 if !tcx.is_const_fn_raw(callee) {
                     if !tcx.is_const_default_method(callee) {
                         // To get to here we must have already found a const impl for the
index b68dd25996b116cd5c60c8027c4a9f0ae46c19dc..038509031b180a3cd42417a23846ff36c00ea7c0 100644 (file)
@@ -280,10 +280,14 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> {
 
     PointerSized,            sym::pointer_sized,       pointer_sized,              Target::Trait,          GenericRequirement::Exact(0);
 
+    Poll,                    sym::Poll,                poll,                       Target::Enum,           GenericRequirement::None;
     PollReady,               sym::Ready,               poll_ready_variant,         Target::Variant,        GenericRequirement::None;
     PollPending,             sym::Pending,             poll_pending_variant,       Target::Variant,        GenericRequirement::None;
 
-    FromGenerator,           sym::from_generator,      from_generator_fn,          Target::Fn,             GenericRequirement::None;
+    // FIXME(swatinem): the following lang items are used for async lowering and
+    // should become obsolete eventually.
+    ResumeTy,                sym::ResumeTy,            resume_ty,                  Target::Struct,         GenericRequirement::None;
+    IdentityFuture,          sym::identity_future,     identity_future_fn,         Target::Fn,             GenericRequirement::None;
     GetContext,              sym::get_context,         get_context_fn,             Target::Fn,             GenericRequirement::None;
 
     FuturePoll,              sym::poll,                future_poll_fn,             Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
index b9e90e47e508bdecbb522fc62d077893bfc8ff59..2c24b9ef14e85833645887c2e9830152c1e51b62 100644 (file)
@@ -56,10 +56,15 @@ pub(super) fn check_fn<'a, 'tcx>(
 
     fn_maybe_err(tcx, span, fn_sig.abi);
 
-    if body.generator_kind.is_some() && can_be_generator.is_some() {
-        let yield_ty = fcx
-            .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
-        fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType);
+    if let Some(kind) = body.generator_kind && can_be_generator.is_some() {
+        let yield_ty = if kind == hir::GeneratorKind::Gen {
+            let yield_ty = fcx
+                .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
+            fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType);
+            yield_ty
+        } else {
+            tcx.mk_unit()
+        };
 
         // Resume type defaults to `()` if the generator has no argument.
         let resume_ty = fn_sig.inputs().get(0).copied().unwrap_or_else(|| tcx.mk_unit());
index a31ab9c8b23b899c00dcad27aad6b7f8816e9a54..5727a120390d49c72755ff8619456b2d2c2d06d5 100644 (file)
@@ -1734,14 +1734,6 @@ fn adjust_fulfillment_error_for_expr_obligation(
         let hir = self.tcx.hir();
         let hir::Node::Expr(expr) = hir.get(hir_id) else { return false; };
 
-        // Skip over mentioning async lang item
-        if Some(def_id) == self.tcx.lang_items().from_generator_fn()
-            && error.obligation.cause.span.desugaring_kind()
-                == Some(rustc_span::DesugaringKind::Async)
-        {
-            return false;
-        }
-
         let Some(unsubstituted_pred) =
             self.tcx.predicates_of(def_id).instantiate_identity(self.tcx).predicates.into_iter().nth(idx)
             else { return false; };
index 0471890230aa6a4d6256ce9a570ea4caeb4f4598..d6a01b425483129a1ff9a8d9c4139c246ed0cbd4 100644 (file)
@@ -319,7 +319,20 @@ fn is_ty_must_use<'tcx>(
                         .map(|inner| MustUsePath::Array(Box::new(inner), len)),
                 },
                 ty::Closure(..) => Some(MustUsePath::Closure(span)),
-                ty::Generator(..) => Some(MustUsePath::Generator(span)),
+                ty::Generator(def_id, ..) => {
+                    // async fn should be treated as "implementor of `Future`"
+                    let must_use = if matches!(
+                        cx.tcx.generator_kind(def_id),
+                        Some(hir::GeneratorKind::Async(..))
+                    ) {
+                        let def_id = cx.tcx.lang_items().future_trait().unwrap();
+                        is_def_must_use(cx, def_id, span)
+                            .map(|inner| MustUsePath::Opaque(Box::new(inner)))
+                    } else {
+                        None
+                    };
+                    must_use.or(Some(MustUsePath::Generator(span)))
+                }
                 _ => None,
             }
         }
index 1890c0e24bb4419c1ec17750293b75764b4a0167..536d2872bf084af6660ffa4cc410aa0bab2831af 100644 (file)
@@ -660,6 +660,9 @@ pub enum ImplSource<'tcx, N> {
     /// ImplSource automatically generated for a generator.
     Generator(ImplSourceGeneratorData<'tcx, N>),
 
+    /// ImplSource automatically generated for a generator backing an async future.
+    Future(ImplSourceFutureData<'tcx, N>),
+
     /// ImplSource for a trait alias.
     TraitAlias(ImplSourceTraitAliasData<'tcx, N>),
 
@@ -676,6 +679,7 @@ pub fn nested_obligations(self) -> Vec<N> {
             ImplSource::AutoImpl(d) => d.nested,
             ImplSource::Closure(c) => c.nested,
             ImplSource::Generator(c) => c.nested,
+            ImplSource::Future(c) => c.nested,
             ImplSource::Object(d) => d.nested,
             ImplSource::FnPointer(d) => d.nested,
             ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
@@ -694,6 +698,7 @@ pub fn borrow_nested_obligations(&self) -> &[N] {
             ImplSource::AutoImpl(d) => &d.nested,
             ImplSource::Closure(c) => &c.nested,
             ImplSource::Generator(c) => &c.nested,
+            ImplSource::Future(c) => &c.nested,
             ImplSource::Object(d) => &d.nested,
             ImplSource::FnPointer(d) => &d.nested,
             ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
@@ -737,6 +742,11 @@ pub fn map<M, F>(self, f: F) -> ImplSource<'tcx, M>
                 substs: c.substs,
                 nested: c.nested.into_iter().map(f).collect(),
             }),
+            ImplSource::Future(c) => ImplSource::Future(ImplSourceFutureData {
+                generator_def_id: c.generator_def_id,
+                substs: c.substs,
+                nested: c.nested.into_iter().map(f).collect(),
+            }),
             ImplSource::FnPointer(p) => ImplSource::FnPointer(ImplSourceFnPointerData {
                 fn_ty: p.fn_ty,
                 nested: p.nested.into_iter().map(f).collect(),
@@ -796,6 +806,16 @@ pub struct ImplSourceGeneratorData<'tcx, N> {
     pub nested: Vec<N>,
 }
 
+#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
+#[derive(TypeFoldable, TypeVisitable)]
+pub struct ImplSourceFutureData<'tcx, N> {
+    pub generator_def_id: DefId,
+    pub substs: SubstsRef<'tcx>,
+    /// Nested obligations. This can be non-empty if the generator
+    /// signature contains associated types.
+    pub nested: Vec<N>,
+}
+
 #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
 #[derive(TypeFoldable, TypeVisitable)]
 pub struct ImplSourceClosureData<'tcx, N> {
index 85ead3171e785fca3148a741506b37092df176ae..99bfa477f74e895112586e7787f31625531599d3 100644 (file)
@@ -131,6 +131,10 @@ pub enum SelectionCandidate<'tcx> {
     /// generated for a generator.
     GeneratorCandidate,
 
+    /// Implementation of a `Future` trait by one of the generator types
+    /// generated for an async construct.
+    FutureCandidate,
+
     /// Implementation of a `Fn`-family trait by one of the anonymous
     /// types generated for a fn pointer type (e.g., `fn(int) -> int`)
     FnPointerCandidate {
index 7fbd57ac7354aa2691dfec008de1a25618e355ea..735cece83997a999723f8aafa0084fbe456ce5b7 100644 (file)
@@ -15,6 +15,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
             super::ImplSource::Generator(ref d) => write!(f, "{:?}", d),
 
+            super::ImplSource::Future(ref d) => write!(f, "{:?}", d),
+
             super::ImplSource::FnPointer(ref d) => write!(f, "({:?})", d),
 
             super::ImplSource::DiscriminantKind(ref d) => write!(f, "{:?}", d),
@@ -58,6 +60,16 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
+impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceFutureData<'tcx, N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "ImplSourceFutureData(generator_def_id={:?}, substs={:?}, nested={:?})",
+            self.generator_def_id, self.substs, self.nested
+        )
+    }
+}
+
 impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceClosureData<'tcx, N> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(
index bddcdd0b693caf367e739a5482b1f68e1ddecc34..c54edf10c2d8f79a5af9ed271c7e8f9a0b7db5ab 100644 (file)
@@ -681,6 +681,17 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
             }
             ty::Str => p!("str"),
             ty::Generator(did, substs, movability) => {
+                // FIXME(swatinem): async constructs used to be pretty printed
+                // as `impl Future` previously due to the `from_generator` wrapping.
+                // lets special case this here for now to avoid churn in diagnostics.
+                let generator_kind = self.tcx().generator_kind(did);
+                if matches!(generator_kind, Some(hir::GeneratorKind::Async(..))) {
+                    let return_ty = substs.as_generator().return_ty();
+                    p!(write("impl Future<Output = {}>", return_ty));
+
+                    return Ok(self);
+                }
+
                 p!(write("["));
                 match movability {
                     hir::Movability::Movable => {}
index fcd63b6cfa17843bdb91f87b838d5c5c1eefadf4..ffe4d43bc88e88970ddf6d36aa24ccda53f7f4f6 100644 (file)
 //! generator in the MIR, since it is used to create the drop glue for the generator. We'd get
 //! infinite recursion otherwise.
 //!
-//! This pass creates the implementation for the Generator::resume function and the drop shim
-//! for the generator based on the MIR input. It converts the generator argument from Self to
-//! &mut Self adding derefs in the MIR as needed. It computes the final layout of the generator
-//! struct which looks like this:
+//! This pass creates the implementation for either the `Generator::resume` or `Future::poll`
+//! function and the drop shim for the generator based on the MIR input.
+//! It converts the generator argument from Self to &mut Self adding derefs in the MIR as needed.
+//! It computes the final layout of the generator struct which looks like this:
 //!     First upvars are stored
 //!     It is followed by the generator state field.
 //!     Then finally the MIR locals which are live across a suspension point are stored.
 //!     2 - Generator has been poisoned
 //!
 //! It also rewrites `return x` and `yield y` as setting a new generator state and returning
-//! GeneratorState::Complete(x) and GeneratorState::Yielded(y) respectively.
+//! `GeneratorState::Complete(x)` and `GeneratorState::Yielded(y)`,
+//! or `Poll::Ready(x)` and `Poll::Pending` respectively.
 //! MIR locals which are live across a suspension point are moved to the generator struct
 //! with references to them being updated with references to the generator struct.
 //!
 //! The pass creates two functions which have a switch on the generator state giving
 //! the action to take.
 //!
-//! One of them is the implementation of Generator::resume.
+//! One of them is the implementation of `Generator::resume` / `Future::poll`.
 //! For generators with state 0 (unresumed) it starts the execution of the generator.
 //! For generators with state 1 (returned) and state 2 (poisoned) it panics.
 //! Otherwise it continues the execution from the last suspension point.
@@ -56,6 +57,7 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
+use rustc_hir::GeneratorKind;
 use rustc_index::bit_set::{BitMatrix, BitSet, GrowableBitSet};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::mir::dump_mir;
@@ -215,6 +217,7 @@ struct SuspensionPoint<'tcx> {
 
 struct TransformVisitor<'tcx> {
     tcx: TyCtxt<'tcx>,
+    is_async_kind: bool,
     state_adt_ref: AdtDef<'tcx>,
     state_substs: SubstsRef<'tcx>,
 
@@ -239,28 +242,57 @@ struct TransformVisitor<'tcx> {
 }
 
 impl<'tcx> TransformVisitor<'tcx> {
-    // Make a GeneratorState variant assignment. `core::ops::GeneratorState` only has single
-    // element tuple variants, so we can just write to the downcasted first field and then set the
+    // Make a `GeneratorState` or `Poll` variant assignment.
+    //
+    // `core::ops::GeneratorState` only has single element tuple variants,
+    // so we can just write to the downcasted first field and then set the
     // discriminant to the appropriate variant.
     fn make_state(
         &self,
-        idx: VariantIdx,
         val: Operand<'tcx>,
         source_info: SourceInfo,
-    ) -> impl Iterator<Item = Statement<'tcx>> {
+        is_return: bool,
+        statements: &mut Vec<Statement<'tcx>>,
+    ) {
+        let idx = VariantIdx::new(match (is_return, self.is_async_kind) {
+            (true, false) => 1,  // GeneratorState::Complete
+            (false, false) => 0, // GeneratorState::Yielded
+            (true, true) => 0,   // Poll::Ready
+            (false, true) => 1,  // Poll::Pending
+        });
+
         let kind = AggregateKind::Adt(self.state_adt_ref.did(), idx, self.state_substs, None, None);
+
+        // `Poll::Pending`
+        if self.is_async_kind && idx == VariantIdx::new(1) {
+            assert_eq!(self.state_adt_ref.variant(idx).fields.len(), 0);
+
+            // FIXME(swatinem): assert that `val` is indeed unit?
+            statements.extend(expand_aggregate(
+                Place::return_place(),
+                std::iter::empty(),
+                kind,
+                source_info,
+                self.tcx,
+            ));
+            return;
+        }
+
+        // else: `Poll::Ready(x)`, `GeneratorState::Yielded(x)` or `GeneratorState::Complete(x)`
         assert_eq!(self.state_adt_ref.variant(idx).fields.len(), 1);
+
         let ty = self
             .tcx
             .bound_type_of(self.state_adt_ref.variant(idx).fields[0].did)
             .subst(self.tcx, self.state_substs);
-        expand_aggregate(
+
+        statements.extend(expand_aggregate(
             Place::return_place(),
             std::iter::once((val, ty)),
             kind,
             source_info,
             self.tcx,
-        )
+        ));
     }
 
     // Create a Place referencing a generator struct field
@@ -331,22 +363,19 @@ fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockDat
         });
 
         let ret_val = match data.terminator().kind {
-            TerminatorKind::Return => Some((
-                VariantIdx::new(1),
-                None,
-                Operand::Move(Place::from(self.new_ret_local)),
-                None,
-            )),
+            TerminatorKind::Return => {
+                Some((true, None, Operand::Move(Place::from(self.new_ret_local)), None))
+            }
             TerminatorKind::Yield { ref value, resume, resume_arg, drop } => {
-                Some((VariantIdx::new(0), Some((resume, resume_arg)), value.clone(), drop))
+                Some((false, Some((resume, resume_arg)), value.clone(), drop))
             }
             _ => None,
         };
 
-        if let Some((state_idx, resume, v, drop)) = ret_val {
+        if let Some((is_return, resume, v, drop)) = ret_val {
             let source_info = data.terminator().source_info;
             // We must assign the value first in case it gets declared dead below
-            data.statements.extend(self.make_state(state_idx, v, source_info));
+            self.make_state(v, source_info, is_return, &mut data.statements);
             let state = if let Some((resume, mut resume_arg)) = resume {
                 // Yield
                 let state = RESERVED_VARIANTS + self.suspension_points.len();
@@ -1268,10 +1297,20 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             }
         };
 
-        // Compute GeneratorState<yield_ty, return_ty>
-        let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
-        let state_adt_ref = tcx.adt_def(state_did);
-        let state_substs = tcx.intern_substs(&[yield_ty.into(), body.return_ty().into()]);
+        let is_async_kind = body.generator_kind().unwrap() != GeneratorKind::Gen;
+        let (state_adt_ref, state_substs) = if is_async_kind {
+            // Compute Poll<return_ty>
+            let state_did = tcx.require_lang_item(LangItem::Poll, None);
+            let state_adt_ref = tcx.adt_def(state_did);
+            let state_substs = tcx.intern_substs(&[body.return_ty().into()]);
+            (state_adt_ref, state_substs)
+        } else {
+            // Compute GeneratorState<yield_ty, return_ty>
+            let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
+            let state_adt_ref = tcx.adt_def(state_did);
+            let state_substs = tcx.intern_substs(&[yield_ty.into(), body.return_ty().into()]);
+            (state_adt_ref, state_substs)
+        };
         let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
 
         // We rename RETURN_PLACE which has type mir.return_ty to new_ret_local
@@ -1327,9 +1366,11 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // Run the transformation which converts Places from Local to generator struct
         // accesses for locals in `remap`.
         // It also rewrites `return x` and `yield y` as writing a new generator state and returning
-        // GeneratorState::Complete(x) and GeneratorState::Yielded(y) respectively.
+        // either GeneratorState::Complete(x) and GeneratorState::Yielded(y),
+        // or Poll::Ready(x) and Poll::Pending respectively depending on `is_async_kind`.
         let mut transform = TransformVisitor {
             tcx,
+            is_async_kind,
             state_adt_ref,
             state_substs,
             remap,
@@ -1367,7 +1408,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 
         body.generator.as_mut().unwrap().generator_drop = Some(drop_shim);
 
-        // Create the Generator::resume function
+        // Create the Generator::resume / Future::poll function
         create_generator_resume_function(tcx, transform, body, can_return);
 
         // Run derefer to fix Derefs that are not in the first place
index 5072d2aad1669ff99e10c879563db2606aa237a8..2cc3e410d206f4e4969847344d6a1630f16c8a9b 100644 (file)
@@ -3912,7 +3912,7 @@ fn resolve_expr(&mut self, expr: &'ast Expr, parent: Option<&'ast Expr>) {
                 visit::walk_expr(self, expr);
                 self.diagnostic_metadata.current_type_ascription.pop();
             }
-            // `async |x| ...` gets desugared to `|x| future_from_generator(|| ...)`, so we need to
+            // `async |x| ...` gets desugared to `|x| async {...}`, so we need to
             // resolve the arguments within the proper scopes so that usages of them inside the
             // closure are detected as upvars rather than normal closure arg usages.
             ExprKind::Closure(box ast::Closure {
index 29312a21b4d464f8af5e6c407d27f133727b6fe5..aba301dce10989ee8dd52c090066809f5db79f65 100644 (file)
         Relaxed,
         Release,
         Result,
+        ResumeTy,
         Return,
         Right,
         Rust,
         frem_fast,
         from,
         from_desugaring,
-        from_generator,
         from_iter,
         from_method,
         from_output,
         i64,
         i8,
         ident,
+        identity_future,
         if_let,
         if_let_guard,
         if_while_or_patterns,
index bb6d7d0e8dff181a1f0586a2413bdb68b7e42aaf..30207033236c5314628a92ab01e09c5f04b715e4 100644 (file)
@@ -1885,13 +1885,9 @@ fn maybe_note_obligation_cause_for_async_await(
         //
         // - `BuiltinDerivedObligation` with a generator witness (B)
         // - `BuiltinDerivedObligation` with a generator (B)
-        // - `BuiltinDerivedObligation` with `std::future::GenFuture` (B)
-        // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
         // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
         // - `BuiltinDerivedObligation` with a generator witness (A)
         // - `BuiltinDerivedObligation` with a generator (A)
-        // - `BuiltinDerivedObligation` with `std::future::GenFuture` (A)
-        // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
         // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
         // - `BindingObligation` with `impl_send (Send requirement)
         //
@@ -2624,30 +2620,24 @@ fn note_obligation_cause_code<T>(
                     }
                 };
 
-                let from_generator = tcx.require_lang_item(LangItem::FromGenerator, None);
+                let identity_future = tcx.require_lang_item(LangItem::IdentityFuture, None);
 
                 // Don't print the tuple of capture types
                 'print: {
                     if !is_upvar_tys_infer_tuple {
                         let msg = format!("required because it appears within the type `{}`", ty);
                         match ty.kind() {
-                            ty::Adt(def, _) => {
-                                // `gen_future` is used in all async functions; it doesn't add any additional info.
-                                if self.tcx.is_diagnostic_item(sym::gen_future, def.did()) {
-                                    break 'print;
-                                }
-                                match self.tcx.opt_item_ident(def.did()) {
-                                    Some(ident) => err.span_note(ident.span, &msg),
-                                    None => err.note(&msg),
-                                }
-                            }
+                            ty::Adt(def, _) => match self.tcx.opt_item_ident(def.did()) {
+                                Some(ident) => err.span_note(ident.span, &msg),
+                                None => err.note(&msg),
+                            },
                             ty::Opaque(def_id, _) => {
-                                // Avoid printing the future from `core::future::from_generator`, it's not helpful
-                                if tcx.parent(*def_id) == from_generator {
+                                // Avoid printing the future from `core::future::identity_future`, it's not helpful
+                                if tcx.parent(*def_id) == identity_future {
                                     break 'print;
                                 }
 
-                                // If the previous type is `from_generator`, this is the future generated by the body of an async function.
+                                // If the previous type is `identity_future`, this is the future generated by the body of an async function.
                                 // Avoid printing it twice (it was already printed in the `ty::Generator` arm below).
                                 let is_future = tcx.ty_is_opaque_future(ty);
                                 debug!(
@@ -2657,8 +2647,11 @@ fn note_obligation_cause_code<T>(
                                 );
                                 if is_future
                                     && obligated_types.last().map_or(false, |ty| match ty.kind() {
-                                        ty::Opaque(last_def_id, _) => {
-                                            tcx.parent(*last_def_id) == from_generator
+                                        ty::Generator(last_def_id, ..) => {
+                                            matches!(
+                                                tcx.generator_kind(last_def_id),
+                                                Some(GeneratorKind::Async(..))
+                                            )
                                         }
                                         _ => false,
                                     })
index 7b2329b1ddd60e3aaa3e28f0d017d59cb539fc0e..f17d702d421bd4e0e39da696c10aed09c00d8d8f 100644 (file)
@@ -12,7 +12,8 @@
 use super::SelectionError;
 use super::{
     ImplSourceClosureData, ImplSourceDiscriminantKindData, ImplSourceFnPointerData,
-    ImplSourceGeneratorData, ImplSourcePointeeData, ImplSourceUserDefinedData,
+    ImplSourceFutureData, ImplSourceGeneratorData, ImplSourcePointeeData,
+    ImplSourceUserDefinedData,
 };
 use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey};
 
@@ -1544,6 +1545,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
         let eligible = match &impl_source {
             super::ImplSource::Closure(_)
             | super::ImplSource::Generator(_)
+            | super::ImplSource::Future(_)
             | super::ImplSource::FnPointer(_)
             | super::ImplSource::TraitAlias(_) => true,
             super::ImplSource::UserDefined(impl_data) => {
@@ -1832,6 +1834,7 @@ fn confirm_select_candidate<'cx, 'tcx>(
     match impl_source {
         super::ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data),
         super::ImplSource::Generator(data) => confirm_generator_candidate(selcx, obligation, data),
+        super::ImplSource::Future(data) => confirm_future_candidate(selcx, obligation, data),
         super::ImplSource::Closure(data) => confirm_closure_candidate(selcx, obligation, data),
         super::ImplSource::FnPointer(data) => confirm_fn_pointer_candidate(selcx, obligation, data),
         super::ImplSource::DiscriminantKind(data) => {
@@ -1905,6 +1908,48 @@ fn confirm_generator_candidate<'cx, 'tcx>(
         .with_addl_obligations(obligations)
 }
 
+fn confirm_future_candidate<'cx, 'tcx>(
+    selcx: &mut SelectionContext<'cx, 'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    impl_source: ImplSourceFutureData<'tcx, PredicateObligation<'tcx>>,
+) -> Progress<'tcx> {
+    let gen_sig = impl_source.substs.as_generator().poly_sig();
+    let Normalized { value: gen_sig, obligations } = normalize_with_depth(
+        selcx,
+        obligation.param_env,
+        obligation.cause.clone(),
+        obligation.recursion_depth + 1,
+        gen_sig,
+    );
+
+    debug!(?obligation, ?gen_sig, ?obligations, "confirm_future_candidate");
+
+    let tcx = selcx.tcx();
+    let fut_def_id = tcx.require_lang_item(LangItem::Future, None);
+
+    let predicate = super::util::future_trait_ref_and_outputs(
+        tcx,
+        fut_def_id,
+        obligation.predicate.self_ty(),
+        gen_sig,
+    )
+    .map_bound(|(trait_ref, return_ty)| {
+        debug_assert_eq!(tcx.associated_item(obligation.predicate.item_def_id).name, sym::Output);
+
+        ty::ProjectionPredicate {
+            projection_ty: ty::ProjectionTy {
+                substs: trait_ref.substs,
+                item_def_id: obligation.predicate.item_def_id,
+            },
+            term: return_ty.into(),
+        }
+    });
+
+    confirm_param_env_candidate(selcx, obligation, predicate, false)
+        .with_addl_obligations(impl_source.nested)
+        .with_addl_obligations(obligations)
+}
+
 fn confirm_discriminant_kind_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
index 3b107d9570f149fbe53f77aa3b8ec7c37f9d81d1..617dbe240e94a19dde6c5a115acbcc6f783e8913 100644 (file)
@@ -314,7 +314,12 @@ pub(super) fn assemble_candidates<'o>(
                     self.assemble_builtin_bound_candidates(clone_conditions, &mut candidates);
                 }
 
-                self.assemble_generator_candidates(obligation, &mut candidates);
+                if lang_items.gen_trait() == Some(def_id) {
+                    self.assemble_generator_candidates(obligation, &mut candidates);
+                } else if lang_items.future_trait() == Some(def_id) {
+                    self.assemble_future_candidates(obligation, &mut candidates);
+                }
+
                 self.assemble_closure_candidates(obligation, &mut candidates);
                 self.assemble_fn_pointer_candidates(obligation, &mut candidates);
                 self.assemble_candidates_from_impls(obligation, &mut candidates);
@@ -402,10 +407,6 @@ fn assemble_generator_candidates(
         obligation: &TraitObligation<'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
-        if self.tcx().lang_items().gen_trait() != Some(obligation.predicate.def_id()) {
-            return;
-        }
-
         // Okay to skip binder because the substs on generator types never
         // touch bound regions, they just capture the in-scope
         // type/region parameters.
@@ -424,6 +425,23 @@ fn assemble_generator_candidates(
         }
     }
 
+    fn assemble_future_candidates(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) {
+        let self_ty = obligation.self_ty().skip_binder();
+        if let ty::Generator(did, ..) = self_ty.kind() {
+            if let Some(rustc_hir::GeneratorKind::Async(_generator_kind)) =
+                self.tcx().generator_kind(did)
+            {
+                debug!(?self_ty, ?obligation, "assemble_future_candidates",);
+
+                candidates.vec.push(FutureCandidate);
+            }
+        }
+    }
+
     /// Checks for the artificial impl that the compiler will create for an obligation like `X :
     /// FnMut<..>` where `X` is a closure type.
     ///
index 2ec5d925b6900af0959b518f8379ffdd30659224..4a90d8baf9e4454063f7cfe9007180e7b4abe07f 100644 (file)
     BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource,
     ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData,
     ImplSourceConstDestructData, ImplSourceDiscriminantKindData, ImplSourceFnPointerData,
-    ImplSourceGeneratorData, ImplSourceObjectData, ImplSourcePointeeData, ImplSourceTraitAliasData,
-    ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, ObjectCastObligation,
-    Obligation, ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection,
-    SelectionError, TraitNotObjectSafe, TraitObligation, Unimplemented, VtblSegment,
+    ImplSourceFutureData, ImplSourceGeneratorData, ImplSourceObjectData, ImplSourcePointeeData,
+    ImplSourceTraitAliasData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized,
+    ObjectCastObligation, Obligation, ObligationCause, OutputTypeParameterMismatch,
+    PredicateObligation, Selection, SelectionError, TraitNotObjectSafe, TraitObligation,
+    Unimplemented, VtblSegment,
 };
 
 use super::BuiltinImplConditions;
@@ -89,6 +90,11 @@ pub(super) fn confirm_candidate(
                 ImplSource::Generator(vtable_generator)
             }
 
+            FutureCandidate => {
+                let vtable_future = self.confirm_future_candidate(obligation)?;
+                ImplSource::Future(vtable_future)
+            }
+
             FnPointerCandidate { .. } => {
                 let data = self.confirm_fn_pointer_candidate(obligation)?;
                 ImplSource::FnPointer(data)
@@ -685,7 +691,21 @@ fn confirm_generator_candidate(
 
         debug!(?obligation, ?generator_def_id, ?substs, "confirm_generator_candidate");
 
-        let trait_ref = self.generator_trait_ref_unnormalized(obligation, substs);
+        let gen_sig = substs.as_generator().poly_sig();
+
+        // (1) Feels icky to skip the binder here, but OTOH we know
+        // that the self-type is an generator type and hence is
+        // in fact unparameterized (or at least does not reference any
+        // regions bound in the obligation). Still probably some
+        // refactoring could make this nicer.
+
+        let trait_ref = super::util::generator_trait_ref_and_outputs(
+            self.tcx(),
+            obligation.predicate.def_id(),
+            obligation.predicate.skip_binder().self_ty(), // (1)
+            gen_sig,
+        )
+        .map_bound(|(trait_ref, ..)| trait_ref);
 
         let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
         debug!(?trait_ref, ?nested, "generator candidate obligations");
@@ -693,6 +713,36 @@ fn confirm_generator_candidate(
         Ok(ImplSourceGeneratorData { generator_def_id, substs, nested })
     }
 
+    fn confirm_future_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+    ) -> Result<ImplSourceFutureData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+        // Okay to skip binder because the substs on generator types never
+        // touch bound regions, they just capture the in-scope
+        // type/region parameters.
+        let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
+        let ty::Generator(generator_def_id, substs, _) = *self_ty.kind() else {
+            bug!("closure candidate for non-closure {:?}", obligation);
+        };
+
+        debug!(?obligation, ?generator_def_id, ?substs, "confirm_future_candidate");
+
+        let gen_sig = substs.as_generator().poly_sig();
+
+        let trait_ref = super::util::future_trait_ref_and_outputs(
+            self.tcx(),
+            obligation.predicate.def_id(),
+            obligation.predicate.no_bound_vars().expect("future has no bound vars").self_ty(),
+            gen_sig,
+        )
+        .map_bound(|(trait_ref, ..)| trait_ref);
+
+        let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
+        debug!(?trait_ref, ?nested, "future candidate obligations");
+
+        Ok(ImplSourceFutureData { generator_def_id, substs, nested })
+    }
+
     #[instrument(skip(self), level = "debug")]
     fn confirm_closure_candidate(
         &mut self,
index 2803a2d38c807b97143273d8b24f59d5acbe138f..9fe13fe296a16fcee2ced1992bd17128f8ab106f 100644 (file)
@@ -1139,9 +1139,10 @@ fn filter_impls(
                     ProjectionCandidate(_, ty::BoundConstness::ConstIfConst) => {}
                     // auto trait impl
                     AutoImplCandidate => {}
-                    // generator, this will raise error in other places
+                    // generator / future, this will raise error in other places
                     // or ignore error with const_async_blocks feature
                     GeneratorCandidate => {}
+                    FutureCandidate => {}
                     // FnDef where the function is const
                     FnPointerCandidate { is_const: true } => {}
                     ConstDestructCandidate(_) => {}
@@ -1620,6 +1621,7 @@ fn candidate_should_be_dropped_in_favor_of(
                 ImplCandidate(..)
                 | ClosureCandidate
                 | GeneratorCandidate
+                | FutureCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
                 | BuiltinUnsizeCandidate
@@ -1638,6 +1640,7 @@ fn candidate_should_be_dropped_in_favor_of(
                 ImplCandidate(_)
                 | ClosureCandidate
                 | GeneratorCandidate
+                | FutureCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
                 | BuiltinUnsizeCandidate
@@ -1668,6 +1671,7 @@ fn candidate_should_be_dropped_in_favor_of(
                 ImplCandidate(..)
                 | ClosureCandidate
                 | GeneratorCandidate
+                | FutureCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
                 | BuiltinUnsizeCandidate
@@ -1680,6 +1684,7 @@ fn candidate_should_be_dropped_in_favor_of(
                 ImplCandidate(..)
                 | ClosureCandidate
                 | GeneratorCandidate
+                | FutureCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
                 | BuiltinUnsizeCandidate
@@ -1761,6 +1766,7 @@ fn candidate_should_be_dropped_in_favor_of(
                 ImplCandidate(_)
                 | ClosureCandidate
                 | GeneratorCandidate
+                | FutureCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
                 | BuiltinUnsizeCandidate
@@ -1770,6 +1776,7 @@ fn candidate_should_be_dropped_in_favor_of(
                 ImplCandidate(_)
                 | ClosureCandidate
                 | GeneratorCandidate
+                | FutureCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
                 | BuiltinUnsizeCandidate
@@ -2279,28 +2286,6 @@ fn closure_trait_ref_unnormalized(
         .map_bound(|(trait_ref, _)| trait_ref)
     }
 
-    fn generator_trait_ref_unnormalized(
-        &mut self,
-        obligation: &TraitObligation<'tcx>,
-        substs: SubstsRef<'tcx>,
-    ) -> ty::PolyTraitRef<'tcx> {
-        let gen_sig = substs.as_generator().poly_sig();
-
-        // (1) Feels icky to skip the binder here, but OTOH we know
-        // that the self-type is an generator type and hence is
-        // in fact unparameterized (or at least does not reference any
-        // regions bound in the obligation). Still probably some
-        // refactoring could make this nicer.
-
-        super::util::generator_trait_ref_and_outputs(
-            self.tcx(),
-            obligation.predicate.def_id(),
-            obligation.predicate.skip_binder().self_ty(), // (1)
-            gen_sig,
-        )
-        .map_bound(|(trait_ref, ..)| trait_ref)
-    }
-
     /// Returns the obligations that are implied by instantiating an
     /// impl or trait. The obligations are substituted and fully
     /// normalized. This is used when confirming an impl or default
index 895b84fd7e9dfe3095d28f9356531ec0c5f0339d..20d8a7a742c3a1487e3616b163fbe9ebdaa88773 100644 (file)
@@ -318,6 +318,17 @@ pub fn generator_trait_ref_and_outputs<'tcx>(
     sig.map_bound(|sig| (trait_ref, sig.yield_ty, sig.return_ty))
 }
 
+pub fn future_trait_ref_and_outputs<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    fn_trait_def_id: DefId,
+    self_ty: Ty<'tcx>,
+    sig: ty::PolyGenSig<'tcx>,
+) -> ty::Binder<'tcx, (ty::TraitRef<'tcx>, Ty<'tcx>)> {
+    debug_assert!(!self_ty.has_escaping_bound_vars());
+    let trait_ref = tcx.mk_trait_ref(fn_trait_def_id, [self_ty]);
+    sig.map_bound(|sig| (trait_ref, sig.return_ty))
+}
+
 pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool {
     assoc_item.defaultness(tcx).is_final()
         && tcx.impl_defaultness(assoc_item.container_id(tcx)).is_final()
index ee013515e86c410b9a4f19597e8bc0921ee73a52..9931a7f32ef7711fbaa45a26640b77113ee27816 100644 (file)
@@ -413,7 +413,11 @@ fn lower_into(self, interner: RustInterner<'tcx>) -> Ty<'tcx> {
             TyKind::Closure(closure, substitution) => {
                 ty::Closure(closure.0, substitution.lower_into(interner))
             }
-            TyKind::Generator(..) => unimplemented!(),
+            TyKind::Generator(generator, substitution) => ty::Generator(
+                generator.0,
+                substitution.lower_into(interner),
+                ast::Movability::Static,
+            ),
             TyKind::GeneratorWitness(..) => unimplemented!(),
             TyKind::Never => ty::Never,
             TyKind::Tuple(_len, substitution) => {
index 6436713b3881154043bf4288158472c3a2d28df5..7f16b2d35e800a680abe223441597f9168f80c2c 100644 (file)
@@ -202,6 +202,12 @@ fn resolve_associated_item<'tcx>(
             )),
             substs: generator_data.substs,
         }),
+        traits::ImplSource::Future(future_data) => Some(Instance {
+            def: ty::InstanceDef::Item(ty::WithOptConstParam::unknown(
+                future_data.generator_def_id,
+            )),
+            substs: future_data.substs,
+        }),
         traits::ImplSource::Closure(closure_data) => {
             let trait_closure_kind = tcx.fn_trait_kind_from_lang_item(trait_id).unwrap();
             Instance::resolve_closure(
index 107cf92c1c0f7c9bb515051591665807010221c1..f2b961d62e00c8149750785c3792cdf94924ce1d 100644 (file)
@@ -9,12 +9,8 @@
 //! [`await`]: ../../std/keyword.await.html
 //! [async book]: https://rust-lang.github.io/async-book/
 
-use crate::{
-    ops::{Generator, GeneratorState},
-    pin::Pin,
-    ptr::NonNull,
-    task::{Context, Poll},
-};
+use crate::ptr::NonNull;
+use crate::task::Context;
 
 mod future;
 mod into_future;
@@ -48,6 +44,7 @@
 ///    non-Send/Sync as well, and we don't want that.
 ///
 /// It also simplifies the HIR lowering of `.await`.
+#[cfg_attr(not(bootstrap), lang = "ResumeTy")]
 #[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
 #[derive(Debug, Copy, Clone)]
@@ -64,15 +61,21 @@ unsafe impl Sync for ResumeTy {}
 /// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
 /// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
 // This is `const` to avoid extra errors after we recover from `const async fn`
-#[lang = "from_generator"]
+#[cfg_attr(bootstrap, lang = "from_generator")]
 #[doc(hidden)]
 #[unstable(feature = "gen_future", issue = "50547")]
 #[rustc_const_unstable(feature = "gen_future", issue = "50547")]
 #[inline]
 pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
 where
-    T: Generator<ResumeTy, Yield = ()>,
+    T: crate::ops::Generator<ResumeTy, Yield = ()>,
 {
+    use crate::{
+        ops::{Generator, GeneratorState},
+        pin::Pin,
+        task::Poll,
+    };
+
     #[rustc_diagnostic_item = "gen_future"]
     struct GenFuture<T: Generator<ResumeTy, Yield = ()>>(T);
 
@@ -109,3 +112,11 @@ pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> {
     // that fulfills all the requirements for a mutable reference.
     unsafe { &mut *cx.0.as_ptr().cast() }
 }
+
+#[cfg_attr(not(bootstrap), lang = "identity_future")]
+#[doc(hidden)]
+#[unstable(feature = "gen_future", issue = "50547")]
+#[inline]
+pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
+    f
+}
index 41f0a25dbc3e08daa688c5b6202ba987d468765a..f1dc4f7b575aaeb03deaaa41ace566fdbb0ec36e 100644 (file)
@@ -9,6 +9,7 @@
 /// scheduled to receive a wakeup instead.
 #[must_use = "this `Poll` may be a `Pending` variant, which should be handled"]
 #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
+#[cfg_attr(not(bootstrap), lang = "Poll")]
 #[stable(feature = "futures_api", since = "1.36.0")]
 pub enum Poll<T> {
     /// Represents that a value is immediately ready.
index 909cd0062a623050a02e6fcb98695e60295fc013..bc2686158140106026ca75b7895d0ce2e644c709 100644 (file)
@@ -11,12 +11,14 @@ async fn async_fn_test() {
     foo().await;
 }
 
-// NONMSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}",
+// NONMSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}", scope: [[GEN_SCOPE:![0-9]*]],
 // MSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<async_fn_debug_awaitee_field::async_fn_test::async_fn_env$0>",
+// NONMSVC: [[GEN_SCOPE:!.*]] = !DINamespace(name: "async_fn_test",
 // CHECK: [[SUSPEND_STRUCT:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend0", scope: [[GEN]],
 // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__awaitee", scope: [[SUSPEND_STRUCT]], {{.*}}, baseType: [[AWAITEE_TYPE:![0-9]*]],
-// NONMSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "GenFuture<async_fn_debug_awaitee_field::foo::{async_fn_env#0}>",
-// MSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "GenFuture<enum2$<async_fn_debug_awaitee_field::foo::async_fn_env$0> >",
+// NONMSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}", scope: [[AWAITEE_SCOPE:![0-9]*]],
+// MSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$<async_fn_debug_awaitee_field::foo::async_fn_env$0>",
+// NONMSVC: [[AWAITEE_SCOPE]] = !DINamespace(name: "foo",
 
 fn main() {
     let _fn = async_fn_test();
index dc06a485a8fc124bd26a7779b81c9bd0ebd1dbef..500dde1f2698ae7d5870f308b19bb8eb75fe9a60 100644 (file)
@@ -72,7 +72,7 @@
    67|       |        }
    68|      2|    }
   ------------------
-  | async2::executor::block_on::<core::future::from_generator::GenFuture<async2::async_func::{closure#0}>>:
+  | async2::executor::block_on::<async2::async_func::{closure#0}>:
   |   51|      1|    pub fn block_on<F: Future>(mut future: F) -> F::Output {
   |   52|      1|        let mut future = unsafe { Pin::new_unchecked(&mut future) };
   |   53|      1|        use std::hint::unreachable_unchecked;
@@ -92,7 +92,7 @@
   |   67|       |        }
   |   68|      1|    }
   ------------------
-  | async2::executor::block_on::<core::future::from_generator::GenFuture<async2::async_func_just_println::{closure#0}>>:
+  | async2::executor::block_on::<async2::async_func_just_println::{closure#0}>:
   |   51|      1|    pub fn block_on<F: Future>(mut future: F) -> F::Output {
   |   52|      1|        let mut future = unsafe { Pin::new_unchecked(&mut future) };
   |   53|      1|        use std::hint::unreachable_unchecked;
index 2a08d5d6ce5f8305aa24a50bb95f9445e7d00701..b8ca64fae831948c51f4ae38810f29034e639205 100644 (file)
@@ -1,8 +1,7 @@
 error[E0267]: `break` inside of an `async` block
   --> $DIR/async-block-control-flow-static-semantics.rs:32:9
    |
-LL |       async {
-   |  ___________-
+LL | /     async {
 LL | |         break 0u8;
    | |         ^^^^^^^^^ cannot `break` inside of an `async` block
 LL | |     };
@@ -11,8 +10,7 @@ LL | |     };
 error[E0267]: `break` inside of an `async` block
   --> $DIR/async-block-control-flow-static-semantics.rs:39:13
    |
-LL |           async {
-   |  _______________-
+LL | /         async {
 LL | |             break 0u8;
    | |             ^^^^^^^^^ cannot `break` inside of an `async` block
 LL | |         };
index f21c811512416a34728af743624f6563dfe7def1..190c59e32ebbbc9dfe69c7e133daec6559eb48b8 100644 (file)
@@ -1,11 +1,11 @@
 error[E0373]: async block may outlive the current function, but it borrows `x`, which is owned by the current function
-  --> $DIR/async-borrowck-escaping-block-error.rs:6:20
+  --> $DIR/async-borrowck-escaping-block-error.rs:6:14
    |
 LL |     Box::new(async { x } )
-   |                    ^^-^^
-   |                    | |
-   |                    | `x` is borrowed here
-   |                    may outlive borrowed value `x`
+   |              ^^^^^^^^-^^
+   |              |       |
+   |              |       `x` is borrowed here
+   |              may outlive borrowed value `x`
    |
 note: async block is returned here
   --> $DIR/async-borrowck-escaping-block-error.rs:6:5
@@ -18,13 +18,13 @@ LL |     Box::new(async move { x } )
    |                    ++++
 
 error[E0373]: async block may outlive the current function, but it borrows `x`, which is owned by the current function
-  --> $DIR/async-borrowck-escaping-block-error.rs:11:11
+  --> $DIR/async-borrowck-escaping-block-error.rs:11:5
    |
 LL |     async { *x }
-   |           ^^--^^
-   |           | |
-   |           | `x` is borrowed here
-   |           may outlive borrowed value `x`
+   |     ^^^^^^^^--^^
+   |     |       |
+   |     |       `x` is borrowed here
+   |     may outlive borrowed value `x`
    |
 note: async block is returned here
   --> $DIR/async-borrowck-escaping-block-error.rs:11:5
index 2494c3feb2a89206e5feff16ebf644aacdcb5e55..774c97966b18eb9f2b97cf73a42a230442d8a824 100644 (file)
@@ -1,20 +1,20 @@
 error[E0308]: mismatched types
-  --> $DIR/generator-desc.rs:10:25
+  --> $DIR/generator-desc.rs:10:19
    |
 LL |     fun(async {}, async {});
-   |               --        ^^
-   |               |         |
-   |               |         expected `async` block, found a different `async` block
-   |               |         arguments to this function are incorrect
-   |               the expected `async` block
+   |         --------  ^^^^^^^^
+   |         |         |
+   |         |         expected `async` block, found a different `async` block
+   |         |         arguments to this function are incorrect
+   |         the expected `async` block
    |
-   = note: expected `async` block `[static generator@$DIR/generator-desc.rs:10:15: 10:17]`
-              found `async` block `[static generator@$DIR/generator-desc.rs:10:25: 10:27]`
+   = note: expected `async` block `impl Future<Output = ()>` (`async` block)
+              found `async` block `impl Future<Output = ()>` (`async` block)
 note: function defined here
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
    |
-LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
-   |              ^^^^^^^^^^^^^^
+LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
+   |              ^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/generator-desc.rs:12:16
@@ -53,16 +53,8 @@ LL |     fun((async || {})(), (async || {})());
    |     |             the expected `async` closure body
    |     arguments to this function are incorrect
    |
-  ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
-   |
-LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
-   |                                           -------------------------------
-   |                                           |
-   |                                           the expected opaque type
-   |                                           the found opaque type
-   |
-   = note: expected opaque type `impl Future<Output = ()>` (`async` closure body)
-              found opaque type `impl Future<Output = ()>` (`async` closure body)
+   = note: expected `async` closure body `impl Future<Output = ()>` (`async` closure body)
+              found `async` closure body `impl Future<Output = ()>` (`async` closure body)
 note: function defined here
   --> $DIR/generator-desc.rs:8:4
    |
index c915164cfce86939c0d902138dc25f0bb80eb7e4..f2802698fd5b646fdd3e993df175ae58705b5abe 100644 (file)
@@ -59,10 +59,10 @@ LL | fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> {
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = Arc<RefCell<i32>>>`, `()`, `Ready<i32>`
 note: required because it's used within this `async` block
-  --> $DIR/issue-68112.rs:60:26
+  --> $DIR/issue-68112.rs:60:20
    |
 LL |       let send_fut = async {
-   |  __________________________^
+   |  ____________________^
 LL | |         let non_send_fut = make_non_send_future2();
 LL | |         let _ = non_send_fut.await;
 LL | |         ready(0).await;
index 11b7d1aaaa6c72621050a9c7c1337f4d103a7bed..38eb85b302fd588abbeb8e8f4b82f84338fa21bb 100644 (file)
@@ -59,10 +59,10 @@ LL | fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> {
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = Arc<RefCell<i32>>>`, `()`, `i32`, `Ready<i32>`
 note: required because it's used within this `async` block
-  --> $DIR/issue-68112.rs:60:26
+  --> $DIR/issue-68112.rs:60:20
    |
 LL |       let send_fut = async {
-   |  __________________________^
+   |  ____________________^
 LL | |         let non_send_fut = make_non_send_future2();
 LL | |         let _ = non_send_fut.await;
 LL | |         ready(0).await;
index 7fb8811666536239d45507cee227e3f1857bc4d0..721234aa4a782875a2e90e32d4c2f5bea168c7f0 100644 (file)
@@ -20,10 +20,9 @@ LL | | }
    | |_^
    = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = ()>`, `()`
 note: required because it's used within this `async` block
-  --> $DIR/issue-70935-complex-spans.rs:16:16
+  --> $DIR/issue-70935-complex-spans.rs:16:5
    |
-LL |       async move {
-   |  ________________^
+LL | /     async move {
 LL | |         baz(|| async{
 LL | |             foo(tx.clone());
 LL | |         }).await;
index 29aa8372f87d087e039cfd225ba88c964cb48051..c1a4b467f104e35c01804d750ee2da16cb1b228b 100644 (file)
@@ -1,8 +1,8 @@
 error[E0373]: async block may outlive the current function, but it borrows `room_ref`, which is owned by the current function
-  --> $DIR/issue-78938-async-block.rs:8:39
+  --> $DIR/issue-78938-async-block.rs:8:33
    |
 LL |       let gameloop_handle = spawn(async {
-   |  _______________________________________^
+   |  _________________________________^
 LL | |         game_loop(Arc::clone(&room_ref))
    | |                               -------- `room_ref` is borrowed here
 LL | |     });
index a55850d76c3d8c2e2b5818baad2cffd9b46cb1a0..4c7b4fa41faea36ba109d7d9e4b1fde4cc1e0836 100644 (file)
@@ -1,8 +1,7 @@
 error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-on-option-in-async.rs:8:10
    |
-LL |       async {
-   |  ___________-
+LL | /     async {
 LL | |         let x: Option<u32> = None;
 LL | |         x?;
    | |          ^ cannot use the `?` operator in an async block that returns `{integer}`
index f53ed53f73c4987aac37a999e5b61a39aef5ece5..6f22d2c593a3b9da365d1a9a55dacb42901eacec 100644 (file)
@@ -1,32 +1,47 @@
-error[E0277]: the trait bound `[static generator@$DIR/async.rs:7:29: 9:2]: Generator<ResumeTy>` is not satisfied
+error[E0277]: `impl Future<Output = u32>` is not a future
   --> $DIR/async.rs:7:29
    |
 LL |   async fn foo(x: u32) -> u32 {
-   |  _____________________________^
+   |  _____________________________-
 LL | |     x
 LL | | }
-   | |_^ the trait `Generator<ResumeTy>` is not implemented for `[static generator@$DIR/async.rs:7:29: 9:2]`
+   | | ^
+   | | |
+   | |_`impl Future<Output = u32>` is not a future
+   |   required by a bound introduced by this call
    |
-note: required by a bound in `std::future::from_generator`
+   = help: the trait `Future` is not implemented for `impl Future<Output = u32>`
+   = note: impl Future<Output = u32> must be a future or must implement `IntoFuture` to be awaited
+note: required by a bound in `identity_future`
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
    |
-LL |     T: Generator<ResumeTy, Yield = ()>,
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `std::future::from_generator`
+LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
+   |                                      ^^^^^^^^^^^^^^^^^^ required by this bound in `identity_future`
 
-error[E0280]: the requirement `<[static generator@$DIR/async.rs:7:29: 9:2] as Generator<ResumeTy>>::Yield == ()` is not satisfied
+error[E0277]: the size for values of type `<impl Future<Output = u32> as Future>::Output` cannot be known at compilation time
   --> $DIR/async.rs:7:29
    |
 LL |   async fn foo(x: u32) -> u32 {
    |  _____________________________^
 LL | |     x
 LL | | }
-   | |_^
+   | |_^ doesn't have a size known at compile-time
    |
-note: required by a bound in `std::future::from_generator`
+   = help: the trait `Sized` is not implemented for `<impl Future<Output = u32> as Future>::Output`
+note: required by a bound in `identity_future`
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
    |
-LL |     T: Generator<ResumeTy, Yield = ()>,
-   |                            ^^^^^^^^^^ required by this bound in `std::future::from_generator`
+LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
+   |                              ^ required by this bound in `identity_future`
+
+error[E0277]: `impl Future<Output = u32>` is not a future
+  --> $DIR/async.rs:7:25
+   |
+LL | async fn foo(x: u32) -> u32 {
+   |                         ^^^ `impl Future<Output = u32>` is not a future
+   |
+   = help: the trait `Future` is not implemented for `impl Future<Output = u32>`
+   = note: impl Future<Output = u32> must be a future or must implement `IntoFuture` to be awaited
 
 error[E0280]: the requirement `<impl Future<Output = u32> as Future>::Output == u32` is not satisfied
   --> $DIR/async.rs:7:25
@@ -34,6 +49,6 @@ error[E0280]: the requirement `<impl Future<Output = u32> as Future>::Output ==
 LL | async fn foo(x: u32) -> u32 {
    |                         ^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
index 10f6bd74031ac7324b1b1d7271dda397255464d6..f02a93ed41b9a03e9b192d80e47c3221850abee3 100644 (file)
@@ -1,6 +1,6 @@
 // check-pass
 
-#![feature(gen_future, generator_trait, negative_impls)]
+#![feature(generator_trait, negative_impls)]
 
 use std::ops::{Generator, GeneratorState};
 use std::task::{Poll, Context};
index 77cef485f30e9a477108aa3e29914a0544e46f80..918d37e65594d8f4fb29cff8c574080030fb3914 100644 (file)
@@ -78,20 +78,21 @@ LL | impl<P: Deref<Target: Unpin>> Pin<P> {
 error[E0308]: mismatched types
   --> $DIR/expected-boxed-future-isnt-pinned.rs:28:5
    |
-LL |   fn zap() -> BoxFuture<'static, i32> {
-   |               ----------------------- expected `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>` because of return type
 LL | /     async {
 LL | |         42
 LL | |     }
-   | |_____^ expected struct `Pin`, found opaque type
-   |
-  ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
-   |
-LL |   pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
-   |                                             ------------------------------- the found opaque type
-   |
-   = note:   expected struct `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>`
-           found opaque type `impl Future<Output = {integer}>`
+   | |     ^
+   | |     |
+   | |_____expected struct `Pin`, found `async` block
+   |       arguments to this function are incorrect
+   |
+   = note:     expected struct `Pin<Box<dyn Future<Output = i32> + Send>>`
+           found `async` block `impl Future<Output = {integer}>`
+note: function defined here
+  --> $SRC_DIR/core/src/future/mod.rs:LL:COL
+   |
+LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
+   |              ^^^^^^^^^^^^^^^
 help: you need to pin and box this expression
    |
 LL ~     Box::pin(async {
index 4557e43288542eac8e232f059e0257039ce27ddd..ae5f9424b2323b015f34a85547c880b5b387bb49 100644 (file)
@@ -427,9 +427,7 @@ fn lint_for_missing_headers(
                 let body = cx.tcx.hir().body(body_id);
                 let ret_ty = typeck.expr_ty(body.value);
                 if implements_trait(cx, ret_ty, future, &[]);
-                if let ty::Opaque(_, subs) = ret_ty.kind();
-                if let Some(gen) = subs.types().next();
-                if let ty::Generator(_, subs, _) = gen.kind();
+                if let ty::Generator(_, subs, _) = ret_ty.kind();
                 if is_type_diagnostic_item(cx, subs.as_generator().return_ty(), sym::Result);
                 then {
                     span_lint(
index 5c6a342b3d074221eaaa9296b06e4a89c9e8e1ae..6a98df4991259a34e7d99424ab988314c58440c8 100644 (file)
@@ -177,7 +177,7 @@ fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>)
         if let Some(args) = cx
             .tcx
             .lang_items()
-            .from_generator_fn()
+            .identity_future_fn()
             .and_then(|def_id| match_function_call_with_def_id(cx, block_expr, def_id));
         if args.len() == 1;
         if let Expr {
index 9de0550d81d0051654cab991cee3a6b240eaeb34..c6acf24c21ecf73cd57470a72d0f1a82a3c602a6 100644 (file)
@@ -45,7 +45,7 @@ if let ExprKind::Closure(CaptureBy::Value, fn_decl, body_id, _, None) = expr.kin
     && expr1 = &cx.tcx.hir().body(body_id).value
     && let ExprKind::Call(func, args) = expr1.kind
     && let ExprKind::Path(ref qpath) = func.kind
-    && matches!(qpath, QPath::LangItem(LangItem::FromGenerator, _))
+    && matches!(qpath, QPath::LangItem(LangItem::IdentityFuture, _))
     && args.len() == 1
     && let ExprKind::Closure(CaptureBy::Value, fn_decl1, body_id1, _, Some(Movability::Static)) = args[0].kind
     && let FnRetTy::DefaultReturn(_) = fn_decl1.output