1 use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs}
;
4 use rustc_ast
::ptr
::P
as AstP
;
6 use rustc_data_structures
::fx
::FxHashMap
;
7 use rustc_data_structures
::stack
::ensure_sufficient_stack
;
8 use rustc_data_structures
::thin_vec
::ThinVec
;
9 use rustc_errors
::struct_span_err
;
11 use rustc_hir
::def
::Res
;
12 use rustc_span
::hygiene
::ForLoopLoc
;
13 use rustc_span
::source_map
::{respan, DesugaringKind, Span, Spanned}
;
14 use rustc_span
::symbol
::{sym, Ident, Symbol}
;
15 use rustc_target
::asm
;
16 use std
::collections
::hash_map
::Entry
;
19 impl<'hir
> LoweringContext
<'_
, 'hir
> {
20 fn lower_exprs(&mut self, exprs
: &[AstP
<Expr
>]) -> &'hir
[hir
::Expr
<'hir
>] {
21 self.arena
.alloc_from_iter(exprs
.iter().map(|x
| self.lower_expr_mut(x
)))
24 pub(super) fn lower_expr(&mut self, e
: &Expr
) -> &'hir hir
::Expr
<'hir
> {
25 self.arena
.alloc(self.lower_expr_mut(e
))
28 pub(super) fn lower_expr_mut(&mut self, e
: &Expr
) -> hir
::Expr
<'hir
> {
29 ensure_sufficient_stack(|| {
30 let kind
= match e
.kind
{
31 ExprKind
::Box(ref inner
) => hir
::ExprKind
::Box(self.lower_expr(inner
)),
32 ExprKind
::Array(ref exprs
) => hir
::ExprKind
::Array(self.lower_exprs(exprs
)),
33 ExprKind
::Repeat(ref expr
, ref count
) => {
34 let expr
= self.lower_expr(expr
);
35 let count
= self.lower_anon_const(count
);
36 hir
::ExprKind
::Repeat(expr
, count
)
38 ExprKind
::Tup(ref elts
) => hir
::ExprKind
::Tup(self.lower_exprs(elts
)),
39 ExprKind
::Call(ref f
, ref args
) => {
40 let f
= self.lower_expr(f
);
41 hir
::ExprKind
::Call(f
, self.lower_exprs(args
))
43 ExprKind
::MethodCall(ref seg
, ref args
, span
) => {
44 let hir_seg
= self.arena
.alloc(self.lower_path_segment(
49 ParenthesizedGenericArgs
::Err
,
50 ImplTraitContext
::disallowed(),
53 let args
= self.lower_exprs(args
);
54 hir
::ExprKind
::MethodCall(hir_seg
, seg
.ident
.span
, args
, span
)
56 ExprKind
::Binary(binop
, ref lhs
, ref rhs
) => {
57 let binop
= self.lower_binop(binop
);
58 let lhs
= self.lower_expr(lhs
);
59 let rhs
= self.lower_expr(rhs
);
60 hir
::ExprKind
::Binary(binop
, lhs
, rhs
)
62 ExprKind
::Unary(op
, ref ohs
) => {
63 let op
= self.lower_unop(op
);
64 let ohs
= self.lower_expr(ohs
);
65 hir
::ExprKind
::Unary(op
, ohs
)
67 ExprKind
::Lit(ref l
) => hir
::ExprKind
::Lit(respan(l
.span
, l
.kind
.clone())),
68 ExprKind
::Cast(ref expr
, ref ty
) => {
69 let expr
= self.lower_expr(expr
);
70 let ty
= self.lower_ty(ty
, ImplTraitContext
::disallowed());
71 hir
::ExprKind
::Cast(expr
, ty
)
73 ExprKind
::Type(ref expr
, ref ty
) => {
74 let expr
= self.lower_expr(expr
);
75 let ty
= self.lower_ty(ty
, ImplTraitContext
::disallowed());
76 hir
::ExprKind
::Type(expr
, ty
)
78 ExprKind
::AddrOf(k
, m
, ref ohs
) => {
79 let ohs
= self.lower_expr(ohs
);
80 hir
::ExprKind
::AddrOf(k
, m
, ohs
)
82 ExprKind
::Let(ref pat
, ref scrutinee
) => {
83 self.lower_expr_let(e
.span
, pat
, scrutinee
)
85 ExprKind
::If(ref cond
, ref then
, ref else_opt
) => {
86 self.lower_expr_if(e
.span
, cond
, then
, else_opt
.as_deref())
88 ExprKind
::While(ref cond
, ref body
, opt_label
) => self
89 .with_loop_scope(e
.id
, |this
| {
90 this
.lower_expr_while_in_loop_scope(e
.span
, cond
, body
, opt_label
)
92 ExprKind
::Loop(ref body
, opt_label
) => self.with_loop_scope(e
.id
, |this
| {
94 this
.lower_block(body
, false),
96 hir
::LoopSource
::Loop
,
99 ExprKind
::TryBlock(ref body
) => self.lower_expr_try_block(body
),
100 ExprKind
::Match(ref expr
, ref arms
) => hir
::ExprKind
::Match(
101 self.lower_expr(expr
),
102 self.arena
.alloc_from_iter(arms
.iter().map(|x
| self.lower_arm(x
))),
103 hir
::MatchSource
::Normal
,
105 ExprKind
::Async(capture_clause
, closure_node_id
, ref block
) => self
111 hir
::AsyncGeneratorKind
::Block
,
112 |this
| this
.with_new_scopes(|this
| this
.lower_block_expr(block
)),
114 ExprKind
::Await(ref expr
) => self.lower_expr_await(e
.span
, expr
),
123 if let Async
::Yes { closure_id, .. }
= asyncness
{
124 self.lower_expr_async_closure(
132 self.lower_expr_closure(
141 ExprKind
::Block(ref blk
, opt_label
) => {
142 hir
::ExprKind
::Block(self.lower_block(blk
, opt_label
.is_some()), opt_label
)
144 ExprKind
::Assign(ref el
, ref er
, span
) => {
145 hir
::ExprKind
::Assign(self.lower_expr(el
), self.lower_expr(er
), span
)
147 ExprKind
::AssignOp(op
, ref el
, ref er
) => hir
::ExprKind
::AssignOp(
148 self.lower_binop(op
),
152 ExprKind
::Field(ref el
, ident
) => hir
::ExprKind
::Field(self.lower_expr(el
), ident
),
153 ExprKind
::Index(ref el
, ref er
) => {
154 hir
::ExprKind
::Index(self.lower_expr(el
), self.lower_expr(er
))
156 ExprKind
::Range(Some(ref e1
), Some(ref e2
), RangeLimits
::Closed
) => {
157 self.lower_expr_range_closed(e
.span
, e1
, e2
)
159 ExprKind
::Range(ref e1
, ref e2
, lims
) => {
160 self.lower_expr_range(e
.span
, e1
.as_deref(), e2
.as_deref(), lims
)
162 ExprKind
::Path(ref qself
, ref path
) => {
163 let qpath
= self.lower_qpath(
168 ImplTraitContext
::disallowed(),
170 hir
::ExprKind
::Path(qpath
)
172 ExprKind
::Break(opt_label
, ref opt_expr
) => {
173 let opt_expr
= opt_expr
.as_ref().map(|x
| self.lower_expr(x
));
174 hir
::ExprKind
::Break(self.lower_jump_destination(e
.id
, opt_label
), opt_expr
)
176 ExprKind
::Continue(opt_label
) => {
177 hir
::ExprKind
::Continue(self.lower_jump_destination(e
.id
, opt_label
))
179 ExprKind
::Ret(ref e
) => {
180 let e
= e
.as_ref().map(|x
| self.lower_expr(x
));
181 hir
::ExprKind
::Ret(e
)
183 ExprKind
::InlineAsm(ref asm
) => self.lower_expr_asm(e
.span
, asm
),
184 ExprKind
::LlvmInlineAsm(ref asm
) => self.lower_expr_llvm_asm(asm
),
185 ExprKind
::Struct(ref path
, ref fields
, ref maybe_expr
) => {
186 let maybe_expr
= maybe_expr
.as_ref().map(|x
| self.lower_expr(x
));
187 hir
::ExprKind
::Struct(
188 self.arena
.alloc(self.lower_qpath(
193 ImplTraitContext
::disallowed(),
195 self.arena
.alloc_from_iter(fields
.iter().map(|x
| self.lower_field(x
))),
199 ExprKind
::Yield(ref opt_expr
) => self.lower_expr_yield(e
.span
, opt_expr
.as_deref()),
200 ExprKind
::Err
=> hir
::ExprKind
::Err
,
201 ExprKind
::Try(ref sub_expr
) => self.lower_expr_try(e
.span
, sub_expr
),
202 ExprKind
::Paren(ref ex
) => {
203 let mut ex
= self.lower_expr_mut(ex
);
204 // Include parens in span, but only if it is a super-span.
205 if e
.span
.contains(ex
.span
) {
208 // Merge attributes into the inner expression.
209 let mut attrs
= e
.attrs
.clone();
210 attrs
.extend
::<Vec
<_
>>(ex
.attrs
.into());
215 // Desugar `ExprForLoop`
216 // from: `[opt_ident]: for <pat> in <head> <body>`
217 ExprKind
::ForLoop(ref pat
, ref head
, ref body
, opt_label
) => {
218 return self.lower_expr_for(e
, pat
, head
, body
, opt_label
);
220 ExprKind
::MacCall(_
) => panic
!("{:?} shouldn't exist here", e
.span
),
224 hir_id
: self.lower_node_id(e
.id
),
227 attrs
: e
.attrs
.iter().map(|a
| self.lower_attr(a
)).collect
::<Vec
<_
>>().into(),
232 fn lower_unop(&mut self, u
: UnOp
) -> hir
::UnOp
{
234 UnOp
::Deref
=> hir
::UnOp
::UnDeref
,
235 UnOp
::Not
=> hir
::UnOp
::UnNot
,
236 UnOp
::Neg
=> hir
::UnOp
::UnNeg
,
240 fn lower_binop(&mut self, b
: BinOp
) -> hir
::BinOp
{
243 BinOpKind
::Add
=> hir
::BinOpKind
::Add
,
244 BinOpKind
::Sub
=> hir
::BinOpKind
::Sub
,
245 BinOpKind
::Mul
=> hir
::BinOpKind
::Mul
,
246 BinOpKind
::Div
=> hir
::BinOpKind
::Div
,
247 BinOpKind
::Rem
=> hir
::BinOpKind
::Rem
,
248 BinOpKind
::And
=> hir
::BinOpKind
::And
,
249 BinOpKind
::Or
=> hir
::BinOpKind
::Or
,
250 BinOpKind
::BitXor
=> hir
::BinOpKind
::BitXor
,
251 BinOpKind
::BitAnd
=> hir
::BinOpKind
::BitAnd
,
252 BinOpKind
::BitOr
=> hir
::BinOpKind
::BitOr
,
253 BinOpKind
::Shl
=> hir
::BinOpKind
::Shl
,
254 BinOpKind
::Shr
=> hir
::BinOpKind
::Shr
,
255 BinOpKind
::Eq
=> hir
::BinOpKind
::Eq
,
256 BinOpKind
::Lt
=> hir
::BinOpKind
::Lt
,
257 BinOpKind
::Le
=> hir
::BinOpKind
::Le
,
258 BinOpKind
::Ne
=> hir
::BinOpKind
::Ne
,
259 BinOpKind
::Ge
=> hir
::BinOpKind
::Ge
,
260 BinOpKind
::Gt
=> hir
::BinOpKind
::Gt
,
266 /// Emit an error and lower `ast::ExprKind::Let(pat, scrutinee)` into:
268 /// match scrutinee { pats => true, _ => false }
270 fn lower_expr_let(&mut self, span
: Span
, pat
: &Pat
, scrutinee
: &Expr
) -> hir
::ExprKind
<'hir
> {
271 // If we got here, the `let` expression is not allowed.
273 if self.sess
.opts
.unstable_features
.is_nightly_build() {
275 .struct_span_err(span
, "`let` expressions are not supported here")
276 .note("only supported directly in conditions of `if`- and `while`-expressions")
277 .note("as well as when nested within `&&` and parenthesis in those conditions")
281 .struct_span_err(span
, "expected expression, found statement (`let`)")
282 .note("variable declaration using `let` is a statement")
286 // For better recovery, we emit:
288 // match scrutinee { pat => true, _ => false }
290 // While this doesn't fully match the user's intent, it has key advantages:
291 // 1. We can avoid using `abort_if_errors`.
292 // 2. We can typeck both `pat` and `scrutinee`.
293 // 3. `pat` is allowed to be refutable.
294 // 4. The return type of the block is `bool` which seems like what the user wanted.
295 let scrutinee
= self.lower_expr(scrutinee
);
297 let pat
= self.lower_pat(pat
);
298 let expr
= self.expr_bool(span
, true);
302 let pat
= self.pat_wild(span
);
303 let expr
= self.expr_bool(span
, false);
306 hir
::ExprKind
::Match(
308 arena_vec
![self; then_arm
, else_arm
],
309 hir
::MatchSource
::Normal
,
318 else_opt
: Option
<&Expr
>,
319 ) -> hir
::ExprKind
<'hir
> {
320 // FIXME(#53667): handle lowering of && and parens.
322 // `_ => else_block` where `else_block` is `{}` if there's `None`:
323 let else_pat
= self.pat_wild(span
);
324 let (else_expr
, contains_else_clause
) = match else_opt
{
325 None
=> (self.expr_block_empty(span
), false),
326 Some(els
) => (self.lower_expr(els
), true),
328 let else_arm
= self.arm(else_pat
, else_expr
);
330 // Handle then + scrutinee:
331 let then_expr
= self.lower_block_expr(then
);
332 let (then_pat
, scrutinee
, desugar
) = match cond
.kind
{
333 // `<pat> => <then>`:
334 ExprKind
::Let(ref pat
, ref scrutinee
) => {
335 let scrutinee
= self.lower_expr(scrutinee
);
336 let pat
= self.lower_pat(pat
);
337 (pat
, scrutinee
, hir
::MatchSource
::IfLetDesugar { contains_else_clause }
)
342 let cond
= self.lower_expr(cond
);
344 self.mark_span_with_reason(DesugaringKind
::CondTemporary
, cond
.span
, None
);
345 // Wrap in a construct equivalent to `{ let _t = $cond; _t }`
346 // to preserve drop semantics since `if cond { ... }` does not
347 // let temporaries live outside of `cond`.
348 let cond
= self.expr_drop_temps(span_block
, cond
, ThinVec
::new());
349 let pat
= self.pat_bool(span
, true);
350 (pat
, cond
, hir
::MatchSource
::IfDesugar { contains_else_clause }
)
353 let then_arm
= self.arm(then_pat
, self.arena
.alloc(then_expr
));
355 hir
::ExprKind
::Match(scrutinee
, arena_vec
![self; then_arm
, else_arm
], desugar
)
358 fn lower_expr_while_in_loop_scope(
363 opt_label
: Option
<Label
>,
364 ) -> hir
::ExprKind
<'hir
> {
365 // FIXME(#53667): handle lowering of && and parens.
367 // Note that the block AND the condition are evaluated in the loop scope.
368 // This is done to allow `break` from inside the condition of the loop.
372 let else_pat
= self.pat_wild(span
);
373 let else_expr
= self.expr_break(span
, ThinVec
::new());
374 self.arm(else_pat
, else_expr
)
377 // Handle then + scrutinee:
378 let then_expr
= self.lower_block_expr(body
);
379 let (then_pat
, scrutinee
, desugar
, source
) = match cond
.kind
{
380 ExprKind
::Let(ref pat
, ref scrutinee
) => {
383 // [opt_ident]: loop {
384 // match <sub_expr> {
389 let scrutinee
= self.with_loop_condition_scope(|t
| t
.lower_expr(scrutinee
));
390 let pat
= self.lower_pat(pat
);
391 (pat
, scrutinee
, hir
::MatchSource
::WhileLetDesugar
, hir
::LoopSource
::WhileLet
)
394 // We desugar: `'label: while $cond $body` into:
398 // match drop-temps { $cond } {
406 let cond
= self.with_loop_condition_scope(|this
| this
.lower_expr(cond
));
408 self.mark_span_with_reason(DesugaringKind
::CondTemporary
, cond
.span
, None
);
409 // Wrap in a construct equivalent to `{ let _t = $cond; _t }`
410 // to preserve drop semantics since `while cond { ... }` does not
411 // let temporaries live outside of `cond`.
412 let cond
= self.expr_drop_temps(span_block
, cond
, ThinVec
::new());
414 let pat
= self.pat_bool(span
, true);
415 (pat
, cond
, hir
::MatchSource
::WhileDesugar
, hir
::LoopSource
::While
)
418 let then_arm
= self.arm(then_pat
, self.arena
.alloc(then_expr
));
420 // `match <scrutinee> { ... }`
422 self.expr_match(span
, scrutinee
, arena_vec
![self; then_arm
, else_arm
], desugar
);
424 // `[opt_ident]: loop { ... }`
425 hir
::ExprKind
::Loop(self.block_expr(self.arena
.alloc(match_expr
)), opt_label
, source
)
428 /// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_ok(<expr>) }`,
429 /// `try { <stmts>; }` into `{ <stmts>; ::std::ops::Try::from_ok(()) }`
430 /// and save the block id to use it as a break target for desugaring of the `?` operator.
431 fn lower_expr_try_block(&mut self, body
: &Block
) -> hir
::ExprKind
<'hir
> {
432 self.with_catch_scope(body
.id
, |this
| {
433 let mut block
= this
.lower_block_noalloc(body
, true);
435 let try_span
= this
.mark_span_with_reason(
436 DesugaringKind
::TryBlock
,
438 this
.allow_try_trait
.clone(),
441 // Final expression of the block (if present) or `()` with span at the end of block
442 let tail_expr
= block
445 .unwrap_or_else(|| this
.expr_unit(this
.sess
.source_map().end_point(try_span
)));
447 let ok_wrapped_span
=
448 this
.mark_span_with_reason(DesugaringKind
::TryBlock
, tail_expr
.span
, None
);
450 // `::std::ops::Try::from_ok($tail_expr)`
451 block
.expr
= Some(this
.wrap_in_try_constructor(
452 hir
::LangItem
::TryFromOk
,
458 hir
::ExprKind
::Block(this
.arena
.alloc(block
), None
)
462 fn wrap_in_try_constructor(
464 lang_item
: hir
::LangItem
,
466 expr
: &'hir hir
::Expr
<'hir
>,
468 ) -> &'hir hir
::Expr
<'hir
> {
470 self.arena
.alloc(self.expr_lang_item_path(method_span
, lang_item
, ThinVec
::new()));
471 self.expr_call(overall_span
, constructor
, std
::slice
::from_ref(expr
))
474 fn lower_arm(&mut self, arm
: &Arm
) -> hir
::Arm
<'hir
> {
476 hir_id
: self.next_id(),
477 attrs
: self.lower_attrs(&arm
.attrs
),
478 pat
: self.lower_pat(&arm
.pat
),
479 guard
: match arm
.guard
{
480 Some(ref x
) => Some(hir
::Guard
::If(self.lower_expr(x
))),
483 body
: self.lower_expr(&arm
.body
),
488 /// Lower an `async` construct to a generator that is then wrapped so it implements `Future`.
493 /// std::future::from_generator(static move? |_task_context| -> <ret_ty> {
497 pub(super) fn make_async_expr(
499 capture_clause
: CaptureBy
,
500 closure_node_id
: NodeId
,
501 ret_ty
: Option
<AstP
<Ty
>>,
503 async_gen_kind
: hir
::AsyncGeneratorKind
,
504 body
: impl FnOnce(&mut Self) -> hir
::Expr
<'hir
>,
505 ) -> hir
::ExprKind
<'hir
> {
506 let output
= match ret_ty
{
507 Some(ty
) => hir
::FnRetTy
::Return(self.lower_ty(&ty
, ImplTraitContext
::disallowed())),
508 None
=> hir
::FnRetTy
::DefaultReturn(span
),
511 // Resume argument type. We let the compiler infer this to simplify the lowering. It is
512 // fully constrained by `future::from_generator`.
513 let input_ty
= hir
::Ty { hir_id: self.next_id(), kind: hir::TyKind::Infer, span }
;
515 // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
516 let decl
= self.arena
.alloc(hir
::FnDecl
{
517 inputs
: arena_vec
![self; input_ty
],
520 implicit_self
: hir
::ImplicitSelfKind
::None
,
523 // Lower the argument pattern/ident. The ident is used again in the `.await` lowering.
524 let (pat
, task_context_hid
) = self.pat_ident_binding_mode(
526 Ident
::with_dummy_span(sym
::_task_context
),
527 hir
::BindingAnnotation
::Mutable
,
529 let param
= hir
::Param { attrs: &[], hir_id: self.next_id(), pat, ty_span: span, span }
;
530 let params
= arena_vec
![self; param
];
532 let body_id
= self.lower_body(move |this
| {
533 this
.generator_kind
= Some(hir
::GeneratorKind
::Async(async_gen_kind
));
535 let old_ctx
= this
.task_context
;
536 this
.task_context
= Some(task_context_hid
);
537 let res
= body(this
);
538 this
.task_context
= old_ctx
;
542 // `static |_task_context| -> <ret_ty> { body }`:
543 let generator_kind
= hir
::ExprKind
::Closure(
548 Some(hir
::Movability
::Static
),
550 let generator
= hir
::Expr
{
551 hir_id
: self.lower_node_id(closure_node_id
),
552 kind
: generator_kind
,
554 attrs
: ThinVec
::new(),
557 // `future::from_generator`:
559 self.mark_span_with_reason(DesugaringKind
::Async
, span
, self.allow_gen_future
.clone());
561 self.expr_lang_item_path(unstable_span
, hir
::LangItem
::FromGenerator
, ThinVec
::new());
563 // `future::from_generator(generator)`:
564 hir
::ExprKind
::Call(self.arena
.alloc(gen_future
), arena_vec
![self; generator
])
567 /// Desugar `<expr>.await` into:
570 /// mut pinned => loop {
571 /// match unsafe { ::std::future::Future::poll(
572 /// <::std::pin::Pin>::new_unchecked(&mut pinned),
573 /// ::std::future::get_context(task_context),
575 /// ::std::task::Poll::Ready(result) => break result,
576 /// ::std::task::Poll::Pending => {}
578 /// task_context = yield ();
582 fn lower_expr_await(&mut self, await_span
: Span
, expr
: &Expr
) -> hir
::ExprKind
<'hir
> {
583 match self.generator_kind
{
584 Some(hir
::GeneratorKind
::Async(_
)) => {}
585 Some(hir
::GeneratorKind
::Gen
) | None
=> {
586 let mut err
= struct_span_err
!(
590 "`await` is only allowed inside `async` functions and blocks"
592 err
.span_label(await_span
, "only allowed inside `async` functions and blocks");
593 if let Some(item_sp
) = self.current_item
{
594 err
.span_label(item_sp
, "this is not `async`");
599 let span
= self.mark_span_with_reason(DesugaringKind
::Await
, await_span
, None
);
600 let gen_future_span
= self.mark_span_with_reason(
601 DesugaringKind
::Await
,
603 self.allow_gen_future
.clone(),
605 let expr
= self.lower_expr(expr
);
607 let pinned_ident
= Ident
::with_dummy_span(sym
::pinned
);
608 let (pinned_pat
, pinned_pat_hid
) =
609 self.pat_ident_binding_mode(span
, pinned_ident
, hir
::BindingAnnotation
::Mutable
);
611 let task_context_ident
= Ident
::with_dummy_span(sym
::_task_context
);
614 // ::std::future::Future::poll(
615 // ::std::pin::Pin::new_unchecked(&mut pinned),
616 // ::std::future::get_context(task_context),
620 let pinned
= self.expr_ident(span
, pinned_ident
, pinned_pat_hid
);
621 let ref_mut_pinned
= self.expr_mut_addr_of(span
, pinned
);
622 let task_context
= if let Some(task_context_hid
) = self.task_context
{
623 self.expr_ident_mut(span
, task_context_ident
, task_context_hid
)
625 // Use of `await` outside of an async context, we cannot use `task_context` here.
628 let new_unchecked
= self.expr_call_lang_item_fn_mut(
630 hir
::LangItem
::PinNewUnchecked
,
631 arena_vec
![self; ref_mut_pinned
],
633 let get_context
= self.expr_call_lang_item_fn_mut(
635 hir
::LangItem
::GetContext
,
636 arena_vec
![self; task_context
],
638 let call
= self.expr_call_lang_item_fn(
640 hir
::LangItem
::FuturePoll
,
641 arena_vec
![self; new_unchecked
, get_context
],
643 self.arena
.alloc(self.expr_unsafe(call
))
646 // `::std::task::Poll::Ready(result) => break result`
647 let loop_node_id
= self.resolver
.next_node_id();
648 let loop_hir_id
= self.lower_node_id(loop_node_id
);
650 let x_ident
= Ident
::with_dummy_span(sym
::result
);
651 let (x_pat
, x_pat_hid
) = self.pat_ident(span
, x_ident
);
652 let x_expr
= self.expr_ident(span
, x_ident
, x_pat_hid
);
653 let ready_field
= self.single_pat_field(span
, x_pat
);
654 let ready_pat
= self.pat_lang_item_variant(span
, hir
::LangItem
::PollReady
, ready_field
);
655 let break_x
= self.with_loop_scope(loop_node_id
, move |this
| {
657 hir
::ExprKind
::Break(this
.lower_loop_destination(None
), Some(x_expr
));
658 this
.arena
.alloc(this
.expr(await_span
, expr_break
, ThinVec
::new()))
660 self.arm(ready_pat
, break_x
)
663 // `::std::task::Poll::Pending => {}`
665 let pending_pat
= self.pat_lang_item_variant(span
, hir
::LangItem
::PollPending
, &[]);
666 let empty_block
= self.expr_block_empty(span
);
667 self.arm(pending_pat
, empty_block
)
670 let inner_match_stmt
= {
671 let match_expr
= self.expr_match(
674 arena_vec
![self; ready_arm
, pending_arm
],
675 hir
::MatchSource
::AwaitDesugar
,
677 self.stmt_expr(span
, match_expr
)
680 // task_context = yield ();
682 let unit
= self.expr_unit(span
);
683 let yield_expr
= self.expr(
685 hir
::ExprKind
::Yield(unit
, hir
::YieldSource
::Await { expr: Some(expr.hir_id) }
),
688 let yield_expr
= self.arena
.alloc(yield_expr
);
690 if let Some(task_context_hid
) = self.task_context
{
691 let lhs
= self.expr_ident(span
, task_context_ident
, task_context_hid
);
693 self.expr(span
, hir
::ExprKind
::Assign(lhs
, yield_expr
, span
), AttrVec
::new());
694 self.stmt_expr(span
, assign
)
696 // Use of `await` outside of an async context. Return `yield_expr` so that we can
697 // proceed with type checking.
698 self.stmt(span
, hir
::StmtKind
::Semi(yield_expr
))
702 let loop_block
= self.block_all(span
, arena_vec
![self; inner_match_stmt
, yield_stmt
], None
);
705 let loop_expr
= self.arena
.alloc(hir
::Expr
{
707 kind
: hir
::ExprKind
::Loop(loop_block
, None
, hir
::LoopSource
::Loop
),
709 attrs
: ThinVec
::new(),
712 // mut pinned => loop { ... }
713 let pinned_arm
= self.arm(pinned_pat
, loop_expr
);
716 // mut pinned => loop { .. }
718 hir
::ExprKind
::Match(expr
, arena_vec
![self; pinned_arm
], hir
::MatchSource
::AwaitDesugar
)
721 fn lower_expr_closure(
723 capture_clause
: CaptureBy
,
724 movability
: Movability
,
728 ) -> hir
::ExprKind
<'hir
> {
729 // Lower outside new scope to preserve `is_in_loop_condition`.
730 let fn_decl
= self.lower_fn_decl(decl
, None
, false, None
);
732 self.with_new_scopes(move |this
| {
733 let prev
= this
.current_item
;
734 this
.current_item
= Some(fn_decl_span
);
735 let mut generator_kind
= None
;
736 let body_id
= this
.lower_fn_body(decl
, |this
| {
737 let e
= this
.lower_expr_mut(body
);
738 generator_kind
= this
.generator_kind
;
741 let generator_option
=
742 this
.generator_movability_for_fn(&decl
, fn_decl_span
, generator_kind
, movability
);
743 this
.current_item
= prev
;
744 hir
::ExprKind
::Closure(capture_clause
, fn_decl
, body_id
, fn_decl_span
, generator_option
)
748 fn generator_movability_for_fn(
752 generator_kind
: Option
<hir
::GeneratorKind
>,
753 movability
: Movability
,
754 ) -> Option
<hir
::Movability
> {
755 match generator_kind
{
756 Some(hir
::GeneratorKind
::Gen
) => {
757 if decl
.inputs
.len() > 1 {
762 "too many parameters for a generator (expected 0 or 1 parameters)"
768 Some(hir
::GeneratorKind
::Async(_
)) => {
769 panic
!("non-`async` closure body turned `async` during lowering");
772 if movability
== Movability
::Static
{
773 struct_span_err
!(self.sess
, fn_decl_span
, E0697
, "closures cannot be static")
781 fn lower_expr_async_closure(
783 capture_clause
: CaptureBy
,
788 ) -> hir
::ExprKind
<'hir
> {
790 FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }
;
791 // We need to lower the declaration outside the new scope, because we
792 // have to conserve the state of being inside a loop condition for the
793 // closure argument types.
794 let fn_decl
= self.lower_fn_decl(&outer_decl
, None
, false, None
);
796 self.with_new_scopes(move |this
| {
797 // FIXME(cramertj): allow `async` non-`move` closures with arguments.
798 if capture_clause
== CaptureBy
::Ref
&& !decl
.inputs
.is_empty() {
803 "`async` non-`move` closures with parameters are not currently supported",
806 "consider using `let` statements to manually capture \
807 variables by reference before entering an `async move` closure",
812 // Transform `async |x: u8| -> X { ... }` into
813 // `|x: u8| future_from_generator(|| -> X { ... })`.
814 let body_id
= this
.lower_fn_body(&outer_decl
, |this
| {
816 if let FnRetTy
::Ty(ty
) = &decl
.output { Some(ty.clone()) }
else { None }
;
817 let async_body
= this
.make_async_expr(
822 hir
::AsyncGeneratorKind
::Closure
,
823 |this
| this
.with_new_scopes(|this
| this
.lower_expr_mut(body
)),
825 this
.expr(fn_decl_span
, async_body
, ThinVec
::new())
827 hir
::ExprKind
::Closure(capture_clause
, fn_decl
, body_id
, fn_decl_span
, None
)
831 /// Desugar `<start>..=<end>` into `std::ops::RangeInclusive::new(<start>, <end>)`.
832 fn lower_expr_range_closed(&mut self, span
: Span
, e1
: &Expr
, e2
: &Expr
) -> hir
::ExprKind
<'hir
> {
833 let e1
= self.lower_expr_mut(e1
);
834 let e2
= self.lower_expr_mut(e2
);
835 let fn_path
= hir
::QPath
::LangItem(hir
::LangItem
::RangeInclusiveNew
, span
);
837 self.arena
.alloc(self.expr(span
, hir
::ExprKind
::Path(fn_path
), ThinVec
::new()));
838 hir
::ExprKind
::Call(fn_expr
, arena_vec
![self; e1
, e2
])
847 ) -> hir
::ExprKind
<'hir
> {
848 use rustc_ast
::RangeLimits
::*;
850 let lang_item
= match (e1
, e2
, lims
) {
851 (None
, None
, HalfOpen
) => hir
::LangItem
::RangeFull
,
852 (Some(..), None
, HalfOpen
) => hir
::LangItem
::RangeFrom
,
853 (None
, Some(..), HalfOpen
) => hir
::LangItem
::RangeTo
,
854 (Some(..), Some(..), HalfOpen
) => hir
::LangItem
::Range
,
855 (None
, Some(..), Closed
) => hir
::LangItem
::RangeToInclusive
,
856 (Some(..), Some(..), Closed
) => unreachable
!(),
857 (_
, None
, Closed
) => {
858 self.diagnostic().span_fatal(span
, "inclusive range with no end").raise()
862 let fields
= self.arena
.alloc_from_iter(
863 e1
.iter().map(|e
| ("start", e
)).chain(e2
.iter().map(|e
| ("end", e
))).map(|(s
, e
)| {
864 let expr
= self.lower_expr(&e
);
865 let ident
= Ident
::new(Symbol
::intern(s
), e
.span
);
866 self.field(ident
, expr
, e
.span
)
870 hir
::ExprKind
::Struct(self.arena
.alloc(hir
::QPath
::LangItem(lang_item
, span
)), fields
, None
)
873 fn lower_loop_destination(&mut self, destination
: Option
<(NodeId
, Label
)>) -> hir
::Destination
{
874 let target_id
= match destination
{
876 if let Some(loop_id
) = self.resolver
.get_label_res(id
) {
877 Ok(self.lower_node_id(loop_id
))
879 Err(hir
::LoopIdError
::UnresolvedLabel
)
886 .map(|id
| Ok(self.lower_node_id(id
)))
887 .unwrap_or(Err(hir
::LoopIdError
::OutsideLoopScope
)),
889 hir
::Destination { label: destination.map(|(_, label)| label), target_id }
892 fn lower_jump_destination(&mut self, id
: NodeId
, opt_label
: Option
<Label
>) -> hir
::Destination
{
893 if self.is_in_loop_condition
&& opt_label
.is_none() {
896 target_id
: Err(hir
::LoopIdError
::UnlabeledCfInWhileCondition
),
899 self.lower_loop_destination(opt_label
.map(|label
| (id
, label
)))
903 fn with_catch_scope
<T
>(&mut self, catch_id
: NodeId
, f
: impl FnOnce(&mut Self) -> T
) -> T
{
904 let len
= self.catch_scopes
.len();
905 self.catch_scopes
.push(catch_id
);
907 let result
= f(self);
910 self.catch_scopes
.len(),
911 "catch scopes should be added and removed in stack order"
914 self.catch_scopes
.pop().unwrap();
919 fn with_loop_scope
<T
>(&mut self, loop_id
: NodeId
, f
: impl FnOnce(&mut Self) -> T
) -> T
{
920 // We're no longer in the base loop's condition; we're in another loop.
921 let was_in_loop_condition
= self.is_in_loop_condition
;
922 self.is_in_loop_condition
= false;
924 let len
= self.loop_scopes
.len();
925 self.loop_scopes
.push(loop_id
);
927 let result
= f(self);
930 self.loop_scopes
.len(),
931 "loop scopes should be added and removed in stack order"
934 self.loop_scopes
.pop().unwrap();
936 self.is_in_loop_condition
= was_in_loop_condition
;
941 fn with_loop_condition_scope
<T
>(&mut self, f
: impl FnOnce(&mut Self) -> T
) -> T
{
942 let was_in_loop_condition
= self.is_in_loop_condition
;
943 self.is_in_loop_condition
= true;
945 let result
= f(self);
947 self.is_in_loop_condition
= was_in_loop_condition
;
952 fn lower_expr_asm(&mut self, sp
: Span
, asm
: &InlineAsm
) -> hir
::ExprKind
<'hir
> {
953 if self.sess
.asm_arch
.is_none() {
954 struct_span_err
!(self.sess
, sp
, E0472
, "asm! is unsupported on this target").emit();
956 if asm
.options
.contains(InlineAsmOptions
::ATT_SYNTAX
)
959 Some(asm
::InlineAsmArch
::X86
| asm
::InlineAsmArch
::X86_64
)
963 .struct_span_err(sp
, "the `att_syntax` option is only supported on x86")
967 // Lower operands to HIR, filter_map skips any operands with invalid
969 let sess
= self.sess
;
970 let operands
: Vec
<_
> = asm
973 .filter_map(|(op
, op_sp
)| {
974 let lower_reg
= |reg
| {
976 InlineAsmRegOrRegClass
::Reg(s
) => asm
::InlineAsmRegOrRegClass
::Reg(
977 asm
::InlineAsmReg
::parse(
979 |feature
| sess
.target_features
.contains(&Symbol
::intern(feature
)),
984 let msg
= format
!("invalid register `{}`: {}", s
.as_str(), e
);
985 sess
.struct_span_err(*op_sp
, &msg
).emit();
989 InlineAsmRegOrRegClass
::RegClass(s
) => {
990 asm
::InlineAsmRegOrRegClass
::RegClass(
991 asm
::InlineAsmRegClass
::parse(sess
.asm_arch?
, s
)
994 "invalid register class `{}`: {}",
998 sess
.struct_span_err(*op_sp
, &msg
).emit();
1006 // lower_reg is executed last because we need to lower all
1007 // sub-expressions even if we throw them away later.
1008 let op
= match *op
{
1009 InlineAsmOperand
::In { reg, ref expr }
=> hir
::InlineAsmOperand
::In
{
1010 expr
: self.lower_expr_mut(expr
),
1011 reg
: lower_reg(reg
)?
,
1013 InlineAsmOperand
::Out { reg, late, ref expr }
=> hir
::InlineAsmOperand
::Out
{
1015 expr
: expr
.as_ref().map(|expr
| self.lower_expr_mut(expr
)),
1016 reg
: lower_reg(reg
)?
,
1018 InlineAsmOperand
::InOut { reg, late, ref expr }
=> {
1019 hir
::InlineAsmOperand
::InOut
{
1021 expr
: self.lower_expr_mut(expr
),
1022 reg
: lower_reg(reg
)?
,
1025 InlineAsmOperand
::SplitInOut { reg, late, ref in_expr, ref out_expr }
=> {
1026 hir
::InlineAsmOperand
::SplitInOut
{
1028 in_expr
: self.lower_expr_mut(in_expr
),
1029 out_expr
: out_expr
.as_ref().map(|expr
| self.lower_expr_mut(expr
)),
1030 reg
: lower_reg(reg
)?
,
1033 InlineAsmOperand
::Const { ref expr }
=> {
1034 hir
::InlineAsmOperand
::Const { expr: self.lower_expr_mut(expr) }
1036 InlineAsmOperand
::Sym { ref expr }
=> {
1037 hir
::InlineAsmOperand
::Sym { expr: self.lower_expr_mut(expr) }
1044 // Stop if there were any errors when lowering the register classes
1045 if operands
.len() != asm
.operands
.len() || sess
.asm_arch
.is_none() {
1046 return hir
::ExprKind
::Err
;
1049 // Validate template modifiers against the register classes for the operands
1050 let asm_arch
= sess
.asm_arch
.unwrap();
1051 for p
in &asm
.template
{
1052 if let InlineAsmTemplatePiece
::Placeholder
{
1054 modifier
: Some(modifier
),
1055 span
: placeholder_span
,
1058 let op_sp
= asm
.operands
[operand_idx
].1;
1059 match &operands
[operand_idx
] {
1060 hir
::InlineAsmOperand
::In { reg, .. }
1061 | hir
::InlineAsmOperand
::Out { reg, .. }
1062 | hir
::InlineAsmOperand
::InOut { reg, .. }
1063 | hir
::InlineAsmOperand
::SplitInOut { reg, .. }
=> {
1064 let class
= reg
.reg_class();
1065 let valid_modifiers
= class
.valid_modifiers(asm_arch
);
1066 if !valid_modifiers
.contains(&modifier
) {
1067 let mut err
= sess
.struct_span_err(
1069 "invalid asm template modifier for this register class",
1071 err
.span_label(placeholder_span
, "template modifier");
1072 err
.span_label(op_sp
, "argument");
1073 if !valid_modifiers
.is_empty() {
1074 let mut mods
= format
!("`{}`", valid_modifiers
[0]);
1075 for m
in &valid_modifiers
[1..] {
1076 let _
= write
!(mods
, ", `{}`", m
);
1079 "the `{}` register class supports \
1080 the following template modifiers: {}",
1086 "the `{}` register class does not support template modifiers",
1093 hir
::InlineAsmOperand
::Const { .. }
=> {
1094 let mut err
= sess
.struct_span_err(
1096 "asm template modifiers are not allowed for `const` arguments",
1098 err
.span_label(placeholder_span
, "template modifier");
1099 err
.span_label(op_sp
, "argument");
1102 hir
::InlineAsmOperand
::Sym { .. }
=> {
1103 let mut err
= sess
.struct_span_err(
1105 "asm template modifiers are not allowed for `sym` arguments",
1107 err
.span_label(placeholder_span
, "template modifier");
1108 err
.span_label(op_sp
, "argument");
1115 let mut used_input_regs
= FxHashMap
::default();
1116 let mut used_output_regs
= FxHashMap
::default();
1117 for (idx
, op
) in operands
.iter().enumerate() {
1118 let op_sp
= asm
.operands
[idx
].1;
1119 if let Some(reg
) = op
.reg() {
1120 // Validate register classes against currently enabled target
1121 // features. We check that at least one type is available for
1122 // the current target.
1123 let reg_class
= reg
.reg_class();
1124 let mut required_features
= vec
![];
1125 for &(_
, feature
) in reg_class
.supported_types(asm_arch
) {
1126 if let Some(feature
) = feature
{
1127 if self.sess
.target_features
.contains(&Symbol
::intern(feature
)) {
1128 required_features
.clear();
1131 required_features
.push(feature
);
1134 required_features
.clear();
1138 required_features
.sort();
1139 required_features
.dedup();
1140 match &required_features
[..] {
1144 "register class `{}` requires the `{}` target feature",
1148 sess
.struct_span_err(op_sp
, &msg
).emit();
1152 "register class `{}` requires at least one target feature: {}",
1156 sess
.struct_span_err(op_sp
, &msg
).emit();
1160 // Check for conflicts between explicit register operands.
1161 if let asm
::InlineAsmRegOrRegClass
::Reg(reg
) = reg
{
1162 let (input
, output
) = match op
{
1163 hir
::InlineAsmOperand
::In { .. }
=> (true, false),
1164 // Late output do not conflict with inputs, but normal outputs do
1165 hir
::InlineAsmOperand
::Out { late, .. }
=> (!late
, true),
1166 hir
::InlineAsmOperand
::InOut { .. }
1167 | hir
::InlineAsmOperand
::SplitInOut { .. }
=> (true, true),
1168 hir
::InlineAsmOperand
::Const { .. }
| hir
::InlineAsmOperand
::Sym { .. }
=> {
1173 // Flag to output the error only once per operand
1174 let mut skip
= false;
1175 reg
.overlapping_regs(|r
| {
1176 let mut check
= |used_regs
: &mut FxHashMap
<asm
::InlineAsmReg
, usize>,
1178 match used_regs
.entry(r
) {
1179 Entry
::Occupied(o
) => {
1183 let idx2
= *o
.get();
1184 let op2
= &operands
[idx2
];
1185 let op_sp2
= asm
.operands
[idx2
].1;
1186 let reg2
= match op2
.reg() {
1187 Some(asm
::InlineAsmRegOrRegClass
::Reg(r
)) => r
,
1188 _
=> unreachable
!(),
1192 "register `{}` conflicts with register `{}`",
1196 let mut err
= sess
.struct_span_err(op_sp
, &msg
);
1199 &format
!("register `{}`", reg
.name()),
1203 &format
!("register `{}`", reg2
.name()),
1208 hir
::InlineAsmOperand
::In { .. }
,
1209 hir
::InlineAsmOperand
::Out { late, .. }
,
1212 hir
::InlineAsmOperand
::Out { late, .. }
,
1213 hir
::InlineAsmOperand
::In { .. }
,
1216 let out_op_sp
= if input { op_sp2 }
else { op_sp }
;
1217 let msg
= "use `lateout` instead of \
1218 `out` to avoid conflict";
1219 err
.span_help(out_op_sp
, msg
);
1227 Entry
::Vacant(v
) => {
1233 check(&mut used_input_regs
, true);
1236 check(&mut used_output_regs
, false);
1243 let operands
= self.arena
.alloc_from_iter(operands
);
1244 let template
= self.arena
.alloc_from_iter(asm
.template
.iter().cloned());
1245 let line_spans
= self.arena
.alloc_slice(&asm
.line_spans
[..]);
1246 let hir_asm
= hir
::InlineAsm { template, operands, options: asm.options, line_spans }
;
1247 hir
::ExprKind
::InlineAsm(self.arena
.alloc(hir_asm
))
1250 fn lower_expr_llvm_asm(&mut self, asm
: &LlvmInlineAsm
) -> hir
::ExprKind
<'hir
> {
1251 let inner
= hir
::LlvmInlineAsmInner
{
1252 inputs
: asm
.inputs
.iter().map(|&(c
, _
)| c
).collect(),
1256 .map(|out
| hir
::LlvmInlineAsmOutput
{
1257 constraint
: out
.constraint
,
1259 is_indirect
: out
.is_indirect
,
1260 span
: out
.expr
.span
,
1264 asm_str_style
: asm
.asm_str_style
,
1265 clobbers
: asm
.clobbers
.clone(),
1266 volatile
: asm
.volatile
,
1267 alignstack
: asm
.alignstack
,
1268 dialect
: asm
.dialect
,
1270 let hir_asm
= hir
::LlvmInlineAsm
{
1272 inputs_exprs
: self.arena
.alloc_from_iter(
1273 asm
.inputs
.iter().map(|&(_
, ref input
)| self.lower_expr_mut(input
)),
1277 .alloc_from_iter(asm
.outputs
.iter().map(|out
| self.lower_expr_mut(&out
.expr
))),
1279 hir
::ExprKind
::LlvmInlineAsm(self.arena
.alloc(hir_asm
))
1282 fn lower_field(&mut self, f
: &Field
) -> hir
::Field
<'hir
> {
1284 hir_id
: self.next_id(),
1286 expr
: self.lower_expr(&f
.expr
),
1288 is_shorthand
: f
.is_shorthand
,
1292 fn lower_expr_yield(&mut self, span
: Span
, opt_expr
: Option
<&Expr
>) -> hir
::ExprKind
<'hir
> {
1293 match self.generator_kind
{
1294 Some(hir
::GeneratorKind
::Gen
) => {}
1295 Some(hir
::GeneratorKind
::Async(_
)) => {
1300 "`async` generators are not yet supported"
1304 None
=> self.generator_kind
= Some(hir
::GeneratorKind
::Gen
),
1308 opt_expr
.as_ref().map(|x
| self.lower_expr(x
)).unwrap_or_else(|| self.expr_unit(span
));
1310 hir
::ExprKind
::Yield(expr
, hir
::YieldSource
::Yield
)
1313 /// Desugar `ExprForLoop` from: `[opt_ident]: for <pat> in <head> <body>` into:
1316 /// let result = match ::std::iter::IntoIterator::into_iter(<head>) {
1318 /// [opt_ident]: loop {
1320 /// match ::std::iter::Iterator::next(&mut iter) {
1321 /// ::std::option::Option::Some(val) => __next = val,
1322 /// ::std::option::Option::None => break
1324 /// let <pat> = __next;
1325 /// StmtKind::Expr(<body>);
1338 opt_label
: Option
<Label
>,
1339 ) -> hir
::Expr
<'hir
> {
1340 let orig_head_span
= head
.span
;
1342 let mut head
= self.lower_expr_mut(head
);
1343 let desugared_span
= self.mark_span_with_reason(
1344 DesugaringKind
::ForLoop(ForLoopLoc
::Head
),
1348 head
.span
= desugared_span
;
1350 let iter
= Ident
::with_dummy_span(sym
::iter
);
1352 let next_ident
= Ident
::with_dummy_span(sym
::__next
);
1353 let (next_pat
, next_pat_hid
) = self.pat_ident_binding_mode(
1356 hir
::BindingAnnotation
::Mutable
,
1359 // `::std::option::Option::Some(val) => __next = val`
1361 let val_ident
= Ident
::with_dummy_span(sym
::val
);
1362 let (val_pat
, val_pat_hid
) = self.pat_ident(pat
.span
, val_ident
);
1363 let val_expr
= self.expr_ident(pat
.span
, val_ident
, val_pat_hid
);
1364 let next_expr
= self.expr_ident(pat
.span
, next_ident
, next_pat_hid
);
1365 let assign
= self.arena
.alloc(self.expr(
1367 hir
::ExprKind
::Assign(next_expr
, val_expr
, pat
.span
),
1370 let some_pat
= self.pat_some(pat
.span
, val_pat
);
1371 self.arm(some_pat
, assign
)
1374 // `::std::option::Option::None => break`
1377 self.with_loop_scope(e
.id
, |this
| this
.expr_break(e
.span
, ThinVec
::new()));
1378 let pat
= self.pat_none(e
.span
);
1379 self.arm(pat
, break_expr
)
1383 let (iter_pat
, iter_pat_nid
) =
1384 self.pat_ident_binding_mode(desugared_span
, iter
, hir
::BindingAnnotation
::Mutable
);
1386 // `match ::std::iter::Iterator::next(&mut iter) { ... }`
1388 let iter
= self.expr_ident(desugared_span
, iter
, iter_pat_nid
);
1389 let ref_mut_iter
= self.expr_mut_addr_of(desugared_span
, iter
);
1390 let next_expr
= self.expr_call_lang_item_fn(
1392 hir
::LangItem
::IteratorNext
,
1393 arena_vec
![self; ref_mut_iter
],
1395 let arms
= arena_vec
![self; pat_arm
, break_arm
];
1397 self.expr_match(desugared_span
, next_expr
, arms
, hir
::MatchSource
::ForLoopDesugar
)
1399 let match_stmt
= self.stmt_expr(desugared_span
, match_expr
);
1401 let next_expr
= self.expr_ident(desugared_span
, next_ident
, next_pat_hid
);
1404 let next_let
= self.stmt_let_pat(
1409 hir
::LocalSource
::ForLoopDesugar
,
1412 // `let <pat> = __next`
1413 let pat
= self.lower_pat(pat
);
1414 let pat_let
= self.stmt_let_pat(
1419 hir
::LocalSource
::ForLoopDesugar
,
1422 let body_block
= self.with_loop_scope(e
.id
, |this
| this
.lower_block(body
, false));
1423 let body_expr
= self.expr_block(body_block
, ThinVec
::new());
1424 let body_stmt
= self.stmt_expr(body
.span
, body_expr
);
1426 let loop_block
= self.block_all(
1428 arena_vec
![self; next_let
, match_stmt
, pat_let
, body_stmt
],
1432 // `[opt_ident]: loop { ... }`
1433 let kind
= hir
::ExprKind
::Loop(loop_block
, opt_label
, hir
::LoopSource
::ForLoop
);
1434 let loop_expr
= self.arena
.alloc(hir
::Expr
{
1435 hir_id
: self.lower_node_id(e
.id
),
1438 attrs
: ThinVec
::new(),
1441 // `mut iter => { ... }`
1442 let iter_arm
= self.arm(iter_pat
, loop_expr
);
1444 let into_iter_span
= self.mark_span_with_reason(
1445 DesugaringKind
::ForLoop(ForLoopLoc
::IntoIter
),
1450 // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
1451 let into_iter_expr
= {
1452 self.expr_call_lang_item_fn(
1454 hir
::LangItem
::IntoIterIntoIter
,
1455 arena_vec
![self; head
],
1459 let match_expr
= self.arena
.alloc(self.expr_match(
1462 arena_vec
![self; iter_arm
],
1463 hir
::MatchSource
::ForLoopDesugar
,
1466 // This is effectively `{ let _result = ...; _result }`.
1467 // The construct was introduced in #21984 and is necessary to make sure that
1468 // temporaries in the `head` expression are dropped and do not leak to the
1469 // surrounding scope of the `match` since the `match` is not a terminating scope.
1471 // Also, add the attributes to the outer returned expr node.
1472 self.expr_drop_temps_mut(desugared_span
, match_expr
, e
.attrs
.clone())
1475 /// Desugar `ExprKind::Try` from: `<expr>?` into:
1477 /// match Try::into_result(<expr>) {
1478 /// Ok(val) => #[allow(unreachable_code)] val,
1479 /// Err(err) => #[allow(unreachable_code)]
1480 /// // If there is an enclosing `try {...}`:
1481 /// break 'catch_target Try::from_error(From::from(err)),
1483 /// return Try::from_error(From::from(err)),
1486 fn lower_expr_try(&mut self, span
: Span
, sub_expr
: &Expr
) -> hir
::ExprKind
<'hir
> {
1487 let unstable_span
= self.mark_span_with_reason(
1488 DesugaringKind
::QuestionMark
,
1490 self.allow_try_trait
.clone(),
1492 let try_span
= self.sess
.source_map().end_point(span
);
1493 let try_span
= self.mark_span_with_reason(
1494 DesugaringKind
::QuestionMark
,
1496 self.allow_try_trait
.clone(),
1499 // `Try::into_result(<expr>)`
1502 let sub_expr
= self.lower_expr_mut(sub_expr
);
1504 self.expr_call_lang_item_fn(
1506 hir
::LangItem
::TryIntoResult
,
1507 arena_vec
![self; sub_expr
],
1511 // `#[allow(unreachable_code)]`
1513 // `allow(unreachable_code)`
1515 let allow_ident
= Ident
::new(sym
::allow
, span
);
1516 let uc_ident
= Ident
::new(sym
::unreachable_code
, span
);
1517 let uc_nested
= attr
::mk_nested_word_item(uc_ident
);
1518 attr
::mk_list_item(allow_ident
, vec
![uc_nested
])
1520 attr
::mk_attr_outer(allow
)
1522 let attrs
= vec
![attr
];
1524 // `Ok(val) => #[allow(unreachable_code)] val,`
1526 let val_ident
= Ident
::with_dummy_span(sym
::val
);
1527 let (val_pat
, val_pat_nid
) = self.pat_ident(span
, val_ident
);
1528 let val_expr
= self.arena
.alloc(self.expr_ident_with_attrs(
1532 ThinVec
::from(attrs
.clone()),
1534 let ok_pat
= self.pat_ok(span
, val_pat
);
1535 self.arm(ok_pat
, val_expr
)
1538 // `Err(err) => #[allow(unreachable_code)]
1539 // return Try::from_error(From::from(err)),`
1541 let err_ident
= Ident
::with_dummy_span(sym
::err
);
1542 let (err_local
, err_local_nid
) = self.pat_ident(try_span
, err_ident
);
1544 let err_expr
= self.expr_ident_mut(try_span
, err_ident
, err_local_nid
);
1545 self.expr_call_lang_item_fn(
1547 hir
::LangItem
::FromFrom
,
1548 arena_vec
![self; err_expr
],
1551 let from_err_expr
= self.wrap_in_try_constructor(
1552 hir
::LangItem
::TryFromError
,
1557 let thin_attrs
= ThinVec
::from(attrs
);
1558 let catch_scope
= self.catch_scopes
.last().copied();
1559 let ret_expr
= if let Some(catch_node
) = catch_scope
{
1560 let target_id
= Ok(self.lower_node_id(catch_node
));
1561 self.arena
.alloc(self.expr(
1563 hir
::ExprKind
::Break(
1564 hir
::Destination { label: None, target_id }
,
1565 Some(from_err_expr
),
1570 self.arena
.alloc(self.expr(
1572 hir
::ExprKind
::Ret(Some(from_err_expr
)),
1577 let err_pat
= self.pat_err(try_span
, err_local
);
1578 self.arm(err_pat
, ret_expr
)
1581 hir
::ExprKind
::Match(
1583 arena_vec
![self; err_arm
, ok_arm
],
1584 hir
::MatchSource
::TryDesugar
,
1588 // =========================================================================
1589 // Helper methods for building HIR.
1590 // =========================================================================
1592 /// Constructs a `true` or `false` literal expression.
1593 pub(super) fn expr_bool(&mut self, span
: Span
, val
: bool
) -> &'hir hir
::Expr
<'hir
> {
1594 let lit
= Spanned { span, node: LitKind::Bool(val) }
;
1595 self.arena
.alloc(self.expr(span
, hir
::ExprKind
::Lit(lit
), ThinVec
::new()))
1598 /// Wrap the given `expr` in a terminating scope using `hir::ExprKind::DropTemps`.
1600 /// In terms of drop order, it has the same effect as wrapping `expr` in
1601 /// `{ let _t = $expr; _t }` but should provide better compile-time performance.
1603 /// The drop order can be important in e.g. `if expr { .. }`.
1604 pub(super) fn expr_drop_temps(
1607 expr
: &'hir hir
::Expr
<'hir
>,
1609 ) -> &'hir hir
::Expr
<'hir
> {
1610 self.arena
.alloc(self.expr_drop_temps_mut(span
, expr
, attrs
))
1613 pub(super) fn expr_drop_temps_mut(
1616 expr
: &'hir hir
::Expr
<'hir
>,
1618 ) -> hir
::Expr
<'hir
> {
1619 self.expr(span
, hir
::ExprKind
::DropTemps(expr
), attrs
)
1625 arg
: &'hir hir
::Expr
<'hir
>,
1626 arms
: &'hir
[hir
::Arm
<'hir
>],
1627 source
: hir
::MatchSource
,
1628 ) -> hir
::Expr
<'hir
> {
1629 self.expr(span
, hir
::ExprKind
::Match(arg
, arms
, source
), ThinVec
::new())
1632 fn expr_break(&mut self, span
: Span
, attrs
: AttrVec
) -> &'hir hir
::Expr
<'hir
> {
1633 let expr_break
= hir
::ExprKind
::Break(self.lower_loop_destination(None
), None
);
1634 self.arena
.alloc(self.expr(span
, expr_break
, attrs
))
1637 fn expr_mut_addr_of(&mut self, span
: Span
, e
: &'hir hir
::Expr
<'hir
>) -> hir
::Expr
<'hir
> {
1640 hir
::ExprKind
::AddrOf(hir
::BorrowKind
::Ref
, hir
::Mutability
::Mut
, e
),
1645 fn expr_unit(&mut self, sp
: Span
) -> &'hir hir
::Expr
<'hir
> {
1646 self.arena
.alloc(self.expr(sp
, hir
::ExprKind
::Tup(&[]), ThinVec
::new()))
1652 e
: &'hir hir
::Expr
<'hir
>,
1653 args
: &'hir
[hir
::Expr
<'hir
>],
1654 ) -> hir
::Expr
<'hir
> {
1655 self.expr(span
, hir
::ExprKind
::Call(e
, args
), ThinVec
::new())
1661 e
: &'hir hir
::Expr
<'hir
>,
1662 args
: &'hir
[hir
::Expr
<'hir
>],
1663 ) -> &'hir hir
::Expr
<'hir
> {
1664 self.arena
.alloc(self.expr_call_mut(span
, e
, args
))
1667 fn expr_call_lang_item_fn_mut(
1670 lang_item
: hir
::LangItem
,
1671 args
: &'hir
[hir
::Expr
<'hir
>],
1672 ) -> hir
::Expr
<'hir
> {
1673 let path
= self.arena
.alloc(self.expr_lang_item_path(span
, lang_item
, ThinVec
::new()));
1674 self.expr_call_mut(span
, path
, args
)
1677 fn expr_call_lang_item_fn(
1680 lang_item
: hir
::LangItem
,
1681 args
: &'hir
[hir
::Expr
<'hir
>],
1682 ) -> &'hir hir
::Expr
<'hir
> {
1683 self.arena
.alloc(self.expr_call_lang_item_fn_mut(span
, lang_item
, args
))
1686 fn expr_lang_item_path(
1689 lang_item
: hir
::LangItem
,
1691 ) -> hir
::Expr
<'hir
> {
1692 self.expr(span
, hir
::ExprKind
::Path(hir
::QPath
::LangItem(lang_item
, span
)), attrs
)
1695 pub(super) fn expr_ident(
1699 binding
: hir
::HirId
,
1700 ) -> &'hir hir
::Expr
<'hir
> {
1701 self.arena
.alloc(self.expr_ident_mut(sp
, ident
, binding
))
1704 pub(super) fn expr_ident_mut(
1708 binding
: hir
::HirId
,
1709 ) -> hir
::Expr
<'hir
> {
1710 self.expr_ident_with_attrs(sp
, ident
, binding
, ThinVec
::new())
1713 fn expr_ident_with_attrs(
1717 binding
: hir
::HirId
,
1719 ) -> hir
::Expr
<'hir
> {
1720 let expr_path
= hir
::ExprKind
::Path(hir
::QPath
::Resolved(
1722 self.arena
.alloc(hir
::Path
{
1724 res
: Res
::Local(binding
),
1725 segments
: arena_vec
![self; hir
::PathSegment
::from_ident(ident
)],
1729 self.expr(span
, expr_path
, attrs
)
1732 fn expr_unsafe(&mut self, expr
: &'hir hir
::Expr
<'hir
>) -> hir
::Expr
<'hir
> {
1733 let hir_id
= self.next_id();
1734 let span
= expr
.span
;
1737 hir
::ExprKind
::Block(
1738 self.arena
.alloc(hir
::Block
{
1742 rules
: hir
::BlockCheckMode
::UnsafeBlock(hir
::UnsafeSource
::CompilerGenerated
),
1744 targeted_by_break
: false,
1752 fn expr_block_empty(&mut self, span
: Span
) -> &'hir hir
::Expr
<'hir
> {
1753 let blk
= self.block_all(span
, &[], None
);
1754 let expr
= self.expr_block(blk
, ThinVec
::new());
1755 self.arena
.alloc(expr
)
1758 pub(super) fn expr_block(
1760 b
: &'hir hir
::Block
<'hir
>,
1762 ) -> hir
::Expr
<'hir
> {
1763 self.expr(b
.span
, hir
::ExprKind
::Block(b
, None
), attrs
)
1769 kind
: hir
::ExprKind
<'hir
>,
1771 ) -> hir
::Expr
<'hir
> {
1772 hir
::Expr { hir_id: self.next_id(), kind, span, attrs }
1775 fn field(&mut self, ident
: Ident
, expr
: &'hir hir
::Expr
<'hir
>, span
: Span
) -> hir
::Field
<'hir
> {
1776 hir
::Field { hir_id: self.next_id(), ident, span, expr, is_shorthand: false }
1779 fn arm(&mut self, pat
: &'hir hir
::Pat
<'hir
>, expr
: &'hir hir
::Expr
<'hir
>) -> hir
::Arm
<'hir
> {
1781 hir_id
: self.next_id(),