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