|  | 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, Box<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()) | 
|  | } | 
|  | } | 
|  | } |