From acb6f17adf78f79db10ec189d719380d35cacee7 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Mon, 18 Dec 2023 17:08:19 -0800 Subject: [PATCH] Use `IntoAsyncIterator` in `for await` loop desugaring --- compiler/rustc_ast_lowering/src/expr.rs | 20 +++++++++++++++++++- compiler/rustc_hir/src/lang_items.rs | 1 + library/core/src/async_iter/async_iter.rs | 1 + 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 2d61f3bceec..a384601a24d 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1803,7 +1803,25 @@ fn lower_expr_for( arena_vec![self; head], ) } - ForLoopKind::ForAwait => self.arena.alloc(head), + // ` unsafe { Pin::new_unchecked(&mut into_async_iter()) }` + ForLoopKind::ForAwait => { + // `::core::async_iter::IntoAsyncIterator::into_async_iter()` + let iter = self.expr_call_lang_item_fn( + head_span, + hir::LangItem::IntoAsyncIterIntoIter, + arena_vec![self; head], + ); + let iter = self.expr_mut_addr_of(head_span, iter); + // `Pin::new_unchecked(...)` + let iter = self.arena.alloc(self.expr_call_lang_item_fn_mut( + head_span, + hir::LangItem::PinNewUnchecked, + arena_vec![self; iter], + )); + // `unsafe { ... }` + let iter = self.arena.alloc(self.expr_unsafe(iter)); + iter + } }; let match_expr = self.arena.alloc(self.expr_match( diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 7691cd11c4f..3f3b57ba94f 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -308,6 +308,7 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> { FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; AsyncIteratorPollNext, sym::async_iterator_poll_next, async_iterator_poll_next, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(0); + IntoAsyncIterIntoIter, sym::into_async_iter_into_iter, into_async_iter_into_iter, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(0); Option, sym::Option, option_type, Target::Enum, GenericRequirement::None; OptionSome, sym::Some, option_some_variant, Target::Variant, GenericRequirement::None; diff --git a/library/core/src/async_iter/async_iter.rs b/library/core/src/async_iter/async_iter.rs index 9ef74991dbb..d5282514cc6 100644 --- a/library/core/src/async_iter/async_iter.rs +++ b/library/core/src/async_iter/async_iter.rs @@ -145,6 +145,7 @@ pub trait IntoAsyncIterator { type IntoAsyncIter: AsyncIterator; /// Converts `self` into an async iterator + #[cfg_attr(not(bootstrap), lang = "into_async_iter_into_iter")] fn into_async_iter(self) -> Self::IntoAsyncIter; }