]> git.lizzy.rs Git - rust.git/blob - src/librustc_ast_lowering/expr.rs
Auto merge of #75137 - Aaron1011:fix/hygiene-skip-expndata, r=petrochenkov
[rust.git] / src / librustc_ast_lowering / expr.rs
1 use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
2
3 use rustc_ast::ast::*;
4 use rustc_ast::attr;
5 use rustc_ast::ptr::P as AstP;
6 use rustc_data_structures::fx::FxHashMap;
7 use rustc_data_structures::stack::ensure_sufficient_stack;
8 use rustc_data_structures::thin_vec::ThinVec;
9 use rustc_errors::struct_span_err;
10 use rustc_hir as hir;
11 use rustc_hir::def::Res;
12 use rustc_span::hygiene::ForLoopLoc;
13 use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
14 use rustc_span::symbol::{sym, Ident, Symbol};
15 use rustc_target::asm;
16 use std::collections::hash_map::Entry;
17 use std::fmt::Write;
18
19 impl<'hir> LoweringContext<'_, 'hir> {
20     fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
21         self.arena.alloc_from_iter(exprs.iter().map(|x| self.lower_expr_mut(x)))
22     }
23
24     pub(super) fn lower_expr(&mut self, e: &Expr) -> &'hir hir::Expr<'hir> {
25         self.arena.alloc(self.lower_expr_mut(e))
26     }
27
28     pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
29         ensure_sufficient_stack(|| {
30             let kind = match e.kind {
31                 ExprKind::Box(ref inner) => hir::ExprKind::Box(self.lower_expr(inner)),
32                 ExprKind::Array(ref exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
33                 ExprKind::Repeat(ref expr, ref count) => {
34                     let expr = self.lower_expr(expr);
35                     let count = self.lower_anon_const(count);
36                     hir::ExprKind::Repeat(expr, count)
37                 }
38                 ExprKind::Tup(ref elts) => hir::ExprKind::Tup(self.lower_exprs(elts)),
39                 ExprKind::Call(ref f, ref args) => {
40                     let f = self.lower_expr(f);
41                     hir::ExprKind::Call(f, self.lower_exprs(args))
42                 }
43                 ExprKind::MethodCall(ref seg, ref args, span) => {
44                     let hir_seg = self.arena.alloc(self.lower_path_segment(
45                         e.span,
46                         seg,
47                         ParamMode::Optional,
48                         0,
49                         ParenthesizedGenericArgs::Err,
50                         ImplTraitContext::disallowed(),
51                         None,
52                     ));
53                     let args = self.lower_exprs(args);
54                     hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args, span)
55                 }
56                 ExprKind::Binary(binop, ref lhs, ref rhs) => {
57                     let binop = self.lower_binop(binop);
58                     let lhs = self.lower_expr(lhs);
59                     let rhs = self.lower_expr(rhs);
60                     hir::ExprKind::Binary(binop, lhs, rhs)
61                 }
62                 ExprKind::Unary(op, ref ohs) => {
63                     let op = self.lower_unop(op);
64                     let ohs = self.lower_expr(ohs);
65                     hir::ExprKind::Unary(op, ohs)
66                 }
67                 ExprKind::Lit(ref l) => hir::ExprKind::Lit(respan(l.span, l.kind.clone())),
68                 ExprKind::Cast(ref expr, ref ty) => {
69                     let expr = self.lower_expr(expr);
70                     let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
71                     hir::ExprKind::Cast(expr, ty)
72                 }
73                 ExprKind::Type(ref expr, ref ty) => {
74                     let expr = self.lower_expr(expr);
75                     let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
76                     hir::ExprKind::Type(expr, ty)
77                 }
78                 ExprKind::AddrOf(k, m, ref ohs) => {
79                     let ohs = self.lower_expr(ohs);
80                     hir::ExprKind::AddrOf(k, m, ohs)
81                 }
82                 ExprKind::Let(ref pat, ref scrutinee) => {
83                     self.lower_expr_let(e.span, pat, scrutinee)
84                 }
85                 ExprKind::If(ref cond, ref then, ref else_opt) => {
86                     self.lower_expr_if(e.span, cond, then, else_opt.as_deref())
87                 }
88                 ExprKind::While(ref cond, ref body, opt_label) => self
89                     .with_loop_scope(e.id, |this| {
90                         this.lower_expr_while_in_loop_scope(e.span, cond, body, opt_label)
91                     }),
92                 ExprKind::Loop(ref body, opt_label) => self.with_loop_scope(e.id, |this| {
93                     hir::ExprKind::Loop(
94                         this.lower_block(body, false),
95                         opt_label,
96                         hir::LoopSource::Loop,
97                     )
98                 }),
99                 ExprKind::TryBlock(ref body) => self.lower_expr_try_block(body),
100                 ExprKind::Match(ref expr, ref arms) => hir::ExprKind::Match(
101                     self.lower_expr(expr),
102                     self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))),
103                     hir::MatchSource::Normal,
104                 ),
105                 ExprKind::Async(capture_clause, closure_node_id, ref block) => self
106                     .make_async_expr(
107                         capture_clause,
108                         closure_node_id,
109                         None,
110                         block.span,
111                         hir::AsyncGeneratorKind::Block,
112                         |this| this.with_new_scopes(|this| this.lower_block_expr(block)),
113                     ),
114                 ExprKind::Await(ref expr) => self.lower_expr_await(e.span, expr),
115                 ExprKind::Closure(
116                     capture_clause,
117                     asyncness,
118                     movability,
119                     ref decl,
120                     ref body,
121                     fn_decl_span,
122                 ) => {
123                     if let Async::Yes { closure_id, .. } = asyncness {
124                         self.lower_expr_async_closure(
125                             capture_clause,
126                             closure_id,
127                             decl,
128                             body,
129                             fn_decl_span,
130                         )
131                     } else {
132                         self.lower_expr_closure(
133                             capture_clause,
134                             movability,
135                             decl,
136                             body,
137                             fn_decl_span,
138                         )
139                     }
140                 }
141                 ExprKind::Block(ref blk, opt_label) => {
142                     hir::ExprKind::Block(self.lower_block(blk, opt_label.is_some()), opt_label)
143                 }
144                 ExprKind::Assign(ref el, ref er, span) => {
145                     hir::ExprKind::Assign(self.lower_expr(el), self.lower_expr(er), span)
146                 }
147                 ExprKind::AssignOp(op, ref el, ref er) => hir::ExprKind::AssignOp(
148                     self.lower_binop(op),
149                     self.lower_expr(el),
150                     self.lower_expr(er),
151                 ),
152                 ExprKind::Field(ref el, ident) => hir::ExprKind::Field(self.lower_expr(el), ident),
153                 ExprKind::Index(ref el, ref er) => {
154                     hir::ExprKind::Index(self.lower_expr(el), self.lower_expr(er))
155                 }
156                 ExprKind::Range(Some(ref e1), Some(ref e2), RangeLimits::Closed) => {
157                     self.lower_expr_range_closed(e.span, e1, e2)
158                 }
159                 ExprKind::Range(ref e1, ref e2, lims) => {
160                     self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), lims)
161                 }
162                 ExprKind::Path(ref qself, ref path) => {
163                     let qpath = self.lower_qpath(
164                         e.id,
165                         qself,
166                         path,
167                         ParamMode::Optional,
168                         ImplTraitContext::disallowed(),
169                     );
170                     hir::ExprKind::Path(qpath)
171                 }
172                 ExprKind::Break(opt_label, ref opt_expr) => {
173                     let opt_expr = opt_expr.as_ref().map(|x| self.lower_expr(x));
174                     hir::ExprKind::Break(self.lower_jump_destination(e.id, opt_label), opt_expr)
175                 }
176                 ExprKind::Continue(opt_label) => {
177                     hir::ExprKind::Continue(self.lower_jump_destination(e.id, opt_label))
178                 }
179                 ExprKind::Ret(ref e) => {
180                     let e = e.as_ref().map(|x| self.lower_expr(x));
181                     hir::ExprKind::Ret(e)
182                 }
183                 ExprKind::InlineAsm(ref asm) => self.lower_expr_asm(e.span, asm),
184                 ExprKind::LlvmInlineAsm(ref asm) => self.lower_expr_llvm_asm(asm),
185                 ExprKind::Struct(ref path, ref fields, ref maybe_expr) => {
186                     let maybe_expr = maybe_expr.as_ref().map(|x| self.lower_expr(x));
187                     hir::ExprKind::Struct(
188                         self.arena.alloc(self.lower_qpath(
189                             e.id,
190                             &None,
191                             path,
192                             ParamMode::Optional,
193                             ImplTraitContext::disallowed(),
194                         )),
195                         self.arena.alloc_from_iter(fields.iter().map(|x| self.lower_field(x))),
196                         maybe_expr,
197                     )
198                 }
199                 ExprKind::Yield(ref opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
200                 ExprKind::Err => hir::ExprKind::Err,
201                 ExprKind::Try(ref sub_expr) => self.lower_expr_try(e.span, sub_expr),
202                 ExprKind::Paren(ref ex) => {
203                     let mut ex = self.lower_expr_mut(ex);
204                     // Include parens in span, but only if it is a super-span.
205                     if e.span.contains(ex.span) {
206                         ex.span = e.span;
207                     }
208                     // Merge attributes into the inner expression.
209                     let mut attrs = e.attrs.clone();
210                     attrs.extend::<Vec<_>>(ex.attrs.into());
211                     ex.attrs = attrs;
212                     return ex;
213                 }
214
215                 // Desugar `ExprForLoop`
216                 // from: `[opt_ident]: for <pat> in <head> <body>`
217                 ExprKind::ForLoop(ref pat, ref head, ref body, opt_label) => {
218                     return self.lower_expr_for(e, pat, head, body, opt_label);
219                 }
220                 ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),
221             };
222
223             hir::Expr {
224                 hir_id: self.lower_node_id(e.id),
225                 kind,
226                 span: e.span,
227                 attrs: e.attrs.iter().map(|a| self.lower_attr(a)).collect::<Vec<_>>().into(),
228             }
229         })
230     }
231
232     fn lower_unop(&mut self, u: UnOp) -> hir::UnOp {
233         match u {
234             UnOp::Deref => hir::UnOp::UnDeref,
235             UnOp::Not => hir::UnOp::UnNot,
236             UnOp::Neg => hir::UnOp::UnNeg,
237         }
238     }
239
240     fn lower_binop(&mut self, b: BinOp) -> hir::BinOp {
241         Spanned {
242             node: match b.node {
243                 BinOpKind::Add => hir::BinOpKind::Add,
244                 BinOpKind::Sub => hir::BinOpKind::Sub,
245                 BinOpKind::Mul => hir::BinOpKind::Mul,
246                 BinOpKind::Div => hir::BinOpKind::Div,
247                 BinOpKind::Rem => hir::BinOpKind::Rem,
248                 BinOpKind::And => hir::BinOpKind::And,
249                 BinOpKind::Or => hir::BinOpKind::Or,
250                 BinOpKind::BitXor => hir::BinOpKind::BitXor,
251                 BinOpKind::BitAnd => hir::BinOpKind::BitAnd,
252                 BinOpKind::BitOr => hir::BinOpKind::BitOr,
253                 BinOpKind::Shl => hir::BinOpKind::Shl,
254                 BinOpKind::Shr => hir::BinOpKind::Shr,
255                 BinOpKind::Eq => hir::BinOpKind::Eq,
256                 BinOpKind::Lt => hir::BinOpKind::Lt,
257                 BinOpKind::Le => hir::BinOpKind::Le,
258                 BinOpKind::Ne => hir::BinOpKind::Ne,
259                 BinOpKind::Ge => hir::BinOpKind::Ge,
260                 BinOpKind::Gt => hir::BinOpKind::Gt,
261             },
262             span: b.span,
263         }
264     }
265
266     /// Emit an error and lower `ast::ExprKind::Let(pat, scrutinee)` into:
267     /// ```rust
268     /// match scrutinee { pats => true, _ => false }
269     /// ```
270     fn lower_expr_let(&mut self, span: Span, pat: &Pat, scrutinee: &Expr) -> hir::ExprKind<'hir> {
271         // If we got here, the `let` expression is not allowed.
272
273         if self.sess.opts.unstable_features.is_nightly_build() {
274             self.sess
275                 .struct_span_err(span, "`let` expressions are not supported here")
276                 .note("only supported directly in conditions of `if`- and `while`-expressions")
277                 .note("as well as when nested within `&&` and parenthesis in those conditions")
278                 .emit();
279         } else {
280             self.sess
281                 .struct_span_err(span, "expected expression, found statement (`let`)")
282                 .note("variable declaration using `let` is a statement")
283                 .emit();
284         }
285
286         // For better recovery, we emit:
287         // ```
288         // match scrutinee { pat => true, _ => false }
289         // ```
290         // While this doesn't fully match the user's intent, it has key advantages:
291         // 1. We can avoid using `abort_if_errors`.
292         // 2. We can typeck both `pat` and `scrutinee`.
293         // 3. `pat` is allowed to be refutable.
294         // 4. The return type of the block is `bool` which seems like what the user wanted.
295         let scrutinee = self.lower_expr(scrutinee);
296         let then_arm = {
297             let pat = self.lower_pat(pat);
298             let expr = self.expr_bool(span, true);
299             self.arm(pat, expr)
300         };
301         let else_arm = {
302             let pat = self.pat_wild(span);
303             let expr = self.expr_bool(span, false);
304             self.arm(pat, expr)
305         };
306         hir::ExprKind::Match(
307             scrutinee,
308             arena_vec![self; then_arm, else_arm],
309             hir::MatchSource::Normal,
310         )
311     }
312
313     fn lower_expr_if(
314         &mut self,
315         span: Span,
316         cond: &Expr,
317         then: &Block,
318         else_opt: Option<&Expr>,
319     ) -> hir::ExprKind<'hir> {
320         // FIXME(#53667): handle lowering of && and parens.
321
322         // `_ => else_block` where `else_block` is `{}` if there's `None`:
323         let else_pat = self.pat_wild(span);
324         let (else_expr, contains_else_clause) = match else_opt {
325             None => (self.expr_block_empty(span), false),
326             Some(els) => (self.lower_expr(els), true),
327         };
328         let else_arm = self.arm(else_pat, else_expr);
329
330         // Handle then + scrutinee:
331         let then_expr = self.lower_block_expr(then);
332         let (then_pat, scrutinee, desugar) = match cond.kind {
333             // `<pat> => <then>`:
334             ExprKind::Let(ref pat, ref scrutinee) => {
335                 let scrutinee = self.lower_expr(scrutinee);
336                 let pat = self.lower_pat(pat);
337                 (pat, scrutinee, hir::MatchSource::IfLetDesugar { contains_else_clause })
338             }
339             // `true => <then>`:
340             _ => {
341                 // Lower condition:
342                 let cond = self.lower_expr(cond);
343                 let span_block =
344                     self.mark_span_with_reason(DesugaringKind::CondTemporary, cond.span, None);
345                 // Wrap in a construct equivalent to `{ let _t = $cond; _t }`
346                 // to preserve drop semantics since `if cond { ... }` does not
347                 // let temporaries live outside of `cond`.
348                 let cond = self.expr_drop_temps(span_block, cond, ThinVec::new());
349                 let pat = self.pat_bool(span, true);
350                 (pat, cond, hir::MatchSource::IfDesugar { contains_else_clause })
351             }
352         };
353         let then_arm = self.arm(then_pat, self.arena.alloc(then_expr));
354
355         hir::ExprKind::Match(scrutinee, arena_vec![self; then_arm, else_arm], desugar)
356     }
357
358     fn lower_expr_while_in_loop_scope(
359         &mut self,
360         span: Span,
361         cond: &Expr,
362         body: &Block,
363         opt_label: Option<Label>,
364     ) -> hir::ExprKind<'hir> {
365         // FIXME(#53667): handle lowering of && and parens.
366
367         // Note that the block AND the condition are evaluated in the loop scope.
368         // This is done to allow `break` from inside the condition of the loop.
369
370         // `_ => break`:
371         let else_arm = {
372             let else_pat = self.pat_wild(span);
373             let else_expr = self.expr_break(span, ThinVec::new());
374             self.arm(else_pat, else_expr)
375         };
376
377         // Handle then + scrutinee:
378         let then_expr = self.lower_block_expr(body);
379         let (then_pat, scrutinee, desugar, source) = match cond.kind {
380             ExprKind::Let(ref pat, ref scrutinee) => {
381                 // to:
382                 //
383                 //   [opt_ident]: loop {
384                 //     match <sub_expr> {
385                 //       <pat> => <body>,
386                 //       _ => break
387                 //     }
388                 //   }
389                 let scrutinee = self.with_loop_condition_scope(|t| t.lower_expr(scrutinee));
390                 let pat = self.lower_pat(pat);
391                 (pat, scrutinee, hir::MatchSource::WhileLetDesugar, hir::LoopSource::WhileLet)
392             }
393             _ => {
394                 // We desugar: `'label: while $cond $body` into:
395                 //
396                 // ```
397                 // 'label: loop {
398                 //     match drop-temps { $cond } {
399                 //         true => $body,
400                 //         _ => break,
401                 //     }
402                 // }
403                 // ```
404
405                 // Lower condition:
406                 let cond = self.with_loop_condition_scope(|this| this.lower_expr(cond));
407                 let span_block =
408                     self.mark_span_with_reason(DesugaringKind::CondTemporary, cond.span, None);
409                 // Wrap in a construct equivalent to `{ let _t = $cond; _t }`
410                 // to preserve drop semantics since `while cond { ... }` does not
411                 // let temporaries live outside of `cond`.
412                 let cond = self.expr_drop_temps(span_block, cond, ThinVec::new());
413                 // `true => <then>`:
414                 let pat = self.pat_bool(span, true);
415                 (pat, cond, hir::MatchSource::WhileDesugar, hir::LoopSource::While)
416             }
417         };
418         let then_arm = self.arm(then_pat, self.arena.alloc(then_expr));
419
420         // `match <scrutinee> { ... }`
421         let match_expr =
422             self.expr_match(span, scrutinee, arena_vec![self; then_arm, else_arm], desugar);
423
424         // `[opt_ident]: loop { ... }`
425         hir::ExprKind::Loop(self.block_expr(self.arena.alloc(match_expr)), opt_label, source)
426     }
427
428     /// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_ok(<expr>) }`,
429     /// `try { <stmts>; }` into `{ <stmts>; ::std::ops::Try::from_ok(()) }`
430     /// and save the block id to use it as a break target for desugaring of the `?` operator.
431     fn lower_expr_try_block(&mut self, body: &Block) -> hir::ExprKind<'hir> {
432         self.with_catch_scope(body.id, |this| {
433             let mut block = this.lower_block_noalloc(body, true);
434
435             let try_span = this.mark_span_with_reason(
436                 DesugaringKind::TryBlock,
437                 body.span,
438                 this.allow_try_trait.clone(),
439             );
440
441             // Final expression of the block (if present) or `()` with span at the end of block
442             let tail_expr = block
443                 .expr
444                 .take()
445                 .unwrap_or_else(|| this.expr_unit(this.sess.source_map().end_point(try_span)));
446
447             let ok_wrapped_span =
448                 this.mark_span_with_reason(DesugaringKind::TryBlock, tail_expr.span, None);
449
450             // `::std::ops::Try::from_ok($tail_expr)`
451             block.expr = Some(this.wrap_in_try_constructor(
452                 sym::from_ok,
453                 try_span,
454                 tail_expr,
455                 ok_wrapped_span,
456             ));
457
458             hir::ExprKind::Block(this.arena.alloc(block), None)
459         })
460     }
461
462     fn wrap_in_try_constructor(
463         &mut self,
464         method: Symbol,
465         method_span: Span,
466         expr: &'hir hir::Expr<'hir>,
467         overall_span: Span,
468     ) -> &'hir hir::Expr<'hir> {
469         let path = &[sym::ops, sym::Try, method];
470         let constructor =
471             self.arena.alloc(self.expr_std_path(method_span, path, None, ThinVec::new()));
472         self.expr_call(overall_span, constructor, std::slice::from_ref(expr))
473     }
474
475     fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
476         hir::Arm {
477             hir_id: self.next_id(),
478             attrs: self.lower_attrs(&arm.attrs),
479             pat: self.lower_pat(&arm.pat),
480             guard: match arm.guard {
481                 Some(ref x) => Some(hir::Guard::If(self.lower_expr(x))),
482                 _ => None,
483             },
484             body: self.lower_expr(&arm.body),
485             span: arm.span,
486         }
487     }
488
489     /// Lower an `async` construct to a generator that is then wrapped so it implements `Future`.
490     ///
491     /// This results in:
492     ///
493     /// ```text
494     /// std::future::from_generator(static move? |_task_context| -> <ret_ty> {
495     ///     <body>
496     /// })
497     /// ```
498     pub(super) fn make_async_expr(
499         &mut self,
500         capture_clause: CaptureBy,
501         closure_node_id: NodeId,
502         ret_ty: Option<AstP<Ty>>,
503         span: Span,
504         async_gen_kind: hir::AsyncGeneratorKind,
505         body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
506     ) -> hir::ExprKind<'hir> {
507         let output = match ret_ty {
508             Some(ty) => hir::FnRetTy::Return(self.lower_ty(&ty, ImplTraitContext::disallowed())),
509             None => hir::FnRetTy::DefaultReturn(span),
510         };
511
512         // Resume argument type. We let the compiler infer this to simplify the lowering. It is
513         // fully constrained by `future::from_generator`.
514         let input_ty = hir::Ty { hir_id: self.next_id(), kind: hir::TyKind::Infer, span };
515
516         // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
517         let decl = self.arena.alloc(hir::FnDecl {
518             inputs: arena_vec![self; input_ty],
519             output,
520             c_variadic: false,
521             implicit_self: hir::ImplicitSelfKind::None,
522         });
523
524         // Lower the argument pattern/ident. The ident is used again in the `.await` lowering.
525         let (pat, task_context_hid) = self.pat_ident_binding_mode(
526             span,
527             Ident::with_dummy_span(sym::_task_context),
528             hir::BindingAnnotation::Mutable,
529         );
530         let param = hir::Param { attrs: &[], hir_id: self.next_id(), pat, ty_span: span, span };
531         let params = arena_vec![self; param];
532
533         let body_id = self.lower_body(move |this| {
534             this.generator_kind = Some(hir::GeneratorKind::Async(async_gen_kind));
535
536             let old_ctx = this.task_context;
537             this.task_context = Some(task_context_hid);
538             let res = body(this);
539             this.task_context = old_ctx;
540             (params, res)
541         });
542
543         // `static |_task_context| -> <ret_ty> { body }`:
544         let generator_kind = hir::ExprKind::Closure(
545             capture_clause,
546             decl,
547             body_id,
548             span,
549             Some(hir::Movability::Static),
550         );
551         let generator = hir::Expr {
552             hir_id: self.lower_node_id(closure_node_id),
553             kind: generator_kind,
554             span,
555             attrs: ThinVec::new(),
556         };
557
558         // `future::from_generator`:
559         let unstable_span =
560             self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
561         let gen_future = self.expr_std_path(
562             unstable_span,
563             &[sym::future, sym::from_generator],
564             None,
565             ThinVec::new(),
566         );
567
568         // `future::from_generator(generator)`:
569         hir::ExprKind::Call(self.arena.alloc(gen_future), arena_vec![self; generator])
570     }
571
572     /// Desugar `<expr>.await` into:
573     /// ```rust
574     /// match <expr> {
575     ///     mut pinned => loop {
576     ///         match unsafe { ::std::future::Future::poll(
577     ///             <::std::pin::Pin>::new_unchecked(&mut pinned),
578     ///             ::std::future::get_context(task_context),
579     ///         ) } {
580     ///             ::std::task::Poll::Ready(result) => break result,
581     ///             ::std::task::Poll::Pending => {}
582     ///         }
583     ///         task_context = yield ();
584     ///     }
585     /// }
586     /// ```
587     fn lower_expr_await(&mut self, await_span: Span, expr: &Expr) -> hir::ExprKind<'hir> {
588         match self.generator_kind {
589             Some(hir::GeneratorKind::Async(_)) => {}
590             Some(hir::GeneratorKind::Gen) | None => {
591                 let mut err = struct_span_err!(
592                     self.sess,
593                     await_span,
594                     E0728,
595                     "`await` is only allowed inside `async` functions and blocks"
596                 );
597                 err.span_label(await_span, "only allowed inside `async` functions and blocks");
598                 if let Some(item_sp) = self.current_item {
599                     err.span_label(item_sp, "this is not `async`");
600                 }
601                 err.emit();
602             }
603         }
604         let span = self.mark_span_with_reason(DesugaringKind::Await, await_span, None);
605         let gen_future_span = self.mark_span_with_reason(
606             DesugaringKind::Await,
607             await_span,
608             self.allow_gen_future.clone(),
609         );
610         let expr = self.lower_expr(expr);
611
612         let pinned_ident = Ident::with_dummy_span(sym::pinned);
613         let (pinned_pat, pinned_pat_hid) =
614             self.pat_ident_binding_mode(span, pinned_ident, hir::BindingAnnotation::Mutable);
615
616         let task_context_ident = Ident::with_dummy_span(sym::_task_context);
617
618         // unsafe {
619         //     ::std::future::Future::poll(
620         //         ::std::pin::Pin::new_unchecked(&mut pinned),
621         //         ::std::future::get_context(task_context),
622         //     )
623         // }
624         let poll_expr = {
625             let pinned = self.expr_ident(span, pinned_ident, pinned_pat_hid);
626             let ref_mut_pinned = self.expr_mut_addr_of(span, pinned);
627             let task_context = if let Some(task_context_hid) = self.task_context {
628                 self.expr_ident_mut(span, task_context_ident, task_context_hid)
629             } else {
630                 // Use of `await` outside of an async context, we cannot use `task_context` here.
631                 self.expr_err(span)
632             };
633             let pin_ty_id = self.next_id();
634             let new_unchecked_expr_kind = self.expr_call_std_assoc_fn(
635                 pin_ty_id,
636                 span,
637                 &[sym::pin, sym::Pin],
638                 "new_unchecked",
639                 arena_vec![self; ref_mut_pinned],
640             );
641             let new_unchecked = self.expr(span, new_unchecked_expr_kind, ThinVec::new());
642             let get_context = self.expr_call_std_path_mut(
643                 gen_future_span,
644                 &[sym::future, sym::get_context],
645                 arena_vec![self; task_context],
646             );
647             let call = self.expr_call_std_path(
648                 span,
649                 &[sym::future, sym::Future, sym::poll],
650                 arena_vec![self; new_unchecked, get_context],
651             );
652             self.arena.alloc(self.expr_unsafe(call))
653         };
654
655         // `::std::task::Poll::Ready(result) => break result`
656         let loop_node_id = self.resolver.next_node_id();
657         let loop_hir_id = self.lower_node_id(loop_node_id);
658         let ready_arm = {
659             let x_ident = Ident::with_dummy_span(sym::result);
660             let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident);
661             let x_expr = self.expr_ident(span, x_ident, x_pat_hid);
662             let ready_pat = self.pat_std_enum(
663                 span,
664                 &[sym::task, sym::Poll, sym::Ready],
665                 arena_vec![self; x_pat],
666             );
667             let break_x = self.with_loop_scope(loop_node_id, move |this| {
668                 let expr_break =
669                     hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr));
670                 this.arena.alloc(this.expr(await_span, expr_break, ThinVec::new()))
671             });
672             self.arm(ready_pat, break_x)
673         };
674
675         // `::std::task::Poll::Pending => {}`
676         let pending_arm = {
677             let pending_pat = self.pat_std_enum(span, &[sym::task, sym::Poll, sym::Pending], &[]);
678             let empty_block = self.expr_block_empty(span);
679             self.arm(pending_pat, empty_block)
680         };
681
682         let inner_match_stmt = {
683             let match_expr = self.expr_match(
684                 span,
685                 poll_expr,
686                 arena_vec![self; ready_arm, pending_arm],
687                 hir::MatchSource::AwaitDesugar,
688             );
689             self.stmt_expr(span, match_expr)
690         };
691
692         // task_context = yield ();
693         let yield_stmt = {
694             let unit = self.expr_unit(span);
695             let yield_expr = self.expr(
696                 span,
697                 hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr.hir_id) }),
698                 ThinVec::new(),
699             );
700             let yield_expr = self.arena.alloc(yield_expr);
701
702             if let Some(task_context_hid) = self.task_context {
703                 let lhs = self.expr_ident(span, task_context_ident, task_context_hid);
704                 let assign =
705                     self.expr(span, hir::ExprKind::Assign(lhs, yield_expr, span), AttrVec::new());
706                 self.stmt_expr(span, assign)
707             } else {
708                 // Use of `await` outside of an async context. Return `yield_expr` so that we can
709                 // proceed with type checking.
710                 self.stmt(span, hir::StmtKind::Semi(yield_expr))
711             }
712         };
713
714         let loop_block = self.block_all(span, arena_vec![self; inner_match_stmt, yield_stmt], None);
715
716         // loop { .. }
717         let loop_expr = self.arena.alloc(hir::Expr {
718             hir_id: loop_hir_id,
719             kind: hir::ExprKind::Loop(loop_block, None, hir::LoopSource::Loop),
720             span,
721             attrs: ThinVec::new(),
722         });
723
724         // mut pinned => loop { ... }
725         let pinned_arm = self.arm(pinned_pat, loop_expr);
726
727         // match <expr> {
728         //     mut pinned => loop { .. }
729         // }
730         hir::ExprKind::Match(expr, arena_vec![self; pinned_arm], hir::MatchSource::AwaitDesugar)
731     }
732
733     fn lower_expr_closure(
734         &mut self,
735         capture_clause: CaptureBy,
736         movability: Movability,
737         decl: &FnDecl,
738         body: &Expr,
739         fn_decl_span: Span,
740     ) -> hir::ExprKind<'hir> {
741         // Lower outside new scope to preserve `is_in_loop_condition`.
742         let fn_decl = self.lower_fn_decl(decl, None, false, None);
743
744         self.with_new_scopes(move |this| {
745             let prev = this.current_item;
746             this.current_item = Some(fn_decl_span);
747             let mut generator_kind = None;
748             let body_id = this.lower_fn_body(decl, |this| {
749                 let e = this.lower_expr_mut(body);
750                 generator_kind = this.generator_kind;
751                 e
752             });
753             let generator_option =
754                 this.generator_movability_for_fn(&decl, fn_decl_span, generator_kind, movability);
755             this.current_item = prev;
756             hir::ExprKind::Closure(capture_clause, fn_decl, body_id, fn_decl_span, generator_option)
757         })
758     }
759
760     fn generator_movability_for_fn(
761         &mut self,
762         decl: &FnDecl,
763         fn_decl_span: Span,
764         generator_kind: Option<hir::GeneratorKind>,
765         movability: Movability,
766     ) -> Option<hir::Movability> {
767         match generator_kind {
768             Some(hir::GeneratorKind::Gen) => {
769                 if decl.inputs.len() > 1 {
770                     struct_span_err!(
771                         self.sess,
772                         fn_decl_span,
773                         E0628,
774                         "too many parameters for a generator (expected 0 or 1 parameters)"
775                     )
776                     .emit();
777                 }
778                 Some(movability)
779             }
780             Some(hir::GeneratorKind::Async(_)) => {
781                 panic!("non-`async` closure body turned `async` during lowering");
782             }
783             None => {
784                 if movability == Movability::Static {
785                     struct_span_err!(self.sess, fn_decl_span, E0697, "closures cannot be static")
786                         .emit();
787                 }
788                 None
789             }
790         }
791     }
792
793     fn lower_expr_async_closure(
794         &mut self,
795         capture_clause: CaptureBy,
796         closure_id: NodeId,
797         decl: &FnDecl,
798         body: &Expr,
799         fn_decl_span: Span,
800     ) -> hir::ExprKind<'hir> {
801         let outer_decl =
802             FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
803         // We need to lower the declaration outside the new scope, because we
804         // have to conserve the state of being inside a loop condition for the
805         // closure argument types.
806         let fn_decl = self.lower_fn_decl(&outer_decl, None, false, None);
807
808         self.with_new_scopes(move |this| {
809             // FIXME(cramertj): allow `async` non-`move` closures with arguments.
810             if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() {
811                 struct_span_err!(
812                     this.sess,
813                     fn_decl_span,
814                     E0708,
815                     "`async` non-`move` closures with parameters are not currently supported",
816                 )
817                 .help(
818                     "consider using `let` statements to manually capture \
819                     variables by reference before entering an `async move` closure",
820                 )
821                 .emit();
822             }
823
824             // Transform `async |x: u8| -> X { ... }` into
825             // `|x: u8| future_from_generator(|| -> X { ... })`.
826             let body_id = this.lower_fn_body(&outer_decl, |this| {
827                 let async_ret_ty =
828                     if let FnRetTy::Ty(ty) = &decl.output { Some(ty.clone()) } else { None };
829                 let async_body = this.make_async_expr(
830                     capture_clause,
831                     closure_id,
832                     async_ret_ty,
833                     body.span,
834                     hir::AsyncGeneratorKind::Closure,
835                     |this| this.with_new_scopes(|this| this.lower_expr_mut(body)),
836                 );
837                 this.expr(fn_decl_span, async_body, ThinVec::new())
838             });
839             hir::ExprKind::Closure(capture_clause, fn_decl, body_id, fn_decl_span, None)
840         })
841     }
842
843     /// Desugar `<start>..=<end>` into `std::ops::RangeInclusive::new(<start>, <end>)`.
844     fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> {
845         let id = self.next_id();
846         let e1 = self.lower_expr_mut(e1);
847         let e2 = self.lower_expr_mut(e2);
848         self.expr_call_std_assoc_fn(
849             id,
850             span,
851             &[sym::ops, sym::RangeInclusive],
852             "new",
853             arena_vec![self; e1, e2],
854         )
855     }
856
857     fn lower_expr_range(
858         &mut self,
859         span: Span,
860         e1: Option<&Expr>,
861         e2: Option<&Expr>,
862         lims: RangeLimits,
863     ) -> hir::ExprKind<'hir> {
864         use rustc_ast::ast::RangeLimits::*;
865
866         let path = match (e1, e2, lims) {
867             (None, None, HalfOpen) => sym::RangeFull,
868             (Some(..), None, HalfOpen) => sym::RangeFrom,
869             (None, Some(..), HalfOpen) => sym::RangeTo,
870             (Some(..), Some(..), HalfOpen) => sym::Range,
871             (None, Some(..), Closed) => sym::RangeToInclusive,
872             (Some(..), Some(..), Closed) => unreachable!(),
873             (_, None, Closed) => {
874                 self.diagnostic().span_fatal(span, "inclusive range with no end").raise()
875             }
876         };
877
878         let fields = self.arena.alloc_from_iter(
879             e1.iter().map(|e| ("start", e)).chain(e2.iter().map(|e| ("end", e))).map(|(s, e)| {
880                 let expr = self.lower_expr(&e);
881                 let ident = Ident::new(Symbol::intern(s), e.span);
882                 self.field(ident, expr, e.span)
883             }),
884         );
885
886         let is_unit = fields.is_empty();
887         let struct_path = [sym::ops, path];
888         let struct_path = self.std_path(span, &struct_path, None, is_unit);
889         let struct_path = hir::QPath::Resolved(None, struct_path);
890
891         if is_unit {
892             hir::ExprKind::Path(struct_path)
893         } else {
894             hir::ExprKind::Struct(self.arena.alloc(struct_path), fields, None)
895         }
896     }
897
898     fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hir::Destination {
899         let target_id = match destination {
900             Some((id, _)) => {
901                 if let Some(loop_id) = self.resolver.get_label_res(id) {
902                     Ok(self.lower_node_id(loop_id))
903                 } else {
904                     Err(hir::LoopIdError::UnresolvedLabel)
905                 }
906             }
907             None => self
908                 .loop_scopes
909                 .last()
910                 .cloned()
911                 .map(|id| Ok(self.lower_node_id(id)))
912                 .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)),
913         };
914         hir::Destination { label: destination.map(|(_, label)| label), target_id }
915     }
916
917     fn lower_jump_destination(&mut self, id: NodeId, opt_label: Option<Label>) -> hir::Destination {
918         if self.is_in_loop_condition && opt_label.is_none() {
919             hir::Destination {
920                 label: None,
921                 target_id: Err(hir::LoopIdError::UnlabeledCfInWhileCondition),
922             }
923         } else {
924             self.lower_loop_destination(opt_label.map(|label| (id, label)))
925         }
926     }
927
928     fn with_catch_scope<T>(&mut self, catch_id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
929         let len = self.catch_scopes.len();
930         self.catch_scopes.push(catch_id);
931
932         let result = f(self);
933         assert_eq!(
934             len + 1,
935             self.catch_scopes.len(),
936             "catch scopes should be added and removed in stack order"
937         );
938
939         self.catch_scopes.pop().unwrap();
940
941         result
942     }
943
944     fn with_loop_scope<T>(&mut self, loop_id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
945         // We're no longer in the base loop's condition; we're in another loop.
946         let was_in_loop_condition = self.is_in_loop_condition;
947         self.is_in_loop_condition = false;
948
949         let len = self.loop_scopes.len();
950         self.loop_scopes.push(loop_id);
951
952         let result = f(self);
953         assert_eq!(
954             len + 1,
955             self.loop_scopes.len(),
956             "loop scopes should be added and removed in stack order"
957         );
958
959         self.loop_scopes.pop().unwrap();
960
961         self.is_in_loop_condition = was_in_loop_condition;
962
963         result
964     }
965
966     fn with_loop_condition_scope<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
967         let was_in_loop_condition = self.is_in_loop_condition;
968         self.is_in_loop_condition = true;
969
970         let result = f(self);
971
972         self.is_in_loop_condition = was_in_loop_condition;
973
974         result
975     }
976
977     fn lower_expr_asm(&mut self, sp: Span, asm: &InlineAsm) -> hir::ExprKind<'hir> {
978         if self.sess.asm_arch.is_none() {
979             struct_span_err!(self.sess, sp, E0472, "asm! is unsupported on this target").emit();
980         }
981         if asm.options.contains(InlineAsmOptions::ATT_SYNTAX)
982             && !matches!(
983                 self.sess.asm_arch,
984                 Some(asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64)
985             )
986         {
987             self.sess
988                 .struct_span_err(sp, "the `att_syntax` option is only supported on x86")
989                 .emit();
990         }
991
992         // Lower operands to HIR, filter_map skips any operands with invalid
993         // register classes.
994         let sess = self.sess;
995         let operands: Vec<_> = asm
996             .operands
997             .iter()
998             .filter_map(|(op, op_sp)| {
999                 let lower_reg = |reg| {
1000                     Some(match reg {
1001                         InlineAsmRegOrRegClass::Reg(s) => asm::InlineAsmRegOrRegClass::Reg(
1002                             asm::InlineAsmReg::parse(
1003                                 sess.asm_arch?,
1004                                 |feature| sess.target_features.contains(&Symbol::intern(feature)),
1005                                 &sess.target.target,
1006                                 s,
1007                             )
1008                             .map_err(|e| {
1009                                 let msg = format!("invalid register `{}`: {}", s.as_str(), e);
1010                                 sess.struct_span_err(*op_sp, &msg).emit();
1011                             })
1012                             .ok()?,
1013                         ),
1014                         InlineAsmRegOrRegClass::RegClass(s) => {
1015                             asm::InlineAsmRegOrRegClass::RegClass(
1016                                 asm::InlineAsmRegClass::parse(sess.asm_arch?, s)
1017                                     .map_err(|e| {
1018                                         let msg = format!(
1019                                             "invalid register class `{}`: {}",
1020                                             s.as_str(),
1021                                             e
1022                                         );
1023                                         sess.struct_span_err(*op_sp, &msg).emit();
1024                                     })
1025                                     .ok()?,
1026                             )
1027                         }
1028                     })
1029                 };
1030
1031                 // lower_reg is executed last because we need to lower all
1032                 // sub-expressions even if we throw them away later.
1033                 let op = match *op {
1034                     InlineAsmOperand::In { reg, ref expr } => hir::InlineAsmOperand::In {
1035                         expr: self.lower_expr_mut(expr),
1036                         reg: lower_reg(reg)?,
1037                     },
1038                     InlineAsmOperand::Out { reg, late, ref expr } => hir::InlineAsmOperand::Out {
1039                         late,
1040                         expr: expr.as_ref().map(|expr| self.lower_expr_mut(expr)),
1041                         reg: lower_reg(reg)?,
1042                     },
1043                     InlineAsmOperand::InOut { reg, late, ref expr } => {
1044                         hir::InlineAsmOperand::InOut {
1045                             late,
1046                             expr: self.lower_expr_mut(expr),
1047                             reg: lower_reg(reg)?,
1048                         }
1049                     }
1050                     InlineAsmOperand::SplitInOut { reg, late, ref in_expr, ref out_expr } => {
1051                         hir::InlineAsmOperand::SplitInOut {
1052                             late,
1053                             in_expr: self.lower_expr_mut(in_expr),
1054                             out_expr: out_expr.as_ref().map(|expr| self.lower_expr_mut(expr)),
1055                             reg: lower_reg(reg)?,
1056                         }
1057                     }
1058                     InlineAsmOperand::Const { ref expr } => {
1059                         hir::InlineAsmOperand::Const { expr: self.lower_expr_mut(expr) }
1060                     }
1061                     InlineAsmOperand::Sym { ref expr } => {
1062                         hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) }
1063                     }
1064                 };
1065                 Some(op)
1066             })
1067             .collect();
1068
1069         // Stop if there were any errors when lowering the register classes
1070         if operands.len() != asm.operands.len() || sess.asm_arch.is_none() {
1071             return hir::ExprKind::Err;
1072         }
1073
1074         // Validate template modifiers against the register classes for the operands
1075         let asm_arch = sess.asm_arch.unwrap();
1076         for p in &asm.template {
1077             if let InlineAsmTemplatePiece::Placeholder {
1078                 operand_idx,
1079                 modifier: Some(modifier),
1080                 span: placeholder_span,
1081             } = *p
1082             {
1083                 let op_sp = asm.operands[operand_idx].1;
1084                 match &operands[operand_idx] {
1085                     hir::InlineAsmOperand::In { reg, .. }
1086                     | hir::InlineAsmOperand::Out { reg, .. }
1087                     | hir::InlineAsmOperand::InOut { reg, .. }
1088                     | hir::InlineAsmOperand::SplitInOut { reg, .. } => {
1089                         let class = reg.reg_class();
1090                         let valid_modifiers = class.valid_modifiers(asm_arch);
1091                         if !valid_modifiers.contains(&modifier) {
1092                             let mut err = sess.struct_span_err(
1093                                 placeholder_span,
1094                                 "invalid asm template modifier for this register class",
1095                             );
1096                             err.span_label(placeholder_span, "template modifier");
1097                             err.span_label(op_sp, "argument");
1098                             if !valid_modifiers.is_empty() {
1099                                 let mut mods = format!("`{}`", valid_modifiers[0]);
1100                                 for m in &valid_modifiers[1..] {
1101                                     let _ = write!(mods, ", `{}`", m);
1102                                 }
1103                                 err.note(&format!(
1104                                     "the `{}` register class supports \
1105                                      the following template modifiers: {}",
1106                                     class.name(),
1107                                     mods
1108                                 ));
1109                             } else {
1110                                 err.note(&format!(
1111                                     "the `{}` register class does not support template modifiers",
1112                                     class.name()
1113                                 ));
1114                             }
1115                             err.emit();
1116                         }
1117                     }
1118                     hir::InlineAsmOperand::Const { .. } => {
1119                         let mut err = sess.struct_span_err(
1120                             placeholder_span,
1121                             "asm template modifiers are not allowed for `const` arguments",
1122                         );
1123                         err.span_label(placeholder_span, "template modifier");
1124                         err.span_label(op_sp, "argument");
1125                         err.emit();
1126                     }
1127                     hir::InlineAsmOperand::Sym { .. } => {
1128                         let mut err = sess.struct_span_err(
1129                             placeholder_span,
1130                             "asm template modifiers are not allowed for `sym` arguments",
1131                         );
1132                         err.span_label(placeholder_span, "template modifier");
1133                         err.span_label(op_sp, "argument");
1134                         err.emit();
1135                     }
1136                 }
1137             }
1138         }
1139
1140         let mut used_input_regs = FxHashMap::default();
1141         let mut used_output_regs = FxHashMap::default();
1142         for (idx, op) in operands.iter().enumerate() {
1143             let op_sp = asm.operands[idx].1;
1144             if let Some(reg) = op.reg() {
1145                 // Validate register classes against currently enabled target
1146                 // features. We check that at least one type is available for
1147                 // the current target.
1148                 let reg_class = reg.reg_class();
1149                 let mut required_features = vec![];
1150                 for &(_, feature) in reg_class.supported_types(asm_arch) {
1151                     if let Some(feature) = feature {
1152                         if self.sess.target_features.contains(&Symbol::intern(feature)) {
1153                             required_features.clear();
1154                             break;
1155                         } else {
1156                             required_features.push(feature);
1157                         }
1158                     } else {
1159                         required_features.clear();
1160                         break;
1161                     }
1162                 }
1163                 required_features.sort();
1164                 required_features.dedup();
1165                 match &required_features[..] {
1166                     [] => {}
1167                     [feature] => {
1168                         let msg = format!(
1169                             "register class `{}` requires the `{}` target feature",
1170                             reg_class.name(),
1171                             feature
1172                         );
1173                         sess.struct_span_err(op_sp, &msg).emit();
1174                     }
1175                     features => {
1176                         let msg = format!(
1177                             "register class `{}` requires at least one target feature: {}",
1178                             reg_class.name(),
1179                             features.join(", ")
1180                         );
1181                         sess.struct_span_err(op_sp, &msg).emit();
1182                     }
1183                 }
1184
1185                 // Check for conflicts between explicit register operands.
1186                 if let asm::InlineAsmRegOrRegClass::Reg(reg) = reg {
1187                     let (input, output) = match op {
1188                         hir::InlineAsmOperand::In { .. } => (true, false),
1189                         // Late output do not conflict with inputs, but normal outputs do
1190                         hir::InlineAsmOperand::Out { late, .. } => (!late, true),
1191                         hir::InlineAsmOperand::InOut { .. }
1192                         | hir::InlineAsmOperand::SplitInOut { .. } => (true, true),
1193                         hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::Sym { .. } => {
1194                             unreachable!()
1195                         }
1196                     };
1197
1198                     // Flag to output the error only once per operand
1199                     let mut skip = false;
1200                     reg.overlapping_regs(|r| {
1201                         let mut check = |used_regs: &mut FxHashMap<asm::InlineAsmReg, usize>,
1202                                          input| {
1203                             match used_regs.entry(r) {
1204                                 Entry::Occupied(o) => {
1205                                     if !skip {
1206                                         skip = true;
1207
1208                                         let idx2 = *o.get();
1209                                         let op2 = &operands[idx2];
1210                                         let op_sp2 = asm.operands[idx2].1;
1211                                         let reg2 = match op2.reg() {
1212                                             Some(asm::InlineAsmRegOrRegClass::Reg(r)) => r,
1213                                             _ => unreachable!(),
1214                                         };
1215
1216                                         let msg = format!(
1217                                             "register `{}` conflicts with register `{}`",
1218                                             reg.name(),
1219                                             reg2.name()
1220                                         );
1221                                         let mut err = sess.struct_span_err(op_sp, &msg);
1222                                         err.span_label(
1223                                             op_sp,
1224                                             &format!("register `{}`", reg.name()),
1225                                         );
1226                                         err.span_label(
1227                                             op_sp2,
1228                                             &format!("register `{}`", reg2.name()),
1229                                         );
1230
1231                                         match (op, op2) {
1232                                             (
1233                                                 hir::InlineAsmOperand::In { .. },
1234                                                 hir::InlineAsmOperand::Out { late, .. },
1235                                             )
1236                                             | (
1237                                                 hir::InlineAsmOperand::Out { late, .. },
1238                                                 hir::InlineAsmOperand::In { .. },
1239                                             ) => {
1240                                                 assert!(!*late);
1241                                                 let out_op_sp = if input { op_sp2 } else { op_sp };
1242                                                 let msg = "use `lateout` instead of \
1243                                                      `out` to avoid conflict";
1244                                                 err.span_help(out_op_sp, msg);
1245                                             }
1246                                             _ => {}
1247                                         }
1248
1249                                         err.emit();
1250                                     }
1251                                 }
1252                                 Entry::Vacant(v) => {
1253                                     v.insert(idx);
1254                                 }
1255                             }
1256                         };
1257                         if input {
1258                             check(&mut used_input_regs, true);
1259                         }
1260                         if output {
1261                             check(&mut used_output_regs, false);
1262                         }
1263                     });
1264                 }
1265             }
1266         }
1267
1268         let operands = self.arena.alloc_from_iter(operands);
1269         let template = self.arena.alloc_from_iter(asm.template.iter().cloned());
1270         let line_spans = self.arena.alloc_slice(&asm.line_spans[..]);
1271         let hir_asm = hir::InlineAsm { template, operands, options: asm.options, line_spans };
1272         hir::ExprKind::InlineAsm(self.arena.alloc(hir_asm))
1273     }
1274
1275     fn lower_expr_llvm_asm(&mut self, asm: &LlvmInlineAsm) -> hir::ExprKind<'hir> {
1276         let inner = hir::LlvmInlineAsmInner {
1277             inputs: asm.inputs.iter().map(|&(c, _)| c).collect(),
1278             outputs: asm
1279                 .outputs
1280                 .iter()
1281                 .map(|out| hir::LlvmInlineAsmOutput {
1282                     constraint: out.constraint,
1283                     is_rw: out.is_rw,
1284                     is_indirect: out.is_indirect,
1285                     span: out.expr.span,
1286                 })
1287                 .collect(),
1288             asm: asm.asm,
1289             asm_str_style: asm.asm_str_style,
1290             clobbers: asm.clobbers.clone(),
1291             volatile: asm.volatile,
1292             alignstack: asm.alignstack,
1293             dialect: asm.dialect,
1294         };
1295         let hir_asm = hir::LlvmInlineAsm {
1296             inner,
1297             inputs_exprs: self.arena.alloc_from_iter(
1298                 asm.inputs.iter().map(|&(_, ref input)| self.lower_expr_mut(input)),
1299             ),
1300             outputs_exprs: self
1301                 .arena
1302                 .alloc_from_iter(asm.outputs.iter().map(|out| self.lower_expr_mut(&out.expr))),
1303         };
1304         hir::ExprKind::LlvmInlineAsm(self.arena.alloc(hir_asm))
1305     }
1306
1307     fn lower_field(&mut self, f: &Field) -> hir::Field<'hir> {
1308         hir::Field {
1309             hir_id: self.next_id(),
1310             ident: f.ident,
1311             expr: self.lower_expr(&f.expr),
1312             span: f.span,
1313             is_shorthand: f.is_shorthand,
1314         }
1315     }
1316
1317     fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> {
1318         match self.generator_kind {
1319             Some(hir::GeneratorKind::Gen) => {}
1320             Some(hir::GeneratorKind::Async(_)) => {
1321                 struct_span_err!(
1322                     self.sess,
1323                     span,
1324                     E0727,
1325                     "`async` generators are not yet supported"
1326                 )
1327                 .emit();
1328             }
1329             None => self.generator_kind = Some(hir::GeneratorKind::Gen),
1330         }
1331
1332         let expr =
1333             opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span));
1334
1335         hir::ExprKind::Yield(expr, hir::YieldSource::Yield)
1336     }
1337
1338     /// Desugar `ExprForLoop` from: `[opt_ident]: for <pat> in <head> <body>` into:
1339     /// ```rust
1340     /// {
1341     ///     let result = match ::std::iter::IntoIterator::into_iter(<head>) {
1342     ///         mut iter => {
1343     ///             [opt_ident]: loop {
1344     ///                 let mut __next;
1345     ///                 match ::std::iter::Iterator::next(&mut iter) {
1346     ///                     ::std::option::Option::Some(val) => __next = val,
1347     ///                     ::std::option::Option::None => break
1348     ///                 };
1349     ///                 let <pat> = __next;
1350     ///                 StmtKind::Expr(<body>);
1351     ///             }
1352     ///         }
1353     ///     };
1354     ///     result
1355     /// }
1356     /// ```
1357     fn lower_expr_for(
1358         &mut self,
1359         e: &Expr,
1360         pat: &Pat,
1361         head: &Expr,
1362         body: &Block,
1363         opt_label: Option<Label>,
1364     ) -> hir::Expr<'hir> {
1365         let orig_head_span = head.span;
1366         // expand <head>
1367         let mut head = self.lower_expr_mut(head);
1368         let desugared_span = self.mark_span_with_reason(
1369             DesugaringKind::ForLoop(ForLoopLoc::Head),
1370             orig_head_span,
1371             None,
1372         );
1373         head.span = desugared_span;
1374
1375         let iter = Ident::with_dummy_span(sym::iter);
1376
1377         let next_ident = Ident::with_dummy_span(sym::__next);
1378         let (next_pat, next_pat_hid) = self.pat_ident_binding_mode(
1379             desugared_span,
1380             next_ident,
1381             hir::BindingAnnotation::Mutable,
1382         );
1383
1384         // `::std::option::Option::Some(val) => __next = val`
1385         let pat_arm = {
1386             let val_ident = Ident::with_dummy_span(sym::val);
1387             let (val_pat, val_pat_hid) = self.pat_ident(pat.span, val_ident);
1388             let val_expr = self.expr_ident(pat.span, val_ident, val_pat_hid);
1389             let next_expr = self.expr_ident(pat.span, next_ident, next_pat_hid);
1390             let assign = self.arena.alloc(self.expr(
1391                 pat.span,
1392                 hir::ExprKind::Assign(next_expr, val_expr, pat.span),
1393                 ThinVec::new(),
1394             ));
1395             let some_pat = self.pat_some(pat.span, val_pat);
1396             self.arm(some_pat, assign)
1397         };
1398
1399         // `::std::option::Option::None => break`
1400         let break_arm = {
1401             let break_expr =
1402                 self.with_loop_scope(e.id, |this| this.expr_break(e.span, ThinVec::new()));
1403             let pat = self.pat_none(e.span);
1404             self.arm(pat, break_expr)
1405         };
1406
1407         // `mut iter`
1408         let (iter_pat, iter_pat_nid) =
1409             self.pat_ident_binding_mode(desugared_span, iter, hir::BindingAnnotation::Mutable);
1410
1411         // `match ::std::iter::Iterator::next(&mut iter) { ... }`
1412         let match_expr = {
1413             let iter = self.expr_ident(desugared_span, iter, iter_pat_nid);
1414             let ref_mut_iter = self.expr_mut_addr_of(desugared_span, iter);
1415             let next_path = &[sym::iter, sym::Iterator, sym::next];
1416             let next_expr =
1417                 self.expr_call_std_path(desugared_span, next_path, arena_vec![self; ref_mut_iter]);
1418             let arms = arena_vec![self; pat_arm, break_arm];
1419
1420             self.expr_match(desugared_span, next_expr, arms, hir::MatchSource::ForLoopDesugar)
1421         };
1422         let match_stmt = self.stmt_expr(desugared_span, match_expr);
1423
1424         let next_expr = self.expr_ident(desugared_span, next_ident, next_pat_hid);
1425
1426         // `let mut __next`
1427         let next_let = self.stmt_let_pat(
1428             ThinVec::new(),
1429             desugared_span,
1430             None,
1431             next_pat,
1432             hir::LocalSource::ForLoopDesugar,
1433         );
1434
1435         // `let <pat> = __next`
1436         let pat = self.lower_pat(pat);
1437         let pat_let = self.stmt_let_pat(
1438             ThinVec::new(),
1439             desugared_span,
1440             Some(next_expr),
1441             pat,
1442             hir::LocalSource::ForLoopDesugar,
1443         );
1444
1445         let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
1446         let body_expr = self.expr_block(body_block, ThinVec::new());
1447         let body_stmt = self.stmt_expr(body.span, body_expr);
1448
1449         let loop_block = self.block_all(
1450             e.span,
1451             arena_vec![self; next_let, match_stmt, pat_let, body_stmt],
1452             None,
1453         );
1454
1455         // `[opt_ident]: loop { ... }`
1456         let kind = hir::ExprKind::Loop(loop_block, opt_label, hir::LoopSource::ForLoop);
1457         let loop_expr = self.arena.alloc(hir::Expr {
1458             hir_id: self.lower_node_id(e.id),
1459             kind,
1460             span: e.span,
1461             attrs: ThinVec::new(),
1462         });
1463
1464         // `mut iter => { ... }`
1465         let iter_arm = self.arm(iter_pat, loop_expr);
1466
1467         let into_iter_span = self.mark_span_with_reason(
1468             DesugaringKind::ForLoop(ForLoopLoc::IntoIter),
1469             orig_head_span,
1470             None,
1471         );
1472
1473         // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
1474         let into_iter_expr = {
1475             let into_iter_path = &[sym::iter, sym::IntoIterator, sym::into_iter];
1476             self.expr_call_std_path(into_iter_span, into_iter_path, arena_vec![self; head])
1477         };
1478
1479         let match_expr = self.arena.alloc(self.expr_match(
1480             desugared_span,
1481             into_iter_expr,
1482             arena_vec![self; iter_arm],
1483             hir::MatchSource::ForLoopDesugar,
1484         ));
1485
1486         // This is effectively `{ let _result = ...; _result }`.
1487         // The construct was introduced in #21984 and is necessary to make sure that
1488         // temporaries in the `head` expression are dropped and do not leak to the
1489         // surrounding scope of the `match` since the `match` is not a terminating scope.
1490         //
1491         // Also, add the attributes to the outer returned expr node.
1492         self.expr_drop_temps_mut(desugared_span, match_expr, e.attrs.clone())
1493     }
1494
1495     /// Desugar `ExprKind::Try` from: `<expr>?` into:
1496     /// ```rust
1497     /// match Try::into_result(<expr>) {
1498     ///     Ok(val) => #[allow(unreachable_code)] val,
1499     ///     Err(err) => #[allow(unreachable_code)]
1500     ///                 // If there is an enclosing `try {...}`:
1501     ///                 break 'catch_target Try::from_error(From::from(err)),
1502     ///                 // Otherwise:
1503     ///                 return Try::from_error(From::from(err)),
1504     /// }
1505     /// ```
1506     fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir> {
1507         let unstable_span = self.mark_span_with_reason(
1508             DesugaringKind::QuestionMark,
1509             span,
1510             self.allow_try_trait.clone(),
1511         );
1512         let try_span = self.sess.source_map().end_point(span);
1513         let try_span = self.mark_span_with_reason(
1514             DesugaringKind::QuestionMark,
1515             try_span,
1516             self.allow_try_trait.clone(),
1517         );
1518
1519         // `Try::into_result(<expr>)`
1520         let scrutinee = {
1521             // expand <expr>
1522             let sub_expr = self.lower_expr_mut(sub_expr);
1523
1524             let path = &[sym::ops, sym::Try, sym::into_result];
1525             self.expr_call_std_path(unstable_span, path, arena_vec![self; sub_expr])
1526         };
1527
1528         // `#[allow(unreachable_code)]`
1529         let attr = {
1530             // `allow(unreachable_code)`
1531             let allow = {
1532                 let allow_ident = Ident::new(sym::allow, span);
1533                 let uc_ident = Ident::new(sym::unreachable_code, span);
1534                 let uc_nested = attr::mk_nested_word_item(uc_ident);
1535                 attr::mk_list_item(allow_ident, vec![uc_nested])
1536             };
1537             attr::mk_attr_outer(allow)
1538         };
1539         let attrs = vec![attr];
1540
1541         // `Ok(val) => #[allow(unreachable_code)] val,`
1542         let ok_arm = {
1543             let val_ident = Ident::with_dummy_span(sym::val);
1544             let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident);
1545             let val_expr = self.arena.alloc(self.expr_ident_with_attrs(
1546                 span,
1547                 val_ident,
1548                 val_pat_nid,
1549                 ThinVec::from(attrs.clone()),
1550             ));
1551             let ok_pat = self.pat_ok(span, val_pat);
1552             self.arm(ok_pat, val_expr)
1553         };
1554
1555         // `Err(err) => #[allow(unreachable_code)]
1556         //              return Try::from_error(From::from(err)),`
1557         let err_arm = {
1558             let err_ident = Ident::with_dummy_span(sym::err);
1559             let (err_local, err_local_nid) = self.pat_ident(try_span, err_ident);
1560             let from_expr = {
1561                 let from_path = &[sym::convert, sym::From, sym::from];
1562                 let err_expr = self.expr_ident_mut(try_span, err_ident, err_local_nid);
1563                 self.expr_call_std_path(try_span, from_path, arena_vec![self; err_expr])
1564             };
1565             let from_err_expr =
1566                 self.wrap_in_try_constructor(sym::from_error, unstable_span, from_expr, try_span);
1567             let thin_attrs = ThinVec::from(attrs);
1568             let catch_scope = self.catch_scopes.last().copied();
1569             let ret_expr = if let Some(catch_node) = catch_scope {
1570                 let target_id = Ok(self.lower_node_id(catch_node));
1571                 self.arena.alloc(self.expr(
1572                     try_span,
1573                     hir::ExprKind::Break(
1574                         hir::Destination { label: None, target_id },
1575                         Some(from_err_expr),
1576                     ),
1577                     thin_attrs,
1578                 ))
1579             } else {
1580                 self.arena.alloc(self.expr(
1581                     try_span,
1582                     hir::ExprKind::Ret(Some(from_err_expr)),
1583                     thin_attrs,
1584                 ))
1585             };
1586
1587             let err_pat = self.pat_err(try_span, err_local);
1588             self.arm(err_pat, ret_expr)
1589         };
1590
1591         hir::ExprKind::Match(
1592             scrutinee,
1593             arena_vec![self; err_arm, ok_arm],
1594             hir::MatchSource::TryDesugar,
1595         )
1596     }
1597
1598     // =========================================================================
1599     // Helper methods for building HIR.
1600     // =========================================================================
1601
1602     /// Constructs a `true` or `false` literal expression.
1603     pub(super) fn expr_bool(&mut self, span: Span, val: bool) -> &'hir hir::Expr<'hir> {
1604         let lit = Spanned { span, node: LitKind::Bool(val) };
1605         self.arena.alloc(self.expr(span, hir::ExprKind::Lit(lit), ThinVec::new()))
1606     }
1607
1608     /// Wrap the given `expr` in a terminating scope using `hir::ExprKind::DropTemps`.
1609     ///
1610     /// In terms of drop order, it has the same effect as wrapping `expr` in
1611     /// `{ let _t = $expr; _t }` but should provide better compile-time performance.
1612     ///
1613     /// The drop order can be important in e.g. `if expr { .. }`.
1614     pub(super) fn expr_drop_temps(
1615         &mut self,
1616         span: Span,
1617         expr: &'hir hir::Expr<'hir>,
1618         attrs: AttrVec,
1619     ) -> &'hir hir::Expr<'hir> {
1620         self.arena.alloc(self.expr_drop_temps_mut(span, expr, attrs))
1621     }
1622
1623     pub(super) fn expr_drop_temps_mut(
1624         &mut self,
1625         span: Span,
1626         expr: &'hir hir::Expr<'hir>,
1627         attrs: AttrVec,
1628     ) -> hir::Expr<'hir> {
1629         self.expr(span, hir::ExprKind::DropTemps(expr), attrs)
1630     }
1631
1632     fn expr_match(
1633         &mut self,
1634         span: Span,
1635         arg: &'hir hir::Expr<'hir>,
1636         arms: &'hir [hir::Arm<'hir>],
1637         source: hir::MatchSource,
1638     ) -> hir::Expr<'hir> {
1639         self.expr(span, hir::ExprKind::Match(arg, arms, source), ThinVec::new())
1640     }
1641
1642     fn expr_break(&mut self, span: Span, attrs: AttrVec) -> &'hir hir::Expr<'hir> {
1643         let expr_break = hir::ExprKind::Break(self.lower_loop_destination(None), None);
1644         self.arena.alloc(self.expr(span, expr_break, attrs))
1645     }
1646
1647     fn expr_mut_addr_of(&mut self, span: Span, e: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
1648         self.expr(
1649             span,
1650             hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e),
1651             ThinVec::new(),
1652         )
1653     }
1654
1655     fn expr_unit(&mut self, sp: Span) -> &'hir hir::Expr<'hir> {
1656         self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[]), ThinVec::new()))
1657     }
1658
1659     fn expr_call_mut(
1660         &mut self,
1661         span: Span,
1662         e: &'hir hir::Expr<'hir>,
1663         args: &'hir [hir::Expr<'hir>],
1664     ) -> hir::Expr<'hir> {
1665         self.expr(span, hir::ExprKind::Call(e, args), ThinVec::new())
1666     }
1667
1668     fn expr_call(
1669         &mut self,
1670         span: Span,
1671         e: &'hir hir::Expr<'hir>,
1672         args: &'hir [hir::Expr<'hir>],
1673     ) -> &'hir hir::Expr<'hir> {
1674         self.arena.alloc(self.expr_call_mut(span, e, args))
1675     }
1676
1677     // Note: associated functions must use `expr_call_std_path`.
1678     fn expr_call_std_path_mut(
1679         &mut self,
1680         span: Span,
1681         path_components: &[Symbol],
1682         args: &'hir [hir::Expr<'hir>],
1683     ) -> hir::Expr<'hir> {
1684         let path =
1685             self.arena.alloc(self.expr_std_path(span, path_components, None, ThinVec::new()));
1686         self.expr_call_mut(span, path, args)
1687     }
1688
1689     fn expr_call_std_path(
1690         &mut self,
1691         span: Span,
1692         path_components: &[Symbol],
1693         args: &'hir [hir::Expr<'hir>],
1694     ) -> &'hir hir::Expr<'hir> {
1695         self.arena.alloc(self.expr_call_std_path_mut(span, path_components, args))
1696     }
1697
1698     // Create an expression calling an associated function of an std type.
1699     //
1700     // Associated functions cannot be resolved through the normal `std_path` function,
1701     // as they are resolved differently and so cannot use `expr_call_std_path`.
1702     //
1703     // This function accepts the path component (`ty_path_components`) separately from
1704     // the name of the associated function (`assoc_fn_name`) in order to facilitate
1705     // separate resolution of the type and creation of a path referring to its associated
1706     // function.
1707     fn expr_call_std_assoc_fn(
1708         &mut self,
1709         ty_path_id: hir::HirId,
1710         span: Span,
1711         ty_path_components: &[Symbol],
1712         assoc_fn_name: &str,
1713         args: &'hir [hir::Expr<'hir>],
1714     ) -> hir::ExprKind<'hir> {
1715         let ty_path = self.std_path(span, ty_path_components, None, false);
1716         let ty =
1717             self.arena.alloc(self.ty_path(ty_path_id, span, hir::QPath::Resolved(None, ty_path)));
1718         let fn_seg = self.arena.alloc(hir::PathSegment::from_ident(Ident::from_str(assoc_fn_name)));
1719         let fn_path = hir::QPath::TypeRelative(ty, fn_seg);
1720         let fn_expr =
1721             self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new()));
1722         hir::ExprKind::Call(fn_expr, args)
1723     }
1724
1725     fn expr_std_path(
1726         &mut self,
1727         span: Span,
1728         components: &[Symbol],
1729         params: Option<&'hir hir::GenericArgs<'hir>>,
1730         attrs: AttrVec,
1731     ) -> hir::Expr<'hir> {
1732         let path = self.std_path(span, components, params, true);
1733         self.expr(span, hir::ExprKind::Path(hir::QPath::Resolved(None, path)), attrs)
1734     }
1735
1736     pub(super) fn expr_ident(
1737         &mut self,
1738         sp: Span,
1739         ident: Ident,
1740         binding: hir::HirId,
1741     ) -> &'hir hir::Expr<'hir> {
1742         self.arena.alloc(self.expr_ident_mut(sp, ident, binding))
1743     }
1744
1745     pub(super) fn expr_ident_mut(
1746         &mut self,
1747         sp: Span,
1748         ident: Ident,
1749         binding: hir::HirId,
1750     ) -> hir::Expr<'hir> {
1751         self.expr_ident_with_attrs(sp, ident, binding, ThinVec::new())
1752     }
1753
1754     fn expr_ident_with_attrs(
1755         &mut self,
1756         span: Span,
1757         ident: Ident,
1758         binding: hir::HirId,
1759         attrs: AttrVec,
1760     ) -> hir::Expr<'hir> {
1761         let expr_path = hir::ExprKind::Path(hir::QPath::Resolved(
1762             None,
1763             self.arena.alloc(hir::Path {
1764                 span,
1765                 res: Res::Local(binding),
1766                 segments: arena_vec![self; hir::PathSegment::from_ident(ident)],
1767             }),
1768         ));
1769
1770         self.expr(span, expr_path, attrs)
1771     }
1772
1773     fn expr_unsafe(&mut self, expr: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
1774         let hir_id = self.next_id();
1775         let span = expr.span;
1776         self.expr(
1777             span,
1778             hir::ExprKind::Block(
1779                 self.arena.alloc(hir::Block {
1780                     stmts: &[],
1781                     expr: Some(expr),
1782                     hir_id,
1783                     rules: hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::CompilerGenerated),
1784                     span,
1785                     targeted_by_break: false,
1786                 }),
1787                 None,
1788             ),
1789             ThinVec::new(),
1790         )
1791     }
1792
1793     fn expr_block_empty(&mut self, span: Span) -> &'hir hir::Expr<'hir> {
1794         let blk = self.block_all(span, &[], None);
1795         let expr = self.expr_block(blk, ThinVec::new());
1796         self.arena.alloc(expr)
1797     }
1798
1799     pub(super) fn expr_block(
1800         &mut self,
1801         b: &'hir hir::Block<'hir>,
1802         attrs: AttrVec,
1803     ) -> hir::Expr<'hir> {
1804         self.expr(b.span, hir::ExprKind::Block(b, None), attrs)
1805     }
1806
1807     pub(super) fn expr(
1808         &mut self,
1809         span: Span,
1810         kind: hir::ExprKind<'hir>,
1811         attrs: AttrVec,
1812     ) -> hir::Expr<'hir> {
1813         hir::Expr { hir_id: self.next_id(), kind, span, attrs }
1814     }
1815
1816     fn field(&mut self, ident: Ident, expr: &'hir hir::Expr<'hir>, span: Span) -> hir::Field<'hir> {
1817         hir::Field { hir_id: self.next_id(), ident, span, expr, is_shorthand: false }
1818     }
1819
1820     fn arm(&mut self, pat: &'hir hir::Pat<'hir>, expr: &'hir hir::Expr<'hir>) -> hir::Arm<'hir> {
1821         hir::Arm {
1822             hir_id: self.next_id(),
1823             attrs: &[],
1824             pat,
1825             guard: None,
1826             span: expr.span,
1827             body: expr,
1828         }
1829     }
1830 }