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