Skip to main content

rustc_ast_lowering/
expr.rs

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