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