1 use super::{LoweringContext, ParamMode, ParenthesizedGenericArgs, ImplTraitContext}
;
2 use crate::hir
::{self, HirVec}
;
3 use crate::hir
::def
::Res
;
4 use crate::hir
::ptr
::P
;
6 use rustc_data_structures
::thin_vec
::ThinVec
;
9 use syntax
::ptr
::P
as AstP
;
11 use syntax
::source_map
::{respan, DesugaringKind, Span, Spanned}
;
12 use syntax
::symbol
::{sym, Symbol}
;
14 use rustc_error_codes
::*;
16 impl LoweringContext
<'_
> {
17 fn lower_exprs(&mut self, exprs
: &[AstP
<Expr
>]) -> HirVec
<hir
::Expr
> {
18 exprs
.iter().map(|x
| self.lower_expr(x
)).collect()
21 pub(super) fn lower_expr(&mut self, e
: &Expr
) -> hir
::Expr
{
22 let kind
= match e
.kind
{
23 ExprKind
::Box(ref inner
) => hir
::ExprKind
::Box(P(self.lower_expr(inner
))),
24 ExprKind
::Array(ref exprs
) => hir
::ExprKind
::Array(self.lower_exprs(exprs
)),
25 ExprKind
::Repeat(ref expr
, ref count
) => {
26 let expr
= P(self.lower_expr(expr
));
27 let count
= self.lower_anon_const(count
);
28 hir
::ExprKind
::Repeat(expr
, count
)
30 ExprKind
::Tup(ref elts
) => hir
::ExprKind
::Tup(self.lower_exprs(elts
)),
31 ExprKind
::Call(ref f
, ref args
) => {
32 let f
= P(self.lower_expr(f
));
33 hir
::ExprKind
::Call(f
, self.lower_exprs(args
))
35 ExprKind
::MethodCall(ref seg
, ref args
) => {
36 let hir_seg
= P(self.lower_path_segment(
41 ParenthesizedGenericArgs
::Err
,
42 ImplTraitContext
::disallowed(),
45 let args
= self.lower_exprs(args
);
46 hir
::ExprKind
::MethodCall(hir_seg
, seg
.ident
.span
, args
)
48 ExprKind
::Binary(binop
, ref lhs
, ref rhs
) => {
49 let binop
= self.lower_binop(binop
);
50 let lhs
= P(self.lower_expr(lhs
));
51 let rhs
= P(self.lower_expr(rhs
));
52 hir
::ExprKind
::Binary(binop
, lhs
, rhs
)
54 ExprKind
::Unary(op
, ref ohs
) => {
55 let op
= self.lower_unop(op
);
56 let ohs
= P(self.lower_expr(ohs
));
57 hir
::ExprKind
::Unary(op
, ohs
)
59 ExprKind
::Lit(ref l
) => hir
::ExprKind
::Lit(respan(l
.span
, l
.kind
.clone())),
60 ExprKind
::Cast(ref expr
, ref ty
) => {
61 let expr
= P(self.lower_expr(expr
));
62 hir
::ExprKind
::Cast(expr
, self.lower_ty(ty
, ImplTraitContext
::disallowed()))
64 ExprKind
::Type(ref expr
, ref ty
) => {
65 let expr
= P(self.lower_expr(expr
));
66 hir
::ExprKind
::Type(expr
, self.lower_ty(ty
, ImplTraitContext
::disallowed()))
68 ExprKind
::AddrOf(k
, m
, ref ohs
) => {
69 let ohs
= P(self.lower_expr(ohs
));
70 hir
::ExprKind
::AddrOf(k
, m
, ohs
)
72 ExprKind
::Let(ref pat
, ref scrutinee
) => self.lower_expr_let(e
.span
, pat
, scrutinee
),
73 ExprKind
::If(ref cond
, ref then
, ref else_opt
) => {
74 self.lower_expr_if(e
.span
, cond
, then
, else_opt
.as_deref())
76 ExprKind
::While(ref cond
, ref body
, opt_label
) => self.with_loop_scope(e
.id
, |this
| {
77 this
.lower_expr_while_in_loop_scope(e
.span
, cond
, body
, opt_label
)
79 ExprKind
::Loop(ref body
, opt_label
) => self.with_loop_scope(e
.id
, |this
| {
81 this
.lower_block(body
, false),
82 this
.lower_label(opt_label
),
83 hir
::LoopSource
::Loop
,
86 ExprKind
::TryBlock(ref body
) => self.lower_expr_try_block(body
),
87 ExprKind
::Match(ref expr
, ref arms
) => hir
::ExprKind
::Match(
88 P(self.lower_expr(expr
)),
89 arms
.iter().map(|x
| self.lower_arm(x
)).collect(),
90 hir
::MatchSource
::Normal
,
92 ExprKind
::Async(capture_clause
, closure_node_id
, ref block
) => {
98 hir
::AsyncGeneratorKind
::Block
,
99 |this
| this
.with_new_scopes(|this
| this
.lower_block_expr(block
)),
102 ExprKind
::Await(ref expr
) => self.lower_expr_await(e
.span
, expr
),
104 capture_clause
, asyncness
, movability
, ref decl
, ref body
, fn_decl_span
105 ) => if let IsAsync
::Async { closure_id, .. }
= asyncness
{
106 self.lower_expr_async_closure(capture_clause
, closure_id
, decl
, body
, fn_decl_span
)
108 self.lower_expr_closure(capture_clause
, movability
, decl
, body
, fn_decl_span
)
110 ExprKind
::Block(ref blk
, opt_label
) => {
111 hir
::ExprKind
::Block(self.lower_block(blk
,
112 opt_label
.is_some()),
113 self.lower_label(opt_label
))
115 ExprKind
::Assign(ref el
, ref er
) => {
116 hir
::ExprKind
::Assign(P(self.lower_expr(el
)), P(self.lower_expr(er
)))
118 ExprKind
::AssignOp(op
, ref el
, ref er
) => hir
::ExprKind
::AssignOp(
119 self.lower_binop(op
),
120 P(self.lower_expr(el
)),
121 P(self.lower_expr(er
)),
123 ExprKind
::Field(ref el
, ident
) => hir
::ExprKind
::Field(P(self.lower_expr(el
)), ident
),
124 ExprKind
::Index(ref el
, ref er
) => {
125 hir
::ExprKind
::Index(P(self.lower_expr(el
)), P(self.lower_expr(er
)))
127 ExprKind
::Range(Some(ref e1
), Some(ref e2
), RangeLimits
::Closed
) => {
128 self.lower_expr_range_closed(e
.span
, e1
, e2
)
130 ExprKind
::Range(ref e1
, ref e2
, lims
) => {
131 self.lower_expr_range(e
.span
, e1
.as_deref(), e2
.as_deref(), lims
)
133 ExprKind
::Path(ref qself
, ref path
) => {
134 let qpath
= self.lower_qpath(
139 ImplTraitContext
::disallowed(),
141 hir
::ExprKind
::Path(qpath
)
143 ExprKind
::Break(opt_label
, ref opt_expr
) => {
144 hir
::ExprKind
::Break(
145 self.lower_jump_destination(e
.id
, opt_label
),
146 opt_expr
.as_ref().map(|x
| P(self.lower_expr(x
))),
149 ExprKind
::Continue(opt_label
) => {
150 hir
::ExprKind
::Continue(self.lower_jump_destination(e
.id
, opt_label
))
152 ExprKind
::Ret(ref e
) => hir
::ExprKind
::Ret(e
.as_ref().map(|x
| P(self.lower_expr(x
)))),
153 ExprKind
::InlineAsm(ref asm
) => self.lower_expr_asm(asm
),
154 ExprKind
::Struct(ref path
, ref fields
, ref maybe_expr
) => hir
::ExprKind
::Struct(
160 ImplTraitContext
::disallowed(),
162 fields
.iter().map(|x
| self.lower_field(x
)).collect(),
163 maybe_expr
.as_ref().map(|x
| P(self.lower_expr(x
))),
165 ExprKind
::Paren(ref ex
) => {
166 let mut ex
= self.lower_expr(ex
);
167 // Include parens in span, but only if it is a super-span.
168 if e
.span
.contains(ex
.span
) {
171 // Merge attributes into the inner expression.
172 let mut attrs
= e
.attrs
.clone();
173 attrs
.extend
::<Vec
<_
>>(ex
.attrs
.into());
178 ExprKind
::Yield(ref opt_expr
) => self.lower_expr_yield(e
.span
, opt_expr
.as_deref()),
180 ExprKind
::Err
=> hir
::ExprKind
::Err
,
182 // Desugar `ExprForLoop`
183 // from: `[opt_ident]: for <pat> in <head> <body>`
184 ExprKind
::ForLoop(ref pat
, ref head
, ref body
, opt_label
) => {
185 return self.lower_expr_for(e
, pat
, head
, body
, opt_label
);
187 ExprKind
::Try(ref sub_expr
) => self.lower_expr_try(e
.span
, sub_expr
),
188 ExprKind
::Mac(_
) => panic
!("Shouldn't exist here"),
192 hir_id
: self.lower_node_id(e
.id
),
195 attrs
: e
.attrs
.clone(),
199 fn lower_unop(&mut self, u
: UnOp
) -> hir
::UnOp
{
201 UnOp
::Deref
=> hir
::UnDeref
,
202 UnOp
::Not
=> hir
::UnNot
,
203 UnOp
::Neg
=> hir
::UnNeg
,
207 fn lower_binop(&mut self, b
: BinOp
) -> hir
::BinOp
{
210 BinOpKind
::Add
=> hir
::BinOpKind
::Add
,
211 BinOpKind
::Sub
=> hir
::BinOpKind
::Sub
,
212 BinOpKind
::Mul
=> hir
::BinOpKind
::Mul
,
213 BinOpKind
::Div
=> hir
::BinOpKind
::Div
,
214 BinOpKind
::Rem
=> hir
::BinOpKind
::Rem
,
215 BinOpKind
::And
=> hir
::BinOpKind
::And
,
216 BinOpKind
::Or
=> hir
::BinOpKind
::Or
,
217 BinOpKind
::BitXor
=> hir
::BinOpKind
::BitXor
,
218 BinOpKind
::BitAnd
=> hir
::BinOpKind
::BitAnd
,
219 BinOpKind
::BitOr
=> hir
::BinOpKind
::BitOr
,
220 BinOpKind
::Shl
=> hir
::BinOpKind
::Shl
,
221 BinOpKind
::Shr
=> hir
::BinOpKind
::Shr
,
222 BinOpKind
::Eq
=> hir
::BinOpKind
::Eq
,
223 BinOpKind
::Lt
=> hir
::BinOpKind
::Lt
,
224 BinOpKind
::Le
=> hir
::BinOpKind
::Le
,
225 BinOpKind
::Ne
=> hir
::BinOpKind
::Ne
,
226 BinOpKind
::Ge
=> hir
::BinOpKind
::Ge
,
227 BinOpKind
::Gt
=> hir
::BinOpKind
::Gt
,
233 /// Emit an error and lower `ast::ExprKind::Let(pat, scrutinee)` into:
235 /// match scrutinee { pats => true, _ => false }
237 fn lower_expr_let(&mut self, span
: Span
, pat
: &Pat
, scrutinee
: &Expr
) -> hir
::ExprKind
{
238 // If we got here, the `let` expression is not allowed.
240 if self.sess
.opts
.unstable_features
.is_nightly_build() {
242 .struct_span_err(span
, "`let` expressions are not supported here")
243 .note("only supported directly in conditions of `if`- and `while`-expressions")
244 .note("as well as when nested within `&&` and parenthesis in those conditions")
249 .struct_span_err(span
, "expected expression, found statement (`let`)")
250 .note("variable declaration using `let` is a statement")
254 // For better recovery, we emit:
256 // match scrutinee { pat => true, _ => false }
258 // While this doesn't fully match the user's intent, it has key advantages:
259 // 1. We can avoid using `abort_if_errors`.
260 // 2. We can typeck both `pat` and `scrutinee`.
261 // 3. `pat` is allowed to be refutable.
262 // 4. The return type of the block is `bool` which seems like what the user wanted.
263 let scrutinee
= self.lower_expr(scrutinee
);
265 let pat
= self.lower_pat(pat
);
266 let expr
= self.expr_bool(span
, true);
267 self.arm(pat
, P(expr
))
270 let pat
= self.pat_wild(span
);
271 let expr
= self.expr_bool(span
, false);
272 self.arm(pat
, P(expr
))
274 hir
::ExprKind
::Match(
276 vec
![then_arm
, else_arm
].into(),
277 hir
::MatchSource
::Normal
,
286 else_opt
: Option
<&Expr
>,
288 // FIXME(#53667): handle lowering of && and parens.
290 // `_ => else_block` where `else_block` is `{}` if there's `None`:
291 let else_pat
= self.pat_wild(span
);
292 let (else_expr
, contains_else_clause
) = match else_opt
{
293 None
=> (self.expr_block_empty(span
), false),
294 Some(els
) => (self.lower_expr(els
), true),
296 let else_arm
= self.arm(else_pat
, P(else_expr
));
298 // Handle then + scrutinee:
299 let then_expr
= self.lower_block_expr(then
);
300 let (then_pat
, scrutinee
, desugar
) = match cond
.kind
{
301 // `<pat> => <then>`:
302 ExprKind
::Let(ref pat
, ref scrutinee
) => {
303 let scrutinee
= self.lower_expr(scrutinee
);
304 let pat
= self.lower_pat(pat
);
305 (pat
, scrutinee
, hir
::MatchSource
::IfLetDesugar { contains_else_clause }
)
310 let cond
= self.lower_expr(cond
);
311 let span_block
= self.mark_span_with_reason(
312 DesugaringKind
::CondTemporary
,
316 // Wrap in a construct equivalent to `{ let _t = $cond; _t }`
317 // to preserve drop semantics since `if cond { ... }` does not
318 // let temporaries live outside of `cond`.
319 let cond
= self.expr_drop_temps(span_block
, P(cond
), ThinVec
::new());
320 let pat
= self.pat_bool(span
, true);
321 (pat
, cond
, hir
::MatchSource
::IfDesugar { contains_else_clause }
)
324 let then_arm
= self.arm(then_pat
, P(then_expr
));
326 hir
::ExprKind
::Match(P(scrutinee
), vec
![then_arm
, else_arm
].into(), desugar
)
329 fn lower_expr_while_in_loop_scope(
334 opt_label
: Option
<Label
>
336 // FIXME(#53667): handle lowering of && and parens.
338 // Note that the block AND the condition are evaluated in the loop scope.
339 // This is done to allow `break` from inside the condition of the loop.
343 let else_pat
= self.pat_wild(span
);
344 let else_expr
= self.expr_break(span
, ThinVec
::new());
345 self.arm(else_pat
, else_expr
)
348 // Handle then + scrutinee:
349 let then_expr
= self.lower_block_expr(body
);
350 let (then_pat
, scrutinee
, desugar
, source
) = match cond
.kind
{
351 ExprKind
::Let(ref pat
, ref scrutinee
) => {
354 // [opt_ident]: loop {
355 // match <sub_expr> {
360 let scrutinee
= self.with_loop_condition_scope(|t
| t
.lower_expr(scrutinee
));
361 let pat
= self.lower_pat(pat
);
362 (pat
, scrutinee
, hir
::MatchSource
::WhileLetDesugar
, hir
::LoopSource
::WhileLet
)
365 // We desugar: `'label: while $cond $body` into:
369 // match drop-temps { $cond } {
377 let cond
= self.with_loop_condition_scope(|this
| this
.lower_expr(cond
));
378 let span_block
= self.mark_span_with_reason(
379 DesugaringKind
::CondTemporary
,
383 // Wrap in a construct equivalent to `{ let _t = $cond; _t }`
384 // to preserve drop semantics since `while cond { ... }` does not
385 // let temporaries live outside of `cond`.
386 let cond
= self.expr_drop_temps(span_block
, P(cond
), ThinVec
::new());
388 let pat
= self.pat_bool(span
, true);
389 (pat
, cond
, hir
::MatchSource
::WhileDesugar
, hir
::LoopSource
::While
)
392 let then_arm
= self.arm(then_pat
, P(then_expr
));
394 // `match <scrutinee> { ... }`
395 let match_expr
= self.expr_match(
398 hir_vec
![then_arm
, else_arm
],
402 // `[opt_ident]: loop { ... }`
404 P(self.block_expr(P(match_expr
))),
405 self.lower_label(opt_label
),
410 /// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_ok(<expr>) }`,
411 /// `try { <stmts>; }` into `{ <stmts>; ::std::ops::Try::from_ok(()) }`
412 /// and save the block id to use it as a break target for desugaring of the `?` operator.
413 fn lower_expr_try_block(&mut self, body
: &Block
) -> hir
::ExprKind
{
414 self.with_catch_scope(body
.id
, |this
| {
415 let mut block
= this
.lower_block(body
, true).into_inner();
417 let try_span
= this
.mark_span_with_reason(
418 DesugaringKind
::TryBlock
,
420 this
.allow_try_trait
.clone(),
423 // Final expression of the block (if present) or `()` with span at the end of block
424 let tail_expr
= block
.expr
.take().map_or_else(
425 || this
.expr_unit(this
.sess
.source_map().end_point(try_span
)),
426 |x
: P
<hir
::Expr
>| x
.into_inner(),
429 let ok_wrapped_span
= this
.mark_span_with_reason(
430 DesugaringKind
::TryBlock
,
435 // `::std::ops::Try::from_ok($tail_expr)`
436 block
.expr
= Some(this
.wrap_in_try_constructor(
437 sym
::from_ok
, try_span
, tail_expr
, ok_wrapped_span
));
439 hir
::ExprKind
::Block(P(block
), None
)
443 fn wrap_in_try_constructor(
450 let path
= &[sym
::ops
, sym
::Try
, method
];
451 let constructor
= P(self.expr_std_path(method_span
, path
, None
, ThinVec
::new()));
452 P(self.expr_call(overall_span
, constructor
, hir_vec
![expr
]))
455 fn lower_arm(&mut self, arm
: &Arm
) -> hir
::Arm
{
457 hir_id
: self.next_id(),
458 attrs
: self.lower_attrs(&arm
.attrs
),
459 pat
: self.lower_pat(&arm
.pat
),
460 guard
: match arm
.guard
{
461 Some(ref x
) => Some(hir
::Guard
::If(P(self.lower_expr(x
)))),
464 body
: P(self.lower_expr(&arm
.body
)),
469 pub(super) fn make_async_expr(
471 capture_clause
: CaptureBy
,
472 closure_node_id
: NodeId
,
473 ret_ty
: Option
<AstP
<Ty
>>,
475 async_gen_kind
: hir
::AsyncGeneratorKind
,
476 body
: impl FnOnce(&mut LoweringContext
<'_
>) -> hir
::Expr
,
478 let output
= match ret_ty
{
479 Some(ty
) => FunctionRetTy
::Ty(ty
),
480 None
=> FunctionRetTy
::Default(span
),
482 let ast_decl
= FnDecl
{
486 let decl
= self.lower_fn_decl(&ast_decl
, None
, /* impl trait allowed */ false, None
);
487 let body_id
= self.lower_fn_body(&ast_decl
, |this
| {
488 this
.generator_kind
= Some(hir
::GeneratorKind
::Async(async_gen_kind
));
492 // `static || -> <ret_ty> { body }`:
493 let generator_kind
= hir
::ExprKind
::Closure(
498 Some(hir
::Movability
::Static
)
500 let generator
= hir
::Expr
{
501 hir_id
: self.lower_node_id(closure_node_id
),
502 kind
: generator_kind
,
504 attrs
: ThinVec
::new(),
507 // `future::from_generator`:
508 let unstable_span
= self.mark_span_with_reason(
509 DesugaringKind
::Async
,
511 self.allow_gen_future
.clone(),
513 let gen_future
= self.expr_std_path(
515 &[sym
::future
, sym
::from_generator
],
520 // `future::from_generator(generator)`:
521 hir
::ExprKind
::Call(P(gen_future
), hir_vec
![generator
])
524 /// Desugar `<expr>.await` into:
527 /// mut pinned => loop {
528 /// match ::std::future::poll_with_tls_context(unsafe {
529 /// <::std::pin::Pin>::new_unchecked(&mut pinned)
531 /// ::std::task::Poll::Ready(result) => break result,
532 /// ::std::task::Poll::Pending => {}
538 fn lower_expr_await(&mut self, await_span
: Span
, expr
: &Expr
) -> hir
::ExprKind
{
539 match self.generator_kind
{
540 Some(hir
::GeneratorKind
::Async(_
)) => {}
,
541 Some(hir
::GeneratorKind
::Gen
) |
543 let mut err
= struct_span_err
!(
547 "`await` is only allowed inside `async` functions and blocks"
549 err
.span_label(await_span
, "only allowed inside `async` functions and blocks");
550 if let Some(item_sp
) = self.current_item
{
551 err
.span_label(item_sp
, "this is not `async`");
556 let span
= self.mark_span_with_reason(
557 DesugaringKind
::Await
,
561 let gen_future_span
= self.mark_span_with_reason(
562 DesugaringKind
::Await
,
564 self.allow_gen_future
.clone(),
567 let pinned_ident
= Ident
::with_dummy_span(sym
::pinned
);
568 let (pinned_pat
, pinned_pat_hid
) = self.pat_ident_binding_mode(
571 hir
::BindingAnnotation
::Mutable
,
574 // ::std::future::poll_with_tls_context(unsafe {
575 // ::std::pin::Pin::new_unchecked(&mut pinned)
578 let pinned
= P(self.expr_ident(span
, pinned_ident
, pinned_pat_hid
));
579 let ref_mut_pinned
= self.expr_mut_addr_of(span
, pinned
);
580 let pin_ty_id
= self.next_id();
581 let new_unchecked_expr_kind
= self.expr_call_std_assoc_fn(
584 &[sym
::pin
, sym
::Pin
],
586 hir_vec
![ref_mut_pinned
],
588 let new_unchecked
= P(self.expr(span
, new_unchecked_expr_kind
, ThinVec
::new()));
589 let unsafe_expr
= self.expr_unsafe(new_unchecked
);
590 P(self.expr_call_std_path(
592 &[sym
::future
, sym
::poll_with_tls_context
],
593 hir_vec
![unsafe_expr
],
597 // `::std::task::Poll::Ready(result) => break result`
598 let loop_node_id
= self.resolver
.next_node_id();
599 let loop_hir_id
= self.lower_node_id(loop_node_id
);
601 let x_ident
= Ident
::with_dummy_span(sym
::result
);
602 let (x_pat
, x_pat_hid
) = self.pat_ident(span
, x_ident
);
603 let x_expr
= P(self.expr_ident(span
, x_ident
, x_pat_hid
));
604 let ready_pat
= self.pat_std_enum(
606 &[sym
::task
, sym
::Poll
, sym
::Ready
],
609 let break_x
= self.with_loop_scope(loop_node_id
, |this
| {
610 let expr_break
= hir
::ExprKind
::Break(
611 this
.lower_loop_destination(None
),
614 P(this
.expr(await_span
, expr_break
, ThinVec
::new()))
616 self.arm(ready_pat
, break_x
)
619 // `::std::task::Poll::Pending => {}`
621 let pending_pat
= self.pat_std_enum(
623 &[sym
::task
, sym
::Poll
, sym
::Pending
],
626 let empty_block
= P(self.expr_block_empty(span
));
627 self.arm(pending_pat
, empty_block
)
630 let inner_match_stmt
= {
631 let match_expr
= self.expr_match(
634 hir_vec
![ready_arm
, pending_arm
],
635 hir
::MatchSource
::AwaitDesugar
,
637 self.stmt_expr(span
, match_expr
)
641 let unit
= self.expr_unit(span
);
642 let yield_expr
= self.expr(
644 hir
::ExprKind
::Yield(P(unit
), hir
::YieldSource
::Await
),
647 self.stmt_expr(span
, yield_expr
)
650 let loop_block
= P(self.block_all(
652 hir_vec
![inner_match_stmt
, yield_stmt
],
657 let loop_expr
= P(hir
::Expr
{
659 kind
: hir
::ExprKind
::Loop(
662 hir
::LoopSource
::Loop
,
665 attrs
: ThinVec
::new(),
668 // mut pinned => loop { ... }
669 let pinned_arm
= self.arm(pinned_pat
, loop_expr
);
672 // mut pinned => loop { .. }
674 let expr
= P(self.lower_expr(expr
));
675 hir
::ExprKind
::Match(expr
, hir_vec
![pinned_arm
], hir
::MatchSource
::AwaitDesugar
)
678 fn lower_expr_closure(
680 capture_clause
: CaptureBy
,
681 movability
: Movability
,
686 // Lower outside new scope to preserve `is_in_loop_condition`.
687 let fn_decl
= self.lower_fn_decl(decl
, None
, false, None
);
689 self.with_new_scopes(|this
| {
690 let prev
= this
.current_item
;
691 this
.current_item
= Some(fn_decl_span
);
692 let mut generator_kind
= None
;
693 let body_id
= this
.lower_fn_body(decl
, |this
| {
694 let e
= this
.lower_expr(body
);
695 generator_kind
= this
.generator_kind
;
698 let generator_option
= this
.generator_movability_for_fn(
704 this
.current_item
= prev
;
705 hir
::ExprKind
::Closure(
715 fn generator_movability_for_fn(
719 generator_kind
: Option
<hir
::GeneratorKind
>,
720 movability
: Movability
,
721 ) -> Option
<hir
::Movability
> {
722 match generator_kind
{
723 Some(hir
::GeneratorKind
::Gen
) => {
724 if !decl
.inputs
.is_empty() {
729 "generators cannot have explicit parameters"
734 Some(hir
::GeneratorKind
::Async(_
)) => {
735 bug
!("non-`async` closure body turned `async` during lowering");
738 if movability
== Movability
::Static
{
743 "closures cannot be static"
751 fn lower_expr_async_closure(
753 capture_clause
: CaptureBy
,
759 let outer_decl
= FnDecl
{
760 inputs
: decl
.inputs
.clone(),
761 output
: FunctionRetTy
::Default(fn_decl_span
),
763 // We need to lower the declaration outside the new scope, because we
764 // have to conserve the state of being inside a loop condition for the
765 // closure argument types.
766 let fn_decl
= self.lower_fn_decl(&outer_decl
, None
, false, None
);
768 self.with_new_scopes(|this
| {
769 // FIXME(cramertj): allow `async` non-`move` closures with arguments.
770 if capture_clause
== CaptureBy
::Ref
&& !decl
.inputs
.is_empty() {
775 "`async` non-`move` closures with parameters are not currently supported",
778 "consider using `let` statements to manually capture \
779 variables by reference before entering an `async move` closure"
784 // Transform `async |x: u8| -> X { ... }` into
785 // `|x: u8| future_from_generator(|| -> X { ... })`.
786 let body_id
= this
.lower_fn_body(&outer_decl
, |this
| {
787 let async_ret_ty
= if let FunctionRetTy
::Ty(ty
) = &decl
.output
{
792 let async_body
= this
.make_async_expr(
797 hir
::AsyncGeneratorKind
::Closure
,
798 |this
| this
.with_new_scopes(|this
| this
.lower_expr(body
)),
800 this
.expr(fn_decl_span
, async_body
, ThinVec
::new())
802 hir
::ExprKind
::Closure(
812 /// Desugar `<start>..=<end>` into `std::ops::RangeInclusive::new(<start>, <end>)`.
813 fn lower_expr_range_closed(&mut self, span
: Span
, e1
: &Expr
, e2
: &Expr
) -> hir
::ExprKind
{
814 let id
= self.next_id();
815 let e1
= self.lower_expr(e1
);
816 let e2
= self.lower_expr(e2
);
817 self.expr_call_std_assoc_fn(
820 &[sym
::ops
, sym
::RangeInclusive
],
833 use syntax
::ast
::RangeLimits
::*;
835 let path
= match (e1
, e2
, lims
) {
836 (None
, None
, HalfOpen
) => sym
::RangeFull
,
837 (Some(..), None
, HalfOpen
) => sym
::RangeFrom
,
838 (None
, Some(..), HalfOpen
) => sym
::RangeTo
,
839 (Some(..), Some(..), HalfOpen
) => sym
::Range
,
840 (None
, Some(..), Closed
) => sym
::RangeToInclusive
,
841 (Some(..), Some(..), Closed
) => unreachable
!(),
842 (_
, None
, Closed
) => self.diagnostic()
843 .span_fatal(span
, "inclusive range with no end")
847 let fields
= e1
.iter()
848 .map(|e
| ("start", e
))
849 .chain(e2
.iter().map(|e
| ("end", e
)))
851 let expr
= P(self.lower_expr(&e
));
852 let ident
= Ident
::new(Symbol
::intern(s
), e
.span
);
853 self.field(ident
, expr
, e
.span
)
855 .collect
::<P
<[hir
::Field
]>>();
857 let is_unit
= fields
.is_empty();
858 let struct_path
= [sym
::ops
, path
];
859 let struct_path
= self.std_path(span
, &struct_path
, None
, is_unit
);
860 let struct_path
= hir
::QPath
::Resolved(None
, P(struct_path
));
863 hir
::ExprKind
::Path(struct_path
)
865 hir
::ExprKind
::Struct(P(struct_path
), fields
, None
)
869 fn lower_label(&mut self, label
: Option
<Label
>) -> Option
<hir
::Label
> {
870 label
.map(|label
| hir
::Label
{
875 fn lower_loop_destination(&mut self, destination
: Option
<(NodeId
, Label
)>) -> hir
::Destination
{
876 let target_id
= match destination
{
878 if let Some(loop_id
) = self.resolver
.get_label_res(id
) {
879 Ok(self.lower_node_id(loop_id
))
881 Err(hir
::LoopIdError
::UnresolvedLabel
)
888 .map(|id
| Ok(self.lower_node_id(id
)))
889 .unwrap_or(Err(hir
::LoopIdError
::OutsideLoopScope
))
894 label
: self.lower_label(destination
.map(|(_
, label
)| label
)),
899 fn lower_jump_destination(&mut self, id
: NodeId
, opt_label
: Option
<Label
>) -> hir
::Destination
{
900 if self.is_in_loop_condition
&& opt_label
.is_none() {
903 target_id
: Err(hir
::LoopIdError
::UnlabeledCfInWhileCondition
).into(),
906 self.lower_loop_destination(opt_label
.map(|label
| (id
, label
)))
910 fn with_catch_scope
<T
, F
>(&mut self, catch_id
: NodeId
, f
: F
) -> T
912 F
: FnOnce(&mut LoweringContext
<'_
>) -> T
,
914 let len
= self.catch_scopes
.len();
915 self.catch_scopes
.push(catch_id
);
917 let result
= f(self);
920 self.catch_scopes
.len(),
921 "catch scopes should be added and removed in stack order"
924 self.catch_scopes
.pop().unwrap();
929 fn with_loop_scope
<T
, F
>(&mut self, loop_id
: NodeId
, f
: F
) -> T
931 F
: FnOnce(&mut LoweringContext
<'_
>) -> T
,
933 // We're no longer in the base loop's condition; we're in another loop.
934 let was_in_loop_condition
= self.is_in_loop_condition
;
935 self.is_in_loop_condition
= false;
937 let len
= self.loop_scopes
.len();
938 self.loop_scopes
.push(loop_id
);
940 let result
= f(self);
943 self.loop_scopes
.len(),
944 "loop scopes should be added and removed in stack order"
947 self.loop_scopes
.pop().unwrap();
949 self.is_in_loop_condition
= was_in_loop_condition
;
954 fn with_loop_condition_scope
<T
, F
>(&mut self, f
: F
) -> T
956 F
: FnOnce(&mut LoweringContext
<'_
>) -> T
,
958 let was_in_loop_condition
= self.is_in_loop_condition
;
959 self.is_in_loop_condition
= true;
961 let result
= f(self);
963 self.is_in_loop_condition
= was_in_loop_condition
;
968 fn lower_expr_asm(&mut self, asm
: &InlineAsm
) -> hir
::ExprKind
{
969 let inner
= hir
::InlineAsmInner
{
970 inputs
: asm
.inputs
.iter().map(|&(ref c
, _
)| c
.clone()).collect(),
973 .map(|out
| hir
::InlineAsmOutput
{
974 constraint
: out
.constraint
.clone(),
976 is_indirect
: out
.is_indirect
,
980 asm
: asm
.asm
.clone(),
981 asm_str_style
: asm
.asm_str_style
,
982 clobbers
: asm
.clobbers
.clone().into(),
983 volatile
: asm
.volatile
,
984 alignstack
: asm
.alignstack
,
985 dialect
: asm
.dialect
,
987 let hir_asm
= hir
::InlineAsm
{
989 inputs_exprs
: asm
.inputs
991 .map(|&(_
, ref input
)| self.lower_expr(input
))
993 outputs_exprs
: asm
.outputs
995 .map(|out
| self.lower_expr(&out
.expr
))
998 hir
::ExprKind
::InlineAsm(P(hir_asm
))
1001 fn lower_field(&mut self, f
: &Field
) -> hir
::Field
{
1003 hir_id
: self.next_id(),
1005 expr
: P(self.lower_expr(&f
.expr
)),
1007 is_shorthand
: f
.is_shorthand
,
1011 fn lower_expr_yield(&mut self, span
: Span
, opt_expr
: Option
<&Expr
>) -> hir
::ExprKind
{
1012 match self.generator_kind
{
1013 Some(hir
::GeneratorKind
::Gen
) => {}
,
1014 Some(hir
::GeneratorKind
::Async(_
)) => {
1019 "`async` generators are not yet supported",
1021 return hir
::ExprKind
::Err
;
1023 None
=> self.generator_kind
= Some(hir
::GeneratorKind
::Gen
),
1028 .map(|x
| self.lower_expr(x
))
1029 .unwrap_or_else(|| self.expr_unit(span
));
1031 hir
::ExprKind
::Yield(P(expr
), hir
::YieldSource
::Yield
)
1034 /// Desugar `ExprForLoop` from: `[opt_ident]: for <pat> in <head> <body>` into:
1037 /// let result = match ::std::iter::IntoIterator::into_iter(<head>) {
1039 /// [opt_ident]: loop {
1041 /// match ::std::iter::Iterator::next(&mut iter) {
1042 /// ::std::option::Option::Some(val) => __next = val,
1043 /// ::std::option::Option::None => break
1045 /// let <pat> = __next;
1046 /// StmtKind::Expr(<body>);
1059 opt_label
: Option
<Label
>,
1062 let mut head
= self.lower_expr(head
);
1063 let desugared_span
= self.mark_span_with_reason(
1064 DesugaringKind
::ForLoop
,
1068 head
.span
= desugared_span
;
1070 let iter
= Ident
::with_dummy_span(sym
::iter
);
1072 let next_ident
= Ident
::with_dummy_span(sym
::__next
);
1073 let (next_pat
, next_pat_hid
) = self.pat_ident_binding_mode(
1076 hir
::BindingAnnotation
::Mutable
,
1079 // `::std::option::Option::Some(val) => __next = val`
1081 let val_ident
= Ident
::with_dummy_span(sym
::val
);
1082 let (val_pat
, val_pat_hid
) = self.pat_ident(pat
.span
, val_ident
);
1083 let val_expr
= P(self.expr_ident(pat
.span
, val_ident
, val_pat_hid
));
1084 let next_expr
= P(self.expr_ident(pat
.span
, next_ident
, next_pat_hid
));
1085 let assign
= P(self.expr(
1087 hir
::ExprKind
::Assign(next_expr
, val_expr
),
1090 let some_pat
= self.pat_some(pat
.span
, val_pat
);
1091 self.arm(some_pat
, assign
)
1094 // `::std::option::Option::None => break`
1097 self.with_loop_scope(e
.id
, |this
| this
.expr_break(e
.span
, ThinVec
::new()));
1098 let pat
= self.pat_none(e
.span
);
1099 self.arm(pat
, break_expr
)
1103 let (iter_pat
, iter_pat_nid
) = self.pat_ident_binding_mode(
1106 hir
::BindingAnnotation
::Mutable
1109 // `match ::std::iter::Iterator::next(&mut iter) { ... }`
1111 let iter
= P(self.expr_ident(desugared_span
, iter
, iter_pat_nid
));
1112 let ref_mut_iter
= self.expr_mut_addr_of(desugared_span
, iter
);
1113 let next_path
= &[sym
::iter
, sym
::Iterator
, sym
::next
];
1114 let next_expr
= P(self.expr_call_std_path(
1117 hir_vec
![ref_mut_iter
],
1119 let arms
= hir_vec
![pat_arm
, break_arm
];
1121 self.expr_match(desugared_span
, next_expr
, arms
, hir
::MatchSource
::ForLoopDesugar
)
1123 let match_stmt
= self.stmt_expr(desugared_span
, match_expr
);
1125 let next_expr
= P(self.expr_ident(desugared_span
, next_ident
, next_pat_hid
));
1128 let next_let
= self.stmt_let_pat(
1133 hir
::LocalSource
::ForLoopDesugar
,
1136 // `let <pat> = __next`
1137 let pat
= self.lower_pat(pat
);
1138 let pat_let
= self.stmt_let_pat(
1143 hir
::LocalSource
::ForLoopDesugar
,
1146 let body_block
= self.with_loop_scope(e
.id
, |this
| this
.lower_block(body
, false));
1147 let body_expr
= self.expr_block(body_block
, ThinVec
::new());
1148 let body_stmt
= self.stmt_expr(body
.span
, body_expr
);
1150 let loop_block
= P(self.block_all(
1152 hir_vec
![next_let
, match_stmt
, pat_let
, body_stmt
],
1156 // `[opt_ident]: loop { ... }`
1157 let kind
= hir
::ExprKind
::Loop(
1159 self.lower_label(opt_label
),
1160 hir
::LoopSource
::ForLoop
,
1162 let loop_expr
= P(hir
::Expr
{
1163 hir_id
: self.lower_node_id(e
.id
),
1166 attrs
: ThinVec
::new(),
1169 // `mut iter => { ... }`
1170 let iter_arm
= self.arm(iter_pat
, loop_expr
);
1172 // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
1173 let into_iter_expr
= {
1174 let into_iter_path
=
1175 &[sym
::iter
, sym
::IntoIterator
, sym
::into_iter
];
1176 P(self.expr_call_std_path(
1183 let match_expr
= P(self.expr_match(
1187 hir
::MatchSource
::ForLoopDesugar
,
1190 // This is effectively `{ let _result = ...; _result }`.
1191 // The construct was introduced in #21984 and is necessary to make sure that
1192 // temporaries in the `head` expression are dropped and do not leak to the
1193 // surrounding scope of the `match` since the `match` is not a terminating scope.
1195 // Also, add the attributes to the outer returned expr node.
1196 self.expr_drop_temps(desugared_span
, match_expr
, e
.attrs
.clone())
1199 /// Desugar `ExprKind::Try` from: `<expr>?` into:
1201 /// match Try::into_result(<expr>) {
1202 /// Ok(val) => #[allow(unreachable_code)] val,
1203 /// Err(err) => #[allow(unreachable_code)]
1204 /// // If there is an enclosing `try {...}`:
1205 /// break 'catch_target Try::from_error(From::from(err)),
1207 /// return Try::from_error(From::from(err)),
1210 fn lower_expr_try(&mut self, span
: Span
, sub_expr
: &Expr
) -> hir
::ExprKind
{
1211 let unstable_span
= self.mark_span_with_reason(
1212 DesugaringKind
::QuestionMark
,
1214 self.allow_try_trait
.clone(),
1216 let try_span
= self.sess
.source_map().end_point(span
);
1217 let try_span
= self.mark_span_with_reason(
1218 DesugaringKind
::QuestionMark
,
1220 self.allow_try_trait
.clone(),
1223 // `Try::into_result(<expr>)`
1226 let sub_expr
= self.lower_expr(sub_expr
);
1228 let path
= &[sym
::ops
, sym
::Try
, sym
::into_result
];
1229 P(self.expr_call_std_path(unstable_span
, path
, hir_vec
![sub_expr
]))
1232 // `#[allow(unreachable_code)]`
1234 // `allow(unreachable_code)`
1236 let allow_ident
= Ident
::new(sym
::allow
, span
);
1237 let uc_ident
= Ident
::new(sym
::unreachable_code
, span
);
1238 let uc_nested
= attr
::mk_nested_word_item(uc_ident
);
1239 attr
::mk_list_item(allow_ident
, vec
![uc_nested
])
1241 attr
::mk_attr_outer(allow
)
1243 let attrs
= vec
![attr
];
1245 // `Ok(val) => #[allow(unreachable_code)] val,`
1247 let val_ident
= Ident
::with_dummy_span(sym
::val
);
1248 let (val_pat
, val_pat_nid
) = self.pat_ident(span
, val_ident
);
1249 let val_expr
= P(self.expr_ident_with_attrs(
1253 ThinVec
::from(attrs
.clone()),
1255 let ok_pat
= self.pat_ok(span
, val_pat
);
1256 self.arm(ok_pat
, val_expr
)
1259 // `Err(err) => #[allow(unreachable_code)]
1260 // return Try::from_error(From::from(err)),`
1262 let err_ident
= Ident
::with_dummy_span(sym
::err
);
1263 let (err_local
, err_local_nid
) = self.pat_ident(try_span
, err_ident
);
1265 let from_path
= &[sym
::convert
, sym
::From
, sym
::from
];
1266 let err_expr
= self.expr_ident(try_span
, err_ident
, err_local_nid
);
1267 self.expr_call_std_path(try_span
, from_path
, hir_vec
![err_expr
])
1270 self.wrap_in_try_constructor(sym
::from_error
, unstable_span
, from_expr
, try_span
);
1271 let thin_attrs
= ThinVec
::from(attrs
);
1272 let catch_scope
= self.catch_scopes
.last().map(|x
| *x
);
1273 let ret_expr
= if let Some(catch_node
) = catch_scope
{
1274 let target_id
= Ok(self.lower_node_id(catch_node
));
1277 hir
::ExprKind
::Break(
1282 Some(from_err_expr
),
1287 P(self.expr(try_span
, hir
::ExprKind
::Ret(Some(from_err_expr
)), thin_attrs
))
1290 let err_pat
= self.pat_err(try_span
, err_local
);
1291 self.arm(err_pat
, ret_expr
)
1294 hir
::ExprKind
::Match(
1296 hir_vec
![err_arm
, ok_arm
],
1297 hir
::MatchSource
::TryDesugar
,
1301 // =========================================================================
1302 // Helper methods for building HIR.
1303 // =========================================================================
1305 /// Constructs a `true` or `false` literal expression.
1306 pub(super) fn expr_bool(&mut self, span
: Span
, val
: bool
) -> hir
::Expr
{
1307 let lit
= Spanned { span, node: LitKind::Bool(val) }
;
1308 self.expr(span
, hir
::ExprKind
::Lit(lit
), ThinVec
::new())
1311 /// Wrap the given `expr` in a terminating scope using `hir::ExprKind::DropTemps`.
1313 /// In terms of drop order, it has the same effect as wrapping `expr` in
1314 /// `{ let _t = $expr; _t }` but should provide better compile-time performance.
1316 /// The drop order can be important in e.g. `if expr { .. }`.
1317 pub(super) fn expr_drop_temps(
1321 attrs
: ThinVec
<Attribute
>
1323 self.expr(span
, hir
::ExprKind
::DropTemps(expr
), attrs
)
1330 arms
: hir
::HirVec
<hir
::Arm
>,
1331 source
: hir
::MatchSource
,
1333 self.expr(span
, hir
::ExprKind
::Match(arg
, arms
, source
), ThinVec
::new())
1336 fn expr_break(&mut self, span
: Span
, attrs
: ThinVec
<Attribute
>) -> P
<hir
::Expr
> {
1337 let expr_break
= hir
::ExprKind
::Break(self.lower_loop_destination(None
), None
);
1338 P(self.expr(span
, expr_break
, attrs
))
1341 fn expr_mut_addr_of(&mut self, span
: Span
, e
: P
<hir
::Expr
>) -> hir
::Expr
{
1344 hir
::ExprKind
::AddrOf(hir
::BorrowKind
::Ref
, hir
::Mutability
::Mutable
, e
),
1349 fn expr_unit(&mut self, sp
: Span
) -> hir
::Expr
{
1350 self.expr_tuple(sp
, hir_vec
![])
1353 fn expr_tuple(&mut self, sp
: Span
, exprs
: hir
::HirVec
<hir
::Expr
>) -> hir
::Expr
{
1354 self.expr(sp
, hir
::ExprKind
::Tup(exprs
), ThinVec
::new())
1361 args
: hir
::HirVec
<hir
::Expr
>,
1363 self.expr(span
, hir
::ExprKind
::Call(e
, args
), ThinVec
::new())
1366 // Note: associated functions must use `expr_call_std_path`.
1367 fn expr_call_std_path(
1370 path_components
: &[Symbol
],
1371 args
: hir
::HirVec
<hir
::Expr
>,
1373 let path
= P(self.expr_std_path(span
, path_components
, None
, ThinVec
::new()));
1374 self.expr_call(span
, path
, args
)
1377 // Create an expression calling an associated function of an std type.
1379 // Associated functions cannot be resolved through the normal `std_path` function,
1380 // as they are resolved differently and so cannot use `expr_call_std_path`.
1382 // This function accepts the path component (`ty_path_components`) separately from
1383 // the name of the associated function (`assoc_fn_name`) in order to facilitate
1384 // separate resolution of the type and creation of a path referring to its associated
1386 fn expr_call_std_assoc_fn(
1388 ty_path_id
: hir
::HirId
,
1390 ty_path_components
: &[Symbol
],
1391 assoc_fn_name
: &str,
1392 args
: hir
::HirVec
<hir
::Expr
>,
1393 ) -> hir
::ExprKind
{
1394 let ty_path
= P(self.std_path(span
, ty_path_components
, None
, false));
1395 let ty
= P(self.ty_path(ty_path_id
, span
, hir
::QPath
::Resolved(None
, ty_path
)));
1396 let fn_seg
= P(hir
::PathSegment
::from_ident(Ident
::from_str(assoc_fn_name
)));
1397 let fn_path
= hir
::QPath
::TypeRelative(ty
, fn_seg
);
1398 let fn_expr
= P(self.expr(span
, hir
::ExprKind
::Path(fn_path
), ThinVec
::new()));
1399 hir
::ExprKind
::Call(fn_expr
, args
)
1405 components
: &[Symbol
],
1406 params
: Option
<P
<hir
::GenericArgs
>>,
1407 attrs
: ThinVec
<Attribute
>,
1409 let path
= self.std_path(span
, components
, params
, true);
1412 hir
::ExprKind
::Path(hir
::QPath
::Resolved(None
, P(path
))),
1417 pub(super) fn expr_ident(&mut self, sp
: Span
, ident
: Ident
, binding
: hir
::HirId
) -> hir
::Expr
{
1418 self.expr_ident_with_attrs(sp
, ident
, binding
, ThinVec
::new())
1421 fn expr_ident_with_attrs(
1425 binding
: hir
::HirId
,
1426 attrs
: ThinVec
<Attribute
>,
1428 let expr_path
= hir
::ExprKind
::Path(hir
::QPath
::Resolved(
1432 res
: Res
::Local(binding
),
1433 segments
: hir_vec
![hir
::PathSegment
::from_ident(ident
)],
1437 self.expr(span
, expr_path
, attrs
)
1440 fn expr_unsafe(&mut self, expr
: P
<hir
::Expr
>) -> hir
::Expr
{
1441 let hir_id
= self.next_id();
1442 let span
= expr
.span
;
1445 hir
::ExprKind
::Block(P(hir
::Block
{
1449 rules
: hir
::UnsafeBlock(hir
::CompilerGenerated
),
1451 targeted_by_break
: false,
1457 fn expr_block_empty(&mut self, span
: Span
) -> hir
::Expr
{
1458 let blk
= self.block_all(span
, hir_vec
![], None
);
1459 self.expr_block(P(blk
), ThinVec
::new())
1462 pub(super) fn expr_block(&mut self, b
: P
<hir
::Block
>, attrs
: ThinVec
<Attribute
>) -> hir
::Expr
{
1463 self.expr(b
.span
, hir
::ExprKind
::Block(b
, None
), attrs
)
1469 kind
: hir
::ExprKind
,
1470 attrs
: ThinVec
<Attribute
>
1472 hir
::Expr { hir_id: self.next_id(), kind, span, attrs }
1475 fn field(&mut self, ident
: Ident
, expr
: P
<hir
::Expr
>, span
: Span
) -> hir
::Field
{
1477 hir_id
: self.next_id(),
1481 is_shorthand
: false,
1485 fn arm(&mut self, pat
: P
<hir
::Pat
>, expr
: P
<hir
::Expr
>) -> hir
::Arm
{
1487 hir_id
: self.next_id(),