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