From 0253be53b706d59da904acbab2a0fca618b7b4f6 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 11 Apr 2024 12:48:32 +0000 Subject: [PATCH] Add explicit syntax for coroutines instead of relying on closures having `yield` expressions --- compiler/rustc_ast_lowering/src/expr.rs | 12 +++++++++++- compiler/rustc_feature/src/builtin_attrs.rs | 6 ++++++ tests/ui/coroutine/derived-drop-parent-expr.rs | 4 ++-- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 2305cc07795db..6c3f03431472b 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -217,6 +217,7 @@ impl<'hir> LoweringContext<'_, 'hir> { binder, *capture_clause, e.id, + hir_id, *constness, *movability, fn_decl, @@ -955,6 +956,7 @@ impl<'hir> LoweringContext<'_, 'hir> { binder: &ClosureBinder, capture_clause: CaptureBy, closure_id: NodeId, + closure_hir_id: hir::HirId, constness: Const, movability: Movability, decl: &FnDecl, @@ -965,7 +967,15 @@ impl<'hir> LoweringContext<'_, 'hir> { let (binder_clause, generic_params) = self.lower_closure_binder(binder); let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| { - let mut coroutine_kind = None; + let mut coroutine_kind = if this + .attrs + .get(&closure_hir_id.local_id) + .is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine))) + { + Some(hir::CoroutineKind::Coroutine(Movability::Movable)) + } else { + None + }; let body_id = this.lower_fn_body(decl, |this| { let e = this.lower_expr_mut(body); coroutine_kind = this.coroutine_kind; diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 4f62323231a73..2c5511d67fd0b 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -534,6 +534,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ EncodeCrossCrate::Yes, experimental!(cfi_encoding) ), + // `#[coroutine]` attribute to be applied to closures to make them coroutines instead + gated!( + coroutine, Normal, template!(Word), ErrorFollowing, + EncodeCrossCrate::No, coroutines, experimental!(coroutines) + ), + // ========================================================================== // Internal attributes: Stability, deprecation, and unsafe: // ========================================================================== diff --git a/tests/ui/coroutine/derived-drop-parent-expr.rs b/tests/ui/coroutine/derived-drop-parent-expr.rs index f70a732c90f08..71f7506ab845e 100644 --- a/tests/ui/coroutine/derived-drop-parent-expr.rs +++ b/tests/ui/coroutine/derived-drop-parent-expr.rs @@ -10,7 +10,7 @@ pub struct Client { pub nickname: String } fn main() { let g = move || match drop(Client { ..Client::default() }) { - _status => yield, - }; + _status => yield, + }; assert_send(g); }