compiler/rustc_ast_lowering/src/expr.rs RUST 2,344 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 2,344.
1use std::mem;2use std::ops::ControlFlow;3use std::sync::Arc;45use 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};1819mod closure;2021use 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};3233pub(super) struct WillCreateDefIdsVisitor;3435/// 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}4445/// 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}5051impl<'hir> Default for MoveExprState<'hir> {52    fn default() -> Self {53        Self { bindings: NodeMap::default(), occurrences: Vec::new() }54    }55}5657pub(super) struct MoveExprOccurrence<'hir> {58    id: NodeId,59    ident: Ident,60    pat: &'hir hir::Pat<'hir>,61    binding: HirId,62    explicit_capture: bool,63}6465/// Looks up the initializer expression for each `move(...)` occurrence.66struct MoveExprInitializerFinder<'a> {67    initializers: Vec<MoveExprInitializer<'a>>,68}6970impl<'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.initializers75    }76}7778impl<'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    }9394    fn visit_item(&mut self, _: &'a Item) {}95}9697impl<'v> rustc_ast::visit::Visitor<'v> for WillCreateDefIdsVisitor {98    type Result = ControlFlow<Span>;99100    fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {101        ControlFlow::Break(c.value.span)102    }103104    fn visit_item(&mut self, item: &'v Item) -> Self::Result {105        ControlFlow::Break(item.span)106    }107108    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}117118impl<'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            span_bug!(DUMMY_SP, "`move_expr_bindings` stack was empty after lowering")128        });129        (result, state)130    }131132    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 = self140            .move_expr_bindings141            .last()142            .and_then(|state| state.as_ref())143            .map_or(0, |state| state.occurrences.len());144        let ident = Ident::from_str_and_span(&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            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    }154155    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    }158159    pub(super) fn lower_expr(&mut self, e: &Expr) -> &'hir hir::Expr<'hir> {160        self.arena.alloc(self.lower_expr_mut(e))161    }162163    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 = self178                            .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 not193                // 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            }200201            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));203204            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 modifiers230                        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 = self259                        .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 = self265                        .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: 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 = self349                            .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                                expr375                            })376                        },377                    )378                }379                ExprKind::Block(blk, opt_label) => {380                    // Different from loops, label of block resolves to block id rather than381                    // 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.arena472                            .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),478479                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                ),489490                ExprKind::Dummy => {491                    span_bug!(e.span, "lowered ExprKind::Dummy")492                }493494                ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),495496                ExprKind::Paren(_) | ExprKind::ForLoop { .. } | ExprKind::Closure(..) => {497                    unreachable!("already handled")498                }499500                ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),501            };502503            hir::Expr { hir_id: expr_hir_id, kind, span }504        })505    }506507    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    }517518    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    }528529    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    }536537    fn lower_binop(&mut self, b: BinOp) -> BinOp {538        Spanned { node: b.node, span: self.lower_span(b.span) }539    }540541    fn lower_assign_op(&mut self, a: AssignOp) -> AssignOp {542        Spanned { node: a.node, span: self.lower_span(a.span) }543    }544545    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            unreachable!();553        };554555        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 = vec![];561                let mut other_args = 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(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        };581582        // Split the arguments into const generics and normal arguments583        let mut real_args = 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                        arg600                    };601602                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        }612613        // Add generic args to the last element of the path.614        let last_segment = path.segments.last_mut().unwrap();615        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        })));620621        // Now lower everything as normal.622        let f = self.lower_expr(&f);623        hir::ExprKind::Call(f, self.lower_exprs(&real_args))624    }625626    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    }644645    // We desugar: `'label: while $cond $body` into:646    //647    // ```648    // 'label: loop {649    //   if { let _t = $cond; _t } {650    //     $body651    //   }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 not660    // 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, 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    }680681    /// 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);693694            // Final expression of the block (if present) or `()` with span at the end of block695            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                );710711                (try_span, this.expr_unit(try_span))712            };713714            let ok_wrapped_span =715                this.mark_span_with_reason(DesugaringKind::TryBlock, tail_expr.span, None);716717            // `::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            ));724725            this.arena.alloc(block)726        });727728        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    }736737    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    }747748    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) = body759            && !is_never_pattern760        {761            body762        } 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            }775776            // We add a fake `loop {}` arm body so that it typecks to `!`. The mir lowering of never777            // 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    }794795    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    }802803    /// 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    /// ```text810    /// 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);827828        // 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 = arena_vec![self; input_ty];846847                // 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 = arena_vec![self; param];860861                (inputs, params, Some(task_context_hid))862            }863            hir::CoroutineDesugaring::Gen => (&[], &[], None),864        };865866        let output =867            return_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span)));868869        let fn_decl = self.arena.alloc(hir::FnDecl {870            inputs,871            output,872            fn_decl_kind: hir::FnDeclFlags::default(),873        });874875        let body = self.lower_body(move |this| {876            this.coroutine_kind = Some(coroutine_kind);877878            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;884885            (params, res)886        });887888        // `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    }903904    /// Forwards a possible `#[track_caller]` annotation from `outer_hir_id` to905    /// `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            && 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    }937938    /// 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    }957958    /// Takes an expr that has already been lowered and generates a desugared await loop around it959    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);966967        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 expr974                // 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                        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        };997998        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;10101011        // Note that the name of this binding must not be changed to something else because1012        // debuggers and debugger extensions expect it to be called `__awaitee`. They use1013        // 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);10171018        let task_context_ident = Ident::with_dummy_span(sym::_task_context);10191020        // 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);10291030            let Some(task_context_hid) = self.task_context else {1031                unreachable!("use of `await` outside of an async context.");1032            };10331034            let task_context = self.expr_ident_mut(span, task_context_ident, task_context_hid);10351036            let new_unchecked = self.expr_call_lang_item_fn_mut(1037                span,1038                hir::LangItem::PinNewUnchecked,1039                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                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                    arena_vec![self; new_unchecked, get_context],1051                ),1052                FutureKind::AsyncIterator => self.expr_call_lang_item_fn(1053                    span,1054                    hir::LangItem::AsyncIteratorPollNext,1055                    arena_vec![self; new_unchecked, get_context],1056                ),1057            };1058            self.arena.alloc(self.expr_unsafe(span, call))1059        };10601061        // `::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        };10771078        // `::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        };10841085        let inner_match_stmt = {1086            let match_expr = self.expr_match(1087                span,1088                poll_expr,1089                arena_vec![self; ready_arm, pending_arm],1090                hir::MatchSource::AwaitDesugar,1091            );1092            self.stmt_expr(span, match_expr)1093        };10941095        // 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            };11041105            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);11101111            let Some(task_context_hid) = self.task_context else {1112                unreachable!("use of `await` outside of an async context.");1113            };11141115            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        };11201121        let loop_block = self.block_all(span, arena_vec![self; inner_match_stmt, yield_stmt], None);11221123        // 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        });11341135        // mut __awaitee => loop { ... }1136        let awaitee_arm = self.arm(awaitee_pat, loop_expr, span);11371138        // `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                arena_vec![self; *expr],1144            ),1145            // Not needed for `for await` because we expect to have already called1146            // `IntoAsyncIterator::into_async_iter` on it.1147            FutureKind::AsyncIterator => expr,1148        };11491150        // match <into_future_expr> {1151        //     mut __awaitee => loop { .. }1152        // }1153        hir::ExprKind::Match(1154            into_future_expr,1155            arena_vec![self; awaitee_arm],1156            hir::MatchSource::AwaitDesugar,1157        )1158    }11591160    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    }11631164    /// 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        }12011202        let mut assignments = vec![];12031204        // 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);12071208        // 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);12111212        // `a = lhs1; b = lhs2;`.1213        let stmts = self.arena.alloc_from_iter(std::iter::once(destructure_let).chain(assignments));12141215        // Wrap everything in a block.1216        hir::ExprKind::Block(self.block_all(whole_span, stmts, None), None)1217    }12181219    /// 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 early1221    /// 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        None1239    }12401241    /// 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 early1243    /// 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        None1261    }12621263    /// 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    }12731274    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        pat1410    }14111412    /// 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 it1415    /// 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                    None1435                } else {1436                    Some(self.destructure_assign_mut(e, eq_sign_span, assignments))1437                }1438            }));1439        (elements, rest)1440    }14411442    /// 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, arena_vec![self; e1, e2])1449    }14501451    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::*;14591460        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::RangeFromCopy1465                } else {1466                    hir::LangItem::RangeFrom1467                }1468            }1469            (None, Some(..), HalfOpen) => hir::LangItem::RangeTo,1470            (Some(..), Some(..), HalfOpen) => {1471                if self.tcx.features().new_range() {1472                    hir::LangItem::RangeCopy1473                } else {1474                    hir::LangItem::Range1475                }1476            }1477            (None, Some(..), Closed) => {1478                if self.tcx.features().new_range() {1479                    hir::LangItem::RangeToInclusiveCopy1480                } else {1481                    hir::LangItem::RangeToInclusive1482                }1483            }1484            (Some(e1), Some(e2), Closed) => {1485                if self.tcx.features().new_range() {1486                    hir::LangItem::RangeInclusiveCopy1487                } 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::RangeFromCopy1497                        } else {1498                            hir::LangItem::RangeFrom1499                        }1500                    }1501                    None => hir::LangItem::RangeFull,1502                }1503            }1504        };15051506        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 matches!(1512                            lang_item,1513                            hir::LangItem::RangeInclusiveCopy | hir::LangItem::RangeToInclusiveCopy1514                        ) {1515                            sym::last1516                        } else {1517                            sym::end1518                        },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        );15301531        hir::ExprKind::Struct(1532            self.arena.alloc(self.make_lang_item_qpath(lang_item, span, None)),1533            fields,1534            hir::StructTailExpr::None,1535        )1536    }15371538    // Record labelled expr's HirId so that we can retrieve it in `lower_jump_destination` without1539    // 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    }15501551    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 = destination1567            .map(|(_, label)| label)1568            .map(|label| Label { ident: self.lower_ident(label.ident) });1569        hir::Destination { label, target_id }1570    }15711572    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    }15821583    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        result1592    }15931594    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;15981599        let old_scope = self.loop_scope.replace(loop_id);1600        let result = f(self);1601        self.loop_scope = old_scope;16021603        self.is_in_loop_condition = was_in_loop_condition;16041605        result1606    }16071608    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;16111612        let result = f(self);16131614        self.is_in_loop_condition = was_in_loop_condition;16151616        result1617    }16181619    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    }16301631    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));16341635        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                msg!("yield syntax is experimental"),1644            )1645            .emit();1646        }16471648        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 expr1653                // 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                        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));16771678                false1679            }1680        };16811682        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 that1685            // 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            );16991700            let Some(task_context_hid) = self.task_context else {1701                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);17051706            hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span))1707        } else {1708            hir::ExprKind::Yield(yielded, hir::YieldSource::Yield)1709        }1710    }17111712    /// 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    ///     result1726    /// }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();17421743        // Try to point both the head and pat spans to their position in the for loop1744        // 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);17491750        let loop_hir_id = self.lower_node_id(e.id);1751        let label = self.lower_label(opt_label, e.id, loop_hir_id);17521753        // `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        };17601761        // 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        };17691770        // `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);17741775        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                        arena_vec![self; ref_mut_iter],1785                    )1786                }1787                ForLoopKind::ForAwait => {1788                    // we'll generate `unsafe { Pin::new_unchecked(&mut iter) })` and then pass this1789                    // to make_lowered_await with `FutureKind::AsyncIterator` which will generator1790                    // calls to `poll_next`. In user code, this would probably be a call to1791                    // `Pin::as_mut` but here it's easy enough to do `new_unchecked`.17921793                    // `&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                        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 = arena_vec![self; none_arm, some_arm];18081809            // `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);18131814        let loop_block = self.block_all(for_span, arena_vec![self; match_stmt], None);18151816        // `[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 });18241825        // `mut iter => { ... }`1826        let iter_arm = self.arm(iter_pat, loop_expr, for_span);18271828        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                    arena_vec![self; head],1835                );18361837                self.arena.alloc(self.expr_match(1838                    for_span,1839                    into_iter_expr,1840                    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                    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                    arena_vec![self; iter_arm],1862                    hir::MatchSource::ForLoopDesugar,1863                ));18641865                // `::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                    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                    arena_vec![self; iter_arm],1876                    hir::MatchSource::ForLoopDesugar,1877                ))1878            }1879        };18801881        // This is effectively `{ let _result = ...; _result }`.1882        // The construct was introduced in #21984 and is necessary to make sure that1883        // temporaries in the `head` expression are dropped and do not leak to the1884        // 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        expr1890    }18911892    /// 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        );19161917        // `Try::branch(<expr>)`1918        let scrutinee = {1919            // expand <expr>1920            let sub_expr = self.lower_expr_mut(sub_expr);19211922            self.expr_call_lang_item_fn(1923                unstable_span,1924                hir::LangItem::TryTraitBranch,1925                arena_vec![self; sub_expr],1926            )1927        };19281929        let attrs: AttrVec = thin_vec![self.unreachable_code_attr(try_span)];19301931        // `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        };19401941        // `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);19481949            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);19791980            let break_pat = self.pat_cf_break(try_span, residual_local);1981            self.arm(break_pat, ret_expr, try_span)1982        };19831984        hir::ExprKind::Match(1985            scrutinee,1986            arena_vec![self; break_arm, continue_arm],1987            hir::MatchSource::TryDesugar(scrutinee.hir_id),1988        )1989    }19901991    /// 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 which1999    /// handles the combined `FromResidual::from_residual(Yeet(residual))`.2000    fn lower_expr_yeet(&mut self, span: Span, sub_expr: Option<&Expr>) -> hir::ExprKind<'hir> {

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.