mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-22 20:47:48 +00:00

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>
54 lines
1.6 KiB
Rust
54 lines
1.6 KiB
Rust
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())
|
|
}
|
|
}
|
|
}
|