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