]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_ast_lowering/src/expr.rs
Rollup merge of #103868 - compiler-errors:trait-engine-less, r=jackh726
[rust.git] / compiler / rustc_ast_lowering / src / expr.rs
1 use super::errors::{
2     AsyncGeneratorsNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks,
3     BaseExpressionDoubleDot, ClosureCannotBeStatic, FunctionalRecordUpdateDestructuringAssignemnt,
4     GeneratorTooManyParameters, InclusiveRangeWithNoEnd, NotSupportedForLifetimeBinderAsyncClosure,
5     RustcBoxAttributeError, UnderscoreExprLhsAssign,
6 };
7 use super::ResolverAstLoweringExt;
8 use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
9 use crate::{FnDeclKind, ImplTraitPosition};
10 use rustc_ast::attr;
11 use rustc_ast::ptr::P as AstP;
12 use rustc_ast::*;
13 use rustc_data_structures::stack::ensure_sufficient_stack;
14 use rustc_hir as hir;
15 use rustc_hir::def::Res;
16 use rustc_hir::definitions::DefPathData;
17 use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
18 use rustc_span::symbol::{sym, Ident};
19 use rustc_span::DUMMY_SP;
20 use thin_vec::thin_vec;
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_array_length(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 e.attrs.get(0).map_or(false, |a| a.has_name(sym::rustc_box)) {
48                         if let [inner] = &args[..] && e.attrs.len() == 1 {
49                             let kind = hir::ExprKind::Box(self.lower_expr(&inner));
50                             let hir_id = self.lower_node_id(e.id);
51                             return hir::Expr { hir_id, kind, span: self.lower_span(e.span) };
52                         } else {
53                             self.tcx.sess.emit_err(RustcBoxAttributeError { span: e.span });
54                             hir::ExprKind::Err
55                         }
56                     } else if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) {
57                         self.lower_legacy_const_generics((**f).clone(), args.clone(), &legacy_args)
58                     } else {
59                         let f = self.lower_expr(f);
60                         hir::ExprKind::Call(f, self.lower_exprs(args))
61                     }
62                 }
63                 ExprKind::MethodCall(ref seg, ref receiver, ref args, span) => {
64                     let hir_seg = self.arena.alloc(self.lower_path_segment(
65                         e.span,
66                         seg,
67                         ParamMode::Optional,
68                         ParenthesizedGenericArgs::Err,
69                         &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
70                     ));
71                     let receiver = self.lower_expr(receiver);
72                     let args =
73                         self.arena.alloc_from_iter(args.iter().map(|x| self.lower_expr_mut(x)));
74                     hir::ExprKind::MethodCall(hir_seg, receiver, args, self.lower_span(span))
75                 }
76                 ExprKind::Binary(binop, ref lhs, ref rhs) => {
77                     let binop = self.lower_binop(binop);
78                     let lhs = self.lower_expr(lhs);
79                     let rhs = self.lower_expr(rhs);
80                     hir::ExprKind::Binary(binop, lhs, rhs)
81                 }
82                 ExprKind::Unary(op, ref ohs) => {
83                     let op = self.lower_unop(op);
84                     let ohs = self.lower_expr(ohs);
85                     hir::ExprKind::Unary(op, ohs)
86                 }
87                 ExprKind::Lit(ref l) => {
88                     hir::ExprKind::Lit(respan(self.lower_span(l.span), l.kind.clone()))
89                 }
90                 ExprKind::Cast(ref expr, ref ty) => {
91                     let expr = self.lower_expr(expr);
92                     let ty =
93                         self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
94                     hir::ExprKind::Cast(expr, ty)
95                 }
96                 ExprKind::Type(ref expr, ref ty) => {
97                     let expr = self.lower_expr(expr);
98                     let ty =
99                         self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
100                     hir::ExprKind::Type(expr, ty)
101                 }
102                 ExprKind::AddrOf(k, m, ref ohs) => {
103                     let ohs = self.lower_expr(ohs);
104                     hir::ExprKind::AddrOf(k, m, ohs)
105                 }
106                 ExprKind::Let(ref pat, ref scrutinee, span) => {
107                     hir::ExprKind::Let(self.arena.alloc(hir::Let {
108                         hir_id: self.next_id(),
109                         span: self.lower_span(span),
110                         pat: self.lower_pat(pat),
111                         ty: None,
112                         init: self.lower_expr(scrutinee),
113                     }))
114                 }
115                 ExprKind::If(ref cond, ref then, ref else_opt) => {
116                     self.lower_expr_if(cond, then, else_opt.as_deref())
117                 }
118                 ExprKind::While(ref cond, ref body, opt_label) => {
119                     self.with_loop_scope(e.id, |this| {
120                         let span =
121                             this.mark_span_with_reason(DesugaringKind::WhileLoop, e.span, None);
122                         this.lower_expr_while_in_loop_scope(span, cond, body, opt_label)
123                     })
124                 }
125                 ExprKind::Loop(ref body, opt_label) => self.with_loop_scope(e.id, |this| {
126                     hir::ExprKind::Loop(
127                         this.lower_block(body, false),
128                         this.lower_label(opt_label),
129                         hir::LoopSource::Loop,
130                         DUMMY_SP,
131                     )
132                 }),
133                 ExprKind::TryBlock(ref body) => self.lower_expr_try_block(body),
134                 ExprKind::Match(ref expr, ref arms) => hir::ExprKind::Match(
135                     self.lower_expr(expr),
136                     self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))),
137                     hir::MatchSource::Normal,
138                 ),
139                 ExprKind::Async(capture_clause, closure_node_id, ref block) => self
140                     .make_async_expr(
141                         capture_clause,
142                         closure_node_id,
143                         None,
144                         block.span,
145                         hir::AsyncGeneratorKind::Block,
146                         |this| this.with_new_scopes(|this| this.lower_block_expr(block)),
147                     ),
148                 ExprKind::Await(ref expr) => {
149                     let dot_await_span = if expr.span.hi() < e.span.hi() {
150                         let span_with_whitespace = self
151                             .tcx
152                             .sess
153                             .source_map()
154                             .span_extend_while(expr.span, char::is_whitespace)
155                             .unwrap_or(expr.span);
156                         span_with_whitespace.shrink_to_hi().with_hi(e.span.hi())
157                     } else {
158                         // this is a recovered `await expr`
159                         e.span
160                     };
161                     self.lower_expr_await(dot_await_span, expr)
162                 }
163                 ExprKind::Closure(
164                     ref binder,
165                     capture_clause,
166                     asyncness,
167                     movability,
168                     ref decl,
169                     ref body,
170                     fn_decl_span,
171                 ) => {
172                     if let Async::Yes { closure_id, .. } = asyncness {
173                         self.lower_expr_async_closure(
174                             binder,
175                             capture_clause,
176                             e.id,
177                             closure_id,
178                             decl,
179                             body,
180                             fn_decl_span,
181                         )
182                     } else {
183                         self.lower_expr_closure(
184                             binder,
185                             capture_clause,
186                             e.id,
187                             movability,
188                             decl,
189                             body,
190                             fn_decl_span,
191                         )
192                     }
193                 }
194                 ExprKind::Block(ref blk, opt_label) => {
195                     let opt_label = self.lower_label(opt_label);
196                     hir::ExprKind::Block(self.lower_block(blk, opt_label.is_some()), opt_label)
197                 }
198                 ExprKind::Assign(ref el, ref er, span) => {
199                     self.lower_expr_assign(el, er, span, e.span)
200                 }
201                 ExprKind::AssignOp(op, ref el, ref er) => hir::ExprKind::AssignOp(
202                     self.lower_binop(op),
203                     self.lower_expr(el),
204                     self.lower_expr(er),
205                 ),
206                 ExprKind::Field(ref el, ident) => {
207                     hir::ExprKind::Field(self.lower_expr(el), self.lower_ident(ident))
208                 }
209                 ExprKind::Index(ref el, ref er) => {
210                     hir::ExprKind::Index(self.lower_expr(el), self.lower_expr(er))
211                 }
212                 ExprKind::Range(Some(ref e1), Some(ref e2), RangeLimits::Closed) => {
213                     self.lower_expr_range_closed(e.span, e1, e2)
214                 }
215                 ExprKind::Range(ref e1, ref e2, lims) => {
216                     self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), lims)
217                 }
218                 ExprKind::Underscore => {
219                     self.tcx.sess.emit_err(UnderscoreExprLhsAssign { span: e.span });
220                     hir::ExprKind::Err
221                 }
222                 ExprKind::Path(ref qself, ref path) => {
223                     let qpath = self.lower_qpath(
224                         e.id,
225                         qself,
226                         path,
227                         ParamMode::Optional,
228                         &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
229                     );
230                     hir::ExprKind::Path(qpath)
231                 }
232                 ExprKind::Break(opt_label, ref opt_expr) => {
233                     let opt_expr = opt_expr.as_ref().map(|x| self.lower_expr(x));
234                     hir::ExprKind::Break(self.lower_jump_destination(e.id, opt_label), opt_expr)
235                 }
236                 ExprKind::Continue(opt_label) => {
237                     hir::ExprKind::Continue(self.lower_jump_destination(e.id, opt_label))
238                 }
239                 ExprKind::Ret(ref e) => {
240                     let e = e.as_ref().map(|x| self.lower_expr(x));
241                     hir::ExprKind::Ret(e)
242                 }
243                 ExprKind::Yeet(ref sub_expr) => self.lower_expr_yeet(e.span, sub_expr.as_deref()),
244                 ExprKind::InlineAsm(ref asm) => {
245                     hir::ExprKind::InlineAsm(self.lower_inline_asm(e.span, asm))
246                 }
247                 ExprKind::Struct(ref se) => {
248                     let rest = match &se.rest {
249                         StructRest::Base(e) => Some(self.lower_expr(e)),
250                         StructRest::Rest(sp) => {
251                             self.tcx.sess.emit_err(BaseExpressionDoubleDot { span: *sp });
252                             Some(&*self.arena.alloc(self.expr_err(*sp)))
253                         }
254                         StructRest::None => None,
255                     };
256                     hir::ExprKind::Struct(
257                         self.arena.alloc(self.lower_qpath(
258                             e.id,
259                             &se.qself,
260                             &se.path,
261                             ParamMode::Optional,
262                             &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
263                         )),
264                         self.arena
265                             .alloc_from_iter(se.fields.iter().map(|x| self.lower_expr_field(x))),
266                         rest,
267                     )
268                 }
269                 ExprKind::Yield(ref opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
270                 ExprKind::Err => hir::ExprKind::Err,
271                 ExprKind::Try(ref sub_expr) => self.lower_expr_try(e.span, sub_expr),
272                 ExprKind::Paren(ref ex) => {
273                     let mut ex = self.lower_expr_mut(ex);
274                     // Include parens in span, but only if it is a super-span.
275                     if e.span.contains(ex.span) {
276                         ex.span = self.lower_span(e.span);
277                     }
278                     // Merge attributes into the inner expression.
279                     if !e.attrs.is_empty() {
280                         let old_attrs =
281                             self.attrs.get(&ex.hir_id.local_id).map(|la| *la).unwrap_or(&[]);
282                         self.attrs.insert(
283                             ex.hir_id.local_id,
284                             &*self.arena.alloc_from_iter(
285                                 e.attrs
286                                     .iter()
287                                     .map(|a| self.lower_attr(a))
288                                     .chain(old_attrs.iter().cloned()),
289                             ),
290                         );
291                     }
292                     return ex;
293                 }
294
295                 // Desugar `ExprForLoop`
296                 // from: `[opt_ident]: for <pat> in <head> <body>`
297                 ExprKind::ForLoop(ref pat, ref head, ref body, opt_label) => {
298                     return self.lower_expr_for(e, pat, head, body, opt_label);
299                 }
300                 ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),
301             };
302
303             let hir_id = self.lower_node_id(e.id);
304             self.lower_attrs(hir_id, &e.attrs);
305             hir::Expr { hir_id, kind, span: self.lower_span(e.span) }
306         })
307     }
308
309     fn lower_unop(&mut self, u: UnOp) -> hir::UnOp {
310         match u {
311             UnOp::Deref => hir::UnOp::Deref,
312             UnOp::Not => hir::UnOp::Not,
313             UnOp::Neg => hir::UnOp::Neg,
314         }
315     }
316
317     fn lower_binop(&mut self, b: BinOp) -> hir::BinOp {
318         Spanned {
319             node: match b.node {
320                 BinOpKind::Add => hir::BinOpKind::Add,
321                 BinOpKind::Sub => hir::BinOpKind::Sub,
322                 BinOpKind::Mul => hir::BinOpKind::Mul,
323                 BinOpKind::Div => hir::BinOpKind::Div,
324                 BinOpKind::Rem => hir::BinOpKind::Rem,
325                 BinOpKind::And => hir::BinOpKind::And,
326                 BinOpKind::Or => hir::BinOpKind::Or,
327                 BinOpKind::BitXor => hir::BinOpKind::BitXor,
328                 BinOpKind::BitAnd => hir::BinOpKind::BitAnd,
329                 BinOpKind::BitOr => hir::BinOpKind::BitOr,
330                 BinOpKind::Shl => hir::BinOpKind::Shl,
331                 BinOpKind::Shr => hir::BinOpKind::Shr,
332                 BinOpKind::Eq => hir::BinOpKind::Eq,
333                 BinOpKind::Lt => hir::BinOpKind::Lt,
334                 BinOpKind::Le => hir::BinOpKind::Le,
335                 BinOpKind::Ne => hir::BinOpKind::Ne,
336                 BinOpKind::Ge => hir::BinOpKind::Ge,
337                 BinOpKind::Gt => hir::BinOpKind::Gt,
338             },
339             span: self.lower_span(b.span),
340         }
341     }
342
343     fn lower_legacy_const_generics(
344         &mut self,
345         mut f: Expr,
346         args: Vec<AstP<Expr>>,
347         legacy_args_idx: &[usize],
348     ) -> hir::ExprKind<'hir> {
349         let ExprKind::Path(None, ref mut path) = f.kind else {
350             unreachable!();
351         };
352
353         // Split the arguments into const generics and normal arguments
354         let mut real_args = vec![];
355         let mut generic_args = vec![];
356         for (idx, arg) in args.into_iter().enumerate() {
357             if legacy_args_idx.contains(&idx) {
358                 let parent_def_id = self.current_hir_id_owner;
359                 let node_id = self.next_node_id();
360
361                 // Add a definition for the in-band const def.
362                 self.create_def(parent_def_id.def_id, node_id, DefPathData::AnonConst);
363
364                 let anon_const = AnonConst { id: node_id, value: arg };
365                 generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const)));
366             } else {
367                 real_args.push(arg);
368             }
369         }
370
371         // Add generic args to the last element of the path.
372         let last_segment = path.segments.last_mut().unwrap();
373         assert!(last_segment.args.is_none());
374         last_segment.args = Some(AstP(GenericArgs::AngleBracketed(AngleBracketedArgs {
375             span: DUMMY_SP,
376             args: generic_args,
377         })));
378
379         // Now lower everything as normal.
380         let f = self.lower_expr(&f);
381         hir::ExprKind::Call(f, self.lower_exprs(&real_args))
382     }
383
384     fn lower_expr_if(
385         &mut self,
386         cond: &Expr,
387         then: &Block,
388         else_opt: Option<&Expr>,
389     ) -> hir::ExprKind<'hir> {
390         let lowered_cond = self.lower_cond(cond);
391         let then_expr = self.lower_block_expr(then);
392         if let Some(rslt) = else_opt {
393             hir::ExprKind::If(
394                 lowered_cond,
395                 self.arena.alloc(then_expr),
396                 Some(self.lower_expr(rslt)),
397             )
398         } else {
399             hir::ExprKind::If(lowered_cond, self.arena.alloc(then_expr), None)
400         }
401     }
402
403     // Lowers a condition (i.e. `cond` in `if cond` or `while cond`), wrapping it in a terminating scope
404     // so that temporaries created in the condition don't live beyond it.
405     fn lower_cond(&mut self, cond: &Expr) -> &'hir hir::Expr<'hir> {
406         fn has_let_expr(expr: &Expr) -> bool {
407             match &expr.kind {
408                 ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
409                 ExprKind::Let(..) => true,
410                 _ => false,
411             }
412         }
413
414         // We have to take special care for `let` exprs in the condition, e.g. in
415         // `if let pat = val` or `if foo && let pat = val`, as we _do_ want `val` to live beyond the
416         // condition in this case.
417         //
418         // In order to mantain the drop behavior for the non `let` parts of the condition,
419         // we still wrap them in terminating scopes, e.g. `if foo && let pat = val` essentially
420         // gets transformed into `if { let _t = foo; _t } && let pat = val`
421         match &cond.kind {
422             ExprKind::Binary(op @ Spanned { node: ast::BinOpKind::And, .. }, lhs, rhs)
423                 if has_let_expr(cond) =>
424             {
425                 let op = self.lower_binop(*op);
426                 let lhs = self.lower_cond(lhs);
427                 let rhs = self.lower_cond(rhs);
428
429                 self.arena.alloc(self.expr(
430                     cond.span,
431                     hir::ExprKind::Binary(op, lhs, rhs),
432                     AttrVec::new(),
433                 ))
434             }
435             ExprKind::Let(..) => self.lower_expr(cond),
436             _ => {
437                 let cond = self.lower_expr(cond);
438                 let reason = DesugaringKind::CondTemporary;
439                 let span_block = self.mark_span_with_reason(reason, cond.span, None);
440                 self.expr_drop_temps(span_block, cond, AttrVec::new())
441             }
442         }
443     }
444
445     // We desugar: `'label: while $cond $body` into:
446     //
447     // ```
448     // 'label: loop {
449     //   if { let _t = $cond; _t } {
450     //     $body
451     //   }
452     //   else {
453     //     break;
454     //   }
455     // }
456     // ```
457     //
458     // Wrap in a construct equivalent to `{ let _t = $cond; _t }`
459     // to preserve drop semantics since `while $cond { ... }` does not
460     // let temporaries live outside of `cond`.
461     fn lower_expr_while_in_loop_scope(
462         &mut self,
463         span: Span,
464         cond: &Expr,
465         body: &Block,
466         opt_label: Option<Label>,
467     ) -> hir::ExprKind<'hir> {
468         let lowered_cond = self.with_loop_condition_scope(|t| t.lower_cond(cond));
469         let then = self.lower_block_expr(body);
470         let expr_break = self.expr_break(span, AttrVec::new());
471         let stmt_break = self.stmt_expr(span, expr_break);
472         let else_blk = self.block_all(span, arena_vec![self; stmt_break], None);
473         let else_expr = self.arena.alloc(self.expr_block(else_blk, AttrVec::new()));
474         let if_kind = hir::ExprKind::If(lowered_cond, self.arena.alloc(then), Some(else_expr));
475         let if_expr = self.expr(span, if_kind, AttrVec::new());
476         let block = self.block_expr(self.arena.alloc(if_expr));
477         let span = self.lower_span(span.with_hi(cond.span.hi()));
478         let opt_label = self.lower_label(opt_label);
479         hir::ExprKind::Loop(block, opt_label, hir::LoopSource::While, span)
480     }
481
482     /// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_output(<expr>) }`,
483     /// `try { <stmts>; }` into `{ <stmts>; ::std::ops::Try::from_output(()) }`
484     /// and save the block id to use it as a break target for desugaring of the `?` operator.
485     fn lower_expr_try_block(&mut self, body: &Block) -> hir::ExprKind<'hir> {
486         self.with_catch_scope(body.id, |this| {
487             let mut block = this.lower_block_noalloc(body, true);
488
489             // Final expression of the block (if present) or `()` with span at the end of block
490             let (try_span, tail_expr) = if let Some(expr) = block.expr.take() {
491                 (
492                     this.mark_span_with_reason(
493                         DesugaringKind::TryBlock,
494                         expr.span,
495                         this.allow_try_trait.clone(),
496                     ),
497                     expr,
498                 )
499             } else {
500                 let try_span = this.mark_span_with_reason(
501                     DesugaringKind::TryBlock,
502                     this.tcx.sess.source_map().end_point(body.span),
503                     this.allow_try_trait.clone(),
504                 );
505
506                 (try_span, this.expr_unit(try_span))
507             };
508
509             let ok_wrapped_span =
510                 this.mark_span_with_reason(DesugaringKind::TryBlock, tail_expr.span, None);
511
512             // `::std::ops::Try::from_output($tail_expr)`
513             block.expr = Some(this.wrap_in_try_constructor(
514                 hir::LangItem::TryTraitFromOutput,
515                 try_span,
516                 tail_expr,
517                 ok_wrapped_span,
518             ));
519
520             hir::ExprKind::Block(this.arena.alloc(block), None)
521         })
522     }
523
524     fn wrap_in_try_constructor(
525         &mut self,
526         lang_item: hir::LangItem,
527         method_span: Span,
528         expr: &'hir hir::Expr<'hir>,
529         overall_span: Span,
530     ) -> &'hir hir::Expr<'hir> {
531         let constructor = self.arena.alloc(self.expr_lang_item_path(
532             method_span,
533             lang_item,
534             AttrVec::new(),
535             None,
536         ));
537         self.expr_call(overall_span, constructor, std::slice::from_ref(expr))
538     }
539
540     fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
541         let pat = self.lower_pat(&arm.pat);
542         let guard = arm.guard.as_ref().map(|cond| {
543             if let ExprKind::Let(ref pat, ref scrutinee, span) = cond.kind {
544                 hir::Guard::IfLet(self.arena.alloc(hir::Let {
545                     hir_id: self.next_id(),
546                     span: self.lower_span(span),
547                     pat: self.lower_pat(pat),
548                     ty: None,
549                     init: self.lower_expr(scrutinee),
550                 }))
551             } else {
552                 hir::Guard::If(self.lower_expr(cond))
553             }
554         });
555         let hir_id = self.next_id();
556         self.lower_attrs(hir_id, &arm.attrs);
557         hir::Arm {
558             hir_id,
559             pat,
560             guard,
561             body: self.lower_expr(&arm.body),
562             span: self.lower_span(arm.span),
563         }
564     }
565
566     /// Lower an `async` construct to a generator that is then wrapped so it implements `Future`.
567     ///
568     /// This results in:
569     ///
570     /// ```text
571     /// std::future::from_generator(static move? |_task_context| -> <ret_ty> {
572     ///     <body>
573     /// })
574     /// ```
575     pub(super) fn make_async_expr(
576         &mut self,
577         capture_clause: CaptureBy,
578         closure_node_id: NodeId,
579         ret_ty: Option<AstP<Ty>>,
580         span: Span,
581         async_gen_kind: hir::AsyncGeneratorKind,
582         body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
583     ) -> hir::ExprKind<'hir> {
584         let output = match ret_ty {
585             Some(ty) => hir::FnRetTy::Return(
586                 self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock)),
587             ),
588             None => hir::FnRetTy::DefaultReturn(self.lower_span(span)),
589         };
590
591         // Resume argument type. We let the compiler infer this to simplify the lowering. It is
592         // fully constrained by `future::from_generator`.
593         let input_ty = hir::Ty {
594             hir_id: self.next_id(),
595             kind: hir::TyKind::Infer,
596             span: self.lower_span(span),
597         };
598
599         // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
600         let fn_decl = self.arena.alloc(hir::FnDecl {
601             inputs: arena_vec![self; input_ty],
602             output,
603             c_variadic: false,
604             implicit_self: hir::ImplicitSelfKind::None,
605         });
606
607         // Lower the argument pattern/ident. The ident is used again in the `.await` lowering.
608         let (pat, task_context_hid) = self.pat_ident_binding_mode(
609             span,
610             Ident::with_dummy_span(sym::_task_context),
611             hir::BindingAnnotation::MUT,
612         );
613         let param = hir::Param {
614             hir_id: self.next_id(),
615             pat,
616             ty_span: self.lower_span(span),
617             span: self.lower_span(span),
618         };
619         let params = arena_vec![self; param];
620
621         let body = self.lower_body(move |this| {
622             this.generator_kind = Some(hir::GeneratorKind::Async(async_gen_kind));
623
624             let old_ctx = this.task_context;
625             this.task_context = Some(task_context_hid);
626             let res = body(this);
627             this.task_context = old_ctx;
628             (params, res)
629         });
630
631         // `static |_task_context| -> <ret_ty> { body }`:
632         let generator_kind = {
633             let c = self.arena.alloc(hir::Closure {
634                 binder: hir::ClosureBinder::Default,
635                 capture_clause,
636                 bound_generic_params: &[],
637                 fn_decl,
638                 body,
639                 fn_decl_span: self.lower_span(span),
640                 movability: Some(hir::Movability::Static),
641             });
642
643             hir::ExprKind::Closure(c)
644         };
645         let generator = hir::Expr {
646             hir_id: self.lower_node_id(closure_node_id),
647             kind: generator_kind,
648             span: self.lower_span(span),
649         };
650
651         // `future::from_generator`:
652         let unstable_span =
653             self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
654         let gen_future = self.expr_lang_item_path(
655             unstable_span,
656             hir::LangItem::FromGenerator,
657             AttrVec::new(),
658             None,
659         );
660
661         // `future::from_generator(generator)`:
662         hir::ExprKind::Call(self.arena.alloc(gen_future), arena_vec![self; generator])
663     }
664
665     /// Desugar `<expr>.await` into:
666     /// ```ignore (pseudo-rust)
667     /// match ::std::future::IntoFuture::into_future(<expr>) {
668     ///     mut __awaitee => loop {
669     ///         match unsafe { ::std::future::Future::poll(
670     ///             <::std::pin::Pin>::new_unchecked(&mut __awaitee),
671     ///             ::std::future::get_context(task_context),
672     ///         ) } {
673     ///             ::std::task::Poll::Ready(result) => break result,
674     ///             ::std::task::Poll::Pending => {}
675     ///         }
676     ///         task_context = yield ();
677     ///     }
678     /// }
679     /// ```
680     fn lower_expr_await(&mut self, dot_await_span: Span, expr: &Expr) -> hir::ExprKind<'hir> {
681         let full_span = expr.span.to(dot_await_span);
682         match self.generator_kind {
683             Some(hir::GeneratorKind::Async(_)) => {}
684             Some(hir::GeneratorKind::Gen) | None => {
685                 self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks {
686                     dot_await_span,
687                     item_span: self.current_item,
688                 });
689             }
690         }
691         let span = self.mark_span_with_reason(DesugaringKind::Await, dot_await_span, None);
692         let gen_future_span = self.mark_span_with_reason(
693             DesugaringKind::Await,
694             full_span,
695             self.allow_gen_future.clone(),
696         );
697         let expr = self.lower_expr_mut(expr);
698         let expr_hir_id = expr.hir_id;
699
700         // Note that the name of this binding must not be changed to something else because
701         // debuggers and debugger extensions expect it to be called `__awaitee`. They use
702         // this name to identify what is being awaited by a suspended async functions.
703         let awaitee_ident = Ident::with_dummy_span(sym::__awaitee);
704         let (awaitee_pat, awaitee_pat_hid) =
705             self.pat_ident_binding_mode(span, awaitee_ident, hir::BindingAnnotation::MUT);
706
707         let task_context_ident = Ident::with_dummy_span(sym::_task_context);
708
709         // unsafe {
710         //     ::std::future::Future::poll(
711         //         ::std::pin::Pin::new_unchecked(&mut __awaitee),
712         //         ::std::future::get_context(task_context),
713         //     )
714         // }
715         let poll_expr = {
716             let awaitee = self.expr_ident(span, awaitee_ident, awaitee_pat_hid);
717             let ref_mut_awaitee = self.expr_mut_addr_of(span, awaitee);
718             let task_context = if let Some(task_context_hid) = self.task_context {
719                 self.expr_ident_mut(span, task_context_ident, task_context_hid)
720             } else {
721                 // Use of `await` outside of an async context, we cannot use `task_context` here.
722                 self.expr_err(span)
723             };
724             let new_unchecked = self.expr_call_lang_item_fn_mut(
725                 span,
726                 hir::LangItem::PinNewUnchecked,
727                 arena_vec![self; ref_mut_awaitee],
728                 Some(expr_hir_id),
729             );
730             let get_context = self.expr_call_lang_item_fn_mut(
731                 gen_future_span,
732                 hir::LangItem::GetContext,
733                 arena_vec![self; task_context],
734                 Some(expr_hir_id),
735             );
736             let call = self.expr_call_lang_item_fn(
737                 span,
738                 hir::LangItem::FuturePoll,
739                 arena_vec![self; new_unchecked, get_context],
740                 Some(expr_hir_id),
741             );
742             self.arena.alloc(self.expr_unsafe(call))
743         };
744
745         // `::std::task::Poll::Ready(result) => break result`
746         let loop_node_id = self.next_node_id();
747         let loop_hir_id = self.lower_node_id(loop_node_id);
748         let ready_arm = {
749             let x_ident = Ident::with_dummy_span(sym::result);
750             let (x_pat, x_pat_hid) = self.pat_ident(gen_future_span, x_ident);
751             let x_expr = self.expr_ident(gen_future_span, x_ident, x_pat_hid);
752             let ready_field = self.single_pat_field(gen_future_span, x_pat);
753             let ready_pat = self.pat_lang_item_variant(
754                 span,
755                 hir::LangItem::PollReady,
756                 ready_field,
757                 Some(expr_hir_id),
758             );
759             let break_x = self.with_loop_scope(loop_node_id, move |this| {
760                 let expr_break =
761                     hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr));
762                 this.arena.alloc(this.expr(gen_future_span, expr_break, AttrVec::new()))
763             });
764             self.arm(ready_pat, break_x)
765         };
766
767         // `::std::task::Poll::Pending => {}`
768         let pending_arm = {
769             let pending_pat = self.pat_lang_item_variant(
770                 span,
771                 hir::LangItem::PollPending,
772                 &[],
773                 Some(expr_hir_id),
774             );
775             let empty_block = self.expr_block_empty(span);
776             self.arm(pending_pat, empty_block)
777         };
778
779         let inner_match_stmt = {
780             let match_expr = self.expr_match(
781                 span,
782                 poll_expr,
783                 arena_vec![self; ready_arm, pending_arm],
784                 hir::MatchSource::AwaitDesugar,
785             );
786             self.stmt_expr(span, match_expr)
787         };
788
789         // task_context = yield ();
790         let yield_stmt = {
791             let unit = self.expr_unit(span);
792             let yield_expr = self.expr(
793                 span,
794                 hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr_hir_id) }),
795                 AttrVec::new(),
796             );
797             let yield_expr = self.arena.alloc(yield_expr);
798
799             if let Some(task_context_hid) = self.task_context {
800                 let lhs = self.expr_ident(span, task_context_ident, task_context_hid);
801                 let assign = self.expr(
802                     span,
803                     hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span)),
804                     AttrVec::new(),
805                 );
806                 self.stmt_expr(span, assign)
807             } else {
808                 // Use of `await` outside of an async context. Return `yield_expr` so that we can
809                 // proceed with type checking.
810                 self.stmt(span, hir::StmtKind::Semi(yield_expr))
811             }
812         };
813
814         let loop_block = self.block_all(span, arena_vec![self; inner_match_stmt, yield_stmt], None);
815
816         // loop { .. }
817         let loop_expr = self.arena.alloc(hir::Expr {
818             hir_id: loop_hir_id,
819             kind: hir::ExprKind::Loop(
820                 loop_block,
821                 None,
822                 hir::LoopSource::Loop,
823                 self.lower_span(span),
824             ),
825             span: self.lower_span(span),
826         });
827
828         // mut __awaitee => loop { ... }
829         let awaitee_arm = self.arm(awaitee_pat, loop_expr);
830
831         // `match ::std::future::IntoFuture::into_future(<expr>) { ... }`
832         let into_future_span = self.mark_span_with_reason(
833             DesugaringKind::Await,
834             dot_await_span,
835             self.allow_into_future.clone(),
836         );
837         let into_future_expr = self.expr_call_lang_item_fn(
838             into_future_span,
839             hir::LangItem::IntoFutureIntoFuture,
840             arena_vec![self; expr],
841             Some(expr_hir_id),
842         );
843
844         // match <into_future_expr> {
845         //     mut __awaitee => loop { .. }
846         // }
847         hir::ExprKind::Match(
848             into_future_expr,
849             arena_vec![self; awaitee_arm],
850             hir::MatchSource::AwaitDesugar,
851         )
852     }
853
854     fn lower_expr_closure(
855         &mut self,
856         binder: &ClosureBinder,
857         capture_clause: CaptureBy,
858         closure_id: NodeId,
859         movability: Movability,
860         decl: &FnDecl,
861         body: &Expr,
862         fn_decl_span: Span,
863     ) -> hir::ExprKind<'hir> {
864         let (binder_clause, generic_params) = self.lower_closure_binder(binder);
865
866         let (body_id, generator_option) = self.with_new_scopes(move |this| {
867             let prev = this.current_item;
868             this.current_item = Some(fn_decl_span);
869             let mut generator_kind = None;
870             let body_id = this.lower_fn_body(decl, |this| {
871                 let e = this.lower_expr_mut(body);
872                 generator_kind = this.generator_kind;
873                 e
874             });
875             let generator_option =
876                 this.generator_movability_for_fn(&decl, fn_decl_span, generator_kind, movability);
877             this.current_item = prev;
878             (body_id, generator_option)
879         });
880
881         let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
882         // Lower outside new scope to preserve `is_in_loop_condition`.
883         let fn_decl = self.lower_fn_decl(decl, None, fn_decl_span, FnDeclKind::Closure, None);
884
885         let c = self.arena.alloc(hir::Closure {
886             binder: binder_clause,
887             capture_clause,
888             bound_generic_params,
889             fn_decl,
890             body: body_id,
891             fn_decl_span: self.lower_span(fn_decl_span),
892             movability: generator_option,
893         });
894
895         hir::ExprKind::Closure(c)
896     }
897
898     fn generator_movability_for_fn(
899         &mut self,
900         decl: &FnDecl,
901         fn_decl_span: Span,
902         generator_kind: Option<hir::GeneratorKind>,
903         movability: Movability,
904     ) -> Option<hir::Movability> {
905         match generator_kind {
906             Some(hir::GeneratorKind::Gen) => {
907                 if decl.inputs.len() > 1 {
908                     self.tcx.sess.emit_err(GeneratorTooManyParameters { fn_decl_span });
909                 }
910                 Some(movability)
911             }
912             Some(hir::GeneratorKind::Async(_)) => {
913                 panic!("non-`async` closure body turned `async` during lowering");
914             }
915             None => {
916                 if movability == Movability::Static {
917                     self.tcx.sess.emit_err(ClosureCannotBeStatic { fn_decl_span });
918                 }
919                 None
920             }
921         }
922     }
923
924     fn lower_closure_binder<'c>(
925         &mut self,
926         binder: &'c ClosureBinder,
927     ) -> (hir::ClosureBinder, &'c [GenericParam]) {
928         let (binder, params) = match binder {
929             ClosureBinder::NotPresent => (hir::ClosureBinder::Default, &[][..]),
930             &ClosureBinder::For { span, ref generic_params } => {
931                 let span = self.lower_span(span);
932                 (hir::ClosureBinder::For { span }, &**generic_params)
933             }
934         };
935
936         (binder, params)
937     }
938
939     fn lower_expr_async_closure(
940         &mut self,
941         binder: &ClosureBinder,
942         capture_clause: CaptureBy,
943         closure_id: NodeId,
944         inner_closure_id: NodeId,
945         decl: &FnDecl,
946         body: &Expr,
947         fn_decl_span: Span,
948     ) -> hir::ExprKind<'hir> {
949         if let &ClosureBinder::For { span, .. } = binder {
950             self.tcx.sess.emit_err(NotSupportedForLifetimeBinderAsyncClosure { span });
951         }
952
953         let (binder_clause, generic_params) = self.lower_closure_binder(binder);
954
955         let outer_decl =
956             FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
957
958         let body = self.with_new_scopes(|this| {
959             // FIXME(cramertj): allow `async` non-`move` closures with arguments.
960             if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() {
961                 this.tcx.sess.emit_err(AsyncNonMoveClosureNotSupported { fn_decl_span });
962             }
963
964             // Transform `async |x: u8| -> X { ... }` into
965             // `|x: u8| future_from_generator(|| -> X { ... })`.
966             let body_id = this.lower_fn_body(&outer_decl, |this| {
967                 let async_ret_ty =
968                     if let FnRetTy::Ty(ty) = &decl.output { Some(ty.clone()) } else { None };
969                 let async_body = this.make_async_expr(
970                     capture_clause,
971                     inner_closure_id,
972                     async_ret_ty,
973                     body.span,
974                     hir::AsyncGeneratorKind::Closure,
975                     |this| this.with_new_scopes(|this| this.lower_expr_mut(body)),
976                 );
977                 this.expr(fn_decl_span, async_body, AttrVec::new())
978             });
979             body_id
980         });
981
982         let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
983         // We need to lower the declaration outside the new scope, because we
984         // have to conserve the state of being inside a loop condition for the
985         // closure argument types.
986         let fn_decl =
987             self.lower_fn_decl(&outer_decl, None, fn_decl_span, FnDeclKind::Closure, None);
988
989         let c = self.arena.alloc(hir::Closure {
990             binder: binder_clause,
991             capture_clause,
992             bound_generic_params,
993             fn_decl,
994             body,
995             fn_decl_span: self.lower_span(fn_decl_span),
996             movability: None,
997         });
998         hir::ExprKind::Closure(c)
999     }
1000
1001     /// Destructure the LHS of complex assignments.
1002     /// For instance, lower `(a, b) = t` to `{ let (lhs1, lhs2) = t; a = lhs1; b = lhs2; }`.
1003     fn lower_expr_assign(
1004         &mut self,
1005         lhs: &Expr,
1006         rhs: &Expr,
1007         eq_sign_span: Span,
1008         whole_span: Span,
1009     ) -> hir::ExprKind<'hir> {
1010         // Return early in case of an ordinary assignment.
1011         fn is_ordinary(lower_ctx: &mut LoweringContext<'_, '_>, lhs: &Expr) -> bool {
1012             match &lhs.kind {
1013                 ExprKind::Array(..)
1014                 | ExprKind::Struct(..)
1015                 | ExprKind::Tup(..)
1016                 | ExprKind::Underscore => false,
1017                 // Check for tuple struct constructor.
1018                 ExprKind::Call(callee, ..) => lower_ctx.extract_tuple_struct_path(callee).is_none(),
1019                 ExprKind::Paren(e) => {
1020                     match e.kind {
1021                         // We special-case `(..)` for consistency with patterns.
1022                         ExprKind::Range(None, None, RangeLimits::HalfOpen) => false,
1023                         _ => is_ordinary(lower_ctx, e),
1024                     }
1025                 }
1026                 _ => true,
1027             }
1028         }
1029         if is_ordinary(self, lhs) {
1030             return hir::ExprKind::Assign(
1031                 self.lower_expr(lhs),
1032                 self.lower_expr(rhs),
1033                 self.lower_span(eq_sign_span),
1034             );
1035         }
1036
1037         let mut assignments = vec![];
1038
1039         // The LHS becomes a pattern: `(lhs1, lhs2)`.
1040         let pat = self.destructure_assign(lhs, eq_sign_span, &mut assignments);
1041         let rhs = self.lower_expr(rhs);
1042
1043         // Introduce a `let` for destructuring: `let (lhs1, lhs2) = t`.
1044         let destructure_let = self.stmt_let_pat(
1045             None,
1046             whole_span,
1047             Some(rhs),
1048             pat,
1049             hir::LocalSource::AssignDesugar(self.lower_span(eq_sign_span)),
1050         );
1051
1052         // `a = lhs1; b = lhs2;`.
1053         let stmts = self
1054             .arena
1055             .alloc_from_iter(std::iter::once(destructure_let).chain(assignments.into_iter()));
1056
1057         // Wrap everything in a block.
1058         hir::ExprKind::Block(&self.block_all(whole_span, stmts, None), None)
1059     }
1060
1061     /// If the given expression is a path to a tuple struct, returns that path.
1062     /// It is not a complete check, but just tries to reject most paths early
1063     /// if they are not tuple structs.
1064     /// Type checking will take care of the full validation later.
1065     fn extract_tuple_struct_path<'a>(
1066         &mut self,
1067         expr: &'a Expr,
1068     ) -> Option<(&'a Option<QSelf>, &'a Path)> {
1069         if let ExprKind::Path(qself, path) = &expr.kind {
1070             // Does the path resolve to something disallowed in a tuple struct/variant pattern?
1071             if let Some(partial_res) = self.resolver.get_partial_res(expr.id) {
1072                 if let Some(res) = partial_res.full_res() && !res.expected_in_tuple_struct_pat() {
1073                     return None;
1074                 }
1075             }
1076             return Some((qself, path));
1077         }
1078         None
1079     }
1080
1081     /// If the given expression is a path to a unit struct, returns that path.
1082     /// It is not a complete check, but just tries to reject most paths early
1083     /// if they are not unit structs.
1084     /// Type checking will take care of the full validation later.
1085     fn extract_unit_struct_path<'a>(
1086         &mut self,
1087         expr: &'a Expr,
1088     ) -> Option<(&'a Option<QSelf>, &'a Path)> {
1089         if let ExprKind::Path(qself, path) = &expr.kind {
1090             // Does the path resolve to something disallowed in a unit struct/variant pattern?
1091             if let Some(partial_res) = self.resolver.get_partial_res(expr.id) {
1092                 if let Some(res) = partial_res.full_res() && !res.expected_in_unit_struct_pat() {
1093                     return None;
1094                 }
1095             }
1096             return Some((qself, path));
1097         }
1098         None
1099     }
1100
1101     /// Convert the LHS of a destructuring assignment to a pattern.
1102     /// Each sub-assignment is recorded in `assignments`.
1103     fn destructure_assign(
1104         &mut self,
1105         lhs: &Expr,
1106         eq_sign_span: Span,
1107         assignments: &mut Vec<hir::Stmt<'hir>>,
1108     ) -> &'hir hir::Pat<'hir> {
1109         self.arena.alloc(self.destructure_assign_mut(lhs, eq_sign_span, assignments))
1110     }
1111
1112     fn destructure_assign_mut(
1113         &mut self,
1114         lhs: &Expr,
1115         eq_sign_span: Span,
1116         assignments: &mut Vec<hir::Stmt<'hir>>,
1117     ) -> hir::Pat<'hir> {
1118         match &lhs.kind {
1119             // Underscore pattern.
1120             ExprKind::Underscore => {
1121                 return self.pat_without_dbm(lhs.span, hir::PatKind::Wild);
1122             }
1123             // Slice patterns.
1124             ExprKind::Array(elements) => {
1125                 let (pats, rest) =
1126                     self.destructure_sequence(elements, "slice", eq_sign_span, assignments);
1127                 let slice_pat = if let Some((i, span)) = rest {
1128                     let (before, after) = pats.split_at(i);
1129                     hir::PatKind::Slice(
1130                         before,
1131                         Some(self.arena.alloc(self.pat_without_dbm(span, hir::PatKind::Wild))),
1132                         after,
1133                     )
1134                 } else {
1135                     hir::PatKind::Slice(pats, None, &[])
1136                 };
1137                 return self.pat_without_dbm(lhs.span, slice_pat);
1138             }
1139             // Tuple structs.
1140             ExprKind::Call(callee, args) => {
1141                 if let Some((qself, path)) = self.extract_tuple_struct_path(callee) {
1142                     let (pats, rest) = self.destructure_sequence(
1143                         args,
1144                         "tuple struct or variant",
1145                         eq_sign_span,
1146                         assignments,
1147                     );
1148                     let qpath = self.lower_qpath(
1149                         callee.id,
1150                         qself,
1151                         path,
1152                         ParamMode::Optional,
1153                         &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
1154                     );
1155                     // Destructure like a tuple struct.
1156                     let tuple_struct_pat = hir::PatKind::TupleStruct(
1157                         qpath,
1158                         pats,
1159                         hir::DotDotPos::new(rest.map(|r| r.0)),
1160                     );
1161                     return self.pat_without_dbm(lhs.span, tuple_struct_pat);
1162                 }
1163             }
1164             // Unit structs and enum variants.
1165             ExprKind::Path(..) => {
1166                 if let Some((qself, path)) = self.extract_unit_struct_path(lhs) {
1167                     let qpath = self.lower_qpath(
1168                         lhs.id,
1169                         qself,
1170                         path,
1171                         ParamMode::Optional,
1172                         &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
1173                     );
1174                     // Destructure like a unit struct.
1175                     let unit_struct_pat = hir::PatKind::Path(qpath);
1176                     return self.pat_without_dbm(lhs.span, unit_struct_pat);
1177                 }
1178             }
1179             // Structs.
1180             ExprKind::Struct(se) => {
1181                 let field_pats = self.arena.alloc_from_iter(se.fields.iter().map(|f| {
1182                     let pat = self.destructure_assign(&f.expr, eq_sign_span, assignments);
1183                     hir::PatField {
1184                         hir_id: self.next_id(),
1185                         ident: self.lower_ident(f.ident),
1186                         pat,
1187                         is_shorthand: f.is_shorthand,
1188                         span: self.lower_span(f.span),
1189                     }
1190                 }));
1191                 let qpath = self.lower_qpath(
1192                     lhs.id,
1193                     &se.qself,
1194                     &se.path,
1195                     ParamMode::Optional,
1196                     &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
1197                 );
1198                 let fields_omitted = match &se.rest {
1199                     StructRest::Base(e) => {
1200                         self.tcx.sess.emit_err(FunctionalRecordUpdateDestructuringAssignemnt {
1201                             span: e.span,
1202                         });
1203                         true
1204                     }
1205                     StructRest::Rest(_) => true,
1206                     StructRest::None => false,
1207                 };
1208                 let struct_pat = hir::PatKind::Struct(qpath, field_pats, fields_omitted);
1209                 return self.pat_without_dbm(lhs.span, struct_pat);
1210             }
1211             // Tuples.
1212             ExprKind::Tup(elements) => {
1213                 let (pats, rest) =
1214                     self.destructure_sequence(elements, "tuple", eq_sign_span, assignments);
1215                 let tuple_pat = hir::PatKind::Tuple(pats, hir::DotDotPos::new(rest.map(|r| r.0)));
1216                 return self.pat_without_dbm(lhs.span, tuple_pat);
1217             }
1218             ExprKind::Paren(e) => {
1219                 // We special-case `(..)` for consistency with patterns.
1220                 if let ExprKind::Range(None, None, RangeLimits::HalfOpen) = e.kind {
1221                     let tuple_pat = hir::PatKind::Tuple(&[], hir::DotDotPos::new(Some(0)));
1222                     return self.pat_without_dbm(lhs.span, tuple_pat);
1223                 } else {
1224                     return self.destructure_assign_mut(e, eq_sign_span, assignments);
1225                 }
1226             }
1227             _ => {}
1228         }
1229         // Treat all other cases as normal lvalue.
1230         let ident = Ident::new(sym::lhs, self.lower_span(lhs.span));
1231         let (pat, binding) = self.pat_ident_mut(lhs.span, ident);
1232         let ident = self.expr_ident(lhs.span, ident, binding);
1233         let assign =
1234             hir::ExprKind::Assign(self.lower_expr(lhs), ident, self.lower_span(eq_sign_span));
1235         let expr = self.expr(lhs.span, assign, AttrVec::new());
1236         assignments.push(self.stmt_expr(lhs.span, expr));
1237         pat
1238     }
1239
1240     /// Destructure a sequence of expressions occurring on the LHS of an assignment.
1241     /// Such a sequence occurs in a tuple (struct)/slice.
1242     /// Return a sequence of corresponding patterns, and the index and the span of `..` if it
1243     /// exists.
1244     /// Each sub-assignment is recorded in `assignments`.
1245     fn destructure_sequence(
1246         &mut self,
1247         elements: &[AstP<Expr>],
1248         ctx: &str,
1249         eq_sign_span: Span,
1250         assignments: &mut Vec<hir::Stmt<'hir>>,
1251     ) -> (&'hir [hir::Pat<'hir>], Option<(usize, Span)>) {
1252         let mut rest = None;
1253         let elements =
1254             self.arena.alloc_from_iter(elements.iter().enumerate().filter_map(|(i, e)| {
1255                 // Check for `..` pattern.
1256                 if let ExprKind::Range(None, None, RangeLimits::HalfOpen) = e.kind {
1257                     if let Some((_, prev_span)) = rest {
1258                         self.ban_extra_rest_pat(e.span, prev_span, ctx);
1259                     } else {
1260                         rest = Some((i, e.span));
1261                     }
1262                     None
1263                 } else {
1264                     Some(self.destructure_assign_mut(e, eq_sign_span, assignments))
1265                 }
1266             }));
1267         (elements, rest)
1268     }
1269
1270     /// Desugar `<start>..=<end>` into `std::ops::RangeInclusive::new(<start>, <end>)`.
1271     fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> {
1272         let e1 = self.lower_expr_mut(e1);
1273         let e2 = self.lower_expr_mut(e2);
1274         let fn_path =
1275             hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span), None);
1276         let fn_expr =
1277             self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), AttrVec::new()));
1278         hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2])
1279     }
1280
1281     fn lower_expr_range(
1282         &mut self,
1283         span: Span,
1284         e1: Option<&Expr>,
1285         e2: Option<&Expr>,
1286         lims: RangeLimits,
1287     ) -> hir::ExprKind<'hir> {
1288         use rustc_ast::RangeLimits::*;
1289
1290         let lang_item = match (e1, e2, lims) {
1291             (None, None, HalfOpen) => hir::LangItem::RangeFull,
1292             (Some(..), None, HalfOpen) => hir::LangItem::RangeFrom,
1293             (None, Some(..), HalfOpen) => hir::LangItem::RangeTo,
1294             (Some(..), Some(..), HalfOpen) => hir::LangItem::Range,
1295             (None, Some(..), Closed) => hir::LangItem::RangeToInclusive,
1296             (Some(..), Some(..), Closed) => unreachable!(),
1297             (start, None, Closed) => {
1298                 self.tcx.sess.emit_err(InclusiveRangeWithNoEnd { span });
1299                 match start {
1300                     Some(..) => hir::LangItem::RangeFrom,
1301                     None => hir::LangItem::RangeFull,
1302                 }
1303             }
1304         };
1305
1306         let fields = self.arena.alloc_from_iter(
1307             e1.iter().map(|e| (sym::start, e)).chain(e2.iter().map(|e| (sym::end, e))).map(
1308                 |(s, e)| {
1309                     let expr = self.lower_expr(&e);
1310                     let ident = Ident::new(s, self.lower_span(e.span));
1311                     self.expr_field(ident, expr, e.span)
1312                 },
1313             ),
1314         );
1315
1316         hir::ExprKind::Struct(
1317             self.arena.alloc(hir::QPath::LangItem(lang_item, self.lower_span(span), None)),
1318             fields,
1319             None,
1320         )
1321     }
1322
1323     fn lower_label(&self, opt_label: Option<Label>) -> Option<Label> {
1324         let label = opt_label?;
1325         Some(Label { ident: self.lower_ident(label.ident) })
1326     }
1327
1328     fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hir::Destination {
1329         let target_id = match destination {
1330             Some((id, _)) => {
1331                 if let Some(loop_id) = self.resolver.get_label_res(id) {
1332                     Ok(self.lower_node_id(loop_id))
1333                 } else {
1334                     Err(hir::LoopIdError::UnresolvedLabel)
1335                 }
1336             }
1337             None => self
1338                 .loop_scope
1339                 .map(|id| Ok(self.lower_node_id(id)))
1340                 .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)),
1341         };
1342         let label = self.lower_label(destination.map(|(_, label)| label));
1343         hir::Destination { label, target_id }
1344     }
1345
1346     fn lower_jump_destination(&mut self, id: NodeId, opt_label: Option<Label>) -> hir::Destination {
1347         if self.is_in_loop_condition && opt_label.is_none() {
1348             hir::Destination {
1349                 label: None,
1350                 target_id: Err(hir::LoopIdError::UnlabeledCfInWhileCondition),
1351             }
1352         } else {
1353             self.lower_loop_destination(opt_label.map(|label| (id, label)))
1354         }
1355     }
1356
1357     fn with_catch_scope<T>(&mut self, catch_id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
1358         let old_scope = self.catch_scope.replace(catch_id);
1359         let result = f(self);
1360         self.catch_scope = old_scope;
1361         result
1362     }
1363
1364     fn with_loop_scope<T>(&mut self, loop_id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
1365         // We're no longer in the base loop's condition; we're in another loop.
1366         let was_in_loop_condition = self.is_in_loop_condition;
1367         self.is_in_loop_condition = false;
1368
1369         let old_scope = self.loop_scope.replace(loop_id);
1370         let result = f(self);
1371         self.loop_scope = old_scope;
1372
1373         self.is_in_loop_condition = was_in_loop_condition;
1374
1375         result
1376     }
1377
1378     fn with_loop_condition_scope<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
1379         let was_in_loop_condition = self.is_in_loop_condition;
1380         self.is_in_loop_condition = true;
1381
1382         let result = f(self);
1383
1384         self.is_in_loop_condition = was_in_loop_condition;
1385
1386         result
1387     }
1388
1389     fn lower_expr_field(&mut self, f: &ExprField) -> hir::ExprField<'hir> {
1390         let hir_id = self.lower_node_id(f.id);
1391         self.lower_attrs(hir_id, &f.attrs);
1392         hir::ExprField {
1393             hir_id,
1394             ident: self.lower_ident(f.ident),
1395             expr: self.lower_expr(&f.expr),
1396             span: self.lower_span(f.span),
1397             is_shorthand: f.is_shorthand,
1398         }
1399     }
1400
1401     fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> {
1402         match self.generator_kind {
1403             Some(hir::GeneratorKind::Gen) => {}
1404             Some(hir::GeneratorKind::Async(_)) => {
1405                 self.tcx.sess.emit_err(AsyncGeneratorsNotSupported { span });
1406             }
1407             None => self.generator_kind = Some(hir::GeneratorKind::Gen),
1408         }
1409
1410         let expr =
1411             opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span));
1412
1413         hir::ExprKind::Yield(expr, hir::YieldSource::Yield)
1414     }
1415
1416     /// Desugar `ExprForLoop` from: `[opt_ident]: for <pat> in <head> <body>` into:
1417     /// ```ignore (pseudo-rust)
1418     /// {
1419     ///     let result = match IntoIterator::into_iter(<head>) {
1420     ///         mut iter => {
1421     ///             [opt_ident]: loop {
1422     ///                 match Iterator::next(&mut iter) {
1423     ///                     None => break,
1424     ///                     Some(<pat>) => <body>,
1425     ///                 };
1426     ///             }
1427     ///         }
1428     ///     };
1429     ///     result
1430     /// }
1431     /// ```
1432     fn lower_expr_for(
1433         &mut self,
1434         e: &Expr,
1435         pat: &Pat,
1436         head: &Expr,
1437         body: &Block,
1438         opt_label: Option<Label>,
1439     ) -> hir::Expr<'hir> {
1440         let head = self.lower_expr_mut(head);
1441         let pat = self.lower_pat(pat);
1442         let for_span =
1443             self.mark_span_with_reason(DesugaringKind::ForLoop, self.lower_span(e.span), None);
1444         let head_span = self.mark_span_with_reason(DesugaringKind::ForLoop, head.span, None);
1445         let pat_span = self.mark_span_with_reason(DesugaringKind::ForLoop, pat.span, None);
1446
1447         // `None => break`
1448         let none_arm = {
1449             let break_expr =
1450                 self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span, AttrVec::new()));
1451             let pat = self.pat_none(for_span);
1452             self.arm(pat, break_expr)
1453         };
1454
1455         // Some(<pat>) => <body>,
1456         let some_arm = {
1457             let some_pat = self.pat_some(pat_span, pat);
1458             let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
1459             let body_expr = self.arena.alloc(self.expr_block(body_block, AttrVec::new()));
1460             self.arm(some_pat, body_expr)
1461         };
1462
1463         // `mut iter`
1464         let iter = Ident::with_dummy_span(sym::iter);
1465         let (iter_pat, iter_pat_nid) =
1466             self.pat_ident_binding_mode(head_span, iter, hir::BindingAnnotation::MUT);
1467
1468         // `match Iterator::next(&mut iter) { ... }`
1469         let match_expr = {
1470             let iter = self.expr_ident(head_span, iter, iter_pat_nid);
1471             let ref_mut_iter = self.expr_mut_addr_of(head_span, iter);
1472             let next_expr = self.expr_call_lang_item_fn(
1473                 head_span,
1474                 hir::LangItem::IteratorNext,
1475                 arena_vec![self; ref_mut_iter],
1476                 None,
1477             );
1478             let arms = arena_vec![self; none_arm, some_arm];
1479
1480             self.expr_match(head_span, next_expr, arms, hir::MatchSource::ForLoopDesugar)
1481         };
1482         let match_stmt = self.stmt_expr(for_span, match_expr);
1483
1484         let loop_block = self.block_all(for_span, arena_vec![self; match_stmt], None);
1485
1486         // `[opt_ident]: loop { ... }`
1487         let kind = hir::ExprKind::Loop(
1488             loop_block,
1489             self.lower_label(opt_label),
1490             hir::LoopSource::ForLoop,
1491             self.lower_span(for_span.with_hi(head.span.hi())),
1492         );
1493         let loop_expr =
1494             self.arena.alloc(hir::Expr { hir_id: self.lower_node_id(e.id), kind, span: for_span });
1495
1496         // `mut iter => { ... }`
1497         let iter_arm = self.arm(iter_pat, loop_expr);
1498
1499         // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
1500         let into_iter_expr = {
1501             self.expr_call_lang_item_fn(
1502                 head_span,
1503                 hir::LangItem::IntoIterIntoIter,
1504                 arena_vec![self; head],
1505                 None,
1506             )
1507         };
1508
1509         let match_expr = self.arena.alloc(self.expr_match(
1510             for_span,
1511             into_iter_expr,
1512             arena_vec![self; iter_arm],
1513             hir::MatchSource::ForLoopDesugar,
1514         ));
1515
1516         // This is effectively `{ let _result = ...; _result }`.
1517         // The construct was introduced in #21984 and is necessary to make sure that
1518         // temporaries in the `head` expression are dropped and do not leak to the
1519         // surrounding scope of the `match` since the `match` is not a terminating scope.
1520         //
1521         // Also, add the attributes to the outer returned expr node.
1522         self.expr_drop_temps_mut(for_span, match_expr, e.attrs.clone())
1523     }
1524
1525     /// Desugar `ExprKind::Try` from: `<expr>?` into:
1526     /// ```ignore (pseudo-rust)
1527     /// match Try::branch(<expr>) {
1528     ///     ControlFlow::Continue(val) => #[allow(unreachable_code)] val,,
1529     ///     ControlFlow::Break(residual) =>
1530     ///         #[allow(unreachable_code)]
1531     ///         // If there is an enclosing `try {...}`:
1532     ///         break 'catch_target Try::from_residual(residual),
1533     ///         // Otherwise:
1534     ///         return Try::from_residual(residual),
1535     /// }
1536     /// ```
1537     fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir> {
1538         let unstable_span = self.mark_span_with_reason(
1539             DesugaringKind::QuestionMark,
1540             span,
1541             self.allow_try_trait.clone(),
1542         );
1543         let try_span = self.tcx.sess.source_map().end_point(span);
1544         let try_span = self.mark_span_with_reason(
1545             DesugaringKind::QuestionMark,
1546             try_span,
1547             self.allow_try_trait.clone(),
1548         );
1549
1550         // `Try::branch(<expr>)`
1551         let scrutinee = {
1552             // expand <expr>
1553             let sub_expr = self.lower_expr_mut(sub_expr);
1554
1555             self.expr_call_lang_item_fn(
1556                 unstable_span,
1557                 hir::LangItem::TryTraitBranch,
1558                 arena_vec![self; sub_expr],
1559                 None,
1560             )
1561         };
1562
1563         // `#[allow(unreachable_code)]`
1564         let attr = {
1565             // `allow(unreachable_code)`
1566             let allow = {
1567                 let allow_ident = Ident::new(sym::allow, self.lower_span(span));
1568                 let uc_ident = Ident::new(sym::unreachable_code, self.lower_span(span));
1569                 let uc_nested = attr::mk_nested_word_item(uc_ident);
1570                 attr::mk_list_item(allow_ident, vec![uc_nested])
1571             };
1572             attr::mk_attr_outer(&self.tcx.sess.parse_sess.attr_id_generator, allow)
1573         };
1574         let attrs: AttrVec = thin_vec![attr];
1575
1576         // `ControlFlow::Continue(val) => #[allow(unreachable_code)] val,`
1577         let continue_arm = {
1578             let val_ident = Ident::with_dummy_span(sym::val);
1579             let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident);
1580             let val_expr = self.arena.alloc(self.expr_ident_with_attrs(
1581                 span,
1582                 val_ident,
1583                 val_pat_nid,
1584                 attrs.clone(),
1585             ));
1586             let continue_pat = self.pat_cf_continue(unstable_span, val_pat);
1587             self.arm(continue_pat, val_expr)
1588         };
1589
1590         // `ControlFlow::Break(residual) =>
1591         //     #[allow(unreachable_code)]
1592         //     return Try::from_residual(residual),`
1593         let break_arm = {
1594             let residual_ident = Ident::with_dummy_span(sym::residual);
1595             let (residual_local, residual_local_nid) = self.pat_ident(try_span, residual_ident);
1596             let residual_expr = self.expr_ident_mut(try_span, residual_ident, residual_local_nid);
1597             let from_residual_expr = self.wrap_in_try_constructor(
1598                 hir::LangItem::TryTraitFromResidual,
1599                 try_span,
1600                 self.arena.alloc(residual_expr),
1601                 unstable_span,
1602             );
1603             let ret_expr = if let Some(catch_node) = self.catch_scope {
1604                 let target_id = Ok(self.lower_node_id(catch_node));
1605                 self.arena.alloc(self.expr(
1606                     try_span,
1607                     hir::ExprKind::Break(
1608                         hir::Destination { label: None, target_id },
1609                         Some(from_residual_expr),
1610                     ),
1611                     attrs,
1612                 ))
1613             } else {
1614                 self.arena.alloc(self.expr(
1615                     try_span,
1616                     hir::ExprKind::Ret(Some(from_residual_expr)),
1617                     attrs,
1618                 ))
1619             };
1620
1621             let break_pat = self.pat_cf_break(try_span, residual_local);
1622             self.arm(break_pat, ret_expr)
1623         };
1624
1625         hir::ExprKind::Match(
1626             scrutinee,
1627             arena_vec![self; break_arm, continue_arm],
1628             hir::MatchSource::TryDesugar,
1629         )
1630     }
1631
1632     /// Desugar `ExprKind::Yeet` from: `do yeet <expr>` into:
1633     /// ```ignore(illustrative)
1634     /// // If there is an enclosing `try {...}`:
1635     /// break 'catch_target FromResidual::from_residual(Yeet(residual));
1636     /// // Otherwise:
1637     /// return FromResidual::from_residual(Yeet(residual));
1638     /// ```
1639     /// But to simplify this, there's a `from_yeet` lang item function which
1640     /// handles the combined `FromResidual::from_residual(Yeet(residual))`.
1641     fn lower_expr_yeet(&mut self, span: Span, sub_expr: Option<&Expr>) -> hir::ExprKind<'hir> {
1642         // The expression (if present) or `()` otherwise.
1643         let (yeeted_span, yeeted_expr) = if let Some(sub_expr) = sub_expr {
1644             (sub_expr.span, self.lower_expr(sub_expr))
1645         } else {
1646             (self.mark_span_with_reason(DesugaringKind::YeetExpr, span, None), self.expr_unit(span))
1647         };
1648
1649         let unstable_span = self.mark_span_with_reason(
1650             DesugaringKind::YeetExpr,
1651             span,
1652             self.allow_try_trait.clone(),
1653         );
1654
1655         let from_yeet_expr = self.wrap_in_try_constructor(
1656             hir::LangItem::TryTraitFromYeet,
1657             unstable_span,
1658             yeeted_expr,
1659             yeeted_span,
1660         );
1661
1662         if let Some(catch_node) = self.catch_scope {
1663             let target_id = Ok(self.lower_node_id(catch_node));
1664             hir::ExprKind::Break(hir::Destination { label: None, target_id }, Some(from_yeet_expr))
1665         } else {
1666             hir::ExprKind::Ret(Some(from_yeet_expr))
1667         }
1668     }
1669
1670     // =========================================================================
1671     // Helper methods for building HIR.
1672     // =========================================================================
1673
1674     /// Wrap the given `expr` in a terminating scope using `hir::ExprKind::DropTemps`.
1675     ///
1676     /// In terms of drop order, it has the same effect as wrapping `expr` in
1677     /// `{ let _t = $expr; _t }` but should provide better compile-time performance.
1678     ///
1679     /// The drop order can be important in e.g. `if expr { .. }`.
1680     pub(super) fn expr_drop_temps(
1681         &mut self,
1682         span: Span,
1683         expr: &'hir hir::Expr<'hir>,
1684         attrs: AttrVec,
1685     ) -> &'hir hir::Expr<'hir> {
1686         self.arena.alloc(self.expr_drop_temps_mut(span, expr, attrs))
1687     }
1688
1689     pub(super) fn expr_drop_temps_mut(
1690         &mut self,
1691         span: Span,
1692         expr: &'hir hir::Expr<'hir>,
1693         attrs: AttrVec,
1694     ) -> hir::Expr<'hir> {
1695         self.expr(span, hir::ExprKind::DropTemps(expr), attrs)
1696     }
1697
1698     fn expr_match(
1699         &mut self,
1700         span: Span,
1701         arg: &'hir hir::Expr<'hir>,
1702         arms: &'hir [hir::Arm<'hir>],
1703         source: hir::MatchSource,
1704     ) -> hir::Expr<'hir> {
1705         self.expr(span, hir::ExprKind::Match(arg, arms, source), AttrVec::new())
1706     }
1707
1708     fn expr_break(&mut self, span: Span, attrs: AttrVec) -> hir::Expr<'hir> {
1709         let expr_break = hir::ExprKind::Break(self.lower_loop_destination(None), None);
1710         self.expr(span, expr_break, attrs)
1711     }
1712
1713     fn expr_break_alloc(&mut self, span: Span, attrs: AttrVec) -> &'hir hir::Expr<'hir> {
1714         let expr_break = self.expr_break(span, attrs);
1715         self.arena.alloc(expr_break)
1716     }
1717
1718     fn expr_mut_addr_of(&mut self, span: Span, e: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
1719         self.expr(
1720             span,
1721             hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e),
1722             AttrVec::new(),
1723         )
1724     }
1725
1726     fn expr_unit(&mut self, sp: Span) -> &'hir hir::Expr<'hir> {
1727         self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[]), AttrVec::new()))
1728     }
1729
1730     fn expr_call_mut(
1731         &mut self,
1732         span: Span,
1733         e: &'hir hir::Expr<'hir>,
1734         args: &'hir [hir::Expr<'hir>],
1735     ) -> hir::Expr<'hir> {
1736         self.expr(span, hir::ExprKind::Call(e, args), AttrVec::new())
1737     }
1738
1739     fn expr_call(
1740         &mut self,
1741         span: Span,
1742         e: &'hir hir::Expr<'hir>,
1743         args: &'hir [hir::Expr<'hir>],
1744     ) -> &'hir hir::Expr<'hir> {
1745         self.arena.alloc(self.expr_call_mut(span, e, args))
1746     }
1747
1748     fn expr_call_lang_item_fn_mut(
1749         &mut self,
1750         span: Span,
1751         lang_item: hir::LangItem,
1752         args: &'hir [hir::Expr<'hir>],
1753         hir_id: Option<hir::HirId>,
1754     ) -> hir::Expr<'hir> {
1755         let path =
1756             self.arena.alloc(self.expr_lang_item_path(span, lang_item, AttrVec::new(), hir_id));
1757         self.expr_call_mut(span, path, args)
1758     }
1759
1760     fn expr_call_lang_item_fn(
1761         &mut self,
1762         span: Span,
1763         lang_item: hir::LangItem,
1764         args: &'hir [hir::Expr<'hir>],
1765         hir_id: Option<hir::HirId>,
1766     ) -> &'hir hir::Expr<'hir> {
1767         self.arena.alloc(self.expr_call_lang_item_fn_mut(span, lang_item, args, hir_id))
1768     }
1769
1770     fn expr_lang_item_path(
1771         &mut self,
1772         span: Span,
1773         lang_item: hir::LangItem,
1774         attrs: AttrVec,
1775         hir_id: Option<hir::HirId>,
1776     ) -> hir::Expr<'hir> {
1777         self.expr(
1778             span,
1779             hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id)),
1780             attrs,
1781         )
1782     }
1783
1784     pub(super) fn expr_ident(
1785         &mut self,
1786         sp: Span,
1787         ident: Ident,
1788         binding: hir::HirId,
1789     ) -> &'hir hir::Expr<'hir> {
1790         self.arena.alloc(self.expr_ident_mut(sp, ident, binding))
1791     }
1792
1793     pub(super) fn expr_ident_mut(
1794         &mut self,
1795         sp: Span,
1796         ident: Ident,
1797         binding: hir::HirId,
1798     ) -> hir::Expr<'hir> {
1799         self.expr_ident_with_attrs(sp, ident, binding, AttrVec::new())
1800     }
1801
1802     fn expr_ident_with_attrs(
1803         &mut self,
1804         span: Span,
1805         ident: Ident,
1806         binding: hir::HirId,
1807         attrs: AttrVec,
1808     ) -> hir::Expr<'hir> {
1809         let hir_id = self.next_id();
1810         let res = Res::Local(binding);
1811         let expr_path = hir::ExprKind::Path(hir::QPath::Resolved(
1812             None,
1813             self.arena.alloc(hir::Path {
1814                 span: self.lower_span(span),
1815                 res,
1816                 segments: arena_vec![self; hir::PathSegment::new(ident, hir_id, res)],
1817             }),
1818         ));
1819
1820         self.expr(span, expr_path, attrs)
1821     }
1822
1823     fn expr_unsafe(&mut self, expr: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
1824         let hir_id = self.next_id();
1825         let span = expr.span;
1826         self.expr(
1827             span,
1828             hir::ExprKind::Block(
1829                 self.arena.alloc(hir::Block {
1830                     stmts: &[],
1831                     expr: Some(expr),
1832                     hir_id,
1833                     rules: hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::CompilerGenerated),
1834                     span: self.lower_span(span),
1835                     targeted_by_break: false,
1836                 }),
1837                 None,
1838             ),
1839             AttrVec::new(),
1840         )
1841     }
1842
1843     fn expr_block_empty(&mut self, span: Span) -> &'hir hir::Expr<'hir> {
1844         let blk = self.block_all(span, &[], None);
1845         let expr = self.expr_block(blk, AttrVec::new());
1846         self.arena.alloc(expr)
1847     }
1848
1849     pub(super) fn expr_block(
1850         &mut self,
1851         b: &'hir hir::Block<'hir>,
1852         attrs: AttrVec,
1853     ) -> hir::Expr<'hir> {
1854         self.expr(b.span, hir::ExprKind::Block(b, None), attrs)
1855     }
1856
1857     pub(super) fn expr(
1858         &mut self,
1859         span: Span,
1860         kind: hir::ExprKind<'hir>,
1861         attrs: AttrVec,
1862     ) -> hir::Expr<'hir> {
1863         let hir_id = self.next_id();
1864         self.lower_attrs(hir_id, &attrs);
1865         hir::Expr { hir_id, kind, span: self.lower_span(span) }
1866     }
1867
1868     fn expr_field(
1869         &mut self,
1870         ident: Ident,
1871         expr: &'hir hir::Expr<'hir>,
1872         span: Span,
1873     ) -> hir::ExprField<'hir> {
1874         hir::ExprField {
1875             hir_id: self.next_id(),
1876             ident,
1877             span: self.lower_span(span),
1878             expr,
1879             is_shorthand: false,
1880         }
1881     }
1882
1883     fn arm(&mut self, pat: &'hir hir::Pat<'hir>, expr: &'hir hir::Expr<'hir>) -> hir::Arm<'hir> {
1884         hir::Arm {
1885             hir_id: self.next_id(),
1886             pat,
1887             guard: None,
1888             span: self.lower_span(expr.span),
1889             body: expr,
1890         }
1891     }
1892 }