Skip to main content

rustc_ast_lowering/
expr.rs

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