diff options
| author | Oli Scherer <github333195615777966@oli-obk.de> | 2025-02-27 09:51:23 +0000 |
|---|---|---|
| committer | Eric Holk <ericholk@microsoft.com> | 2025-06-03 10:52:32 -0700 |
| commit | 5fbdfc3e1018072e0c272d19308d72ac5165f01a (patch) | |
| tree | b8b697529f74f05d2d0636f5387e600ed449b822 /compiler/rustc_builtin_macros/src/iter.rs | |
| parent | aae43c4532690153af7465227816c93036bb1604 (diff) | |
| download | rust-5fbdfc3e1018072e0c272d19308d72ac5165f01a.tar.gz rust-5fbdfc3e1018072e0c272d19308d72ac5165f01a.zip | |
Add `iter` macro
This adds an `iter!` macro that can be used to create movable generators. This also adds a yield_expr feature so the `yield` keyword can be used within iter! macro bodies. This was needed because several unstable features each need `yield` expressions, so this allows us to stabilize them separately from any individual feature. Co-authored-by: Oli Scherer <github35764891676564198441@oli-obk.de> Co-authored-by: Jieyou Xu <jieyouxu@outlook.com> Co-authored-by: Travis Cross <tc@traviscross.com>
Diffstat (limited to 'compiler/rustc_builtin_macros/src/iter.rs')
| -rw-r--r-- | compiler/rustc_builtin_macros/src/iter.rs | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/compiler/rustc_builtin_macros/src/iter.rs b/compiler/rustc_builtin_macros/src/iter.rs new file mode 100644 index 00000000000..7ad83903a1b --- /dev/null +++ b/compiler/rustc_builtin_macros/src/iter.rs @@ -0,0 +1,53 @@ +use rustc_ast::ptr::P; +use rustc_ast::tokenstream::TokenStream; +use rustc_ast::{CoroutineKind, DUMMY_NODE_ID, Expr, ast, token}; +use rustc_errors::PResult; +use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult}; +use rustc_span::Span; + +pub(crate) fn expand<'cx>( + cx: &'cx mut ExtCtxt<'_>, + sp: Span, + tts: TokenStream, +) -> MacroExpanderResult<'cx> { + let closure = match parse_closure(cx, sp, tts) { + Ok(parsed) => parsed, + Err(err) => { + return ExpandResult::Ready(DummyResult::any(sp, err.emit())); + } + }; + + ExpandResult::Ready(base::MacEager::expr(closure)) +} + +fn parse_closure<'a>( + cx: &mut ExtCtxt<'a>, + span: Span, + stream: TokenStream, +) -> PResult<'a, P<Expr>> { + let mut closure_parser = cx.new_parser_from_tts(stream); + + let coroutine_kind = Some(CoroutineKind::Gen { + span, + closure_id: DUMMY_NODE_ID, + return_impl_trait_id: DUMMY_NODE_ID, + }); + + let mut closure = closure_parser.parse_expr()?; + match &mut closure.kind { + ast::ExprKind::Closure(c) => { + if let Some(kind) = c.coroutine_kind { + cx.dcx().span_err(kind.span(), "only plain closures allowed in `iter!`"); + } + c.coroutine_kind = coroutine_kind; + if closure_parser.token != token::Eof { + closure_parser.unexpected()?; + } + Ok(closure) + } + _ => { + cx.dcx().span_err(closure.span, "`iter!` body must be a closure"); + Err(closure_parser.unexpected().unwrap_err()) + } + } +} |
