File is large — showing lines 1–2,000 of 2,402.
1use std::mem;2use std::ops::ControlFlow;3use std::sync::Arc;45use rustc_ast::*;6use rustc_ast_pretty::pprust::expr_to_string;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};1819use super::errors::{20 AsyncCoroutinesNotSupported, AwaitOnlyInAsyncFnAndBlocks, ClosureCannotBeStatic,21 CoroutineTooManyParameters, FunctionalRecordUpdateDestructuringAssignment,22 InclusiveRangeWithNoEnd, MatchArmWithNoBody, NeverPatternWithBody, NeverPatternWithGuard,23 UnderscoreExprLhsAssign,24};25use super::{26 GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt,27};28use crate::errors::{InvalidLegacyConstGenericArg, UseConstGenericArg, YieldInClosure};29use crate::{AllowReturnTypeNotation, FnDeclKind, ImplTraitPosition, TryBlockScope};3031pub(super) struct WillCreateDefIdsVisitor;3233impl<'v> rustc_ast::visit::Visitor<'v> for WillCreateDefIdsVisitor {34 type Result = ControlFlow<Span>;3536 fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {37 ControlFlow::Break(c.value.span)38 }3940 fn visit_item(&mut self, item: &'v Item) -> Self::Result {41 ControlFlow::Break(item.span)42 }4344 fn visit_expr(&mut self, ex: &'v Expr) -> Self::Result {45 match ex.kind {46 ExprKind::Gen(..) | ExprKind::ConstBlock(..) | ExprKind::Closure(..) => {47 ControlFlow::Break(ex.span)48 }49 _ => walk_expr(self, ex),50 }51 }52}5354impl<'hir> LoweringContext<'_, 'hir> {55 fn lower_exprs(&mut self, exprs: &[Box<Expr>]) -> &'hir [hir::Expr<'hir>] {56 self.arena.alloc_from_iter(exprs.iter().map(|x| self.lower_expr_mut(x)))57 }5859 pub(super) fn lower_expr(&mut self, e: &Expr) -> &'hir hir::Expr<'hir> {60 self.arena.alloc(self.lower_expr_mut(e))61 }6263 pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {64 ensure_sufficient_stack(|| {65 let mut span = self.lower_span(e.span);66 match &e.kind {67 // Parenthesis expression does not have a HirId and is handled specially.68 ExprKind::Paren(ex) => {69 let mut ex = self.lower_expr_mut(ex);70 // Include parens in span, but only if it is a super-span.71 if e.span.contains(ex.span) {72 ex.span = self.lower_span(e.span.with_ctxt(ex.span.ctxt()));73 }74 // Merge attributes into the inner expression.75 if !e.attrs.is_empty() {76 let old_attrs = self.attrs.get(&ex.hir_id.local_id).copied().unwrap_or(&[]);77 let new_attrs = self78 .lower_attrs_vec(&e.attrs, e.span, ex.hir_id, Target::from_expr(e))79 .into_iter()80 .chain(old_attrs.iter().cloned());81 let new_attrs = &*self.arena.alloc_from_iter(new_attrs);82 if new_attrs.is_empty() {83 return ex;84 }85 self.attrs.insert(ex.hir_id.local_id, new_attrs);86 }87 return ex;88 }89 // Desugar `ExprForLoop`90 // from: `[opt_ident]: for await? <pat> in <iter> <body>`91 //92 // This also needs special handling because the HirId of the returned `hir::Expr` will not93 // correspond to the `e.id`, so `lower_expr_for` handles attribute lowering itself.94 ExprKind::ForLoop { pat, iter, body, label, kind } => {95 return self.lower_expr_for(e, pat, iter, body, *label, *kind);96 }97 _ => (),98 }99100 let expr_hir_id = self.lower_node_id(e.id);101 let attrs = self.lower_attrs(expr_hir_id, &e.attrs, e.span, Target::from_expr(e));102103 let kind = match &e.kind {104 ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),105 ExprKind::ConstBlock(c) => hir::ExprKind::ConstBlock(self.lower_const_block(c)),106 ExprKind::Repeat(expr, count) => {107 let expr = self.lower_expr(expr);108 let count = self.lower_array_length_to_const_arg(count);109 hir::ExprKind::Repeat(expr, count)110 }111 ExprKind::Tup(elts) => hir::ExprKind::Tup(self.lower_exprs(elts)),112 ExprKind::Call(f, args) => {113 if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f, self.tcx)114 {115 self.lower_legacy_const_generics((**f).clone(), args.clone(), &legacy_args)116 } else {117 let f = self.lower_expr(f);118 hir::ExprKind::Call(f, self.lower_exprs(args))119 }120 }121 ExprKind::MethodCall(box MethodCall { seg, receiver, args, span }) => {122 let hir_seg = self.arena.alloc(self.lower_path_segment(123 e.span,124 seg,125 ParamMode::Optional,126 GenericArgsMode::Err,127 ImplTraitContext::Disallowed(ImplTraitPosition::Path),128 // Method calls can't have bound modifiers129 None,130 ));131 let receiver = self.lower_expr(receiver);132 let args =133 self.arena.alloc_from_iter(args.iter().map(|x| self.lower_expr_mut(x)));134 hir::ExprKind::MethodCall(hir_seg, receiver, args, self.lower_span(*span))135 }136 ExprKind::Binary(binop, lhs, rhs) => {137 let binop = self.lower_binop(*binop);138 let lhs = self.lower_expr(lhs);139 let rhs = self.lower_expr(rhs);140 hir::ExprKind::Binary(binop, lhs, rhs)141 }142 ExprKind::Unary(op, ohs) => {143 let op = self.lower_unop(*op);144 let ohs = self.lower_expr(ohs);145 hir::ExprKind::Unary(op, ohs)146 }147 ExprKind::Lit(token_lit) => hir::ExprKind::Lit(self.lower_lit(token_lit, e.span)),148 ExprKind::IncludedBytes(byte_sym) => {149 let lit = respan(150 self.lower_span(e.span),151 LitKind::ByteStr(*byte_sym, StrStyle::Cooked),152 );153 hir::ExprKind::Lit(lit)154 }155 ExprKind::Cast(expr, ty) => {156 let expr = self.lower_expr(expr);157 let ty = self158 .lower_ty_alloc(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Cast));159 hir::ExprKind::Cast(expr, ty)160 }161 ExprKind::Type(expr, ty) => {162 let expr = self.lower_expr(expr);163 let ty = self164 .lower_ty_alloc(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Cast));165 hir::ExprKind::Type(expr, ty)166 }167 ExprKind::AddrOf(k, m, ohs) => {168 let ohs = self.lower_expr(ohs);169 hir::ExprKind::AddrOf(*k, *m, ohs)170 }171 ExprKind::Let(pat, scrutinee, span, recovered) => {172 hir::ExprKind::Let(self.arena.alloc(hir::LetExpr {173 span: self.lower_span(*span),174 pat: self.lower_pat(pat),175 ty: None,176 init: self.lower_expr(scrutinee),177 recovered: *recovered,178 }))179 }180 ExprKind::If(cond, then, else_opt) => {181 self.lower_expr_if(cond, then, else_opt.as_deref())182 }183 ExprKind::While(cond, body, opt_label) => {184 self.with_loop_scope(expr_hir_id, |this| {185 let span =186 this.mark_span_with_reason(DesugaringKind::WhileLoop, e.span, None);187 let opt_label = this.lower_label(*opt_label, e.id, expr_hir_id);188 this.lower_expr_while_in_loop_scope(span, cond, body, opt_label)189 })190 }191 ExprKind::Loop(body, opt_label, span) => {192 self.with_loop_scope(expr_hir_id, |this| {193 let opt_label = this.lower_label(*opt_label, e.id, expr_hir_id);194 hir::ExprKind::Loop(195 this.lower_block(body, false),196 opt_label,197 hir::LoopSource::Loop,198 this.lower_span(*span),199 )200 })201 }202 ExprKind::TryBlock(body, opt_ty) => {203 self.lower_expr_try_block(body, opt_ty.as_deref())204 }205 ExprKind::Match(expr, arms, kind) => hir::ExprKind::Match(206 self.lower_expr(expr),207 self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))),208 match kind {209 MatchKind::Prefix => hir::MatchSource::Normal,210 MatchKind::Postfix => hir::MatchSource::Postfix,211 },212 ),213 ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr),214 ExprKind::Use(expr, use_kw_span) => self.lower_expr_use(*use_kw_span, expr),215 ExprKind::Closure(box Closure {216 binder,217 capture_clause,218 constness,219 coroutine_kind,220 movability,221 fn_decl,222 body,223 fn_decl_span,224 fn_arg_span,225 }) => match coroutine_kind {226 Some(coroutine_kind) => self.lower_expr_coroutine_closure(227 binder,228 *capture_clause,229 e.id,230 expr_hir_id,231 *coroutine_kind,232 *constness,233 fn_decl,234 body,235 *fn_decl_span,236 *fn_arg_span,237 ),238 None => self.lower_expr_closure(239 attrs,240 binder,241 *capture_clause,242 e.id,243 *constness,244 *movability,245 fn_decl,246 body,247 *fn_decl_span,248 *fn_arg_span,249 ),250 },251 ExprKind::Gen(capture_clause, block, genblock_kind, decl_span) => {252 let desugaring_kind = match genblock_kind {253 GenBlockKind::Async => hir::CoroutineDesugaring::Async,254 GenBlockKind::Gen => hir::CoroutineDesugaring::Gen,255 GenBlockKind::AsyncGen => hir::CoroutineDesugaring::AsyncGen,256 };257 self.make_desugared_coroutine_expr(258 *capture_clause,259 e.id,260 None,261 *decl_span,262 e.span,263 desugaring_kind,264 hir::CoroutineSource::Block,265 |this| this.with_new_scopes(e.span, |this| this.lower_block_expr(block)),266 )267 }268 ExprKind::Block(blk, opt_label) => {269 // Different from loops, label of block resolves to block id rather than270 // expr node id.271 let block_hir_id = self.lower_node_id(blk.id);272 let opt_label = self.lower_label(*opt_label, blk.id, block_hir_id);273 let hir_block = self.arena.alloc(self.lower_block_noalloc(274 block_hir_id,275 blk,276 opt_label.is_some(),277 ));278 hir::ExprKind::Block(hir_block, opt_label)279 }280 ExprKind::Assign(el, er, span) => self.lower_expr_assign(el, er, *span, e.span),281 ExprKind::AssignOp(op, el, er) => hir::ExprKind::AssignOp(282 self.lower_assign_op(*op),283 self.lower_expr(el),284 self.lower_expr(er),285 ),286 ExprKind::Field(el, ident) => {287 hir::ExprKind::Field(self.lower_expr(el), self.lower_ident(*ident))288 }289 ExprKind::Index(el, er, brackets_span) => hir::ExprKind::Index(290 self.lower_expr(el),291 self.lower_expr(er),292 self.lower_span(*brackets_span),293 ),294 ExprKind::Range(e1, e2, lims) => {295 span = self.mark_span_with_reason(DesugaringKind::RangeExpr, span, None);296 self.lower_expr_range(span, e1.as_deref(), e2.as_deref(), *lims)297 }298 ExprKind::Underscore => {299 let guar = self.dcx().emit_err(UnderscoreExprLhsAssign { span: e.span });300 hir::ExprKind::Err(guar)301 }302 ExprKind::Path(qself, path) => {303 let qpath = self.lower_qpath(304 e.id,305 qself,306 path,307 ParamMode::Optional,308 AllowReturnTypeNotation::No,309 ImplTraitContext::Disallowed(ImplTraitPosition::Path),310 None,311 );312 hir::ExprKind::Path(qpath)313 }314 ExprKind::Break(opt_label, opt_expr) => {315 let opt_expr = opt_expr.as_ref().map(|x| self.lower_expr(x));316 hir::ExprKind::Break(self.lower_jump_destination(e.id, *opt_label), opt_expr)317 }318 ExprKind::Continue(opt_label) => {319 hir::ExprKind::Continue(self.lower_jump_destination(e.id, *opt_label))320 }321 ExprKind::Ret(e) => {322 let expr = e.as_ref().map(|x| self.lower_expr(x));323 self.checked_return(expr)324 }325 ExprKind::Yeet(sub_expr) => self.lower_expr_yeet(e.span, sub_expr.as_deref()),326 ExprKind::Become(sub_expr) => {327 let sub_expr = self.lower_expr(sub_expr);328 hir::ExprKind::Become(sub_expr)329 }330 ExprKind::InlineAsm(asm) => {331 hir::ExprKind::InlineAsm(self.lower_inline_asm(e.span, asm))332 }333 ExprKind::FormatArgs(fmt) => self.lower_format_args(e.span, fmt),334 ExprKind::OffsetOf(container, fields) => hir::ExprKind::OffsetOf(335 self.lower_ty_alloc(336 container,337 ImplTraitContext::Disallowed(ImplTraitPosition::OffsetOf),338 ),339 self.arena.alloc_from_iter(fields.iter().map(|&ident| self.lower_ident(ident))),340 ),341 ExprKind::Struct(se) => {342 let rest = match se.rest {343 StructRest::Base(ref e) => hir::StructTailExpr::Base(self.lower_expr(e)),344 StructRest::Rest(sp) => {345 hir::StructTailExpr::DefaultFields(self.lower_span(sp))346 }347 StructRest::None => hir::StructTailExpr::None,348 StructRest::NoneWithError(guar) => hir::StructTailExpr::NoneWithError(guar),349 };350 hir::ExprKind::Struct(351 self.arena.alloc(self.lower_qpath(352 e.id,353 &se.qself,354 &se.path,355 ParamMode::Optional,356 AllowReturnTypeNotation::No,357 ImplTraitContext::Disallowed(ImplTraitPosition::Path),358 None,359 )),360 self.arena361 .alloc_from_iter(se.fields.iter().map(|x| self.lower_expr_field(x))),362 rest,363 )364 }365 ExprKind::Yield(kind) => self.lower_expr_yield(e.span, kind.expr().map(|x| &**x)),366 ExprKind::Err(guar) => hir::ExprKind::Err(*guar),367368 ExprKind::UnsafeBinderCast(kind, expr, ty) => hir::ExprKind::UnsafeBinderCast(369 *kind,370 self.lower_expr(expr),371 ty.as_ref().map(|ty| {372 self.lower_ty_alloc(373 ty,374 ImplTraitContext::Disallowed(ImplTraitPosition::Cast),375 )376 }),377 ),378379 ExprKind::Dummy => {380 span_bug!(e.span, "lowered ExprKind::Dummy")381 }382383 ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),384385 ExprKind::Paren(_) | ExprKind::ForLoop { .. } => {386 unreachable!("already handled")387 }388389 ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),390 };391392 hir::Expr { hir_id: expr_hir_id, kind, span }393 })394 }395396 pub(crate) fn lower_const_block(&mut self, c: &AnonConst) -> hir::ConstBlock {397 self.with_new_scopes(c.value.span, |this| {398 let def_id = this.local_def_id(c.id);399 hir::ConstBlock {400 def_id,401 hir_id: this.lower_node_id(c.id),402 body: this.lower_const_body(c.value.span, Some(&c.value)),403 }404 })405 }406407 pub(crate) fn lower_lit(&mut self, token_lit: &token::Lit, span: Span) -> hir::Lit {408 let lit_kind = match LitKind::from_token_lit(*token_lit) {409 Ok(lit_kind) => lit_kind,410 Err(err) => {411 let guar = report_lit_error(&self.tcx.sess.psess, err, *token_lit, span);412 LitKind::Err(guar)413 }414 };415 respan(self.lower_span(span), lit_kind)416 }417418 fn lower_unop(&mut self, u: UnOp) -> hir::UnOp {419 match u {420 UnOp::Deref => hir::UnOp::Deref,421 UnOp::Not => hir::UnOp::Not,422 UnOp::Neg => hir::UnOp::Neg,423 }424 }425426 fn lower_binop(&mut self, b: BinOp) -> BinOp {427 Spanned { node: b.node, span: self.lower_span(b.span) }428 }429430 fn lower_assign_op(&mut self, a: AssignOp) -> AssignOp {431 Spanned { node: a.node, span: self.lower_span(a.span) }432 }433434 fn lower_legacy_const_generics(435 &mut self,436 mut f: Expr,437 args: ThinVec<Box<Expr>>,438 legacy_args_idx: &[usize],439 ) -> hir::ExprKind<'hir> {440 let ExprKind::Path(None, path) = &mut f.kind else {441 unreachable!();442 };443444 let mut error = None;445 let mut invalid_expr_error = |tcx: TyCtxt<'_>, span| {446 // Avoid emitting the error multiple times.447 if error.is_none() {448 let mut const_args = vec![];449 let mut other_args = vec![];450 for (idx, arg) in args.iter().enumerate() {451 if legacy_args_idx.contains(&idx) {452 const_args.push(format!("{{ {} }}", expr_to_string(arg)));453 } else {454 other_args.push(expr_to_string(arg));455 }456 }457 let suggestion = UseConstGenericArg {458 end_of_fn: f.span.shrink_to_hi(),459 const_args: const_args.join(", "),460 other_args: other_args.join(", "),461 call_args: args[0].span.to(args.last().unwrap().span),462 };463 error = Some(tcx.dcx().emit_err(InvalidLegacyConstGenericArg { span, suggestion }));464 }465 error.unwrap()466 };467468 // Split the arguments into const generics and normal arguments469 let mut real_args = vec![];470 let mut generic_args = ThinVec::new();471 for (idx, arg) in args.iter().cloned().enumerate() {472 if legacy_args_idx.contains(&idx) {473 let node_id = self.next_node_id();474 self.create_def(node_id, None, DefKind::AnonConst, f.span);475 let const_value =476 if let ControlFlow::Break(span) = WillCreateDefIdsVisitor.visit_expr(&arg) {477 Box::new(Expr {478 id: self.next_node_id(),479 kind: ExprKind::Err(invalid_expr_error(self.tcx, span)),480 span: f.span,481 attrs: [].into(),482 tokens: None,483 })484 } else {485 arg486 };487488 let anon_const = AnonConst {489 id: node_id,490 value: const_value,491 mgca_disambiguation: MgcaDisambiguation::AnonConst,492 };493 generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const)));494 } else {495 real_args.push(arg);496 }497 }498499 // Add generic args to the last element of the path.500 let last_segment = path.segments.last_mut().unwrap();501 assert!(last_segment.args.is_none());502 last_segment.args = Some(Box::new(GenericArgs::AngleBracketed(AngleBracketedArgs {503 span: DUMMY_SP,504 args: generic_args,505 })));506507 // Now lower everything as normal.508 let f = self.lower_expr(&f);509 hir::ExprKind::Call(f, self.lower_exprs(&real_args))510 }511512 fn lower_expr_if(513 &mut self,514 cond: &Expr,515 then: &Block,516 else_opt: Option<&Expr>,517 ) -> hir::ExprKind<'hir> {518 let lowered_cond = self.lower_expr(cond);519 let then_expr = self.lower_block_expr(then);520 if let Some(rslt) = else_opt {521 hir::ExprKind::If(522 lowered_cond,523 self.arena.alloc(then_expr),524 Some(self.lower_expr(rslt)),525 )526 } else {527 hir::ExprKind::If(lowered_cond, self.arena.alloc(then_expr), None)528 }529 }530531 // We desugar: `'label: while $cond $body` into:532 //533 // ```534 // 'label: loop {535 // if { let _t = $cond; _t } {536 // $body537 // }538 // else {539 // break;540 // }541 // }542 // ```543 //544 // Wrap in a construct equivalent to `{ let _t = $cond; _t }`545 // to preserve drop semantics since `while $cond { ... }` does not546 // let temporaries live outside of `cond`.547 fn lower_expr_while_in_loop_scope(548 &mut self,549 span: Span,550 cond: &Expr,551 body: &Block,552 opt_label: Option<Label>,553 ) -> hir::ExprKind<'hir> {554 let lowered_cond = self.with_loop_condition_scope(|t| t.lower_expr(cond));555 let then = self.lower_block_expr(body);556 let expr_break = self.expr_break(span);557 let stmt_break = self.stmt_expr(span, expr_break);558 let else_blk = self.block_all(span, arena_vec![self; stmt_break], None);559 let else_expr = self.arena.alloc(self.expr_block(else_blk));560 let if_kind = hir::ExprKind::If(lowered_cond, self.arena.alloc(then), Some(else_expr));561 let if_expr = self.expr(span, if_kind);562 let block = self.block_expr(self.arena.alloc(if_expr));563 let span = self.lower_span(span.with_hi(cond.span.hi()));564 hir::ExprKind::Loop(block, opt_label, hir::LoopSource::While, span)565 }566567 /// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_output(<expr>) }`,568 /// `try { <stmts>; }` into `{ <stmts>; ::std::ops::Try::from_output(()) }`569 /// and save the block id to use it as a break target for desugaring of the `?` operator.570 fn lower_expr_try_block(&mut self, body: &Block, opt_ty: Option<&Ty>) -> hir::ExprKind<'hir> {571 let body_hir_id = self.lower_node_id(body.id);572 let new_scope = if opt_ty.is_some() {573 TryBlockScope::Heterogeneous(body_hir_id)574 } else {575 TryBlockScope::Homogeneous(body_hir_id)576 };577 let whole_block = self.with_try_block_scope(new_scope, |this| {578 let mut block = this.lower_block_noalloc(body_hir_id, body, true);579580 // Final expression of the block (if present) or `()` with span at the end of block581 let (try_span, tail_expr) = if let Some(expr) = block.expr.take() {582 (583 this.mark_span_with_reason(584 DesugaringKind::TryBlock,585 expr.span,586 Some(Arc::clone(&this.allow_try_trait)),587 ),588 expr,589 )590 } else {591 let try_span = this.mark_span_with_reason(592 DesugaringKind::TryBlock,593 this.tcx.sess.source_map().end_point(body.span),594 Some(Arc::clone(&this.allow_try_trait)),595 );596597 (try_span, this.expr_unit(try_span))598 };599600 let ok_wrapped_span =601 this.mark_span_with_reason(DesugaringKind::TryBlock, tail_expr.span, None);602603 // `::std::ops::Try::from_output($tail_expr)`604 block.expr = Some(this.wrap_in_try_constructor(605 hir::LangItem::TryTraitFromOutput,606 try_span,607 tail_expr,608 ok_wrapped_span,609 ));610611 this.arena.alloc(block)612 });613614 if let Some(ty) = opt_ty {615 let ty = self.lower_ty_alloc(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Path));616 let block_expr = self.arena.alloc(self.expr_block(whole_block));617 hir::ExprKind::Type(block_expr, ty)618 } else {619 hir::ExprKind::Block(whole_block, None)620 }621 }622623 fn wrap_in_try_constructor(624 &mut self,625 lang_item: hir::LangItem,626 method_span: Span,627 expr: &'hir hir::Expr<'hir>,628 overall_span: Span,629 ) -> &'hir hir::Expr<'hir> {630 let constructor = self.arena.alloc(self.expr_lang_item_path(method_span, lang_item));631 self.expr_call(overall_span, constructor, std::slice::from_ref(expr))632 }633634 fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {635 let pat = self.lower_pat(&arm.pat);636 let guard = arm.guard.as_ref().map(|guard| self.lower_expr(&guard.cond));637 let hir_id = self.next_id();638 let span = self.lower_span(arm.span);639 self.lower_attrs(hir_id, &arm.attrs, arm.span, Target::Arm);640 let is_never_pattern = pat.is_never_pattern();641 // We need to lower the body even if it's unneeded for never pattern in match,642 // ensure that we can get HirId for DefId if need (issue #137708).643 let body = arm.body.as_ref().map(|x| self.lower_expr(x));644 let body = if let Some(body) = body645 && !is_never_pattern646 {647 body648 } else {649 // Either `body.is_none()` or `is_never_pattern` here.650 if !is_never_pattern {651 if self.tcx.features().never_patterns() {652 // If the feature is off we already emitted the error after parsing.653 let suggestion = span.shrink_to_hi();654 self.dcx().emit_err(MatchArmWithNoBody { span, suggestion });655 }656 } else if let Some(body) = &arm.body {657 self.dcx().emit_err(NeverPatternWithBody { span: body.span });658 } else if let Some(g) = &arm.guard {659 self.dcx().emit_err(NeverPatternWithGuard { span: g.span() });660 }661662 // We add a fake `loop {}` arm body so that it typecks to `!`. The mir lowering of never663 // patterns ensures this loop is not reachable.664 let block = self.arena.alloc(hir::Block {665 stmts: &[],666 expr: None,667 hir_id: self.next_id(),668 rules: hir::BlockCheckMode::DefaultBlock,669 span,670 targeted_by_break: false,671 });672 self.arena.alloc(hir::Expr {673 hir_id: self.next_id(),674 kind: hir::ExprKind::Loop(block, None, hir::LoopSource::Loop, span),675 span,676 })677 };678 hir::Arm { hir_id, pat, guard, body, span }679 }680681 fn lower_capture_clause(&mut self, capture_clause: CaptureBy) -> CaptureBy {682 match capture_clause {683 CaptureBy::Ref => CaptureBy::Ref,684 CaptureBy::Use { use_kw } => CaptureBy::Use { use_kw: self.lower_span(use_kw) },685 CaptureBy::Value { move_kw } => CaptureBy::Value { move_kw: self.lower_span(move_kw) },686 }687 }688689 /// Lower/desugar a coroutine construct.690 ///691 /// In particular, this creates the correct async resume argument and `_task_context`.692 ///693 /// This results in:694 ///695 /// ```text696 /// static move? |<_task_context?>| -> <return_ty> {697 /// <body>698 /// }699 /// ```700 pub(super) fn make_desugared_coroutine_expr(701 &mut self,702 capture_clause: CaptureBy,703 closure_node_id: NodeId,704 return_ty: Option<hir::FnRetTy<'hir>>,705 fn_decl_span: Span,706 span: Span,707 desugaring_kind: hir::CoroutineDesugaring,708 coroutine_source: hir::CoroutineSource,709 body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,710 ) -> hir::ExprKind<'hir> {711 let closure_def_id = self.local_def_id(closure_node_id);712 let coroutine_kind = hir::CoroutineKind::Desugared(desugaring_kind, coroutine_source);713714 // The `async` desugaring takes a resume argument and maintains a `task_context`,715 // whereas a generator does not.716 let (inputs, params, task_context): (&[_], &[_], _) = match desugaring_kind {717 hir::CoroutineDesugaring::Async | hir::CoroutineDesugaring::AsyncGen => {718 // Resume argument type: `ResumeTy`719 let unstable_span = self.mark_span_with_reason(720 DesugaringKind::Async,721 self.lower_span(span),722 Some(Arc::clone(&self.allow_gen_future)),723 );724 let resume_ty =725 self.make_lang_item_qpath(hir::LangItem::ResumeTy, unstable_span, None);726 let input_ty = hir::Ty {727 hir_id: self.next_id(),728 kind: hir::TyKind::Path(resume_ty),729 span: unstable_span,730 };731 let inputs = arena_vec![self; input_ty];732733 // Lower the argument pattern/ident. The ident is used again in the `.await` lowering.734 let (pat, task_context_hid) = self.pat_ident_binding_mode(735 span,736 Ident::with_dummy_span(sym::_task_context),737 hir::BindingMode::MUT,738 );739 let param = hir::Param {740 hir_id: self.next_id(),741 pat,742 ty_span: self.lower_span(span),743 span: self.lower_span(span),744 };745 let params = arena_vec![self; param];746747 (inputs, params, Some(task_context_hid))748 }749 hir::CoroutineDesugaring::Gen => (&[], &[], None),750 };751752 let output =753 return_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span)));754755 let fn_decl = self.arena.alloc(hir::FnDecl {756 inputs,757 output,758 fn_decl_kind: hir::FnDeclFlags::default(),759 });760761 let body = self.lower_body(move |this| {762 this.coroutine_kind = Some(coroutine_kind);763764 let old_ctx = this.task_context;765 if task_context.is_some() {766 this.task_context = task_context;767 }768 let res = body(this);769 this.task_context = old_ctx;770771 (params, res)772 });773774 // `static |<_task_context?>| -> <return_ty> { <body> }`:775 hir::ExprKind::Closure(self.arena.alloc(hir::Closure {776 def_id: closure_def_id,777 binder: hir::ClosureBinder::Default,778 capture_clause: self.lower_capture_clause(capture_clause),779 bound_generic_params: &[],780 fn_decl,781 body,782 fn_decl_span: self.lower_span(fn_decl_span),783 fn_arg_span: None,784 kind: hir::ClosureKind::Coroutine(coroutine_kind),785 constness: hir::Constness::NotConst,786 }))787 }788789 /// Forwards a possible `#[track_caller]` annotation from `outer_hir_id` to790 /// `inner_hir_id` in case the `async_fn_track_caller` feature is enabled.791 pub(super) fn maybe_forward_track_caller(792 &mut self,793 span: Span,794 outer_hir_id: HirId,795 inner_hir_id: HirId,796 ) {797 if self.tcx.features().async_fn_track_caller()798 && let Some(attrs) = self.attrs.get(&outer_hir_id.local_id)799 && find_attr!(*attrs, TrackCaller(_))800 {801 let unstable_span = self.mark_span_with_reason(802 DesugaringKind::Async,803 span,804 Some(Arc::clone(&self.allow_gen_future)),805 );806 self.lower_attrs(807 inner_hir_id,808 &[Attribute {809 kind: AttrKind::Normal(Box::new(NormalAttr::from_ident(Ident::new(810 sym::track_caller,811 span,812 )))),813 id: self.tcx.sess.psess.attr_id_generator.mk_attr_id(),814 style: AttrStyle::Outer,815 span: unstable_span,816 }],817 span,818 Target::Fn,819 );820 }821 }822823 /// Desugar `<expr>.await` into:824 /// ```ignore (pseudo-rust)825 /// match ::std::future::IntoFuture::into_future(<expr>) {826 /// mut __awaitee => loop {827 /// match unsafe { ::std::future::Future::poll(828 /// <::std::pin::Pin>::new_unchecked(&mut __awaitee),829 /// ::std::future::get_context(task_context),830 /// ) } {831 /// ::std::task::Poll::Ready(result) => break result,832 /// ::std::task::Poll::Pending => {}833 /// }834 /// task_context = yield ();835 /// }836 /// }837 /// ```838 fn lower_expr_await(&mut self, await_kw_span: Span, expr: &Expr) -> hir::ExprKind<'hir> {839 let expr = self.arena.alloc(self.lower_expr_mut(expr));840 self.make_lowered_await(await_kw_span, expr, FutureKind::Future)841 }842843 /// Takes an expr that has already been lowered and generates a desugared await loop around it844 fn make_lowered_await(845 &mut self,846 await_kw_span: Span,847 expr: &'hir hir::Expr<'hir>,848 await_kind: FutureKind,849 ) -> hir::ExprKind<'hir> {850 let full_span = expr.span.to(await_kw_span);851852 let is_async_gen = match self.coroutine_kind {853 Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => false,854 Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => true,855 Some(hir::CoroutineKind::Coroutine(_))856 | Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _))857 | None => {858 // Lower to a block `{ EXPR; <error> }` so that the awaited expr859 // is not accidentally orphaned.860 let stmt_id = self.next_id();861 let expr_err = self.expr(862 expr.span,863 hir::ExprKind::Err(self.dcx().emit_err(AwaitOnlyInAsyncFnAndBlocks {864 await_kw_span,865 item_span: self.current_item,866 })),867 );868 return hir::ExprKind::Block(869 self.block_all(870 expr.span,871 arena_vec![self; hir::Stmt {872 hir_id: stmt_id,873 kind: hir::StmtKind::Semi(expr),874 span: expr.span,875 }],876 Some(self.arena.alloc(expr_err)),877 ),878 None,879 );880 }881 };882883 let features = match await_kind {884 FutureKind::Future if is_async_gen => Some(Arc::clone(&self.allow_async_gen)),885 FutureKind::Future => None,886 FutureKind::AsyncIterator => Some(Arc::clone(&self.allow_for_await)),887 };888 let span = self.mark_span_with_reason(DesugaringKind::Await, await_kw_span, features);889 let gen_future_span = self.mark_span_with_reason(890 DesugaringKind::Await,891 full_span,892 Some(Arc::clone(&self.allow_gen_future)),893 );894 let expr_hir_id = expr.hir_id;895896 // Note that the name of this binding must not be changed to something else because897 // debuggers and debugger extensions expect it to be called `__awaitee`. They use898 // this name to identify what is being awaited by a suspended async functions.899 let awaitee_ident = Ident::with_dummy_span(sym::__awaitee);900 let (awaitee_pat, awaitee_pat_hid) =901 self.pat_ident_binding_mode(gen_future_span, awaitee_ident, hir::BindingMode::MUT);902903 let task_context_ident = Ident::with_dummy_span(sym::_task_context);904905 // unsafe {906 // ::std::future::Future::poll(907 // ::std::pin::Pin::new_unchecked(&mut __awaitee),908 // ::std::future::get_context(task_context),909 // )910 // }911 let poll_expr = {912 let awaitee = self.expr_ident(span, awaitee_ident, awaitee_pat_hid);913 let ref_mut_awaitee = self.expr_mut_addr_of(span, awaitee);914915 let Some(task_context_hid) = self.task_context else {916 unreachable!("use of `await` outside of an async context.");917 };918919 let task_context = self.expr_ident_mut(span, task_context_ident, task_context_hid);920921 let new_unchecked = self.expr_call_lang_item_fn_mut(922 span,923 hir::LangItem::PinNewUnchecked,924 arena_vec![self; ref_mut_awaitee],925 );926 let get_context = self.expr_call_lang_item_fn_mut(927 gen_future_span,928 hir::LangItem::GetContext,929 arena_vec![self; task_context],930 );931 let call = match await_kind {932 FutureKind::Future => self.expr_call_lang_item_fn(933 span,934 hir::LangItem::FuturePoll,935 arena_vec![self; new_unchecked, get_context],936 ),937 FutureKind::AsyncIterator => self.expr_call_lang_item_fn(938 span,939 hir::LangItem::AsyncIteratorPollNext,940 arena_vec![self; new_unchecked, get_context],941 ),942 };943 self.arena.alloc(self.expr_unsafe(span, call))944 };945946 // `::std::task::Poll::Ready(result) => break result`947 let loop_node_id = self.next_node_id();948 let loop_hir_id = self.lower_node_id(loop_node_id);949 let ready_arm = {950 let x_ident = Ident::with_dummy_span(sym::result);951 let (x_pat, x_pat_hid) = self.pat_ident(gen_future_span, x_ident);952 let x_expr = self.expr_ident(gen_future_span, x_ident, x_pat_hid);953 let ready_field = self.single_pat_field(gen_future_span, x_pat);954 let ready_pat = self.pat_lang_item_variant(span, hir::LangItem::PollReady, ready_field);955 let break_x = self.with_loop_scope(loop_hir_id, move |this| {956 let expr_break =957 hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr));958 this.arena.alloc(this.expr(gen_future_span, expr_break))959 });960 self.arm(ready_pat, break_x, span)961 };962963 // `::std::task::Poll::Pending => {}`964 let pending_arm = {965 let pending_pat = self.pat_lang_item_variant(span, hir::LangItem::PollPending, &[]);966 let empty_block = self.expr_block_empty(span);967 self.arm(pending_pat, empty_block, span)968 };969970 let inner_match_stmt = {971 let match_expr = self.expr_match(972 span,973 poll_expr,974 arena_vec![self; ready_arm, pending_arm],975 hir::MatchSource::AwaitDesugar,976 );977 self.stmt_expr(span, match_expr)978 };979980 // Depending on `async` of `async gen`:981 // async - task_context = yield ();982 // async gen - task_context = yield ASYNC_GEN_PENDING;983 let yield_stmt = {984 let yielded = if is_async_gen {985 self.arena.alloc(self.expr_lang_item_path(span, hir::LangItem::AsyncGenPending))986 } else {987 self.expr_unit(span)988 };989990 let yield_expr = self.expr(991 span,992 hir::ExprKind::Yield(yielded, hir::YieldSource::Await { expr: Some(expr_hir_id) }),993 );994 let yield_expr = self.arena.alloc(yield_expr);995996 let Some(task_context_hid) = self.task_context else {997 unreachable!("use of `await` outside of an async context.");998 };9991000 let lhs = self.expr_ident(span, task_context_ident, task_context_hid);1001 let assign =1002 self.expr(span, hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span)));1003 self.stmt_expr(span, assign)1004 };10051006 let loop_block = self.block_all(span, arena_vec![self; inner_match_stmt, yield_stmt], None);10071008 // loop { .. }1009 let loop_expr = self.arena.alloc(hir::Expr {1010 hir_id: loop_hir_id,1011 kind: hir::ExprKind::Loop(1012 loop_block,1013 None,1014 hir::LoopSource::Loop,1015 self.lower_span(span),1016 ),1017 span: self.lower_span(span),1018 });10191020 // mut __awaitee => loop { ... }1021 let awaitee_arm = self.arm(awaitee_pat, loop_expr, span);10221023 // `match ::std::future::IntoFuture::into_future(<expr>) { ... }`1024 let into_future_expr = match await_kind {1025 FutureKind::Future => self.expr_call_lang_item_fn(1026 span,1027 hir::LangItem::IntoFutureIntoFuture,1028 arena_vec![self; *expr],1029 ),1030 // Not needed for `for await` because we expect to have already called1031 // `IntoAsyncIterator::into_async_iter` on it.1032 FutureKind::AsyncIterator => expr,1033 };10341035 // match <into_future_expr> {1036 // mut __awaitee => loop { .. }1037 // }1038 hir::ExprKind::Match(1039 into_future_expr,1040 arena_vec![self; awaitee_arm],1041 hir::MatchSource::AwaitDesugar,1042 )1043 }10441045 fn lower_expr_use(&mut self, use_kw_span: Span, expr: &Expr) -> hir::ExprKind<'hir> {1046 hir::ExprKind::Use(self.lower_expr(expr), self.lower_span(use_kw_span))1047 }10481049 fn lower_expr_closure(1050 &mut self,1051 attrs: &[rustc_hir::Attribute],1052 binder: &ClosureBinder,1053 capture_clause: CaptureBy,1054 closure_id: NodeId,1055 constness: Const,1056 movability: Movability,1057 decl: &FnDecl,1058 body: &Expr,1059 fn_decl_span: Span,1060 fn_arg_span: Span,1061 ) -> hir::ExprKind<'hir> {1062 let closure_def_id = self.local_def_id(closure_id);1063 let (binder_clause, generic_params) = self.lower_closure_binder(binder);10641065 let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| {1066 let mut coroutine_kind =1067 find_attr!(attrs, Coroutine => hir::CoroutineKind::Coroutine(Movability::Movable));10681069 // FIXME(contracts): Support contracts on closures?1070 let body_id = this.lower_fn_body(decl, None, |this| {1071 this.coroutine_kind = coroutine_kind;1072 let e = this.lower_expr_mut(body);1073 coroutine_kind = this.coroutine_kind;1074 e1075 });1076 let coroutine_option =1077 this.closure_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability);1078 (body_id, coroutine_option)1079 });10801081 let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);1082 // Lower outside new scope to preserve `is_in_loop_condition`.1083 let fn_decl = self.lower_fn_decl(decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);10841085 let c = self.arena.alloc(hir::Closure {1086 def_id: closure_def_id,1087 binder: binder_clause,1088 capture_clause: self.lower_capture_clause(capture_clause),1089 bound_generic_params,1090 fn_decl,1091 body: body_id,1092 fn_decl_span: self.lower_span(fn_decl_span),1093 fn_arg_span: Some(self.lower_span(fn_arg_span)),1094 kind: closure_kind,1095 constness: self.lower_constness(constness),1096 });10971098 hir::ExprKind::Closure(c)1099 }11001101 fn closure_movability_for_fn(1102 &mut self,1103 decl: &FnDecl,1104 fn_decl_span: Span,1105 coroutine_kind: Option<hir::CoroutineKind>,1106 movability: Movability,1107 ) -> hir::ClosureKind {1108 match coroutine_kind {1109 Some(hir::CoroutineKind::Coroutine(_)) => {1110 if decl.inputs.len() > 1 {1111 self.dcx().emit_err(CoroutineTooManyParameters { fn_decl_span });1112 }1113 hir::ClosureKind::Coroutine(hir::CoroutineKind::Coroutine(movability))1114 }1115 Some(1116 hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)1117 | hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)1118 | hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _),1119 ) => {1120 panic!("non-`async`/`gen` closure body turned `async`/`gen` during lowering");1121 }1122 None => {1123 if movability == Movability::Static {1124 self.dcx().emit_err(ClosureCannotBeStatic { fn_decl_span });1125 }1126 hir::ClosureKind::Closure1127 }1128 }1129 }11301131 fn lower_closure_binder<'c>(1132 &mut self,1133 binder: &'c ClosureBinder,1134 ) -> (hir::ClosureBinder, &'c [GenericParam]) {1135 let (binder, params) = match binder {1136 ClosureBinder::NotPresent => (hir::ClosureBinder::Default, &[][..]),1137 ClosureBinder::For { span, generic_params } => {1138 let span = self.lower_span(*span);1139 (hir::ClosureBinder::For { span }, &**generic_params)1140 }1141 };11421143 (binder, params)1144 }11451146 fn lower_expr_coroutine_closure(1147 &mut self,1148 binder: &ClosureBinder,1149 capture_clause: CaptureBy,1150 closure_id: NodeId,1151 closure_hir_id: HirId,1152 coroutine_kind: CoroutineKind,1153 constness: Const,1154 decl: &FnDecl,1155 body: &Expr,1156 fn_decl_span: Span,1157 fn_arg_span: Span,1158 ) -> hir::ExprKind<'hir> {1159 let closure_def_id = self.local_def_id(closure_id);1160 let (binder_clause, generic_params) = self.lower_closure_binder(binder);11611162 let coroutine_desugaring = match coroutine_kind {1163 CoroutineKind::Async { .. } => hir::CoroutineDesugaring::Async,1164 CoroutineKind::Gen { .. } => hir::CoroutineDesugaring::Gen,1165 CoroutineKind::AsyncGen { span, .. } => {1166 span_bug!(span, "only async closures and `iter!` closures are supported currently")1167 }1168 };11691170 let body = self.with_new_scopes(fn_decl_span, |this| {1171 let inner_decl =1172 FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };11731174 // Transform `async |x: u8| -> X { ... }` into1175 // `|x: u8| || -> X { ... }`.1176 let body_id = this.lower_body(|this| {1177 let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(1178 &inner_decl,1179 |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),1180 fn_decl_span,1181 body.span,1182 coroutine_kind,1183 hir::CoroutineSource::Closure,1184 );11851186 this.maybe_forward_track_caller(body.span, closure_hir_id, expr.hir_id);11871188 (parameters, expr)1189 });1190 body_id1191 });11921193 let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);1194 // We need to lower the declaration outside the new scope, because we1195 // have to conserve the state of being inside a loop condition for the1196 // closure argument types.1197 let fn_decl =1198 self.lower_fn_decl(&decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);11991200 if let Const::Yes(span) = constness {1201 self.dcx().span_err(span, "const coroutines are not supported");1202 }12031204 let c = self.arena.alloc(hir::Closure {1205 def_id: closure_def_id,1206 binder: binder_clause,1207 capture_clause: self.lower_capture_clause(capture_clause),1208 bound_generic_params,1209 fn_decl,1210 body,1211 fn_decl_span: self.lower_span(fn_decl_span),1212 fn_arg_span: Some(self.lower_span(fn_arg_span)),1213 // Lower this as a `CoroutineClosure`. That will ensure that HIR typeck1214 // knows that a `FnDecl` output type like `-> &str` actually means1215 // "coroutine that returns &str", rather than directly returning a `&str`.1216 kind: hir::ClosureKind::CoroutineClosure(coroutine_desugaring),1217 constness: self.lower_constness(constness),1218 });1219 hir::ExprKind::Closure(c)1220 }12211222 /// Destructure the LHS of complex assignments.1223 /// For instance, lower `(a, b) = t` to `{ let (lhs1, lhs2) = t; a = lhs1; b = lhs2; }`.1224 fn lower_expr_assign(1225 &mut self,1226 lhs: &Expr,1227 rhs: &Expr,1228 eq_sign_span: Span,1229 whole_span: Span,1230 ) -> hir::ExprKind<'hir> {1231 // Return early in case of an ordinary assignment.1232 fn is_ordinary(lower_ctx: &mut LoweringContext<'_, '_>, lhs: &Expr) -> bool {1233 match &lhs.kind {1234 ExprKind::Array(..)1235 | ExprKind::Struct(..)1236 | ExprKind::Tup(..)1237 | ExprKind::Underscore => false,1238 // Check for unit struct constructor.1239 ExprKind::Path(..) => lower_ctx.extract_unit_struct_path(lhs).is_none(),1240 // Check for tuple struct constructor.1241 ExprKind::Call(callee, ..) => lower_ctx.extract_tuple_struct_path(callee).is_none(),1242 ExprKind::Paren(e) => {1243 match e.kind {1244 // We special-case `(..)` for consistency with patterns.1245 ExprKind::Range(None, None, RangeLimits::HalfOpen) => false,1246 _ => is_ordinary(lower_ctx, e),1247 }1248 }1249 _ => true,1250 }1251 }1252 if is_ordinary(self, lhs) {1253 return hir::ExprKind::Assign(1254 self.lower_expr(lhs),1255 self.lower_expr(rhs),1256 self.lower_span(eq_sign_span),1257 );1258 }12591260 let mut assignments = vec![];12611262 // The LHS becomes a pattern: `(lhs1, lhs2)`.1263 let pat = self.destructure_assign(lhs, eq_sign_span, &mut assignments);1264 let rhs = self.lower_expr(rhs);12651266 // Introduce a `let` for destructuring: `let (lhs1, lhs2) = t`.1267 let destructure_let =1268 self.stmt_let_pat(None, whole_span, Some(rhs), pat, hir::LocalSource::AssignDesugar);12691270 // `a = lhs1; b = lhs2;`.1271 let stmts = self.arena.alloc_from_iter(std::iter::once(destructure_let).chain(assignments));12721273 // Wrap everything in a block.1274 hir::ExprKind::Block(self.block_all(whole_span, stmts, None), None)1275 }12761277 /// If the given expression is a path to a tuple struct, returns that path.1278 /// It is not a complete check, but just tries to reject most paths early1279 /// if they are not tuple structs.1280 /// Type checking will take care of the full validation later.1281 fn extract_tuple_struct_path<'a>(1282 &mut self,1283 expr: &'a Expr,1284 ) -> Option<(&'a Option<Box<QSelf>>, &'a Path)> {1285 if let ExprKind::Path(qself, path) = &expr.kind {1286 // Does the path resolve to something disallowed in a tuple struct/variant pattern?1287 if let Some(partial_res) = self.get_partial_res(expr.id) {1288 if let Some(res) = partial_res.full_res()1289 && !res.expected_in_tuple_struct_pat()1290 {1291 return None;1292 }1293 }1294 return Some((qself, path));1295 }1296 None1297 }12981299 /// If the given expression is a path to a unit struct, returns that path.1300 /// It is not a complete check, but just tries to reject most paths early1301 /// if they are not unit structs.1302 /// Type checking will take care of the full validation later.1303 fn extract_unit_struct_path<'a>(1304 &mut self,1305 expr: &'a Expr,1306 ) -> Option<(&'a Option<Box<QSelf>>, &'a Path)> {1307 if let ExprKind::Path(qself, path) = &expr.kind {1308 // Does the path resolve to something disallowed in a unit struct/variant pattern?1309 if let Some(partial_res) = self.get_partial_res(expr.id) {1310 if let Some(res) = partial_res.full_res()1311 && !res.expected_in_unit_struct_pat()1312 {1313 return None;1314 }1315 }1316 return Some((qself, path));1317 }1318 None1319 }13201321 /// Convert the LHS of a destructuring assignment to a pattern.1322 /// Each sub-assignment is recorded in `assignments`.1323 fn destructure_assign(1324 &mut self,1325 lhs: &Expr,1326 eq_sign_span: Span,1327 assignments: &mut Vec<hir::Stmt<'hir>>,1328 ) -> &'hir hir::Pat<'hir> {1329 self.arena.alloc(self.destructure_assign_mut(lhs, eq_sign_span, assignments))1330 }13311332 fn destructure_assign_mut(1333 &mut self,1334 lhs: &Expr,1335 eq_sign_span: Span,1336 assignments: &mut Vec<hir::Stmt<'hir>>,1337 ) -> hir::Pat<'hir> {1338 match &lhs.kind {1339 // Underscore pattern.1340 ExprKind::Underscore => {1341 return self.pat_without_dbm(lhs.span, hir::PatKind::Wild);1342 }1343 // Slice patterns.1344 ExprKind::Array(elements) => {1345 let (pats, rest) =1346 self.destructure_sequence(elements, "slice", eq_sign_span, assignments);1347 let slice_pat = if let Some((i, span)) = rest {1348 let (before, after) = pats.split_at(i);1349 hir::PatKind::Slice(1350 before,1351 Some(self.arena.alloc(self.pat_without_dbm(span, hir::PatKind::Wild))),1352 after,1353 )1354 } else {1355 hir::PatKind::Slice(pats, None, &[])1356 };1357 return self.pat_without_dbm(lhs.span, slice_pat);1358 }1359 // Tuple structs.1360 ExprKind::Call(callee, args) => {1361 if let Some((qself, path)) = self.extract_tuple_struct_path(callee) {1362 let (pats, rest) = self.destructure_sequence(1363 args,1364 "tuple struct or variant",1365 eq_sign_span,1366 assignments,1367 );1368 let qpath = self.lower_qpath(1369 callee.id,1370 qself,1371 path,1372 ParamMode::Optional,1373 AllowReturnTypeNotation::No,1374 ImplTraitContext::Disallowed(ImplTraitPosition::Path),1375 None,1376 );1377 // Destructure like a tuple struct.1378 let tuple_struct_pat = hir::PatKind::TupleStruct(1379 qpath,1380 pats,1381 hir::DotDotPos::new(rest.map(|r| r.0)),1382 );1383 return self.pat_without_dbm(lhs.span, tuple_struct_pat);1384 }1385 }1386 // Unit structs and enum variants.1387 ExprKind::Path(..) => {1388 if let Some((qself, path)) = self.extract_unit_struct_path(lhs) {1389 let qpath = self.lower_qpath(1390 lhs.id,1391 qself,1392 path,1393 ParamMode::Optional,1394 AllowReturnTypeNotation::No,1395 ImplTraitContext::Disallowed(ImplTraitPosition::Path),1396 None,1397 );1398 // Destructure like a unit struct.1399 let unit_struct_pat = hir::PatKind::Expr(self.arena.alloc(hir::PatExpr {1400 kind: hir::PatExprKind::Path(qpath),1401 hir_id: self.next_id(),1402 span: self.lower_span(lhs.span),1403 }));1404 return self.pat_without_dbm(lhs.span, unit_struct_pat);1405 }1406 }1407 // Structs.1408 ExprKind::Struct(se) => {1409 let field_pats = self.arena.alloc_from_iter(se.fields.iter().map(|f| {1410 let pat = self.destructure_assign(&f.expr, eq_sign_span, assignments);1411 hir::PatField {1412 hir_id: self.next_id(),1413 ident: self.lower_ident(f.ident),1414 pat,1415 is_shorthand: f.is_shorthand,1416 span: self.lower_span(f.span),1417 }1418 }));1419 let qpath = self.lower_qpath(1420 lhs.id,1421 &se.qself,1422 &se.path,1423 ParamMode::Optional,1424 AllowReturnTypeNotation::No,1425 ImplTraitContext::Disallowed(ImplTraitPosition::Path),1426 None,1427 );1428 let fields_omitted = match &se.rest {1429 StructRest::Base(e) => {1430 self.dcx().emit_err(FunctionalRecordUpdateDestructuringAssignment {1431 span: e.span,1432 });1433 Some(self.lower_span(e.span))1434 }1435 StructRest::Rest(span) => Some(self.lower_span(*span)),1436 StructRest::None | StructRest::NoneWithError(_) => None,1437 };1438 let struct_pat = hir::PatKind::Struct(qpath, field_pats, fields_omitted);1439 return self.pat_without_dbm(lhs.span, struct_pat);1440 }1441 // Tuples.1442 ExprKind::Tup(elements) => {1443 let (pats, rest) =1444 self.destructure_sequence(elements, "tuple", eq_sign_span, assignments);1445 let tuple_pat = hir::PatKind::Tuple(pats, hir::DotDotPos::new(rest.map(|r| r.0)));1446 return self.pat_without_dbm(lhs.span, tuple_pat);1447 }1448 ExprKind::Paren(e) => {1449 // We special-case `(..)` for consistency with patterns.1450 if let ExprKind::Range(None, None, RangeLimits::HalfOpen) = e.kind {1451 let tuple_pat = hir::PatKind::Tuple(&[], hir::DotDotPos::new(Some(0)));1452 return self.pat_without_dbm(lhs.span, tuple_pat);1453 } else {1454 return self.destructure_assign_mut(e, eq_sign_span, assignments);1455 }1456 }1457 _ => {}1458 }1459 // Treat all other cases as normal lvalue.1460 let ident = Ident::new(sym::lhs, self.lower_span(lhs.span));1461 let (pat, binding) = self.pat_ident_mut(lhs.span, ident);1462 let ident = self.expr_ident(lhs.span, ident, binding);1463 let assign =1464 hir::ExprKind::Assign(self.lower_expr(lhs), ident, self.lower_span(eq_sign_span));1465 let expr = self.expr(lhs.span, assign);1466 assignments.push(self.stmt_expr(lhs.span, expr));1467 pat1468 }14691470 /// Destructure a sequence of expressions occurring on the LHS of an assignment.1471 /// Such a sequence occurs in a tuple (struct)/slice.1472 /// Return a sequence of corresponding patterns, and the index and the span of `..` if it1473 /// exists.1474 /// Each sub-assignment is recorded in `assignments`.1475 fn destructure_sequence(1476 &mut self,1477 elements: &[Box<Expr>],1478 ctx: &str,1479 eq_sign_span: Span,1480 assignments: &mut Vec<hir::Stmt<'hir>>,1481 ) -> (&'hir [hir::Pat<'hir>], Option<(usize, Span)>) {1482 let mut rest = None;1483 let elements =1484 self.arena.alloc_from_iter(elements.iter().enumerate().filter_map(|(i, e)| {1485 // Check for `..` pattern.1486 if let ExprKind::Range(None, None, RangeLimits::HalfOpen) = e.kind {1487 if let Some((_, prev_span)) = rest {1488 self.ban_extra_rest_pat(e.span, prev_span, ctx);1489 } else {1490 rest = Some((i, e.span));1491 }1492 None1493 } else {1494 Some(self.destructure_assign_mut(e, eq_sign_span, assignments))1495 }1496 }));1497 (elements, rest)1498 }14991500 /// Desugar `<start>..=<end>` into `std::ops::RangeInclusive::new(<start>, <end>)`.1501 fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> {1502 let e1 = self.lower_expr_mut(e1);1503 let e2 = self.lower_expr_mut(e2);1504 let fn_path = self.make_lang_item_qpath(hir::LangItem::RangeInclusiveNew, span, None);1505 let fn_expr = self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path)));1506 hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2])1507 }15081509 fn lower_expr_range(1510 &mut self,1511 span: Span,1512 e1: Option<&Expr>,1513 e2: Option<&Expr>,1514 lims: RangeLimits,1515 ) -> hir::ExprKind<'hir> {1516 use rustc_ast::RangeLimits::*;15171518 let lang_item = match (e1, e2, lims) {1519 (None, None, HalfOpen) => hir::LangItem::RangeFull,1520 (Some(..), None, HalfOpen) => {1521 if self.tcx.features().new_range() {1522 hir::LangItem::RangeFromCopy1523 } else {1524 hir::LangItem::RangeFrom1525 }1526 }1527 (None, Some(..), HalfOpen) => hir::LangItem::RangeTo,1528 (Some(..), Some(..), HalfOpen) => {1529 if self.tcx.features().new_range() {1530 hir::LangItem::RangeCopy1531 } else {1532 hir::LangItem::Range1533 }1534 }1535 (None, Some(..), Closed) => {1536 if self.tcx.features().new_range() {1537 hir::LangItem::RangeToInclusiveCopy1538 } else {1539 hir::LangItem::RangeToInclusive1540 }1541 }1542 (Some(e1), Some(e2), Closed) => {1543 if self.tcx.features().new_range() {1544 hir::LangItem::RangeInclusiveCopy1545 } else {1546 return self.lower_expr_range_closed(span, e1, e2);1547 }1548 }1549 (start, None, Closed) => {1550 self.dcx().emit_err(InclusiveRangeWithNoEnd { span });1551 match start {1552 Some(..) => {1553 if self.tcx.features().new_range() {1554 hir::LangItem::RangeFromCopy1555 } else {1556 hir::LangItem::RangeFrom1557 }1558 }1559 None => hir::LangItem::RangeFull,1560 }1561 }1562 };15631564 let fields = self.arena.alloc_from_iter(1565 e1.iter()1566 .map(|e| (sym::start, e))1567 .chain(e2.iter().map(|e| {1568 (1569 if matches!(1570 lang_item,1571 hir::LangItem::RangeInclusiveCopy | hir::LangItem::RangeToInclusiveCopy1572 ) {1573 sym::last1574 } else {1575 sym::end1576 },1577 e,1578 )1579 }))1580 .map(|(s, e)| {1581 let span = self.lower_span(e.span);1582 let span = self.mark_span_with_reason(DesugaringKind::RangeExpr, span, None);1583 let expr = self.lower_expr(e);1584 let ident = Ident::new(s, span);1585 self.expr_field(ident, expr, span)1586 }),1587 );15881589 hir::ExprKind::Struct(1590 self.arena.alloc(self.make_lang_item_qpath(lang_item, span, None)),1591 fields,1592 hir::StructTailExpr::None,1593 )1594 }15951596 // Record labelled expr's HirId so that we can retrieve it in `lower_jump_destination` without1597 // lowering node id again.1598 fn lower_label(1599 &mut self,1600 opt_label: Option<Label>,1601 dest_id: NodeId,1602 dest_hir_id: hir::HirId,1603 ) -> Option<Label> {1604 let label = opt_label?;1605 self.ident_and_label_to_local_id.insert(dest_id, dest_hir_id.local_id);1606 Some(Label { ident: self.lower_ident(label.ident) })1607 }16081609 fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hir::Destination {1610 let target_id = match destination {1611 Some((id, _)) => {1612 if let Some(loop_id) = self.resolver.get_label_res(id) {1613 let local_id = self.ident_and_label_to_local_id[&loop_id];1614 let loop_hir_id = HirId { owner: self.current_hir_id_owner, local_id };1615 Ok(loop_hir_id)1616 } else {1617 Err(hir::LoopIdError::UnresolvedLabel)1618 }1619 }1620 None => {1621 self.loop_scope.map(|id| Ok(id)).unwrap_or(Err(hir::LoopIdError::OutsideLoopScope))1622 }1623 };1624 let label = destination1625 .map(|(_, label)| label)1626 .map(|label| Label { ident: self.lower_ident(label.ident) });1627 hir::Destination { label, target_id }1628 }16291630 fn lower_jump_destination(&mut self, id: NodeId, opt_label: Option<Label>) -> hir::Destination {1631 if self.is_in_loop_condition && opt_label.is_none() {1632 hir::Destination {1633 label: None,1634 target_id: Err(hir::LoopIdError::UnlabeledCfInWhileCondition),1635 }1636 } else {1637 self.lower_loop_destination(opt_label.map(|label| (id, label)))1638 }1639 }16401641 fn with_try_block_scope<T>(1642 &mut self,1643 scope: TryBlockScope,1644 f: impl FnOnce(&mut Self) -> T,1645 ) -> T {1646 let old_scope = mem::replace(&mut self.try_block_scope, scope);1647 let result = f(self);1648 self.try_block_scope = old_scope;1649 result1650 }16511652 fn with_loop_scope<T>(&mut self, loop_id: hir::HirId, f: impl FnOnce(&mut Self) -> T) -> T {1653 // We're no longer in the base loop's condition; we're in another loop.1654 let was_in_loop_condition = self.is_in_loop_condition;1655 self.is_in_loop_condition = false;16561657 let old_scope = self.loop_scope.replace(loop_id);1658 let result = f(self);1659 self.loop_scope = old_scope;16601661 self.is_in_loop_condition = was_in_loop_condition;16621663 result1664 }16651666 fn with_loop_condition_scope<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {1667 let was_in_loop_condition = self.is_in_loop_condition;1668 self.is_in_loop_condition = true;16691670 let result = f(self);16711672 self.is_in_loop_condition = was_in_loop_condition;16731674 result1675 }16761677 fn lower_expr_field(&mut self, f: &ExprField) -> hir::ExprField<'hir> {1678 let hir_id = self.lower_node_id(f.id);1679 self.lower_attrs(hir_id, &f.attrs, f.span, Target::ExprField);1680 hir::ExprField {1681 hir_id,1682 ident: self.lower_ident(f.ident),1683 expr: self.lower_expr(&f.expr),1684 span: self.lower_span(f.span),1685 is_shorthand: f.is_shorthand,1686 }1687 }16881689 fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> {1690 let yielded =1691 opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span));16921693 if !self.tcx.features().yield_expr()1694 && !self.tcx.features().coroutines()1695 && !self.tcx.features().gen_blocks()1696 {1697 rustc_session::errors::feature_err(1698 &self.tcx.sess,1699 sym::yield_expr,1700 span,1701 msg!("yield syntax is experimental"),1702 )1703 .emit();1704 }17051706 let is_async_gen = match self.coroutine_kind {1707 Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) => false,1708 Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => true,1709 Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => {1710 // Lower to a block `{ EXPR; <error> }` so that the awaited expr1711 // is not accidentally orphaned.1712 let stmt_id = self.next_id();1713 let expr_err = self.expr(1714 yielded.span,1715 hir::ExprKind::Err(self.dcx().emit_err(AsyncCoroutinesNotSupported { span })),1716 );1717 return hir::ExprKind::Block(1718 self.block_all(1719 yielded.span,1720 arena_vec![self; hir::Stmt {1721 hir_id: stmt_id,1722 kind: hir::StmtKind::Semi(yielded),1723 span: yielded.span,1724 }],1725 Some(self.arena.alloc(expr_err)),1726 ),1727 None,1728 );1729 }1730 Some(hir::CoroutineKind::Coroutine(_)) => false,1731 None => {1732 let suggestion = self.current_item.map(|s| s.shrink_to_lo());1733 self.dcx().emit_err(YieldInClosure { span, suggestion });1734 self.coroutine_kind = Some(hir::CoroutineKind::Coroutine(Movability::Movable));17351736 false1737 }1738 };17391740 if is_async_gen {1741 // `yield $expr` is transformed into `task_context = yield async_gen_ready($expr)`.1742 // This ensures that we store our resumed `ResumeContext` correctly, and also that1743 // the apparent value of the `yield` expression is `()`.1744 let desugar_span = self.mark_span_with_reason(1745 DesugaringKind::Async,1746 span,1747 Some(Arc::clone(&self.allow_async_gen)),1748 );1749 let wrapped_yielded = self.expr_call_lang_item_fn(1750 desugar_span,1751 hir::LangItem::AsyncGenReady,1752 std::slice::from_ref(yielded),1753 );1754 let yield_expr = self.arena.alloc(1755 self.expr(span, hir::ExprKind::Yield(wrapped_yielded, hir::YieldSource::Yield)),1756 );17571758 let Some(task_context_hid) = self.task_context else {1759 unreachable!("use of `await` outside of an async context.");1760 };1761 let task_context_ident = Ident::with_dummy_span(sym::_task_context);1762 let lhs = self.expr_ident(desugar_span, task_context_ident, task_context_hid);17631764 hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span))1765 } else {1766 hir::ExprKind::Yield(yielded, hir::YieldSource::Yield)1767 }1768 }17691770 /// Desugar `ExprForLoop` from: `[opt_ident]: for <pat> in <head> <body>` into:1771 /// ```ignore (pseudo-rust)1772 /// {1773 /// let result = match IntoIterator::into_iter(<head>) {1774 /// mut iter => {1775 /// [opt_ident]: loop {1776 /// match Iterator::next(&mut iter) {1777 /// None => break,1778 /// Some(<pat>) => <body>,1779 /// };1780 /// }1781 /// }1782 /// };1783 /// result1784 /// }1785 /// ```1786 fn lower_expr_for(1787 &mut self,1788 e: &Expr,1789 pat: &Pat,1790 head: &Expr,1791 body: &Block,1792 opt_label: Option<Label>,1793 loop_kind: ForLoopKind,1794 ) -> hir::Expr<'hir> {1795 let head = self.lower_expr_mut(head);1796 let pat = self.lower_pat(pat);1797 let for_span =1798 self.mark_span_with_reason(DesugaringKind::ForLoop, self.lower_span(e.span), None);1799 let for_ctxt = for_span.ctxt();18001801 // Try to point both the head and pat spans to their position in the for loop1802 // rather than inside a macro.1803 let head_span =1804 head.span.find_ancestor_in_same_ctxt(e.span).unwrap_or(head.span).with_ctxt(for_ctxt);1805 let pat_span =1806 pat.span.find_ancestor_in_same_ctxt(e.span).unwrap_or(pat.span).with_ctxt(for_ctxt);18071808 let loop_hir_id = self.lower_node_id(e.id);1809 let label = self.lower_label(opt_label, e.id, loop_hir_id);18101811 // `None => break`1812 let none_arm = {1813 let break_expr =1814 self.with_loop_scope(loop_hir_id, |this| this.expr_break_alloc(for_span));1815 let pat = self.pat_none(for_span);1816 self.arm(pat, break_expr, for_span)1817 };18181819 // Some(<pat>) => <body>,1820 let some_arm = {1821 let some_pat = self.pat_some(pat_span, pat);1822 let body_block =1823 self.with_loop_scope(loop_hir_id, |this| this.lower_block(body, false));1824 let body_expr = self.arena.alloc(self.expr_block(body_block));1825 self.arm(some_pat, body_expr, for_span)1826 };18271828 // `mut iter`1829 let iter = Ident::with_dummy_span(sym::iter);1830 let (iter_pat, iter_pat_nid) =1831 self.pat_ident_binding_mode(head_span, iter, hir::BindingMode::MUT);18321833 let match_expr = {1834 let iter = self.expr_ident(head_span, iter, iter_pat_nid);1835 let next_expr = match loop_kind {1836 ForLoopKind::For => {1837 // `Iterator::next(&mut iter)`1838 let ref_mut_iter = self.expr_mut_addr_of(head_span, iter);1839 self.expr_call_lang_item_fn(1840 head_span,1841 hir::LangItem::IteratorNext,1842 arena_vec![self; ref_mut_iter],1843 )1844 }1845 ForLoopKind::ForAwait => {1846 // we'll generate `unsafe { Pin::new_unchecked(&mut iter) })` and then pass this1847 // to make_lowered_await with `FutureKind::AsyncIterator` which will generator1848 // calls to `poll_next`. In user code, this would probably be a call to1849 // `Pin::as_mut` but here it's easy enough to do `new_unchecked`.18501851 // `&mut iter`1852 let iter = self.expr_mut_addr_of(head_span, iter);1853 // `Pin::new_unchecked(...)`1854 let iter = self.arena.alloc(self.expr_call_lang_item_fn_mut(1855 head_span,1856 hir::LangItem::PinNewUnchecked,1857 arena_vec![self; iter],1858 ));1859 // `unsafe { ... }`1860 let iter = self.arena.alloc(self.expr_unsafe(head_span, iter));1861 let kind = self.make_lowered_await(head_span, iter, FutureKind::AsyncIterator);1862 self.arena.alloc(hir::Expr { hir_id: self.next_id(), kind, span: head_span })1863 }1864 };1865 let arms = arena_vec![self; none_arm, some_arm];18661867 // `match $next_expr { ... }`1868 self.expr_match(head_span, next_expr, arms, hir::MatchSource::ForLoopDesugar)1869 };1870 let match_stmt = self.stmt_expr(for_span, match_expr);18711872 let loop_block = self.block_all(for_span, arena_vec![self; match_stmt], None);18731874 // `[opt_ident]: loop { ... }`1875 let kind = hir::ExprKind::Loop(1876 loop_block,1877 label,1878 hir::LoopSource::ForLoop,1879 self.lower_span(for_span.with_hi(head.span.hi())),1880 );1881 let loop_expr = self.arena.alloc(hir::Expr { hir_id: loop_hir_id, kind, span: for_span });18821883 // `mut iter => { ... }`1884 let iter_arm = self.arm(iter_pat, loop_expr, for_span);18851886 let match_expr = match loop_kind {1887 ForLoopKind::For => {1888 // `::std::iter::IntoIterator::into_iter(<head>)`1889 let into_iter_expr = self.expr_call_lang_item_fn(1890 head_span,1891 hir::LangItem::IntoIterIntoIter,1892 arena_vec![self; head],1893 );18941895 self.arena.alloc(self.expr_match(1896 for_span,1897 into_iter_expr,1898 arena_vec![self; iter_arm],1899 hir::MatchSource::ForLoopDesugar,1900 ))1901 }1902 // `match into_async_iter(<head>) { ref mut iter => match unsafe { Pin::new_unchecked(iter) } { ... } }`1903 ForLoopKind::ForAwait => {1904 let iter_ident = iter;1905 let (async_iter_pat, async_iter_pat_id) =1906 self.pat_ident_binding_mode(head_span, iter_ident, hir::BindingMode::REF_MUT);1907 let iter = self.expr_ident_mut(head_span, iter_ident, async_iter_pat_id);1908 // `Pin::new_unchecked(...)`1909 let iter = self.arena.alloc(self.expr_call_lang_item_fn_mut(1910 head_span,1911 hir::LangItem::PinNewUnchecked,1912 arena_vec![self; iter],1913 ));1914 // `unsafe { ... }`1915 let iter = self.arena.alloc(self.expr_unsafe(head_span, iter));1916 let inner_match_expr = self.arena.alloc(self.expr_match(1917 for_span,1918 iter,1919 arena_vec![self; iter_arm],1920 hir::MatchSource::ForLoopDesugar,1921 ));19221923 // `::core::async_iter::IntoAsyncIterator::into_async_iter(<head>)`1924 let iter = self.expr_call_lang_item_fn(1925 head_span,1926 hir::LangItem::IntoAsyncIterIntoIter,1927 arena_vec![self; head],1928 );1929 let iter_arm = self.arm(async_iter_pat, inner_match_expr, for_span);1930 self.arena.alloc(self.expr_match(1931 for_span,1932 iter,1933 arena_vec![self; iter_arm],1934 hir::MatchSource::ForLoopDesugar,1935 ))1936 }1937 };19381939 // This is effectively `{ let _result = ...; _result }`.1940 // The construct was introduced in #21984 and is necessary to make sure that1941 // temporaries in the `head` expression are dropped and do not leak to the1942 // surrounding scope of the `match` since the `match` is not a terminating scope.1943 //1944 // Also, add the attributes to the outer returned expr node.1945 let expr = self.expr_drop_temps_mut(for_span, match_expr);1946 self.lower_attrs(expr.hir_id, &e.attrs, e.span, Target::from_expr(e));1947 expr1948 }19491950 /// Desugar `ExprKind::Try` from: `<expr>?` into:1951 /// ```ignore (pseudo-rust)1952 /// match Try::branch(<expr>) {1953 /// ControlFlow::Continue(val) => #[allow(unreachable_code)] val,,1954 /// ControlFlow::Break(residual) =>1955 /// #[allow(unreachable_code)]1956 /// // If there is an enclosing `try {...}`:1957 /// break 'catch_target Residual::into_try_type(residual),1958 /// // Otherwise:1959 /// return Try::from_residual(residual),1960 /// }1961 /// ```1962 fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir> {1963 let unstable_span = self.mark_span_with_reason(1964 DesugaringKind::QuestionMark,1965 span,1966 Some(Arc::clone(&self.allow_try_trait)),1967 );1968 let try_span = self.tcx.sess.source_map().end_point(span);1969 let try_span = self.mark_span_with_reason(1970 DesugaringKind::QuestionMark,1971 try_span,1972 Some(Arc::clone(&self.allow_try_trait)),1973 );19741975 // `Try::branch(<expr>)`1976 let scrutinee = {1977 // expand <expr>1978 let sub_expr = self.lower_expr_mut(sub_expr);19791980 self.expr_call_lang_item_fn(1981 unstable_span,1982 hir::LangItem::TryTraitBranch,1983 arena_vec![self; sub_expr],1984 )1985 };19861987 let attrs: AttrVec = thin_vec![self.unreachable_code_attr(try_span)];19881989 // `ControlFlow::Continue(val) => #[allow(unreachable_code)] val,`1990 let continue_arm = {1991 let val_ident = Ident::with_dummy_span(sym::val);1992 let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident);1993 let val_expr = self.expr_ident(span, val_ident, val_pat_nid);1994 self.lower_attrs(val_expr.hir_id, &attrs, span, Target::Expression);1995 let continue_pat = self.pat_cf_continue(unstable_span, val_pat);1996 self.arm(continue_pat, val_expr, try_span)1997 };19981999 // `ControlFlow::Break(residual) =>2000 // #[allow(unreachable_code)]