rustc_ast_lowering/
expr.rs

1use std::assert_matches::assert_matches;
2use std::ops::ControlFlow;
3use std::sync::Arc;
4
5use rustc_ast::ptr::P as AstP;
6use rustc_ast::*;
7use rustc_ast_pretty::pprust::expr_to_string;
8use rustc_data_structures::stack::ensure_sufficient_stack;
9use rustc_hir as hir;
10use rustc_hir::HirId;
11use rustc_hir::def::{DefKind, Res};
12use rustc_middle::span_bug;
13use rustc_middle::ty::TyCtxt;
14use rustc_session::errors::report_lit_error;
15use rustc_span::source_map::{Spanned, respan};
16use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym};
17use thin_vec::{ThinVec, thin_vec};
18use visit::{Visitor, walk_expr};
19
20use super::errors::{
21    AsyncCoroutinesNotSupported, AwaitOnlyInAsyncFnAndBlocks, ClosureCannotBeStatic,
22    CoroutineTooManyParameters, FunctionalRecordUpdateDestructuringAssignment,
23    InclusiveRangeWithNoEnd, MatchArmWithNoBody, NeverPatternWithBody, NeverPatternWithGuard,
24    UnderscoreExprLhsAssign,
25};
26use super::{
27    GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt,
28};
29use crate::errors::{InvalidLegacyConstGenericArg, UseConstGenericArg, YieldInClosure};
30use crate::{AllowReturnTypeNotation, FnDeclKind, ImplTraitPosition, fluent_generated};
31
32struct WillCreateDefIdsVisitor {}
33
34impl<'v> rustc_ast::visit::Visitor<'v> for WillCreateDefIdsVisitor {
35    type Result = ControlFlow<Span>;
36
37    fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {
38        ControlFlow::Break(c.value.span)
39    }
40
41    fn visit_item(&mut self, item: &'v Item) -> Self::Result {
42        ControlFlow::Break(item.span)
43    }
44
45    fn visit_expr(&mut self, ex: &'v Expr) -> Self::Result {
46        match ex.kind {
47            ExprKind::Gen(..) | ExprKind::ConstBlock(..) | ExprKind::Closure(..) => {
48                ControlFlow::Break(ex.span)
49            }
50            _ => walk_expr(self, ex),
51        }
52    }
53}
54
55impl<'hir> LoweringContext<'_, 'hir> {
56    fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
57        self.arena.alloc_from_iter(exprs.iter().map(|x| self.lower_expr_mut(x)))
58    }
59
60    pub(super) fn lower_expr(&mut self, e: &Expr) -> &'hir hir::Expr<'hir> {
61        self.arena.alloc(self.lower_expr_mut(e))
62    }
63
64    pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
65        ensure_sufficient_stack(|| {
66            match &e.kind {
67                // Parenthesis expression does not have a HirId and is handled specially.
68                ExprKind::Paren(ex) => {
69                    let mut ex = self.lower_expr_mut(ex);
70                    // Include parens in span, but only if it is a super-span.
71                    if e.span.contains(ex.span) {
72                        ex.span = self.lower_span(e.span);
73                    }
74                    // Merge attributes into the inner expression.
75                    if !e.attrs.is_empty() {
76                        let old_attrs = self.attrs.get(&ex.hir_id.local_id).copied().unwrap_or(&[]);
77                        self.attrs.insert(
78                            ex.hir_id.local_id,
79                            &*self.arena.alloc_from_iter(
80                                e.attrs
81                                    .iter()
82                                    .map(|a| self.lower_attr(a))
83                                    .chain(old_attrs.iter().cloned()),
84                            ),
85                        );
86                    }
87                    return ex;
88                }
89                // Desugar `ExprForLoop`
90                // from: `[opt_ident]: for await? <pat> in <iter> <body>`
91                //
92                // This also needs special handling because the HirId of the returned `hir::Expr` will not
93                // correspond to the `e.id`, so `lower_expr_for` handles attribute lowering itself.
94                ExprKind::ForLoop { pat, iter, body, label, kind } => {
95                    return self.lower_expr_for(e, pat, iter, body, *label, *kind);
96                }
97                _ => (),
98            }
99
100            let expr_hir_id = self.lower_node_id(e.id);
101            self.lower_attrs(expr_hir_id, &e.attrs);
102
103            let kind = match &e.kind {
104                ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
105                ExprKind::ConstBlock(c) => hir::ExprKind::ConstBlock(self.lower_const_block(c)),
106                ExprKind::Repeat(expr, count) => {
107                    let expr = self.lower_expr(expr);
108                    let count = self.lower_array_length_to_const_arg(count);
109                    hir::ExprKind::Repeat(expr, count)
110                }
111                ExprKind::Tup(elts) => hir::ExprKind::Tup(self.lower_exprs(elts)),
112                ExprKind::Call(f, args) => {
113                    if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) {
114                        self.lower_legacy_const_generics((**f).clone(), args.clone(), &legacy_args)
115                    } else {
116                        let f = self.lower_expr(f);
117                        hir::ExprKind::Call(f, self.lower_exprs(args))
118                    }
119                }
120                ExprKind::MethodCall(box MethodCall { seg, receiver, args, span }) => {
121                    let hir_seg = self.arena.alloc(self.lower_path_segment(
122                        e.span,
123                        seg,
124                        ParamMode::Optional,
125                        GenericArgsMode::Err,
126                        ImplTraitContext::Disallowed(ImplTraitPosition::Path),
127                        // Method calls can't have bound modifiers
128                        None,
129                    ));
130                    let receiver = self.lower_expr(receiver);
131                    let args =
132                        self.arena.alloc_from_iter(args.iter().map(|x| self.lower_expr_mut(x)));
133                    hir::ExprKind::MethodCall(hir_seg, receiver, args, self.lower_span(*span))
134                }
135                ExprKind::Binary(binop, lhs, rhs) => {
136                    let binop = self.lower_binop(*binop);
137                    let lhs = self.lower_expr(lhs);
138                    let rhs = self.lower_expr(rhs);
139                    hir::ExprKind::Binary(binop, lhs, rhs)
140                }
141                ExprKind::Unary(op, ohs) => {
142                    let op = self.lower_unop(*op);
143                    let ohs = self.lower_expr(ohs);
144                    hir::ExprKind::Unary(op, ohs)
145                }
146                ExprKind::Lit(token_lit) => hir::ExprKind::Lit(self.lower_lit(token_lit, e.span)),
147                ExprKind::IncludedBytes(bytes) => {
148                    let lit = self.arena.alloc(respan(
149                        self.lower_span(e.span),
150                        LitKind::ByteStr(Arc::clone(bytes), StrStyle::Cooked),
151                    ));
152                    hir::ExprKind::Lit(lit)
153                }
154                ExprKind::Cast(expr, ty) => {
155                    let expr = self.lower_expr(expr);
156                    let ty =
157                        self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Cast));
158                    hir::ExprKind::Cast(expr, ty)
159                }
160                ExprKind::Type(expr, ty) => {
161                    let expr = self.lower_expr(expr);
162                    let ty =
163                        self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Cast));
164                    hir::ExprKind::Type(expr, ty)
165                }
166                ExprKind::AddrOf(k, m, ohs) => {
167                    let ohs = self.lower_expr(ohs);
168                    hir::ExprKind::AddrOf(*k, *m, ohs)
169                }
170                ExprKind::Let(pat, scrutinee, span, recovered) => {
171                    hir::ExprKind::Let(self.arena.alloc(hir::LetExpr {
172                        span: self.lower_span(*span),
173                        pat: self.lower_pat(pat),
174                        ty: None,
175                        init: self.lower_expr(scrutinee),
176                        recovered: *recovered,
177                    }))
178                }
179                ExprKind::If(cond, then, else_opt) => {
180                    self.lower_expr_if(cond, then, else_opt.as_deref())
181                }
182                ExprKind::While(cond, body, opt_label) => {
183                    self.with_loop_scope(expr_hir_id, |this| {
184                        let span =
185                            this.mark_span_with_reason(DesugaringKind::WhileLoop, e.span, None);
186                        let opt_label = this.lower_label(*opt_label, e.id, expr_hir_id);
187                        this.lower_expr_while_in_loop_scope(span, cond, body, opt_label)
188                    })
189                }
190                ExprKind::Loop(body, opt_label, span) => {
191                    self.with_loop_scope(expr_hir_id, |this| {
192                        let opt_label = this.lower_label(*opt_label, e.id, expr_hir_id);
193                        hir::ExprKind::Loop(
194                            this.lower_block(body, false),
195                            opt_label,
196                            hir::LoopSource::Loop,
197                            this.lower_span(*span),
198                        )
199                    })
200                }
201                ExprKind::TryBlock(body) => self.lower_expr_try_block(body),
202                ExprKind::Match(expr, arms, kind) => hir::ExprKind::Match(
203                    self.lower_expr(expr),
204                    self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))),
205                    match kind {
206                        MatchKind::Prefix => hir::MatchSource::Normal,
207                        MatchKind::Postfix => hir::MatchSource::Postfix,
208                    },
209                ),
210                ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr),
211                ExprKind::Closure(box Closure {
212                    binder,
213                    capture_clause,
214                    constness,
215                    coroutine_kind,
216                    movability,
217                    fn_decl,
218                    body,
219                    fn_decl_span,
220                    fn_arg_span,
221                }) => match coroutine_kind {
222                    Some(coroutine_kind) => self.lower_expr_coroutine_closure(
223                        binder,
224                        *capture_clause,
225                        e.id,
226                        expr_hir_id,
227                        *coroutine_kind,
228                        fn_decl,
229                        body,
230                        *fn_decl_span,
231                        *fn_arg_span,
232                    ),
233                    None => self.lower_expr_closure(
234                        binder,
235                        *capture_clause,
236                        e.id,
237                        expr_hir_id,
238                        *constness,
239                        *movability,
240                        fn_decl,
241                        body,
242                        *fn_decl_span,
243                        *fn_arg_span,
244                    ),
245                },
246                ExprKind::Gen(capture_clause, block, genblock_kind, decl_span) => {
247                    let desugaring_kind = match genblock_kind {
248                        GenBlockKind::Async => hir::CoroutineDesugaring::Async,
249                        GenBlockKind::Gen => hir::CoroutineDesugaring::Gen,
250                        GenBlockKind::AsyncGen => hir::CoroutineDesugaring::AsyncGen,
251                    };
252                    self.make_desugared_coroutine_expr(
253                        *capture_clause,
254                        e.id,
255                        None,
256                        *decl_span,
257                        e.span,
258                        desugaring_kind,
259                        hir::CoroutineSource::Block,
260                        |this| this.with_new_scopes(e.span, |this| this.lower_block_expr(block)),
261                    )
262                }
263                ExprKind::Block(blk, opt_label) => {
264                    // Different from loops, label of block resolves to block id rather than
265                    // expr node id.
266                    let block_hir_id = self.lower_node_id(blk.id);
267                    let opt_label = self.lower_label(*opt_label, blk.id, block_hir_id);
268                    let hir_block = self.arena.alloc(self.lower_block_noalloc(
269                        block_hir_id,
270                        blk,
271                        opt_label.is_some(),
272                    ));
273                    hir::ExprKind::Block(hir_block, opt_label)
274                }
275                ExprKind::Assign(el, er, span) => self.lower_expr_assign(el, er, *span, e.span),
276                ExprKind::AssignOp(op, el, er) => hir::ExprKind::AssignOp(
277                    self.lower_binop(*op),
278                    self.lower_expr(el),
279                    self.lower_expr(er),
280                ),
281                ExprKind::Field(el, ident) => {
282                    hir::ExprKind::Field(self.lower_expr(el), self.lower_ident(*ident))
283                }
284                ExprKind::Index(el, er, brackets_span) => {
285                    hir::ExprKind::Index(self.lower_expr(el), self.lower_expr(er), *brackets_span)
286                }
287                ExprKind::Range(e1, e2, lims) => {
288                    self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), *lims)
289                }
290                ExprKind::Underscore => {
291                    let guar = self.dcx().emit_err(UnderscoreExprLhsAssign { span: e.span });
292                    hir::ExprKind::Err(guar)
293                }
294                ExprKind::Path(qself, path) => {
295                    let qpath = self.lower_qpath(
296                        e.id,
297                        qself,
298                        path,
299                        ParamMode::Optional,
300                        AllowReturnTypeNotation::No,
301                        ImplTraitContext::Disallowed(ImplTraitPosition::Path),
302                        None,
303                    );
304                    hir::ExprKind::Path(qpath)
305                }
306                ExprKind::Break(opt_label, opt_expr) => {
307                    let opt_expr = opt_expr.as_ref().map(|x| self.lower_expr(x));
308                    hir::ExprKind::Break(self.lower_jump_destination(e.id, *opt_label), opt_expr)
309                }
310                ExprKind::Continue(opt_label) => {
311                    hir::ExprKind::Continue(self.lower_jump_destination(e.id, *opt_label))
312                }
313                ExprKind::Ret(e) => {
314                    let expr = e.as_ref().map(|x| self.lower_expr(x));
315                    self.checked_return(expr)
316                }
317                ExprKind::Yeet(sub_expr) => self.lower_expr_yeet(e.span, sub_expr.as_deref()),
318                ExprKind::Become(sub_expr) => {
319                    let sub_expr = self.lower_expr(sub_expr);
320                    hir::ExprKind::Become(sub_expr)
321                }
322                ExprKind::InlineAsm(asm) => {
323                    hir::ExprKind::InlineAsm(self.lower_inline_asm(e.span, asm))
324                }
325                ExprKind::FormatArgs(fmt) => self.lower_format_args(e.span, fmt),
326                ExprKind::OffsetOf(container, fields) => hir::ExprKind::OffsetOf(
327                    self.lower_ty(
328                        container,
329                        ImplTraitContext::Disallowed(ImplTraitPosition::OffsetOf),
330                    ),
331                    self.arena.alloc_from_iter(fields.iter().map(|&ident| self.lower_ident(ident))),
332                ),
333                ExprKind::Struct(se) => {
334                    let rest = match &se.rest {
335                        StructRest::Base(e) => hir::StructTailExpr::Base(self.lower_expr(e)),
336                        StructRest::Rest(sp) => hir::StructTailExpr::DefaultFields(*sp),
337                        StructRest::None => hir::StructTailExpr::None,
338                    };
339                    hir::ExprKind::Struct(
340                        self.arena.alloc(self.lower_qpath(
341                            e.id,
342                            &se.qself,
343                            &se.path,
344                            ParamMode::Optional,
345                            AllowReturnTypeNotation::No,
346                            ImplTraitContext::Disallowed(ImplTraitPosition::Path),
347                            None,
348                        )),
349                        self.arena
350                            .alloc_from_iter(se.fields.iter().map(|x| self.lower_expr_field(x))),
351                        rest,
352                    )
353                }
354                ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
355                ExprKind::Err(guar) => hir::ExprKind::Err(*guar),
356
357                ExprKind::UnsafeBinderCast(kind, expr, ty) => hir::ExprKind::UnsafeBinderCast(
358                    *kind,
359                    self.lower_expr(expr),
360                    ty.as_ref().map(|ty| {
361                        self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Cast))
362                    }),
363                ),
364
365                ExprKind::Dummy => {
366                    span_bug!(e.span, "lowered ExprKind::Dummy")
367                }
368
369                ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),
370
371                ExprKind::Paren(_) | ExprKind::ForLoop { .. } => {
372                    unreachable!("already handled")
373                }
374
375                ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),
376            };
377
378            hir::Expr { hir_id: expr_hir_id, kind, span: self.lower_span(e.span) }
379        })
380    }
381
382    /// Create an `ExprKind::Ret` that is optionally wrapped by a call to check
383    /// a contract ensures clause, if it exists.
384    fn checked_return(&mut self, opt_expr: Option<&'hir hir::Expr<'hir>>) -> hir::ExprKind<'hir> {
385        let checked_ret =
386            if let Some((check_span, check_ident, check_hir_id)) = self.contract_ensures {
387                let expr = opt_expr.unwrap_or_else(|| self.expr_unit(check_span));
388                Some(self.inject_ensures_check(expr, check_span, check_ident, check_hir_id))
389            } else {
390                opt_expr
391            };
392        hir::ExprKind::Ret(checked_ret)
393    }
394
395    /// Wraps an expression with a call to the ensures check before it gets returned.
396    pub(crate) fn inject_ensures_check(
397        &mut self,
398        expr: &'hir hir::Expr<'hir>,
399        span: Span,
400        check_ident: Ident,
401        check_hir_id: HirId,
402    ) -> &'hir hir::Expr<'hir> {
403        let checker_fn = self.expr_ident(span, check_ident, check_hir_id);
404        let span = self.mark_span_with_reason(DesugaringKind::Contract, span, None);
405        self.expr_call(span, checker_fn, std::slice::from_ref(expr))
406    }
407
408    pub(crate) fn lower_const_block(&mut self, c: &AnonConst) -> hir::ConstBlock {
409        self.with_new_scopes(c.value.span, |this| {
410            let def_id = this.local_def_id(c.id);
411            hir::ConstBlock {
412                def_id,
413                hir_id: this.lower_node_id(c.id),
414                body: this.lower_const_body(c.value.span, Some(&c.value)),
415            }
416        })
417    }
418
419    pub(crate) fn lower_lit(
420        &mut self,
421        token_lit: &token::Lit,
422        span: Span,
423    ) -> &'hir Spanned<LitKind> {
424        let lit_kind = match LitKind::from_token_lit(*token_lit) {
425            Ok(lit_kind) => lit_kind,
426            Err(err) => {
427                let guar = report_lit_error(&self.tcx.sess.psess, err, *token_lit, span);
428                LitKind::Err(guar)
429            }
430        };
431        self.arena.alloc(respan(self.lower_span(span), lit_kind))
432    }
433
434    fn lower_unop(&mut self, u: UnOp) -> hir::UnOp {
435        match u {
436            UnOp::Deref => hir::UnOp::Deref,
437            UnOp::Not => hir::UnOp::Not,
438            UnOp::Neg => hir::UnOp::Neg,
439        }
440    }
441
442    fn lower_binop(&mut self, b: BinOp) -> BinOp {
443        Spanned { node: b.node, span: self.lower_span(b.span) }
444    }
445
446    fn lower_legacy_const_generics(
447        &mut self,
448        mut f: Expr,
449        args: ThinVec<AstP<Expr>>,
450        legacy_args_idx: &[usize],
451    ) -> hir::ExprKind<'hir> {
452        let ExprKind::Path(None, path) = &mut f.kind else {
453            unreachable!();
454        };
455
456        let mut error = None;
457        let mut invalid_expr_error = |tcx: TyCtxt<'_>, span| {
458            // Avoid emitting the error multiple times.
459            if error.is_none() {
460                let mut const_args = vec![];
461                let mut other_args = vec![];
462                for (idx, arg) in args.iter().enumerate() {
463                    if legacy_args_idx.contains(&idx) {
464                        const_args.push(format!("{{ {} }}", expr_to_string(arg)));
465                    } else {
466                        other_args.push(expr_to_string(arg));
467                    }
468                }
469                let suggestion = UseConstGenericArg {
470                    end_of_fn: f.span.shrink_to_hi(),
471                    const_args: const_args.join(", "),
472                    other_args: other_args.join(", "),
473                    call_args: args[0].span.to(args.last().unwrap().span),
474                };
475                error = Some(tcx.dcx().emit_err(InvalidLegacyConstGenericArg { span, suggestion }));
476            }
477            error.unwrap()
478        };
479
480        // Split the arguments into const generics and normal arguments
481        let mut real_args = vec![];
482        let mut generic_args = ThinVec::new();
483        for (idx, arg) in args.iter().cloned().enumerate() {
484            if legacy_args_idx.contains(&idx) {
485                let parent_def_id = self.current_hir_id_owner.def_id;
486                let node_id = self.next_node_id();
487                self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span);
488                let mut visitor = WillCreateDefIdsVisitor {};
489                let const_value = if let ControlFlow::Break(span) = visitor.visit_expr(&arg) {
490                    AstP(Expr {
491                        id: self.next_node_id(),
492                        kind: ExprKind::Err(invalid_expr_error(self.tcx, span)),
493                        span: f.span,
494                        attrs: [].into(),
495                        tokens: None,
496                    })
497                } else {
498                    arg
499                };
500
501                let anon_const = AnonConst { id: node_id, value: const_value };
502                generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const)));
503            } else {
504                real_args.push(arg);
505            }
506        }
507
508        // Add generic args to the last element of the path.
509        let last_segment = path.segments.last_mut().unwrap();
510        assert!(last_segment.args.is_none());
511        last_segment.args = Some(AstP(GenericArgs::AngleBracketed(AngleBracketedArgs {
512            span: DUMMY_SP,
513            args: generic_args,
514        })));
515
516        // Now lower everything as normal.
517        let f = self.lower_expr(&f);
518        hir::ExprKind::Call(f, self.lower_exprs(&real_args))
519    }
520
521    fn lower_expr_if(
522        &mut self,
523        cond: &Expr,
524        then: &Block,
525        else_opt: Option<&Expr>,
526    ) -> hir::ExprKind<'hir> {
527        let lowered_cond = self.lower_cond(cond);
528        let then_expr = self.lower_block_expr(then);
529        if let Some(rslt) = else_opt {
530            hir::ExprKind::If(
531                lowered_cond,
532                self.arena.alloc(then_expr),
533                Some(self.lower_expr(rslt)),
534            )
535        } else {
536            hir::ExprKind::If(lowered_cond, self.arena.alloc(then_expr), None)
537        }
538    }
539
540    // Lowers a condition (i.e. `cond` in `if cond` or `while cond`), wrapping it in a terminating scope
541    // so that temporaries created in the condition don't live beyond it.
542    fn lower_cond(&mut self, cond: &Expr) -> &'hir hir::Expr<'hir> {
543        fn has_let_expr(expr: &Expr) -> bool {
544            match &expr.kind {
545                ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
546                ExprKind::Let(..) => true,
547                _ => false,
548            }
549        }
550
551        // We have to take special care for `let` exprs in the condition, e.g. in
552        // `if let pat = val` or `if foo && let pat = val`, as we _do_ want `val` to live beyond the
553        // condition in this case.
554        //
555        // In order to maintain the drop behavior for the non `let` parts of the condition,
556        // we still wrap them in terminating scopes, e.g. `if foo && let pat = val` essentially
557        // gets transformed into `if { let _t = foo; _t } && let pat = val`
558        match &cond.kind {
559            ExprKind::Binary(op @ Spanned { node: ast::BinOpKind::And, .. }, lhs, rhs)
560                if has_let_expr(cond) =>
561            {
562                let op = self.lower_binop(*op);
563                let lhs = self.lower_cond(lhs);
564                let rhs = self.lower_cond(rhs);
565
566                self.arena.alloc(self.expr(cond.span, hir::ExprKind::Binary(op, lhs, rhs)))
567            }
568            ExprKind::Let(..) => self.lower_expr(cond),
569            _ => {
570                let cond = self.lower_expr(cond);
571                let reason = DesugaringKind::CondTemporary;
572                let span_block = self.mark_span_with_reason(reason, cond.span, None);
573                self.expr_drop_temps(span_block, cond)
574            }
575        }
576    }
577
578    // We desugar: `'label: while $cond $body` into:
579    //
580    // ```
581    // 'label: loop {
582    //   if { let _t = $cond; _t } {
583    //     $body
584    //   }
585    //   else {
586    //     break;
587    //   }
588    // }
589    // ```
590    //
591    // Wrap in a construct equivalent to `{ let _t = $cond; _t }`
592    // to preserve drop semantics since `while $cond { ... }` does not
593    // let temporaries live outside of `cond`.
594    fn lower_expr_while_in_loop_scope(
595        &mut self,
596        span: Span,
597        cond: &Expr,
598        body: &Block,
599        opt_label: Option<Label>,
600    ) -> hir::ExprKind<'hir> {
601        let lowered_cond = self.with_loop_condition_scope(|t| t.lower_cond(cond));
602        let then = self.lower_block_expr(body);
603        let expr_break = self.expr_break(span);
604        let stmt_break = self.stmt_expr(span, expr_break);
605        let else_blk = self.block_all(span, arena_vec![self; stmt_break], None);
606        let else_expr = self.arena.alloc(self.expr_block(else_blk));
607        let if_kind = hir::ExprKind::If(lowered_cond, self.arena.alloc(then), Some(else_expr));
608        let if_expr = self.expr(span, if_kind);
609        let block = self.block_expr(self.arena.alloc(if_expr));
610        let span = self.lower_span(span.with_hi(cond.span.hi()));
611        hir::ExprKind::Loop(block, opt_label, hir::LoopSource::While, span)
612    }
613
614    /// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_output(<expr>) }`,
615    /// `try { <stmts>; }` into `{ <stmts>; ::std::ops::Try::from_output(()) }`
616    /// and save the block id to use it as a break target for desugaring of the `?` operator.
617    fn lower_expr_try_block(&mut self, body: &Block) -> hir::ExprKind<'hir> {
618        let body_hir_id = self.lower_node_id(body.id);
619        self.with_catch_scope(body_hir_id, |this| {
620            let mut block = this.lower_block_noalloc(body_hir_id, body, true);
621
622            // Final expression of the block (if present) or `()` with span at the end of block
623            let (try_span, tail_expr) = if let Some(expr) = block.expr.take() {
624                (
625                    this.mark_span_with_reason(
626                        DesugaringKind::TryBlock,
627                        expr.span,
628                        Some(Arc::clone(&this.allow_try_trait)),
629                    ),
630                    expr,
631                )
632            } else {
633                let try_span = this.mark_span_with_reason(
634                    DesugaringKind::TryBlock,
635                    this.tcx.sess.source_map().end_point(body.span),
636                    Some(Arc::clone(&this.allow_try_trait)),
637                );
638
639                (try_span, this.expr_unit(try_span))
640            };
641
642            let ok_wrapped_span =
643                this.mark_span_with_reason(DesugaringKind::TryBlock, tail_expr.span, None);
644
645            // `::std::ops::Try::from_output($tail_expr)`
646            block.expr = Some(this.wrap_in_try_constructor(
647                hir::LangItem::TryTraitFromOutput,
648                try_span,
649                tail_expr,
650                ok_wrapped_span,
651            ));
652
653            hir::ExprKind::Block(this.arena.alloc(block), None)
654        })
655    }
656
657    fn wrap_in_try_constructor(
658        &mut self,
659        lang_item: hir::LangItem,
660        method_span: Span,
661        expr: &'hir hir::Expr<'hir>,
662        overall_span: Span,
663    ) -> &'hir hir::Expr<'hir> {
664        let constructor = self.arena.alloc(self.expr_lang_item_path(method_span, lang_item));
665        self.expr_call(overall_span, constructor, std::slice::from_ref(expr))
666    }
667
668    fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
669        let pat = self.lower_pat(&arm.pat);
670        let guard = arm.guard.as_ref().map(|cond| self.lower_expr(cond));
671        let hir_id = self.next_id();
672        let span = self.lower_span(arm.span);
673        self.lower_attrs(hir_id, &arm.attrs);
674        let is_never_pattern = pat.is_never_pattern();
675        let body = if let Some(body) = &arm.body
676            && !is_never_pattern
677        {
678            self.lower_expr(body)
679        } else {
680            // Either `body.is_none()` or `is_never_pattern` here.
681            if !is_never_pattern {
682                if self.tcx.features().never_patterns() {
683                    // If the feature is off we already emitted the error after parsing.
684                    let suggestion = span.shrink_to_hi();
685                    self.dcx().emit_err(MatchArmWithNoBody { span, suggestion });
686                }
687            } else if let Some(body) = &arm.body {
688                self.dcx().emit_err(NeverPatternWithBody { span: body.span });
689            } else if let Some(g) = &arm.guard {
690                self.dcx().emit_err(NeverPatternWithGuard { span: g.span });
691            }
692
693            // We add a fake `loop {}` arm body so that it typecks to `!`. The mir lowering of never
694            // patterns ensures this loop is not reachable.
695            let block = self.arena.alloc(hir::Block {
696                stmts: &[],
697                expr: None,
698                hir_id: self.next_id(),
699                rules: hir::BlockCheckMode::DefaultBlock,
700                span,
701                targeted_by_break: false,
702            });
703            self.arena.alloc(hir::Expr {
704                hir_id: self.next_id(),
705                kind: hir::ExprKind::Loop(block, None, hir::LoopSource::Loop, span),
706                span,
707            })
708        };
709        hir::Arm { hir_id, pat, guard, body, span }
710    }
711
712    /// Lower/desugar a coroutine construct.
713    ///
714    /// In particular, this creates the correct async resume argument and `_task_context`.
715    ///
716    /// This results in:
717    ///
718    /// ```text
719    /// static move? |<_task_context?>| -> <return_ty> {
720    ///     <body>
721    /// }
722    /// ```
723    pub(super) fn make_desugared_coroutine_expr(
724        &mut self,
725        capture_clause: CaptureBy,
726        closure_node_id: NodeId,
727        return_ty: Option<hir::FnRetTy<'hir>>,
728        fn_decl_span: Span,
729        span: Span,
730        desugaring_kind: hir::CoroutineDesugaring,
731        coroutine_source: hir::CoroutineSource,
732        body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
733    ) -> hir::ExprKind<'hir> {
734        let closure_def_id = self.local_def_id(closure_node_id);
735        let coroutine_kind = hir::CoroutineKind::Desugared(desugaring_kind, coroutine_source);
736
737        // The `async` desugaring takes a resume argument and maintains a `task_context`,
738        // whereas a generator does not.
739        let (inputs, params, task_context): (&[_], &[_], _) = match desugaring_kind {
740            hir::CoroutineDesugaring::Async | hir::CoroutineDesugaring::AsyncGen => {
741                // Resume argument type: `ResumeTy`
742                let unstable_span = self.mark_span_with_reason(
743                    DesugaringKind::Async,
744                    self.lower_span(span),
745                    Some(Arc::clone(&self.allow_gen_future)),
746                );
747                let resume_ty =
748                    self.make_lang_item_qpath(hir::LangItem::ResumeTy, unstable_span, None);
749                let input_ty = hir::Ty {
750                    hir_id: self.next_id(),
751                    kind: hir::TyKind::Path(resume_ty),
752                    span: unstable_span,
753                };
754                let inputs = arena_vec![self; input_ty];
755
756                // Lower the argument pattern/ident. The ident is used again in the `.await` lowering.
757                let (pat, task_context_hid) = self.pat_ident_binding_mode(
758                    span,
759                    Ident::with_dummy_span(sym::_task_context),
760                    hir::BindingMode::MUT,
761                );
762                let param = hir::Param {
763                    hir_id: self.next_id(),
764                    pat,
765                    ty_span: self.lower_span(span),
766                    span: self.lower_span(span),
767                };
768                let params = arena_vec![self; param];
769
770                (inputs, params, Some(task_context_hid))
771            }
772            hir::CoroutineDesugaring::Gen => (&[], &[], None),
773        };
774
775        let output =
776            return_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span)));
777
778        let fn_decl = self.arena.alloc(hir::FnDecl {
779            inputs,
780            output,
781            c_variadic: false,
782            implicit_self: hir::ImplicitSelfKind::None,
783            lifetime_elision_allowed: false,
784        });
785
786        let body = self.lower_body(move |this| {
787            this.coroutine_kind = Some(coroutine_kind);
788
789            let old_ctx = this.task_context;
790            if task_context.is_some() {
791                this.task_context = task_context;
792            }
793            let res = body(this);
794            this.task_context = old_ctx;
795
796            (params, res)
797        });
798
799        // `static |<_task_context?>| -> <return_ty> { <body> }`:
800        hir::ExprKind::Closure(self.arena.alloc(hir::Closure {
801            def_id: closure_def_id,
802            binder: hir::ClosureBinder::Default,
803            capture_clause,
804            bound_generic_params: &[],
805            fn_decl,
806            body,
807            fn_decl_span: self.lower_span(fn_decl_span),
808            fn_arg_span: None,
809            kind: hir::ClosureKind::Coroutine(coroutine_kind),
810            constness: hir::Constness::NotConst,
811        }))
812    }
813
814    /// Forwards a possible `#[track_caller]` annotation from `outer_hir_id` to
815    /// `inner_hir_id` in case the `async_fn_track_caller` feature is enabled.
816    pub(super) fn maybe_forward_track_caller(
817        &mut self,
818        span: Span,
819        outer_hir_id: HirId,
820        inner_hir_id: HirId,
821    ) {
822        if self.tcx.features().async_fn_track_caller()
823            && let Some(attrs) = self.attrs.get(&outer_hir_id.local_id)
824            && attrs.into_iter().any(|attr| attr.has_name(sym::track_caller))
825        {
826            let unstable_span = self.mark_span_with_reason(
827                DesugaringKind::Async,
828                span,
829                Some(Arc::clone(&self.allow_gen_future)),
830            );
831            self.lower_attrs(
832                inner_hir_id,
833                &[Attribute {
834                    kind: AttrKind::Normal(ptr::P(NormalAttr::from_ident(Ident::new(
835                        sym::track_caller,
836                        span,
837                    )))),
838                    id: self.tcx.sess.psess.attr_id_generator.mk_attr_id(),
839                    style: AttrStyle::Outer,
840                    span: unstable_span,
841                }],
842            );
843        }
844    }
845
846    /// Desugar `<expr>.await` into:
847    /// ```ignore (pseudo-rust)
848    /// match ::std::future::IntoFuture::into_future(<expr>) {
849    ///     mut __awaitee => loop {
850    ///         match unsafe { ::std::future::Future::poll(
851    ///             <::std::pin::Pin>::new_unchecked(&mut __awaitee),
852    ///             ::std::future::get_context(task_context),
853    ///         ) } {
854    ///             ::std::task::Poll::Ready(result) => break result,
855    ///             ::std::task::Poll::Pending => {}
856    ///         }
857    ///         task_context = yield ();
858    ///     }
859    /// }
860    /// ```
861    fn lower_expr_await(&mut self, await_kw_span: Span, expr: &Expr) -> hir::ExprKind<'hir> {
862        let expr = self.arena.alloc(self.lower_expr_mut(expr));
863        self.make_lowered_await(await_kw_span, expr, FutureKind::Future)
864    }
865
866    /// Takes an expr that has already been lowered and generates a desugared await loop around it
867    fn make_lowered_await(
868        &mut self,
869        await_kw_span: Span,
870        expr: &'hir hir::Expr<'hir>,
871        await_kind: FutureKind,
872    ) -> hir::ExprKind<'hir> {
873        let full_span = expr.span.to(await_kw_span);
874
875        let is_async_gen = match self.coroutine_kind {
876            Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => false,
877            Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => true,
878            Some(hir::CoroutineKind::Coroutine(_))
879            | Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _))
880            | None => {
881                // Lower to a block `{ EXPR; <error> }` so that the awaited expr
882                // is not accidentally orphaned.
883                let stmt_id = self.next_id();
884                let expr_err = self.expr(
885                    expr.span,
886                    hir::ExprKind::Err(self.dcx().emit_err(AwaitOnlyInAsyncFnAndBlocks {
887                        await_kw_span,
888                        item_span: self.current_item,
889                    })),
890                );
891                return hir::ExprKind::Block(
892                    self.block_all(
893                        expr.span,
894                        arena_vec![self; hir::Stmt {
895                            hir_id: stmt_id,
896                            kind: hir::StmtKind::Semi(expr),
897                            span: expr.span,
898                        }],
899                        Some(self.arena.alloc(expr_err)),
900                    ),
901                    None,
902                );
903            }
904        };
905
906        let features = match await_kind {
907            FutureKind::Future => None,
908            FutureKind::AsyncIterator => Some(Arc::clone(&self.allow_for_await)),
909        };
910        let span = self.mark_span_with_reason(DesugaringKind::Await, await_kw_span, features);
911        let gen_future_span = self.mark_span_with_reason(
912            DesugaringKind::Await,
913            full_span,
914            Some(Arc::clone(&self.allow_gen_future)),
915        );
916        let expr_hir_id = expr.hir_id;
917
918        // Note that the name of this binding must not be changed to something else because
919        // debuggers and debugger extensions expect it to be called `__awaitee`. They use
920        // this name to identify what is being awaited by a suspended async functions.
921        let awaitee_ident = Ident::with_dummy_span(sym::__awaitee);
922        let (awaitee_pat, awaitee_pat_hid) =
923            self.pat_ident_binding_mode(gen_future_span, awaitee_ident, hir::BindingMode::MUT);
924
925        let task_context_ident = Ident::with_dummy_span(sym::_task_context);
926
927        // unsafe {
928        //     ::std::future::Future::poll(
929        //         ::std::pin::Pin::new_unchecked(&mut __awaitee),
930        //         ::std::future::get_context(task_context),
931        //     )
932        // }
933        let poll_expr = {
934            let awaitee = self.expr_ident(span, awaitee_ident, awaitee_pat_hid);
935            let ref_mut_awaitee = self.expr_mut_addr_of(span, awaitee);
936
937            let Some(task_context_hid) = self.task_context else {
938                unreachable!("use of `await` outside of an async context.");
939            };
940
941            let task_context = self.expr_ident_mut(span, task_context_ident, task_context_hid);
942
943            let new_unchecked = self.expr_call_lang_item_fn_mut(
944                span,
945                hir::LangItem::PinNewUnchecked,
946                arena_vec![self; ref_mut_awaitee],
947            );
948            let get_context = self.expr_call_lang_item_fn_mut(
949                gen_future_span,
950                hir::LangItem::GetContext,
951                arena_vec![self; task_context],
952            );
953            let call = match await_kind {
954                FutureKind::Future => self.expr_call_lang_item_fn(
955                    span,
956                    hir::LangItem::FuturePoll,
957                    arena_vec![self; new_unchecked, get_context],
958                ),
959                FutureKind::AsyncIterator => self.expr_call_lang_item_fn(
960                    span,
961                    hir::LangItem::AsyncIteratorPollNext,
962                    arena_vec![self; new_unchecked, get_context],
963                ),
964            };
965            self.arena.alloc(self.expr_unsafe(call))
966        };
967
968        // `::std::task::Poll::Ready(result) => break result`
969        let loop_node_id = self.next_node_id();
970        let loop_hir_id = self.lower_node_id(loop_node_id);
971        let ready_arm = {
972            let x_ident = Ident::with_dummy_span(sym::result);
973            let (x_pat, x_pat_hid) = self.pat_ident(gen_future_span, x_ident);
974            let x_expr = self.expr_ident(gen_future_span, x_ident, x_pat_hid);
975            let ready_field = self.single_pat_field(gen_future_span, x_pat);
976            let ready_pat = self.pat_lang_item_variant(span, hir::LangItem::PollReady, ready_field);
977            let break_x = self.with_loop_scope(loop_hir_id, move |this| {
978                let expr_break =
979                    hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr));
980                this.arena.alloc(this.expr(gen_future_span, expr_break))
981            });
982            self.arm(ready_pat, break_x)
983        };
984
985        // `::std::task::Poll::Pending => {}`
986        let pending_arm = {
987            let pending_pat = self.pat_lang_item_variant(span, hir::LangItem::PollPending, &[]);
988            let empty_block = self.expr_block_empty(span);
989            self.arm(pending_pat, empty_block)
990        };
991
992        let inner_match_stmt = {
993            let match_expr = self.expr_match(
994                span,
995                poll_expr,
996                arena_vec![self; ready_arm, pending_arm],
997                hir::MatchSource::AwaitDesugar,
998            );
999            self.stmt_expr(span, match_expr)
1000        };
1001
1002        // Depending on `async` of `async gen`:
1003        // async     - task_context = yield ();
1004        // async gen - task_context = yield ASYNC_GEN_PENDING;
1005        let yield_stmt = {
1006            let yielded = if is_async_gen {
1007                self.arena.alloc(self.expr_lang_item_path(span, hir::LangItem::AsyncGenPending))
1008            } else {
1009                self.expr_unit(span)
1010            };
1011
1012            let yield_expr = self.expr(
1013                span,
1014                hir::ExprKind::Yield(yielded, hir::YieldSource::Await { expr: Some(expr_hir_id) }),
1015            );
1016            let yield_expr = self.arena.alloc(yield_expr);
1017
1018            let Some(task_context_hid) = self.task_context else {
1019                unreachable!("use of `await` outside of an async context.");
1020            };
1021
1022            let lhs = self.expr_ident(span, task_context_ident, task_context_hid);
1023            let assign =
1024                self.expr(span, hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span)));
1025            self.stmt_expr(span, assign)
1026        };
1027
1028        let loop_block = self.block_all(span, arena_vec![self; inner_match_stmt, yield_stmt], None);
1029
1030        // loop { .. }
1031        let loop_expr = self.arena.alloc(hir::Expr {
1032            hir_id: loop_hir_id,
1033            kind: hir::ExprKind::Loop(
1034                loop_block,
1035                None,
1036                hir::LoopSource::Loop,
1037                self.lower_span(span),
1038            ),
1039            span: self.lower_span(span),
1040        });
1041
1042        // mut __awaitee => loop { ... }
1043        let awaitee_arm = self.arm(awaitee_pat, loop_expr);
1044
1045        // `match ::std::future::IntoFuture::into_future(<expr>) { ... }`
1046        let into_future_expr = match await_kind {
1047            FutureKind::Future => self.expr_call_lang_item_fn(
1048                span,
1049                hir::LangItem::IntoFutureIntoFuture,
1050                arena_vec![self; *expr],
1051            ),
1052            // Not needed for `for await` because we expect to have already called
1053            // `IntoAsyncIterator::into_async_iter` on it.
1054            FutureKind::AsyncIterator => expr,
1055        };
1056
1057        // match <into_future_expr> {
1058        //     mut __awaitee => loop { .. }
1059        // }
1060        hir::ExprKind::Match(
1061            into_future_expr,
1062            arena_vec![self; awaitee_arm],
1063            hir::MatchSource::AwaitDesugar,
1064        )
1065    }
1066
1067    fn lower_expr_closure(
1068        &mut self,
1069        binder: &ClosureBinder,
1070        capture_clause: CaptureBy,
1071        closure_id: NodeId,
1072        closure_hir_id: hir::HirId,
1073        constness: Const,
1074        movability: Movability,
1075        decl: &FnDecl,
1076        body: &Expr,
1077        fn_decl_span: Span,
1078        fn_arg_span: Span,
1079    ) -> hir::ExprKind<'hir> {
1080        let closure_def_id = self.local_def_id(closure_id);
1081        let (binder_clause, generic_params) = self.lower_closure_binder(binder);
1082
1083        let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| {
1084            let mut coroutine_kind = if this
1085                .attrs
1086                .get(&closure_hir_id.local_id)
1087                .is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine)))
1088            {
1089                Some(hir::CoroutineKind::Coroutine(Movability::Movable))
1090            } else {
1091                None
1092            };
1093            // FIXME(contracts): Support contracts on closures?
1094            let body_id = this.lower_fn_body(decl, None, |this| {
1095                this.coroutine_kind = coroutine_kind;
1096                let e = this.lower_expr_mut(body);
1097                coroutine_kind = this.coroutine_kind;
1098                e
1099            });
1100            let coroutine_option =
1101                this.closure_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability);
1102            (body_id, coroutine_option)
1103        });
1104
1105        let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
1106        // Lower outside new scope to preserve `is_in_loop_condition`.
1107        let fn_decl = self.lower_fn_decl(decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);
1108
1109        let c = self.arena.alloc(hir::Closure {
1110            def_id: closure_def_id,
1111            binder: binder_clause,
1112            capture_clause,
1113            bound_generic_params,
1114            fn_decl,
1115            body: body_id,
1116            fn_decl_span: self.lower_span(fn_decl_span),
1117            fn_arg_span: Some(self.lower_span(fn_arg_span)),
1118            kind: closure_kind,
1119            constness: self.lower_constness(constness),
1120        });
1121
1122        hir::ExprKind::Closure(c)
1123    }
1124
1125    fn closure_movability_for_fn(
1126        &mut self,
1127        decl: &FnDecl,
1128        fn_decl_span: Span,
1129        coroutine_kind: Option<hir::CoroutineKind>,
1130        movability: Movability,
1131    ) -> hir::ClosureKind {
1132        match coroutine_kind {
1133            Some(hir::CoroutineKind::Coroutine(_)) => {
1134                if decl.inputs.len() > 1 {
1135                    self.dcx().emit_err(CoroutineTooManyParameters { fn_decl_span });
1136                }
1137                hir::ClosureKind::Coroutine(hir::CoroutineKind::Coroutine(movability))
1138            }
1139            Some(
1140                hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
1141                | hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)
1142                | hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _),
1143            ) => {
1144                panic!("non-`async`/`gen` closure body turned `async`/`gen` during lowering");
1145            }
1146            None => {
1147                if movability == Movability::Static {
1148                    self.dcx().emit_err(ClosureCannotBeStatic { fn_decl_span });
1149                }
1150                hir::ClosureKind::Closure
1151            }
1152        }
1153    }
1154
1155    fn lower_closure_binder<'c>(
1156        &mut self,
1157        binder: &'c ClosureBinder,
1158    ) -> (hir::ClosureBinder, &'c [GenericParam]) {
1159        let (binder, params) = match binder {
1160            ClosureBinder::NotPresent => (hir::ClosureBinder::Default, &[][..]),
1161            ClosureBinder::For { span, generic_params } => {
1162                let span = self.lower_span(*span);
1163                (hir::ClosureBinder::For { span }, &**generic_params)
1164            }
1165        };
1166
1167        (binder, params)
1168    }
1169
1170    fn lower_expr_coroutine_closure(
1171        &mut self,
1172        binder: &ClosureBinder,
1173        capture_clause: CaptureBy,
1174        closure_id: NodeId,
1175        closure_hir_id: HirId,
1176        coroutine_kind: CoroutineKind,
1177        decl: &FnDecl,
1178        body: &Expr,
1179        fn_decl_span: Span,
1180        fn_arg_span: Span,
1181    ) -> hir::ExprKind<'hir> {
1182        let closure_def_id = self.local_def_id(closure_id);
1183        let (binder_clause, generic_params) = self.lower_closure_binder(binder);
1184
1185        assert_matches!(
1186            coroutine_kind,
1187            CoroutineKind::Async { .. },
1188            "only async closures are supported currently"
1189        );
1190
1191        let body = self.with_new_scopes(fn_decl_span, |this| {
1192            let inner_decl =
1193                FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
1194
1195            // Transform `async |x: u8| -> X { ... }` into
1196            // `|x: u8| || -> X { ... }`.
1197            let body_id = this.lower_body(|this| {
1198                let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
1199                    &inner_decl,
1200                    |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
1201                    fn_decl_span,
1202                    body.span,
1203                    coroutine_kind,
1204                    hir::CoroutineSource::Closure,
1205                );
1206
1207                this.maybe_forward_track_caller(body.span, closure_hir_id, expr.hir_id);
1208
1209                (parameters, expr)
1210            });
1211            body_id
1212        });
1213
1214        let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
1215        // We need to lower the declaration outside the new scope, because we
1216        // have to conserve the state of being inside a loop condition for the
1217        // closure argument types.
1218        let fn_decl =
1219            self.lower_fn_decl(&decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);
1220
1221        let c = self.arena.alloc(hir::Closure {
1222            def_id: closure_def_id,
1223            binder: binder_clause,
1224            capture_clause,
1225            bound_generic_params,
1226            fn_decl,
1227            body,
1228            fn_decl_span: self.lower_span(fn_decl_span),
1229            fn_arg_span: Some(self.lower_span(fn_arg_span)),
1230            // Lower this as a `CoroutineClosure`. That will ensure that HIR typeck
1231            // knows that a `FnDecl` output type like `-> &str` actually means
1232            // "coroutine that returns &str", rather than directly returning a `&str`.
1233            kind: hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async),
1234            constness: hir::Constness::NotConst,
1235        });
1236        hir::ExprKind::Closure(c)
1237    }
1238
1239    /// Destructure the LHS of complex assignments.
1240    /// For instance, lower `(a, b) = t` to `{ let (lhs1, lhs2) = t; a = lhs1; b = lhs2; }`.
1241    fn lower_expr_assign(
1242        &mut self,
1243        lhs: &Expr,
1244        rhs: &Expr,
1245        eq_sign_span: Span,
1246        whole_span: Span,
1247    ) -> hir::ExprKind<'hir> {
1248        // Return early in case of an ordinary assignment.
1249        fn is_ordinary(lower_ctx: &mut LoweringContext<'_, '_>, lhs: &Expr) -> bool {
1250            match &lhs.kind {
1251                ExprKind::Array(..)
1252                | ExprKind::Struct(..)
1253                | ExprKind::Tup(..)
1254                | ExprKind::Underscore => false,
1255                // Check for unit struct constructor.
1256                ExprKind::Path(..) => lower_ctx.extract_unit_struct_path(lhs).is_none(),
1257                // Check for tuple struct constructor.
1258                ExprKind::Call(callee, ..) => lower_ctx.extract_tuple_struct_path(callee).is_none(),
1259                ExprKind::Paren(e) => {
1260                    match e.kind {
1261                        // We special-case `(..)` for consistency with patterns.
1262                        ExprKind::Range(None, None, RangeLimits::HalfOpen) => false,
1263                        _ => is_ordinary(lower_ctx, e),
1264                    }
1265                }
1266                _ => true,
1267            }
1268        }
1269        if is_ordinary(self, lhs) {
1270            return hir::ExprKind::Assign(
1271                self.lower_expr(lhs),
1272                self.lower_expr(rhs),
1273                self.lower_span(eq_sign_span),
1274            );
1275        }
1276
1277        let mut assignments = vec![];
1278
1279        // The LHS becomes a pattern: `(lhs1, lhs2)`.
1280        let pat = self.destructure_assign(lhs, eq_sign_span, &mut assignments);
1281        let rhs = self.lower_expr(rhs);
1282
1283        // Introduce a `let` for destructuring: `let (lhs1, lhs2) = t`.
1284        let destructure_let = self.stmt_let_pat(
1285            None,
1286            whole_span,
1287            Some(rhs),
1288            pat,
1289            hir::LocalSource::AssignDesugar(self.lower_span(eq_sign_span)),
1290        );
1291
1292        // `a = lhs1; b = lhs2;`.
1293        let stmts = self.arena.alloc_from_iter(std::iter::once(destructure_let).chain(assignments));
1294
1295        // Wrap everything in a block.
1296        hir::ExprKind::Block(self.block_all(whole_span, stmts, None), None)
1297    }
1298
1299    /// If the given expression is a path to a tuple struct, returns that path.
1300    /// It is not a complete check, but just tries to reject most paths early
1301    /// if they are not tuple structs.
1302    /// Type checking will take care of the full validation later.
1303    fn extract_tuple_struct_path<'a>(
1304        &mut self,
1305        expr: &'a Expr,
1306    ) -> Option<(&'a Option<AstP<QSelf>>, &'a Path)> {
1307        if let ExprKind::Path(qself, path) = &expr.kind {
1308            // Does the path resolve to something disallowed in a tuple struct/variant pattern?
1309            if let Some(partial_res) = self.resolver.get_partial_res(expr.id) {
1310                if let Some(res) = partial_res.full_res()
1311                    && !res.expected_in_tuple_struct_pat()
1312                {
1313                    return None;
1314                }
1315            }
1316            return Some((qself, path));
1317        }
1318        None
1319    }
1320
1321    /// If the given expression is a path to a unit struct, returns that path.
1322    /// It is not a complete check, but just tries to reject most paths early
1323    /// if they are not unit structs.
1324    /// Type checking will take care of the full validation later.
1325    fn extract_unit_struct_path<'a>(
1326        &mut self,
1327        expr: &'a Expr,
1328    ) -> Option<(&'a Option<AstP<QSelf>>, &'a Path)> {
1329        if let ExprKind::Path(qself, path) = &expr.kind {
1330            // Does the path resolve to something disallowed in a unit struct/variant pattern?
1331            if let Some(partial_res) = self.resolver.get_partial_res(expr.id) {
1332                if let Some(res) = partial_res.full_res()
1333                    && !res.expected_in_unit_struct_pat()
1334                {
1335                    return None;
1336                }
1337            }
1338            return Some((qself, path));
1339        }
1340        None
1341    }
1342
1343    /// Convert the LHS of a destructuring assignment to a pattern.
1344    /// Each sub-assignment is recorded in `assignments`.
1345    fn destructure_assign(
1346        &mut self,
1347        lhs: &Expr,
1348        eq_sign_span: Span,
1349        assignments: &mut Vec<hir::Stmt<'hir>>,
1350    ) -> &'hir hir::Pat<'hir> {
1351        self.arena.alloc(self.destructure_assign_mut(lhs, eq_sign_span, assignments))
1352    }
1353
1354    fn destructure_assign_mut(
1355        &mut self,
1356        lhs: &Expr,
1357        eq_sign_span: Span,
1358        assignments: &mut Vec<hir::Stmt<'hir>>,
1359    ) -> hir::Pat<'hir> {
1360        match &lhs.kind {
1361            // Underscore pattern.
1362            ExprKind::Underscore => {
1363                return self.pat_without_dbm(lhs.span, hir::PatKind::Wild);
1364            }
1365            // Slice patterns.
1366            ExprKind::Array(elements) => {
1367                let (pats, rest) =
1368                    self.destructure_sequence(elements, "slice", eq_sign_span, assignments);
1369                let slice_pat = if let Some((i, span)) = rest {
1370                    let (before, after) = pats.split_at(i);
1371                    hir::PatKind::Slice(
1372                        before,
1373                        Some(self.arena.alloc(self.pat_without_dbm(span, hir::PatKind::Wild))),
1374                        after,
1375                    )
1376                } else {
1377                    hir::PatKind::Slice(pats, None, &[])
1378                };
1379                return self.pat_without_dbm(lhs.span, slice_pat);
1380            }
1381            // Tuple structs.
1382            ExprKind::Call(callee, args) => {
1383                if let Some((qself, path)) = self.extract_tuple_struct_path(callee) {
1384                    let (pats, rest) = self.destructure_sequence(
1385                        args,
1386                        "tuple struct or variant",
1387                        eq_sign_span,
1388                        assignments,
1389                    );
1390                    let qpath = self.lower_qpath(
1391                        callee.id,
1392                        qself,
1393                        path,
1394                        ParamMode::Optional,
1395                        AllowReturnTypeNotation::No,
1396                        ImplTraitContext::Disallowed(ImplTraitPosition::Path),
1397                        None,
1398                    );
1399                    // Destructure like a tuple struct.
1400                    let tuple_struct_pat = hir::PatKind::TupleStruct(
1401                        qpath,
1402                        pats,
1403                        hir::DotDotPos::new(rest.map(|r| r.0)),
1404                    );
1405                    return self.pat_without_dbm(lhs.span, tuple_struct_pat);
1406                }
1407            }
1408            // Unit structs and enum variants.
1409            ExprKind::Path(..) => {
1410                if let Some((qself, path)) = self.extract_unit_struct_path(lhs) {
1411                    let qpath = self.lower_qpath(
1412                        lhs.id,
1413                        qself,
1414                        path,
1415                        ParamMode::Optional,
1416                        AllowReturnTypeNotation::No,
1417                        ImplTraitContext::Disallowed(ImplTraitPosition::Path),
1418                        None,
1419                    );
1420                    // Destructure like a unit struct.
1421                    let unit_struct_pat = hir::PatKind::Expr(self.arena.alloc(hir::PatExpr {
1422                        kind: hir::PatExprKind::Path(qpath),
1423                        hir_id: self.next_id(),
1424                        span: self.lower_span(lhs.span),
1425                    }));
1426                    return self.pat_without_dbm(lhs.span, unit_struct_pat);
1427                }
1428            }
1429            // Structs.
1430            ExprKind::Struct(se) => {
1431                let field_pats = self.arena.alloc_from_iter(se.fields.iter().map(|f| {
1432                    let pat = self.destructure_assign(&f.expr, eq_sign_span, assignments);
1433                    hir::PatField {
1434                        hir_id: self.next_id(),
1435                        ident: self.lower_ident(f.ident),
1436                        pat,
1437                        is_shorthand: f.is_shorthand,
1438                        span: self.lower_span(f.span),
1439                    }
1440                }));
1441                let qpath = self.lower_qpath(
1442                    lhs.id,
1443                    &se.qself,
1444                    &se.path,
1445                    ParamMode::Optional,
1446                    AllowReturnTypeNotation::No,
1447                    ImplTraitContext::Disallowed(ImplTraitPosition::Path),
1448                    None,
1449                );
1450                let fields_omitted = match &se.rest {
1451                    StructRest::Base(e) => {
1452                        self.dcx().emit_err(FunctionalRecordUpdateDestructuringAssignment {
1453                            span: e.span,
1454                        });
1455                        true
1456                    }
1457                    StructRest::Rest(_) => true,
1458                    StructRest::None => false,
1459                };
1460                let struct_pat = hir::PatKind::Struct(qpath, field_pats, fields_omitted);
1461                return self.pat_without_dbm(lhs.span, struct_pat);
1462            }
1463            // Tuples.
1464            ExprKind::Tup(elements) => {
1465                let (pats, rest) =
1466                    self.destructure_sequence(elements, "tuple", eq_sign_span, assignments);
1467                let tuple_pat = hir::PatKind::Tuple(pats, hir::DotDotPos::new(rest.map(|r| r.0)));
1468                return self.pat_without_dbm(lhs.span, tuple_pat);
1469            }
1470            ExprKind::Paren(e) => {
1471                // We special-case `(..)` for consistency with patterns.
1472                if let ExprKind::Range(None, None, RangeLimits::HalfOpen) = e.kind {
1473                    let tuple_pat = hir::PatKind::Tuple(&[], hir::DotDotPos::new(Some(0)));
1474                    return self.pat_without_dbm(lhs.span, tuple_pat);
1475                } else {
1476                    return self.destructure_assign_mut(e, eq_sign_span, assignments);
1477                }
1478            }
1479            _ => {}
1480        }
1481        // Treat all other cases as normal lvalue.
1482        let ident = Ident::new(sym::lhs, self.lower_span(lhs.span));
1483        let (pat, binding) = self.pat_ident_mut(lhs.span, ident);
1484        let ident = self.expr_ident(lhs.span, ident, binding);
1485        let assign =
1486            hir::ExprKind::Assign(self.lower_expr(lhs), ident, self.lower_span(eq_sign_span));
1487        let expr = self.expr(lhs.span, assign);
1488        assignments.push(self.stmt_expr(lhs.span, expr));
1489        pat
1490    }
1491
1492    /// Destructure a sequence of expressions occurring on the LHS of an assignment.
1493    /// Such a sequence occurs in a tuple (struct)/slice.
1494    /// Return a sequence of corresponding patterns, and the index and the span of `..` if it
1495    /// exists.
1496    /// Each sub-assignment is recorded in `assignments`.
1497    fn destructure_sequence(
1498        &mut self,
1499        elements: &[AstP<Expr>],
1500        ctx: &str,
1501        eq_sign_span: Span,
1502        assignments: &mut Vec<hir::Stmt<'hir>>,
1503    ) -> (&'hir [hir::Pat<'hir>], Option<(usize, Span)>) {
1504        let mut rest = None;
1505        let elements =
1506            self.arena.alloc_from_iter(elements.iter().enumerate().filter_map(|(i, e)| {
1507                // Check for `..` pattern.
1508                if let ExprKind::Range(None, None, RangeLimits::HalfOpen) = e.kind {
1509                    if let Some((_, prev_span)) = rest {
1510                        self.ban_extra_rest_pat(e.span, prev_span, ctx);
1511                    } else {
1512                        rest = Some((i, e.span));
1513                    }
1514                    None
1515                } else {
1516                    Some(self.destructure_assign_mut(e, eq_sign_span, assignments))
1517                }
1518            }));
1519        (elements, rest)
1520    }
1521
1522    /// Desugar `<start>..=<end>` into `std::ops::RangeInclusive::new(<start>, <end>)`.
1523    fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> {
1524        let e1 = self.lower_expr_mut(e1);
1525        let e2 = self.lower_expr_mut(e2);
1526        let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span));
1527        let fn_expr = self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path)));
1528        hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2])
1529    }
1530
1531    fn lower_expr_range(
1532        &mut self,
1533        span: Span,
1534        e1: Option<&Expr>,
1535        e2: Option<&Expr>,
1536        lims: RangeLimits,
1537    ) -> hir::ExprKind<'hir> {
1538        use rustc_ast::RangeLimits::*;
1539
1540        let lang_item = match (e1, e2, lims) {
1541            (None, None, HalfOpen) => hir::LangItem::RangeFull,
1542            (Some(..), None, HalfOpen) => {
1543                if self.tcx.features().new_range() {
1544                    hir::LangItem::RangeFromCopy
1545                } else {
1546                    hir::LangItem::RangeFrom
1547                }
1548            }
1549            (None, Some(..), HalfOpen) => hir::LangItem::RangeTo,
1550            (Some(..), Some(..), HalfOpen) => {
1551                if self.tcx.features().new_range() {
1552                    hir::LangItem::RangeCopy
1553                } else {
1554                    hir::LangItem::Range
1555                }
1556            }
1557            (None, Some(..), Closed) => hir::LangItem::RangeToInclusive,
1558            (Some(e1), Some(e2), Closed) => {
1559                if self.tcx.features().new_range() {
1560                    hir::LangItem::RangeInclusiveCopy
1561                } else {
1562                    return self.lower_expr_range_closed(span, e1, e2);
1563                }
1564            }
1565            (start, None, Closed) => {
1566                self.dcx().emit_err(InclusiveRangeWithNoEnd { span });
1567                match start {
1568                    Some(..) => {
1569                        if self.tcx.features().new_range() {
1570                            hir::LangItem::RangeFromCopy
1571                        } else {
1572                            hir::LangItem::RangeFrom
1573                        }
1574                    }
1575                    None => hir::LangItem::RangeFull,
1576                }
1577            }
1578        };
1579
1580        let fields = self.arena.alloc_from_iter(
1581            e1.iter().map(|e| (sym::start, e)).chain(e2.iter().map(|e| (sym::end, e))).map(
1582                |(s, e)| {
1583                    let expr = self.lower_expr(e);
1584                    let ident = Ident::new(s, self.lower_span(e.span));
1585                    self.expr_field(ident, expr, e.span)
1586                },
1587            ),
1588        );
1589
1590        hir::ExprKind::Struct(
1591            self.arena.alloc(hir::QPath::LangItem(lang_item, self.lower_span(span))),
1592            fields,
1593            hir::StructTailExpr::None,
1594        )
1595    }
1596
1597    // Record labelled expr's HirId so that we can retrieve it in `lower_jump_destination` without
1598    // lowering node id again.
1599    fn lower_label(
1600        &mut self,
1601        opt_label: Option<Label>,
1602        dest_id: NodeId,
1603        dest_hir_id: hir::HirId,
1604    ) -> Option<Label> {
1605        let label = opt_label?;
1606        self.ident_and_label_to_local_id.insert(dest_id, dest_hir_id.local_id);
1607        Some(Label { ident: self.lower_ident(label.ident) })
1608    }
1609
1610    fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hir::Destination {
1611        let target_id = match destination {
1612            Some((id, _)) => {
1613                if let Some(loop_id) = self.resolver.get_label_res(id) {
1614                    let local_id = self.ident_and_label_to_local_id[&loop_id];
1615                    let loop_hir_id = HirId { owner: self.current_hir_id_owner, local_id };
1616                    Ok(loop_hir_id)
1617                } else {
1618                    Err(hir::LoopIdError::UnresolvedLabel)
1619                }
1620            }
1621            None => {
1622                self.loop_scope.map(|id| Ok(id)).unwrap_or(Err(hir::LoopIdError::OutsideLoopScope))
1623            }
1624        };
1625        let label = destination
1626            .map(|(_, label)| label)
1627            .map(|label| Label { ident: self.lower_ident(label.ident) });
1628        hir::Destination { label, target_id }
1629    }
1630
1631    fn lower_jump_destination(&mut self, id: NodeId, opt_label: Option<Label>) -> hir::Destination {
1632        if self.is_in_loop_condition && opt_label.is_none() {
1633            hir::Destination {
1634                label: None,
1635                target_id: Err(hir::LoopIdError::UnlabeledCfInWhileCondition),
1636            }
1637        } else {
1638            self.lower_loop_destination(opt_label.map(|label| (id, label)))
1639        }
1640    }
1641
1642    fn with_catch_scope<T>(&mut self, catch_id: hir::HirId, f: impl FnOnce(&mut Self) -> T) -> T {
1643        let old_scope = self.catch_scope.replace(catch_id);
1644        let result = f(self);
1645        self.catch_scope = old_scope;
1646        result
1647    }
1648
1649    fn with_loop_scope<T>(&mut self, loop_id: hir::HirId, f: impl FnOnce(&mut Self) -> T) -> T {
1650        // We're no longer in the base loop's condition; we're in another loop.
1651        let was_in_loop_condition = self.is_in_loop_condition;
1652        self.is_in_loop_condition = false;
1653
1654        let old_scope = self.loop_scope.replace(loop_id);
1655        let result = f(self);
1656        self.loop_scope = old_scope;
1657
1658        self.is_in_loop_condition = was_in_loop_condition;
1659
1660        result
1661    }
1662
1663    fn with_loop_condition_scope<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
1664        let was_in_loop_condition = self.is_in_loop_condition;
1665        self.is_in_loop_condition = true;
1666
1667        let result = f(self);
1668
1669        self.is_in_loop_condition = was_in_loop_condition;
1670
1671        result
1672    }
1673
1674    fn lower_expr_field(&mut self, f: &ExprField) -> hir::ExprField<'hir> {
1675        let hir_id = self.lower_node_id(f.id);
1676        self.lower_attrs(hir_id, &f.attrs);
1677        hir::ExprField {
1678            hir_id,
1679            ident: self.lower_ident(f.ident),
1680            expr: self.lower_expr(&f.expr),
1681            span: self.lower_span(f.span),
1682            is_shorthand: f.is_shorthand,
1683        }
1684    }
1685
1686    fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> {
1687        let yielded =
1688            opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span));
1689
1690        let is_async_gen = match self.coroutine_kind {
1691            Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) => false,
1692            Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => true,
1693            Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => {
1694                // Lower to a block `{ EXPR; <error> }` so that the awaited expr
1695                // is not accidentally orphaned.
1696                let stmt_id = self.next_id();
1697                let expr_err = self.expr(
1698                    yielded.span,
1699                    hir::ExprKind::Err(self.dcx().emit_err(AsyncCoroutinesNotSupported { span })),
1700                );
1701                return hir::ExprKind::Block(
1702                    self.block_all(
1703                        yielded.span,
1704                        arena_vec![self; hir::Stmt {
1705                            hir_id: stmt_id,
1706                            kind: hir::StmtKind::Semi(yielded),
1707                            span: yielded.span,
1708                        }],
1709                        Some(self.arena.alloc(expr_err)),
1710                    ),
1711                    None,
1712                );
1713            }
1714            Some(hir::CoroutineKind::Coroutine(_)) => {
1715                if !self.tcx.features().coroutines() {
1716                    rustc_session::parse::feature_err(
1717                        &self.tcx.sess,
1718                        sym::coroutines,
1719                        span,
1720                        fluent_generated::ast_lowering_yield,
1721                    )
1722                    .emit();
1723                }
1724                false
1725            }
1726            None => {
1727                if !self.tcx.features().coroutines() {
1728                    rustc_session::parse::feature_err(
1729                        &self.tcx.sess,
1730                        sym::coroutines,
1731                        span,
1732                        fluent_generated::ast_lowering_yield,
1733                    )
1734                    .emit();
1735                }
1736                let suggestion = self.current_item.map(|s| s.shrink_to_lo());
1737                self.dcx().emit_err(YieldInClosure { span, suggestion });
1738                self.coroutine_kind = Some(hir::CoroutineKind::Coroutine(Movability::Movable));
1739
1740                false
1741            }
1742        };
1743
1744        if is_async_gen {
1745            // `yield $expr` is transformed into `task_context = yield async_gen_ready($expr)`.
1746            // This ensures that we store our resumed `ResumeContext` correctly, and also that
1747            // the apparent value of the `yield` expression is `()`.
1748            let wrapped_yielded = self.expr_call_lang_item_fn(
1749                span,
1750                hir::LangItem::AsyncGenReady,
1751                std::slice::from_ref(yielded),
1752            );
1753            let yield_expr = self.arena.alloc(
1754                self.expr(span, hir::ExprKind::Yield(wrapped_yielded, hir::YieldSource::Yield)),
1755            );
1756
1757            let Some(task_context_hid) = self.task_context else {
1758                unreachable!("use of `await` outside of an async context.");
1759            };
1760            let task_context_ident = Ident::with_dummy_span(sym::_task_context);
1761            let lhs = self.expr_ident(span, task_context_ident, task_context_hid);
1762
1763            hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span))
1764        } else {
1765            hir::ExprKind::Yield(yielded, hir::YieldSource::Yield)
1766        }
1767    }
1768
1769    /// Desugar `ExprForLoop` from: `[opt_ident]: for <pat> in <head> <body>` into:
1770    /// ```ignore (pseudo-rust)
1771    /// {
1772    ///     let result = match IntoIterator::into_iter(<head>) {
1773    ///         mut iter => {
1774    ///             [opt_ident]: loop {
1775    ///                 match Iterator::next(&mut iter) {
1776    ///                     None => break,
1777    ///                     Some(<pat>) => <body>,
1778    ///                 };
1779    ///             }
1780    ///         }
1781    ///     };
1782    ///     result
1783    /// }
1784    /// ```
1785    fn lower_expr_for(
1786        &mut self,
1787        e: &Expr,
1788        pat: &Pat,
1789        head: &Expr,
1790        body: &Block,
1791        opt_label: Option<Label>,
1792        loop_kind: ForLoopKind,
1793    ) -> hir::Expr<'hir> {
1794        let head = self.lower_expr_mut(head);
1795        let pat = self.lower_pat(pat);
1796        let for_span =
1797            self.mark_span_with_reason(DesugaringKind::ForLoop, self.lower_span(e.span), None);
1798        let head_span = self.mark_span_with_reason(DesugaringKind::ForLoop, head.span, None);
1799        let pat_span = self.mark_span_with_reason(DesugaringKind::ForLoop, pat.span, None);
1800
1801        let loop_hir_id = self.lower_node_id(e.id);
1802        let label = self.lower_label(opt_label, e.id, loop_hir_id);
1803
1804        // `None => break`
1805        let none_arm = {
1806            let break_expr =
1807                self.with_loop_scope(loop_hir_id, |this| this.expr_break_alloc(for_span));
1808            let pat = self.pat_none(for_span);
1809            self.arm(pat, break_expr)
1810        };
1811
1812        // Some(<pat>) => <body>,
1813        let some_arm = {
1814            let some_pat = self.pat_some(pat_span, pat);
1815            let body_block =
1816                self.with_loop_scope(loop_hir_id, |this| this.lower_block(body, false));
1817            let body_expr = self.arena.alloc(self.expr_block(body_block));
1818            self.arm(some_pat, body_expr)
1819        };
1820
1821        // `mut iter`
1822        let iter = Ident::with_dummy_span(sym::iter);
1823        let (iter_pat, iter_pat_nid) =
1824            self.pat_ident_binding_mode(head_span, iter, hir::BindingMode::MUT);
1825
1826        let match_expr = {
1827            let iter = self.expr_ident(head_span, iter, iter_pat_nid);
1828            let next_expr = match loop_kind {
1829                ForLoopKind::For => {
1830                    // `Iterator::next(&mut iter)`
1831                    let ref_mut_iter = self.expr_mut_addr_of(head_span, iter);
1832                    self.expr_call_lang_item_fn(
1833                        head_span,
1834                        hir::LangItem::IteratorNext,
1835                        arena_vec![self; ref_mut_iter],
1836                    )
1837                }
1838                ForLoopKind::ForAwait => {
1839                    // we'll generate `unsafe { Pin::new_unchecked(&mut iter) })` and then pass this
1840                    // to make_lowered_await with `FutureKind::AsyncIterator` which will generator
1841                    // calls to `poll_next`. In user code, this would probably be a call to
1842                    // `Pin::as_mut` but here it's easy enough to do `new_unchecked`.
1843
1844                    // `&mut iter`
1845                    let iter = self.expr_mut_addr_of(head_span, iter);
1846                    // `Pin::new_unchecked(...)`
1847                    let iter = self.arena.alloc(self.expr_call_lang_item_fn_mut(
1848                        head_span,
1849                        hir::LangItem::PinNewUnchecked,
1850                        arena_vec![self; iter],
1851                    ));
1852                    // `unsafe { ... }`
1853                    let iter = self.arena.alloc(self.expr_unsafe(iter));
1854                    let kind = self.make_lowered_await(head_span, iter, FutureKind::AsyncIterator);
1855                    self.arena.alloc(hir::Expr { hir_id: self.next_id(), kind, span: head_span })
1856                }
1857            };
1858            let arms = arena_vec![self; none_arm, some_arm];
1859
1860            // `match $next_expr { ... }`
1861            self.expr_match(head_span, next_expr, arms, hir::MatchSource::ForLoopDesugar)
1862        };
1863        let match_stmt = self.stmt_expr(for_span, match_expr);
1864
1865        let loop_block = self.block_all(for_span, arena_vec![self; match_stmt], None);
1866
1867        // `[opt_ident]: loop { ... }`
1868        let kind = hir::ExprKind::Loop(
1869            loop_block,
1870            label,
1871            hir::LoopSource::ForLoop,
1872            self.lower_span(for_span.with_hi(head.span.hi())),
1873        );
1874        let loop_expr = self.arena.alloc(hir::Expr { hir_id: loop_hir_id, kind, span: for_span });
1875
1876        // `mut iter => { ... }`
1877        let iter_arm = self.arm(iter_pat, loop_expr);
1878
1879        let match_expr = match loop_kind {
1880            ForLoopKind::For => {
1881                // `::std::iter::IntoIterator::into_iter(<head>)`
1882                let into_iter_expr = self.expr_call_lang_item_fn(
1883                    head_span,
1884                    hir::LangItem::IntoIterIntoIter,
1885                    arena_vec![self; head],
1886                );
1887
1888                self.arena.alloc(self.expr_match(
1889                    for_span,
1890                    into_iter_expr,
1891                    arena_vec![self; iter_arm],
1892                    hir::MatchSource::ForLoopDesugar,
1893                ))
1894            }
1895            // `match into_async_iter(<head>) { ref mut iter => match unsafe { Pin::new_unchecked(iter) } { ... } }`
1896            ForLoopKind::ForAwait => {
1897                let iter_ident = iter;
1898                let (async_iter_pat, async_iter_pat_id) =
1899                    self.pat_ident_binding_mode(head_span, iter_ident, hir::BindingMode::REF_MUT);
1900                let iter = self.expr_ident_mut(head_span, iter_ident, async_iter_pat_id);
1901                // `Pin::new_unchecked(...)`
1902                let iter = self.arena.alloc(self.expr_call_lang_item_fn_mut(
1903                    head_span,
1904                    hir::LangItem::PinNewUnchecked,
1905                    arena_vec![self; iter],
1906                ));
1907                // `unsafe { ... }`
1908                let iter = self.arena.alloc(self.expr_unsafe(iter));
1909                let inner_match_expr = self.arena.alloc(self.expr_match(
1910                    for_span,
1911                    iter,
1912                    arena_vec![self; iter_arm],
1913                    hir::MatchSource::ForLoopDesugar,
1914                ));
1915
1916                // `::core::async_iter::IntoAsyncIterator::into_async_iter(<head>)`
1917                let iter = self.expr_call_lang_item_fn(
1918                    head_span,
1919                    hir::LangItem::IntoAsyncIterIntoIter,
1920                    arena_vec![self; head],
1921                );
1922                let iter_arm = self.arm(async_iter_pat, inner_match_expr);
1923                self.arena.alloc(self.expr_match(
1924                    for_span,
1925                    iter,
1926                    arena_vec![self; iter_arm],
1927                    hir::MatchSource::ForLoopDesugar,
1928                ))
1929            }
1930        };
1931
1932        // This is effectively `{ let _result = ...; _result }`.
1933        // The construct was introduced in #21984 and is necessary to make sure that
1934        // temporaries in the `head` expression are dropped and do not leak to the
1935        // surrounding scope of the `match` since the `match` is not a terminating scope.
1936        //
1937        // Also, add the attributes to the outer returned expr node.
1938        let expr = self.expr_drop_temps_mut(for_span, match_expr);
1939        self.lower_attrs(expr.hir_id, &e.attrs);
1940        expr
1941    }
1942
1943    /// Desugar `ExprKind::Try` from: `<expr>?` into:
1944    /// ```ignore (pseudo-rust)
1945    /// match Try::branch(<expr>) {
1946    ///     ControlFlow::Continue(val) => #[allow(unreachable_code)] val,,
1947    ///     ControlFlow::Break(residual) =>
1948    ///         #[allow(unreachable_code)]
1949    ///         // If there is an enclosing `try {...}`:
1950    ///         break 'catch_target Try::from_residual(residual),
1951    ///         // Otherwise:
1952    ///         return Try::from_residual(residual),
1953    /// }
1954    /// ```
1955    fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir> {
1956        let unstable_span = self.mark_span_with_reason(
1957            DesugaringKind::QuestionMark,
1958            span,
1959            Some(Arc::clone(&self.allow_try_trait)),
1960        );
1961        let try_span = self.tcx.sess.source_map().end_point(span);
1962        let try_span = self.mark_span_with_reason(
1963            DesugaringKind::QuestionMark,
1964            try_span,
1965            Some(Arc::clone(&self.allow_try_trait)),
1966        );
1967
1968        // `Try::branch(<expr>)`
1969        let scrutinee = {
1970            // expand <expr>
1971            let sub_expr = self.lower_expr_mut(sub_expr);
1972
1973            self.expr_call_lang_item_fn(
1974                unstable_span,
1975                hir::LangItem::TryTraitBranch,
1976                arena_vec![self; sub_expr],
1977            )
1978        };
1979
1980        // `#[allow(unreachable_code)]`
1981        let attr = attr::mk_attr_nested_word(
1982            &self.tcx.sess.psess.attr_id_generator,
1983            AttrStyle::Outer,
1984            Safety::Default,
1985            sym::allow,
1986            sym::unreachable_code,
1987            try_span,
1988        );
1989        let attrs: AttrVec = thin_vec![attr];
1990
1991        // `ControlFlow::Continue(val) => #[allow(unreachable_code)] val,`
1992        let continue_arm = {
1993            let val_ident = Ident::with_dummy_span(sym::val);
1994            let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident);
1995            let val_expr = self.expr_ident(span, val_ident, val_pat_nid);
1996            self.lower_attrs(val_expr.hir_id, &attrs);
1997            let continue_pat = self.pat_cf_continue(unstable_span, val_pat);
1998            self.arm(continue_pat, val_expr)
1999        };
2000
2001        // `ControlFlow::Break(residual) =>
2002        //     #[allow(unreachable_code)]
2003        //     return Try::from_residual(residual),`
2004        let break_arm = {
2005            let residual_ident = Ident::with_dummy_span(sym::residual);
2006            let (residual_local, residual_local_nid) = self.pat_ident(try_span, residual_ident);
2007            let residual_expr = self.expr_ident_mut(try_span, residual_ident, residual_local_nid);
2008            let from_residual_expr = self.wrap_in_try_constructor(
2009                hir::LangItem::TryTraitFromResidual,
2010                try_span,
2011                self.arena.alloc(residual_expr),
2012                unstable_span,
2013            );
2014            let ret_expr = if let Some(catch_id) = self.catch_scope {
2015                let target_id = Ok(catch_id);
2016                self.arena.alloc(self.expr(
2017                    try_span,
2018                    hir::ExprKind::Break(
2019                        hir::Destination { label: None, target_id },
2020                        Some(from_residual_expr),
2021                    ),
2022                ))
2023            } else {
2024                let ret_expr = self.checked_return(Some(from_residual_expr));
2025                self.arena.alloc(self.expr(try_span, ret_expr))
2026            };
2027            self.lower_attrs(ret_expr.hir_id, &attrs);
2028
2029            let break_pat = self.pat_cf_break(try_span, residual_local);
2030            self.arm(break_pat, ret_expr)
2031        };
2032
2033        hir::ExprKind::Match(
2034            scrutinee,
2035            arena_vec![self; break_arm, continue_arm],
2036            hir::MatchSource::TryDesugar(scrutinee.hir_id),
2037        )
2038    }
2039
2040    /// Desugar `ExprKind::Yeet` from: `do yeet <expr>` into:
2041    /// ```ignore(illustrative)
2042    /// // If there is an enclosing `try {...}`:
2043    /// break 'catch_target FromResidual::from_residual(Yeet(residual));
2044    /// // Otherwise:
2045    /// return FromResidual::from_residual(Yeet(residual));
2046    /// ```
2047    /// But to simplify this, there's a `from_yeet` lang item function which
2048    /// handles the combined `FromResidual::from_residual(Yeet(residual))`.
2049    fn lower_expr_yeet(&mut self, span: Span, sub_expr: Option<&Expr>) -> hir::ExprKind<'hir> {
2050        // The expression (if present) or `()` otherwise.
2051        let (yeeted_span, yeeted_expr) = if let Some(sub_expr) = sub_expr {
2052            (sub_expr.span, self.lower_expr(sub_expr))
2053        } else {
2054            (self.mark_span_with_reason(DesugaringKind::YeetExpr, span, None), self.expr_unit(span))
2055        };
2056
2057        let unstable_span = self.mark_span_with_reason(
2058            DesugaringKind::YeetExpr,
2059            span,
2060            Some(Arc::clone(&self.allow_try_trait)),
2061        );
2062
2063        let from_yeet_expr = self.wrap_in_try_constructor(
2064            hir::LangItem::TryTraitFromYeet,
2065            unstable_span,
2066            yeeted_expr,
2067            yeeted_span,
2068        );
2069
2070        if let Some(catch_id) = self.catch_scope {
2071            let target_id = Ok(catch_id);
2072            hir::ExprKind::Break(hir::Destination { label: None, target_id }, Some(from_yeet_expr))
2073        } else {
2074            self.checked_return(Some(from_yeet_expr))
2075        }
2076    }
2077
2078    // =========================================================================
2079    // Helper methods for building HIR.
2080    // =========================================================================
2081
2082    /// Wrap the given `expr` in a terminating scope using `hir::ExprKind::DropTemps`.
2083    ///
2084    /// In terms of drop order, it has the same effect as wrapping `expr` in
2085    /// `{ let _t = $expr; _t }` but should provide better compile-time performance.
2086    ///
2087    /// The drop order can be important in e.g. `if expr { .. }`.
2088    pub(super) fn expr_drop_temps(
2089        &mut self,
2090        span: Span,
2091        expr: &'hir hir::Expr<'hir>,
2092    ) -> &'hir hir::Expr<'hir> {
2093        self.arena.alloc(self.expr_drop_temps_mut(span, expr))
2094    }
2095
2096    pub(super) fn expr_drop_temps_mut(
2097        &mut self,
2098        span: Span,
2099        expr: &'hir hir::Expr<'hir>,
2100    ) -> hir::Expr<'hir> {
2101        self.expr(span, hir::ExprKind::DropTemps(expr))
2102    }
2103
2104    pub(super) fn expr_match(
2105        &mut self,
2106        span: Span,
2107        arg: &'hir hir::Expr<'hir>,
2108        arms: &'hir [hir::Arm<'hir>],
2109        source: hir::MatchSource,
2110    ) -> hir::Expr<'hir> {
2111        self.expr(span, hir::ExprKind::Match(arg, arms, source))
2112    }
2113
2114    fn expr_break(&mut self, span: Span) -> hir::Expr<'hir> {
2115        let expr_break = hir::ExprKind::Break(self.lower_loop_destination(None), None);
2116        self.expr(span, expr_break)
2117    }
2118
2119    fn expr_break_alloc(&mut self, span: Span) -> &'hir hir::Expr<'hir> {
2120        let expr_break = self.expr_break(span);
2121        self.arena.alloc(expr_break)
2122    }
2123
2124    fn expr_mut_addr_of(&mut self, span: Span, e: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
2125        self.expr(span, hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e))
2126    }
2127
2128    fn expr_unit(&mut self, sp: Span) -> &'hir hir::Expr<'hir> {
2129        self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[])))
2130    }
2131
2132    pub(super) fn expr_usize(&mut self, sp: Span, value: usize) -> hir::Expr<'hir> {
2133        let lit = self.arena.alloc(hir::Lit {
2134            span: sp,
2135            node: ast::LitKind::Int(
2136                (value as u128).into(),
2137                ast::LitIntType::Unsigned(ast::UintTy::Usize),
2138            ),
2139        });
2140        self.expr(sp, hir::ExprKind::Lit(lit))
2141    }
2142
2143    pub(super) fn expr_u32(&mut self, sp: Span, value: u32) -> hir::Expr<'hir> {
2144        let lit = self.arena.alloc(hir::Lit {
2145            span: sp,
2146            node: ast::LitKind::Int(
2147                u128::from(value).into(),
2148                ast::LitIntType::Unsigned(ast::UintTy::U32),
2149            ),
2150        });
2151        self.expr(sp, hir::ExprKind::Lit(lit))
2152    }
2153
2154    pub(super) fn expr_char(&mut self, sp: Span, value: char) -> hir::Expr<'hir> {
2155        let lit = self.arena.alloc(hir::Lit { span: sp, node: ast::LitKind::Char(value) });
2156        self.expr(sp, hir::ExprKind::Lit(lit))
2157    }
2158
2159    pub(super) fn expr_str(&mut self, sp: Span, value: Symbol) -> hir::Expr<'hir> {
2160        let lit = self
2161            .arena
2162            .alloc(hir::Lit { span: sp, node: ast::LitKind::Str(value, ast::StrStyle::Cooked) });
2163        self.expr(sp, hir::ExprKind::Lit(lit))
2164    }
2165
2166    pub(super) fn expr_call_mut(
2167        &mut self,
2168        span: Span,
2169        e: &'hir hir::Expr<'hir>,
2170        args: &'hir [hir::Expr<'hir>],
2171    ) -> hir::Expr<'hir> {
2172        self.expr(span, hir::ExprKind::Call(e, args))
2173    }
2174
2175    pub(super) fn expr_call(
2176        &mut self,
2177        span: Span,
2178        e: &'hir hir::Expr<'hir>,
2179        args: &'hir [hir::Expr<'hir>],
2180    ) -> &'hir hir::Expr<'hir> {
2181        self.arena.alloc(self.expr_call_mut(span, e, args))
2182    }
2183
2184    pub(super) fn expr_call_lang_item_fn_mut(
2185        &mut self,
2186        span: Span,
2187        lang_item: hir::LangItem,
2188        args: &'hir [hir::Expr<'hir>],
2189    ) -> hir::Expr<'hir> {
2190        let path = self.arena.alloc(self.expr_lang_item_path(span, lang_item));
2191        self.expr_call_mut(span, path, args)
2192    }
2193
2194    pub(super) fn expr_call_lang_item_fn(
2195        &mut self,
2196        span: Span,
2197        lang_item: hir::LangItem,
2198        args: &'hir [hir::Expr<'hir>],
2199    ) -> &'hir hir::Expr<'hir> {
2200        self.arena.alloc(self.expr_call_lang_item_fn_mut(span, lang_item, args))
2201    }
2202
2203    fn expr_lang_item_path(&mut self, span: Span, lang_item: hir::LangItem) -> hir::Expr<'hir> {
2204        self.expr(span, hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span))))
2205    }
2206
2207    /// `<LangItem>::name`
2208    pub(super) fn expr_lang_item_type_relative(
2209        &mut self,
2210        span: Span,
2211        lang_item: hir::LangItem,
2212        name: Symbol,
2213    ) -> hir::Expr<'hir> {
2214        let qpath = self.make_lang_item_qpath(lang_item, self.lower_span(span), None);
2215        let path = hir::ExprKind::Path(hir::QPath::TypeRelative(
2216            self.arena.alloc(self.ty(span, hir::TyKind::Path(qpath))),
2217            self.arena.alloc(hir::PathSegment::new(
2218                Ident::new(name, self.lower_span(span)),
2219                self.next_id(),
2220                Res::Err,
2221            )),
2222        ));
2223        self.expr(span, path)
2224    }
2225
2226    pub(super) fn expr_ident(
2227        &mut self,
2228        sp: Span,
2229        ident: Ident,
2230        binding: HirId,
2231    ) -> &'hir hir::Expr<'hir> {
2232        self.arena.alloc(self.expr_ident_mut(sp, ident, binding))
2233    }
2234
2235    pub(super) fn expr_ident_mut(
2236        &mut self,
2237        span: Span,
2238        ident: Ident,
2239        binding: HirId,
2240    ) -> hir::Expr<'hir> {
2241        let hir_id = self.next_id();
2242        let res = Res::Local(binding);
2243        let expr_path = hir::ExprKind::Path(hir::QPath::Resolved(
2244            None,
2245            self.arena.alloc(hir::Path {
2246                span: self.lower_span(span),
2247                res,
2248                segments: arena_vec![self; hir::PathSegment::new(ident, hir_id, res)],
2249            }),
2250        ));
2251
2252        self.expr(span, expr_path)
2253    }
2254
2255    fn expr_unsafe(&mut self, expr: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
2256        let hir_id = self.next_id();
2257        let span = expr.span;
2258        self.expr(
2259            span,
2260            hir::ExprKind::Block(
2261                self.arena.alloc(hir::Block {
2262                    stmts: &[],
2263                    expr: Some(expr),
2264                    hir_id,
2265                    rules: hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::CompilerGenerated),
2266                    span: self.lower_span(span),
2267                    targeted_by_break: false,
2268                }),
2269                None,
2270            ),
2271        )
2272    }
2273
2274    fn expr_block_empty(&mut self, span: Span) -> &'hir hir::Expr<'hir> {
2275        let blk = self.block_all(span, &[], None);
2276        let expr = self.expr_block(blk);
2277        self.arena.alloc(expr)
2278    }
2279
2280    pub(super) fn expr_block(&mut self, b: &'hir hir::Block<'hir>) -> hir::Expr<'hir> {
2281        self.expr(b.span, hir::ExprKind::Block(b, None))
2282    }
2283
2284    pub(super) fn expr_array_ref(
2285        &mut self,
2286        span: Span,
2287        elements: &'hir [hir::Expr<'hir>],
2288    ) -> hir::Expr<'hir> {
2289        let addrof = hir::ExprKind::AddrOf(
2290            hir::BorrowKind::Ref,
2291            hir::Mutability::Not,
2292            self.arena.alloc(self.expr(span, hir::ExprKind::Array(elements))),
2293        );
2294        self.expr(span, addrof)
2295    }
2296
2297    pub(super) fn expr(&mut self, span: Span, kind: hir::ExprKind<'hir>) -> hir::Expr<'hir> {
2298        let hir_id = self.next_id();
2299        hir::Expr { hir_id, kind, span: self.lower_span(span) }
2300    }
2301
2302    pub(super) fn expr_field(
2303        &mut self,
2304        ident: Ident,
2305        expr: &'hir hir::Expr<'hir>,
2306        span: Span,
2307    ) -> hir::ExprField<'hir> {
2308        hir::ExprField {
2309            hir_id: self.next_id(),
2310            ident,
2311            span: self.lower_span(span),
2312            expr,
2313            is_shorthand: false,
2314        }
2315    }
2316
2317    pub(super) fn arm(
2318        &mut self,
2319        pat: &'hir hir::Pat<'hir>,
2320        expr: &'hir hir::Expr<'hir>,
2321    ) -> hir::Arm<'hir> {
2322        hir::Arm {
2323            hir_id: self.next_id(),
2324            pat,
2325            guard: None,
2326            span: self.lower_span(expr.span),
2327            body: expr,
2328        }
2329    }
2330}
2331
2332/// Used by [`LoweringContext::make_lowered_await`] to customize the desugaring based on what kind
2333/// of future we are awaiting.
2334#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2335enum FutureKind {
2336    /// We are awaiting a normal future
2337    Future,
2338    /// We are awaiting something that's known to be an AsyncIterator (i.e. we are in the header of
2339    /// a `for await` loop)
2340    AsyncIterator,
2341}