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